Compare commits

112 Commits

Author SHA1 Message Date
KOWX712
b07c9f8f5a v2.9 Merry Christmas 2024-12-25 16:41:34 +08:00
KOWX712
dad4bed07e Restructure css 2024-12-25 16:22:39 +08:00
KOWX712
a7214cfa81 Preserve ! and ? during update target
#7
2024-12-25 15:32:49 +08:00
KOWX712
82c489f787 local icon
No longer need internet connection to load icon
2024-12-24 22:40:03 +08:00
KOWX712
de43439200 Restructure index.js, simplify translation process
No big change
2024-12-24 22:25:41 +08:00
KOWX712
5347ac29bf Restructure translation (no functional change) 2024-12-24 15:55:09 +08:00
Keinta15
37467411cf Update es-ES.json
Adjusted phrasing for better fluency and corrected minor grammar issues
2024-12-20 01:18:30 +00:00
KOWX712
4fd5b47817 add Spanish 2024-12-20 00:36:54 +08:00
KOWX712
610f106913 Weak connection fix + code optimize + fix typo
Don't show applist before finish check update. Slightly slower loading but remove freeze on weak connection device
2024-12-19 22:58:33 +08:00
KOWX712
dc46e5f12e Remove restriction on installation
But module will still removed automatically if tricky store module not found to keep the convenient for user to remove webui when uninstalling tricky store.
2024-12-16 02:38:54 +08:00
backslashxx
f46cc964e4 module: common/get_extra: reorder functions 2024-12-15 13:44:17 +08:00
backslashxx
a7963c53dc module: common/get_extra: remove bashism 2024-12-15 13:44:17 +08:00
backslashxx
7c5b144492 module: common/get_extra: use download instead 2024-12-15 13:44:17 +08:00
backslashxx
4230929dc9 module: common/get_extra: import download function from bindhosts 2024-12-15 13:44:17 +08:00
backslashxx
437237e3d4 module: common/get_extra: drop check_wget function 2024-12-15 13:44:17 +08:00
KOWX712
cfb51e28fb v2.8 release 2024-12-14 16:08:51 +08:00
KOWX712
6bdfff7f92 fix auto select language
fix auto language select missing due to change in ff6244b140
2024-12-14 16:06:34 +08:00
KOWX712
4146f09062 Merge pull request #4 from reindex-ot/main
Add Japanese locale.
2024-12-14 12:38:00 +08:00
KOWX712
d223b39e29 add option in html 2024-12-14 12:37:14 +08:00
Re*Index. (ot_inc)
6bf5009cb8 Add files via upload 2024-12-14 11:16:51 +09:00
KOWX712
22bdb3986a lite 2024-12-13 03:44:35 +08:00
KOWX712
2a04b7426d Update README.md 2024-12-13 03:33:10 +08:00
KOWX712
a03b785323 adjust ui 2024-12-13 03:09:52 +08:00
KOWX712
d307c57171 update README.md 2024-12-11 17:09:14 +08:00
KOWX712
c6339f4e5d Add back missing no connection prompt 2024-12-11 16:27:59 +08:00
KOWX712
4c9e56c1db Fix lag on deselect unnecessary option 2024-12-11 15:41:20 +08:00
KOWX712
9302d39910 Fix update operation in ksu/apatch
Simplified the code, better readability.
2024-12-11 15:05:45 +08:00
KOWX712
06d2edf57f Update README.md 2024-12-10 22:55:33 +08:00
KOWX712
ff6244b140 Invisible module full implementation
NOT STABLE, not tested on KSU
2024-12-10 22:25:01 +08:00
KOWX712
dfe4a23f8a loading time optimization
probably removed all loading time
2024-12-10 04:05:06 +08:00
KOWX712
5dd1496ca7 Merge pull request #3 from DerGoogler/main
Add metadata for MMRL
2024-12-08 09:53:32 +08:00
Der_Googler
8c831cea39 Add metadata for MMRL
Also includes a note
2024-12-08 00:40:36 +01:00
KOWX712
42a8f6baae v2.7.1 quick fix 2024-12-07 21:20:53 +08:00
KOWX712
befa011c15 remove unused logic 2024-12-07 21:19:19 +08:00
KOWX712
f576b4bb2f link redirect quick fix 2024-12-07 20:52:01 +08:00
KOWX712
a2b2da27f8 v2.7 release 2024-12-07 17:59:57 +08:00
KOWX712
b3282816cb handle tmpdir in Magisk 2024-12-07 17:47:40 +08:00
KOWX712
15f975ee67 increase prompt priority 2024-12-07 17:33:59 +08:00
KOWX712
11d3b34657 remove residue changing from invisible to visible 2024-12-07 17:28:08 +08:00
KOWX712
ad905cb6e0 fix invisible ksu residue 2024-12-07 17:02:42 +08:00
KOWX712
5b966f5626 fix visible broken logic 2024-12-07 16:40:14 +08:00
KOWX712
c500e7476a Update customize.sh 2024-12-07 16:32:13 +08:00
KOWX712
1b2a1701f4 Invisible module update method, more
New update card for invisible module, refine module visibility logic (better adapt with MMRL). Add active class.
2024-12-07 16:10:13 +08:00
KOWX712
4563a3399d Update A-translate.md 2024-12-07 03:47:22 +08:00
KOWX712
873354b11c Adapt with MMRL 2024-12-07 03:47:15 +08:00
KOWX712
3d8ca67a6a Update more-excldue.json 2024-12-06 12:22:20 +08:00
KOWX712
f13e4ecca5 Update install_func.sh 2024-12-05 11:15:02 +08:00
KOWX712
878a5faacf Simplify the translation process 2024-12-05 01:27:40 +08:00
KOWX712
504918a289 Fix some possible issue may happen in future 2024-12-05 01:24:53 +08:00
KOWX712
6f9d4482a7 Update .extra 2024-12-05 00:39:25 +08:00
KOWX712
765444fcd5 Update .extra 2024-12-04 21:18:57 +08:00
KOWX712
7905ebcca5 Merge branch 'main' of https://github.com/KOWX712/Tricky-Addon-Update-Target-List 2024-12-04 10:33:56 +08:00
KOWX712
030f48f8ce Update .extra 2024-12-04 10:33:48 +08:00
KOWX712
27b932ed82 Update README.md 2024-12-04 02:36:49 +08:00
KOWX712
d839e3ea4d Update .extra 2024-12-04 01:12:51 +08:00
KOWX712
119e0aa2cf Cleanup, rearrange code 2024-12-03 22:03:30 +08:00
KOWX712
d17ca1d7ef prevent mistouch 2024-12-03 21:10:52 +08:00
KOWX712
3f5832608e add missing folder 2024-12-03 20:19:46 +08:00
KOWX712
b06ffda6bf Remove module if tricky store uninstalled 2024-12-03 19:59:04 +08:00
KOWX712
8f6dc6523d adjust again 2024-12-03 19:37:10 +08:00
KOWX712
552758a01f Update README.md 2024-12-03 19:14:08 +08:00
KOWX712
6a21702f25 slightly adjust ui on large screen display 2024-12-03 19:13:36 +08:00
KOWX712
31a229e52b save button style 2024-12-03 02:24:15 +08:00
KOWX712
c7fa970158 add manually run workflow 2024-12-03 02:22:59 +08:00
KOWX712
9e569421cd Update README.md 2024-12-03 01:19:59 +08:00
KOWX712
13f020ebd0 test canary 2024-12-03 01:00:24 +08:00
KOWX712
f1ca044c4f merge workflow 2024-12-03 00:59:11 +08:00
KOWX712
227cbeeb5b Revert "change path"
This reverts commit ba2e699ca5.
2024-12-03 00:58:29 +08:00
KOWX712
951ae11bcd add prerelease detect 2024-12-02 21:00:16 +08:00
KOWX712
410576094a Update .extra 2024-12-02 19:28:36 +08:00
KOWX712
20747caa66 Update README.md 2024-12-02 16:38:18 +08:00
KOWX712
879735e33a Update README.md 2024-12-02 16:13:10 +08:00
KOWX712
a44941d482 Wait for next 2024-12-02 14:16:29 +08:00
KOWX712
3504ec15ce fix typo 2024-12-02 00:37:41 +08:00
KOWX712
ba2e699ca5 change path 2024-12-02 00:24:56 +08:00
KOWX712
785250d748 update translation 2024-12-02 00:12:53 +08:00
KOWX712
b227ad990c Update changelog.md 2024-12-01 23:52:14 +08:00
KOWX712
cb2d8c0192 Update README.md 2024-12-01 23:49:34 +08:00
KOWX712
f12fe49d17 Update README.md 2024-12-01 23:47:54 +08:00
KOWX712
a0b0c5ca15 webui: improve ui 2024-12-01 22:58:39 +08:00
KOWX712
69198fa458 translation: update string 2024-12-01 22:58:16 +08:00
KOWX712
2198313a4a cleanup: abandon UpdateTargetList.sh 2024-12-01 22:57:55 +08:00
KOWX712
85998d76fe service: abandon UpdateTargetList.sh 2024-12-01 22:57:45 +08:00
KOWX712
a399c4a69a action: abandon UpdateTargetList.sh 2024-12-01 22:57:34 +08:00
KOWX712
18e3048028 installation: abandon UpdateTargetList.sh 2024-12-01 22:57:22 +08:00
KOWX712
9b5293f7b0 webui: abandon UpdateTargetList.sh 2024-12-01 22:56:44 +08:00
KOWX712
375af46292 Update canary.yml 2024-12-01 17:25:21 +08:00
KOWX712
017491b652 Squashed commit of the following:
commit 1562a97de621efe514274962826bc2601f694441
Author: KOWX712 <leecc0503@gmail.com>
Date:   Sun Dec 1 00:02:36 2024 +0800

    update translation guide
2024-12-01 00:03:47 +08:00
KOWX712
aea3e9fff3 push v2.6 2024-11-30 21:10:12 +08:00
KOWX712
84b7bd9f4e release v2.6 2024-11-30 21:08:04 +08:00
KOWX712
9fa022bad6 workflow fix 4 2024-11-30 21:06:46 +08:00
KOWX712
ec024a2936 workflow fix 3 2024-11-30 21:02:45 +08:00
KOWX712
72d505dec5 fix release workflow 2024-11-30 20:58:48 +08:00
KOWX712
0e06ea4902 Update module.prop 2024-11-30 20:53:26 +08:00
KOWX712
45657574d2 test run workflow 2024-11-30 20:51:41 +08:00
KOWX712
315f254123 fix multiple zip 2024-11-30 20:51:14 +08:00
KOWX712
4772755965 workflow test 2024-11-30 20:48:45 +08:00
KOWX712
18968a4fcb fix workflow 2 2024-11-30 20:42:16 +08:00
KOWX712
457c771cfa fix workflow 2024-11-30 20:37:12 +08:00
KOWX712
c5804fabdc revert 2024-11-30 20:33:11 +08:00
KOWX712
60ae2e42f9 limit to module folder only 2024-11-30 20:24:40 +08:00
KOWX712
04394ca65d Update README.md 2024-11-30 20:18:34 +08:00
KOWX712
3f8ef22b83 Update update.json 2024-11-30 20:16:43 +08:00
KOWX712
71e6d7ec8b Update module.prop 2024-11-30 20:14:50 +08:00
KOWX712
01300c9524 Update changelog.md 2024-11-30 20:14:08 +08:00
KOWX712
8747df3969 v2.6 changelog 2024-11-30 20:12:18 +08:00
KOWX712
792e5a15a1 push v2.6 stable 2024-11-30 20:12:09 +08:00
KOWX712
df7167dc55 workflow test 2024-11-30 20:09:11 +08:00
KOWX712
ffa0aa461d migrate to main 2024-11-30 04:08:19 +08:00
KOWX712
3926980b28 Update README.md 2024-11-30 03:57:56 +08:00
KOWX712
a92928838b Update README.md 2024-11-28 19:19:20 +08:00
KOWX712
fd837d41e8 beta3 2024-11-28 19:17:50 +08:00
59 changed files with 3036 additions and 2388 deletions

2
.extra

File diff suppressed because one or more lines are too long

124
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,124 @@
name: build
on:
push:
branches:
- main
paths:
- 'module/**'
workflow_dispatch:
jobs:
build:
name: build
runs-on: ubuntu-latest
outputs:
version_tag_exists: ${{ steps.check_tag.outputs.version_tag_exists }}
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 2
fetch-tags: true
- name: Extract Module Info
id: extract_info
run: |
MODULE_VERSION=$(grep -oP '^version=\K.*' module/module.prop)
BUILD_COUNT=$((1000 + ${{ github.run_number }}))
ARTIFACT_NAME="TrickyAddonModule-${MODULE_VERSION}-canary-${BUILD_COUNT}"
echo "MODULE_VERSION=${MODULE_VERSION}" >> $GITHUB_ENV
echo "ARTIFACT_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.ARTIFACT_NAME }}
path: module/
include-hidden-files: true
- name: Check if valid to release
id: check_tag
run: |
VERSION=$(grep '^version=' module/module.prop | sed 's/version=//')
git fetch --tags
if git tag | grep -qx "^$VERSION"; then
echo "version_tag_exists=true" >> $GITHUB_OUTPUT
else
echo "version_tag_exists=false" >> $GITHUB_OUTPUT
fi
release:
name: release
runs-on: ubuntu-latest
needs: build
if: ${{ needs.build.outputs.version_tag_exists == 'false' }}
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Configure Git user
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
- name: Create a new tag
run: |
VERSION=$(grep '^version=' module/module.prop | sed 's/version=//')
git tag -a "$VERSION" -m "Release version $VERSION"
git push origin "$VERSION"
- name: Set release variables
id: set_release_variables
run: |
VERSION=$(grep '^version=' module/module.prop | sed 's/version=//')
CURRENT_TAG="$VERSION"
RELEASE_NOTES=$(awk -v tag="### $CURRENT_TAG" '
$0 == tag {flag=1; next}
/^###/ && flag {exit}
flag {print}
' changelog.md)
if [[ "$VERSION" == *"beta"* ]]; then
PRERELEASE=true
FORMATTED_RELEASE_NOTES=$(echo -e "- Due to extensive code refactoring, you might encounter unexpected bugs in this version, feedback in [Telegram](https://t.me/kowchannel) or [create issue](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/issues) if you found any issues.\n---\n### Tricky Addon module\n$RELEASE_NOTES")
FILES="TrickyAddonModule-${VERSION}.zip"
else
PRERELEASE=false
FORMATTED_RELEASE_NOTES=$(echo -e "### Tricky Addon module\n$RELEASE_NOTES\n---\n### Tricky Addon Lite - script only\n- Check on [changelog](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/tree/main/lite-script_only#tricky-addon-lite-update-target-list-script)")
FILES="TrickyAddonModule-${VERSION}.zip,TrickyAddonLite_ScriptOnly_Extract-${VERSION}.zip"
fi
echo "CURRENT_TAG=$CURRENT_TAG" >> $GITHUB_ENV
echo "ZIP_NAME=TrickyAddonModule-${VERSION}.zip" >> $GITHUB_ENV
echo "LITE_SCRIPT_ONLY_ZIP_NAME=TrickyAddonLite_ScriptOnly_Extract-${VERSION}.zip" >> $GITHUB_ENV
echo "RELEASE_NOTES<<EOF" >> $GITHUB_ENV
echo "$FORMATTED_RELEASE_NOTES" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
echo "FILES=$FILES" >> $GITHUB_ENV
echo "PRERELEASE=$PRERELEASE" >> $GITHUB_ENV
- name: Compress module folder
run: |
cd module && zip -r "../${{ env.ZIP_NAME }}" ./*
echo "Created zip file: ${{ env.ZIP_NAME }}"
- name: Compress lite-script_only folder
if: ${{ env.PRERELEASE == 'false' }}
run: |
cd lite-script_only && zip -r "../${{ env.LITE_SCRIPT_ONLY_ZIP_NAME }}" ./*
echo "Created zip file: ${{ env.LITE_SCRIPT_ONLY_ZIP_NAME }}"
- name: Create release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: ${{ env.FILES }}
tag_name: ${{ env.CURRENT_TAG }}
name: ${{ env.CURRENT_TAG }}
body: ${{ env.RELEASE_NOTES }}
draft: false
prerelease: ${{ env.PRERELEASE }}

View File

@@ -1,41 +1,46 @@
# **Tricky Addon - Update Target List**
A **KSU WebUI** to configure tricky store target.txt
# Tricky Addon - Update Target List
Configure Tricky Store target.txt with KSU WebUI.
---
## Description
- Automated script to update tricky store target list.
- System app excluded by default
- This module is **not** a part of Tricky Store module, DO NOT report to Tricky Store if you encounter any issue.
- This is **not** a necessary module for root hide but for those who lazy to do it manually
[![Latest Release](https://img.shields.io/github/v/release/KOWX712/Tricky-Addon-Update-Target-List?label=Release&logo=github)](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/latest)
[![Nightly Release](https://custom-icon-badges.demolab.com/badge/Nightly-canary_build-640064?logo=nightly-logo)](https://nightly.link/KOWX712/Tricky-Addon-Update-Target-List/workflows/build/main?status=completed)
> [!WARNING]
> This module is **not** a part of the Tricky Store module. DO NOT report any issues to Tricky Store if encountered.
## Requirements
- [Tricky store](https://github.com/5ec1cff/TrickyStore) module installed
## Custom Configuration
- Configuration target list with **KSU WebUI**
- For Magisk users, first attempt perform action button can install KSU WebUI (optional).
- Advance configure: ADDITION and EXCLUDE in `/data/adb/tricky_store/target_list_config`
## Instructions
### Automatic update
- On boot
### KernelSU & Apatch
- KSU WebUI
### Manually update
**KSU WebUI**
- Configure target list
- Save and Update
### Magisk
- Action button to open WebUI
- Support KSUWebUIStandalone and latest MMRL
- Automatic install [KSUWebUIStandalone](https://github.com/5ec1cff/KsuWebUIStandalone) if none of them are installed.
**Manual script method**
- Run `UpdateTargetList.sh` under `/data/adb/tricky_store` manually.
- MT manager is recommened for this method
### What Can This Module Do
| Feature | Status |
|:---|:---:|
| Configure target.txt with app name display | ✅ |
| Select apps from Magisk DenyList (optional) | ✅ |
| Deselect [unnecessary apps](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/blob/main/more-excldue.json) (optional) | ✅ |
| Set verifiedBootHash (optional) | ✅ |
| Provide AOSP Keybox (optional) | ✅ |
| Valid Keybox (not guaranteed) | ❌ |
| Shamiko Whitelist switch ([Why?](https://github.com/rushizgithub/shamiko?tab=readme-ov-file#whitelist)) | ❌ |
| Add `!` or `?` to the target ([Not needed](https://github.com/5ec1cff/TrickyStore/releases/tag/1.1.0)) | ❌ |
| Periodically update target and add new apps | ❌ |
| Add system apps (GMS added by default) | ❌ |
## Translation
- Read [Translation Guide](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/tree/master/module/webroot/locales/A-translate.md)
## Localization
- Read [Translation Guide](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/blob/main/module/webui/locales/A-translate.md)
## Acknowledgement
- [j-hc/zygisk-detach](https://github.com/j-hc/zygisk-detach) - KSU WebUI template
## Links
Download: [GitHub release](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases)
Telegram channel: [KOW's Little World](https://t.me/kowchannel)
[![release](https://custom-icon-badges.demolab.com/badge/-Download-F25278?style=for-the-badge&logo=download&logoColor=white)](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases)
[![issue](https://custom-icon-badges.demolab.com/badge/-Open%20Issue-palegreen?style=for-the-badge&logoColor=black&logo=issue-opened)](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/issues)
[![changelog](https://custom-icon-badges.demolab.com/badge/-Update%20History-orange?style=for-the-badge&logo=history&logoColor=white)](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/blob/main/changelog.md)
[![Telegram](https://custom-icon-badges.demolab.com/badge/-KOW's%20little%20world-blue?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/kowchannel)

View File

@@ -1,15 +1,49 @@
### Tricky Addon: Update Target List
A **KSU WebUI** to configure tricky store target.txt
Requirement: Tricky Store module installed
This module is not a part of Tricky Store, DO NOT report to Tricky Store if you encounter any issue.
*This module is **not** a part of the Tricky Store module. DO NOT report any issues to Tricky Store if encountered.*
GitHub release: [Tricky Addon: Update Target List](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/latest)
Telegram channel: [KOW's Little World](https://t.me/kowchannel)
## Changelog
### v2.9
- Preserve `!` and `?` during update target in WebUi.
- Optimized scripts, thanks to @backslashxx.
- Fixed freeze in weak connection.
- Added Spanish, thanks to @Keinta15.
- Removed rescriction on installation but module will still be removed if tricky store is not found after reboot.
### v2.8
- Fixed all KSUWebUIStandalone freeze issue, removed visible option.
- Reduced WebUI loading time.
- Added Japanese. Thanks to @reindex-ot.
### v2.7.1
- Link redirect quick fix
### v2.7
- Abandoned `UpdateTargetList.sh`; No longer automatically update target on boot.
- Adapted with MMRL, Magisk user can uninstall KSUWebUIStandalone if you have latest MMRL installed, action button will redirect to MMRL if KSUWebUIStandalone not found.
- New update card for invisible module.
- Improved UI.
- Press any position of app card to select/deselct.
### v2.6
- Invisible module, intergrate action button & webui on tricky store card. You can stil use visible option if you found any issue with invisble module. Thanks for idea from @backslashxx.
- To uninstall invisble module, scroll down to the bottom of WebUI and press Uninstall WebUI.
- Add update prompt if found new version in webui, and show module if found an update. (invisible)
- Reduced WebUI loading time
- Added feature to save verifiedBootHash
- New way to detect Xposed module, now can catch all Xposed module apk package name in Deselect Unnecessary option, feedback in [Telegram](https://t.me/kowchannel) or [create issue](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/issues) if missed any.
- **Initial support for multiple languages**
- Language available: **en-US**, **ru-RU**, **tl-PH**, **zh-CN**, **zh-TW**
- Add language or fix translation error? [Read here](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/tree/master/module/webui/locales/A-translate.md).
### v2.6-beta.3
- Check in [release notes](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/tag/v2.6-beta.3).
### v2.6-beta.2
- Check in [release notes](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/tag/v2.6-beta.2).
@@ -23,7 +57,7 @@ Telegram channel: [KOW's Little World](https://t.me/kowchannel)
### v2.4
- Added aapt binary for app name display
**KSU WebUI**
- **KSU WebUI:**
- Added app name display
### v2.3
@@ -33,13 +67,13 @@ Telegram channel: [KOW's Little World](https://t.me/kowchannel)
- Abandoned action button in KernelSU and Apatch
- Magisk action button: open WebUI, automatic download if not installed (optional)
**KSU WebUI**
- **KSU WebUI:**
- Option to select app from DenyList (Magisk)
### v2.2
**KSU WebUI:**
- **KSU WebUI:**
- Added help menu
- Added extra [unnecessary app](https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/more-excldue.json) exclude option
- Added extra [unnecessary app](https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/more-excldue.json) exclude option
- Added no Internet connection prompt
### v2.1

View File

@@ -4,7 +4,10 @@
- Recommend to run with MT manager
## Changelog
### v2.1, v2.2, v2.3, v2.4, v2.5
### v2.8
- Remove wait time
### v2.1~2.7.1
- Remain same with v2.0
### v2.0
@@ -31,7 +34,6 @@
- Synched some code with module script
## Link
[Telegram channel](https://t.me/kowchannel)
[GitHub Release](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/latest)
[![release](https://custom-icon-badges.demolab.com/badge/-Download-F25278?style=for-the-badge&logo=download&logoColor=white)](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases)
[![issue](https://custom-icon-badges.demolab.com/badge/-Open%20Issue-palegreen?style=for-the-badge&logoColor=black&logo=issue-opened)](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/issues)
[![Telegram](https://custom-icon-badges.demolab.com/badge/-KOW's%20little%20world-blue?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/kowchannel)

View File

@@ -1,14 +1,14 @@
#!/bin/sh
# Tricky Addon Lite: Update Target List Script v2.5
# GitHub Repository: https://github.com/KOWX712/Tricky-Addon-Update-Target-List/blob/master/lite-script_only/README.md
# Tricky Addon Lite: Update Target List Script v2.8
# GitHub Repository: https://github.com/KOWX712/Tricky-Addon-Update-Target-List/tree/main/lite-script_only
# Telegram channel: https://t.me/kowchannel
# This script will put all non-system app into /data/adb/tricky_store/target.txt
###################################################
# Configurable exclude and addition list
# DO NOT remove default package names here
# Don't remove default package names here
###################################################
EXCLUDE="
@@ -39,7 +39,6 @@ ADDITION=$(echo "$ADDITION" | tr '\n' ' ' | sed 's/^ //;s/ $//')
# Add all non-system apps to the target file and remove exclusions
su -c pm list packages -3 </dev/null 2>&1 | cat | awk -F: '{print $2}' | grep -Ev "$EXCLUDE" > /data/adb/tricky_store/target.txt
sleep 1
# Add additional apps to the target file if they are not already present
for app in $ADDITION; do

View File

@@ -5,33 +5,68 @@
MODPATH="/data/adb/modules/.TA_utl"
COMPATH="$MODPATH/common"
SCRIPT_DIR="/data/adb/tricky_store"
URL="https://github.com/5ec1cff/KsuWebUIStandalone/releases/download/v1.0/KsuWebUI-1.0-34-release.apk"
APK_DIR="$COMPATH/tmp"
BBPATH="/data/adb/magisk/busybox \
/data/adb/ksu/bin/busybox \
/data/adb/ap/bin/busybox \
/data/adb/modules/busybox-ndk/system/*/busybox"
. "$COMPATH/util_func.sh"
if pm list packages | grep -q "$PACKAGE_NAME"; then
echo "- Launching KSU WebUI..."
am start -n "${PACKAGE_NAME}/.WebUIActivity" -e id "$MODID"
else
SKIP_FILE="$SCRIPT_DIR/target_list_config/skipwebui"
if [ ! -f "$SKIP_FILE" ]; then
echo "**********************************************"
echo "- Do you want to install KSU WebUI standalone?"
echo " VOL [+]: YES"
echo " VOL [-]: NO"
echo "**********************************************"
key_check
if [[ "$keycheck" == "KEY_VOLUMEUP" ]]; then
echo "- Installing KSU WebUI..."
. "$COMPATH/get_WebUI.sh"
check_wget() {
for path in $BBPATH; do
[ -f "$path" ] && BUSYBOX="$path" && break
done
if ! command -v wget >/dev/null || grep -q "wget-curl" "$(command -v wget)"; then
if [ -n "$BUSYBOX" ]; then
wget() { "$BUSYBOX" wget "$@"; }
else
echo "- Skipping WebUI installation..."
touch "$SKIP_FILE"
echo "- Skip WebUI check until next installation."
echo ""
update_script
exit 1
fi
else
update_script
fi
fi
}
get_webui() {
echo "- Downloading the WebUI APK..."
check_wget
if ! wget --no-check-certificate -P "$APK_DIR" "$URL"; then
echo "! Error: APK download failed."
exit 1
fi
echo "- Download complete."
APK_PATH=$(find "$APK_DIR" -type f -name "*.apk" | head -n 1)
if [ -z "$APK_PATH" ]; then
echo "! Error: No APK file found in $APK_DIR."
exit 1
fi
echo "- Installing..."
if ! pm install -r "$APK_PATH" >/dev/null 2>&1; then
echo "! Error: APK installation failed."
rm -f "$APK_PATH"
exit 1
fi
echo "- Done."
rm -f "$APK_PATH"
echo "- Launching..."
if ! am start -n "io.github.a13e300.ksuwebui/.WebUIActivity" -e id "tricky_store"; then
echo "! Error: WebUI launch failed."
exit 1
fi
echo "- Application launched successfully."
}
# Lunch KSUWebUI standalone or MMRL, install KSUWebUI standalone if both are not installed
if pm list packages | grep -q "io.github.a13e300.ksuwebui"; then
echo "- Launching WebUI in KSUWebUIStandalone..."
am start -n "io.github.a13e300.ksuwebui/.WebUIActivity" -e id "tricky_store"
elif pm list packages | grep -q "com.dergoogler.mmrl"; then
echo "- Launching WebUI in MMRL WebUI..."
am start -n "com.dergoogler.mmrl/.ui.activity.webui.WebUIActivity" -e MOD_ID "tricky_store"
else
echo "- Installing KSU WebUI..."
get_webui
fi

View File

@@ -1,8 +0,0 @@
# This is the list of additional apps to include in the target file
# DO NOT remove the default app here
# You can add your custom addition app's package name here
# Each app package name should be on a new line
com.google.android.gms
io.github.vvb2060.keyattestation
io.github.vvb2060.mahoshojo
icu.nullptr.nativetest

View File

@@ -1,10 +0,0 @@
# This is the list of apps to exclude from the target file
# DO NOT remove the default app here
# You can add your custom exclusion app here
# Each app package name should be on a new line
oneplus
coloros
miui
com.android.patch
me.bmax.apatch
me.garfieldhan.apatch.next

View File

@@ -1,49 +0,0 @@
#!/bin/sh
# This script will put non-system app into /data/adb/tricky_store/target.txt
CONFIG_DIR="/data/adb/tricky_store/target_list_config"
echo "- Checking config files..."
echo " "
if [ ! -f "$CONFIG_DIR/EXCLUDE" ]; then
echo "! Exclude list is missing, please install module again"
exit 1
else
echo "- Exclude config file found"
echo " "
fi
if [ ! -f "$CONFIG_DIR/ADDITION" ]; then
echo "! Addition list is missing, please install module again"
exit 1
else
echo "- Addition config file found"
echo " "
fi
EXCLUDE=$(grep -vE '^[[:space:]]*#|^[[:space:]]*$' "$CONFIG_DIR/EXCLUDE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
ADDITION=$(grep -vE '^[[:space:]]*#|^[[:space:]]*$' "$CONFIG_DIR/ADDITION" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
for app in $ADDITION; do
app=$(echo "$app" | tr -d '[:space:]')
if grep -Fq "$app" "$CONFIG_DIR/EXCLUDE"; then
sed -i "\|^$app$|d" "$CONFIG_DIR/EXCLUDE"
fi
done
EXCLUDE=$(grep -vE '^[[:space:]]*#|^[[:space:]]*$' "$CONFIG_DIR/EXCLUDE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | tr '\n' '|' | sed 's/|$//')
echo "- Adding apps into /data/adb/tricky_store/target.txt..."
echo " "
pm list packages -3 </dev/null 2>&1 | awk -F: '{print $2}' | grep -Ev "$EXCLUDE" > /data/adb/tricky_store/target.txt
echo "- Adding addition app..."
echo " "
for app in $ADDITION; do
app=$(echo "$app" | tr -d '[:space:]')
if ! grep -Fq "$app" /data/adb/tricky_store/target.txt; then
echo "$app" >> /data/adb/tricky_store/target.txt
fi
done
echo "- target.txt updated successfully"
echo " "

View File

@@ -1,27 +0,0 @@
URL="https://github.com/5ec1cff/KsuWebUIStandalone/releases/download/v1.0/KsuWebUI-1.0-34-release.apk"
APK_DIR="$COMPATH"
find_busybox
check_wget
echo "- Downloading the WebUI apk..."
download_webui
echo "- Download complete."
APK_PATH=$(find "$APK_DIR" -type f -name "*.apk" | head -n 1)
if [ -z "$APK_PATH" ]; then
echo "Error: No APK file found in $APK_DIR."
exit 1
fi
echo "- Installing..."
install_webui
echo "- Done."
rm -f "$APK_PATH"
echo "- Launching..."
am start -n "${PACKAGE_NAME}/.WebUIActivity" -e id "$MODID" </dev/null 2>&1 | cat
if [ $? -ne 0 ]; then
echo "Error: Failed to start application."
exit 1
fi
echo "- Application launched successfully."

View File

@@ -1,49 +1,93 @@
#!/system/bin/sh
#!/bin/sh
PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:/data/data/com.termux/files/usr/bin:$PATH
MODPATH=${0%/*}
SKIPLIST="$MODPATH/skiplist"
OUTPUT="$MODPATH/exclude-list"
KBOUTPUT="$MODPATH/.extra"
SKIPLIST="$MODPATH/tmp/skiplist"
OUTPUT="$MODPATH/tmp/exclude-list"
KBOUTPUT="$MODPATH/tmp/.extra"
. $MODPATH/util_func.sh
aapt() { "$MODPATH/aapt" "$@"; }
find_busybox
check_wget
# Fetch additional package names
wget --no-check-certificate -q -O - "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/more-excldue.json" 2>/dev/null | \
grep -o '"package-name": *"[^"]*"' | \
awk -F'"' '{print $4}' > "$OUTPUT"
if [ ! -s "$OUTPUT" ]; then
rm -f "$KBOUTPUT"
skipfetch=true
fi
# Find xposed package name
pm list packages -3 </dev/null 2>&1 | cat | awk -F: '{print $2}' | while read -r PACKAGE; do
if ! grep -Fq "$PACKAGE" "$SKIPLIST"; then
pm path "$PACKAGE" | grep "base.apk" | awk -F: '{print $2}' | tr -d '\r' | while read -r APK_PATH; do
aapt dump xmltree "$APK_PATH" AndroidManifest.xml 2>/dev/null | grep -qE "xposed.category|xposeddescription" && echo "$PACKAGE" >> "$OUTPUT"
done
# probe for downloaders
# wget = low pref, no ssl.
# curl, has ssl on android, we use it if found
download() {
if command -v curl >/dev/null 2>&1; then
timeout 3 curl -s "$1"
else
timeout 3 busybox wget --no-check-certificate -qO - "$1"
fi
done
}
if [ "$skipfetch" != "true" ]; then
wget --no-check-certificate -qO "$KBOUTPUT" "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/.extra"
get_kb() {
download "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/.extra" > "$KBOUTPUT"
[ -s "$KBOUTPUT" ] || rm -f "$KBOUTPUT"
}
if [ ! -s "$KBOUTPUT" ]; then
rm -f "$KBOUTPUT"
get_xposed() {
pm list packages -3 | cut -d':' -f2 | grep -vxF -f "$SKIPLIST" | grep -vxF -f "$OUTPUT" | while read -r PACKAGE; do
APK_PATH=$(pm path "$PACKAGE" | grep "base.apk" | cut -d':' -f2 | tr -d '\r')
if [ -n "$APK_PATH" ]; then
if aapt dump xmltree "$APK_PATH" AndroidManifest.xml 2>/dev/null | grep -qE "xposed.category|xposeddescription"; then
echo "$PACKAGE" >>"$OUTPUT"
fi
fi
done
}
get_unnecessary() {
if [ ! -s "$OUTPUT" ] || [ ! -f "$OUTPUT" ]; then
download "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/more-exclude.json" 2>/dev/null | grep -o '"package-name": *"[^"]*"' | awk -F'"' '{print $4}' >"$OUTPUT"
fi
get_xposed
}
if [ -d "$MODPATH/temp" ]; then
JSON=$(wget --no-check-certificate -q -O - "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/update.json")
check_update() {
if [ -d "$MODPATH/update" ]; then
JSON=$(download "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/update.json") || exit 1
REMOTE_VERSION=$(echo "$JSON" | grep -o '"versionCode": *[0-9]*' | awk -F: '{print $2}' | tr -d ' ')
LOCAL_VERSION=$(grep -o 'versionCode=[0-9]*' "$MODPATH/temp/module.prop" | awk -F= '{print $2}')
LOCAL_VERSION=$(grep -o 'versionCode=[0-9]*' "$MODPATH/update/module.prop" | awk -F= '{print $2}')
if [ "$REMOTE_VERSION" -gt "$LOCAL_VERSION" ]; then
echo "update"
if [ "$MODPATH" = "/data/adb/modules/.TA_utl/common" ]; then
[ -d "/data/adb/modules/TA_utl" ] && rm -rf "/data/adb/modules/TA_utl"
cp -rf "$MODPATH/update" "/data/adb/modules/TA_utl"
else
cp -f "$MODPATH/update/module.prop" "/data/adb/modules/TA_utl/module.prop"
fi
echo "update"
fi
fi
else
exit 1
fi
}
uninstall() {
if [ "$MODPATH" = "/data/adb/modules/.TA_utl/common" ]; then
[ -d "/data/adb/modules/TA_utl" ] && rm -rf "/data/adb/modules/TA_utl"
cp -rf "$MODPATH/update" "/data/adb/modules/TA_utl"
else
cp -f "$MODPATH/update/module.prop" "/data/adb/modules/TA_utl/module.prop"
fi
touch "/data/adb/modules/TA_utl/remove"
}
case "$1" in
--kb)
get_kb
exit
;;
--unnecessary)
get_unnecessary
exit
;;
--xposed)
get_xposed
exit
;;
--update)
check_update
exit
;;
--uninstall)
uninstall
exit
;;
esac

11
module/common/repo.json Normal file
View File

@@ -0,0 +1,11 @@
{
"support": "https://github.com/KOWX712/Tricky-Addon-Update-Target-List/issues",
"categories": [
"WebUI"
],
"readme": "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/refs/heads/main/README.md",
"note": {
"message": "This module is not a part of the Tricky Store module. DO NOT report any issues to Tricky Store if encountered"
},
"license": " GPL-3.0"
}

View File

@@ -1,22 +0,0 @@
MODPATH=${0%/*}
TS="/data/adb/modules/tricky_store"
SCRIPT_DIR="/data/adb/tricky_store"
# Enable back TSupport-A auto update
if [ -f "/storage/emulated/0/stop-tspa-auto-target" ]; then
rm -f "/storage/emulated/0/stop-tspa-auto-target"
fi
# Remove residue and restore aosp keybox.
rm -rf "/data/adb/modules/.TA_utl"
rm -rf "$SCRIPT_DIR/target_list_config"
rm -f "$SCRIPT_DIR/UpdateTargetList.sh"
rm -f "/data/adb/boot_hash"
if [ -d "$TS" ]; then
if [ -f "$TS/action.sh" ]; then
rm -f "$TS/action.sh"
else
rm -rf "$TS/webroot"
fi
fi
xxd -r -p "$MODPATH/.default" | base64 -d > "$SCRIPT_DIR/keybox.xml"

View File

@@ -1,86 +0,0 @@
PACKAGE_NAME="io.github.a13e300.ksuwebui"
MODID="set-id"
BBPATH="/data/adb/modules/busybox-ndk/system/*/busybox \
/data/adb/magisk/busybox \
/data/adb/ksu/bin/busybox \
/data/adb/ap/bin/busybox"
find_busybox() {
for path in $BBPATH; do
if [ -f "$path" ]; then
BUSYBOX="$path"
return 0
fi
done
return 1
}
check_wget() {
if ! command -v wget >/dev/null || grep -q "wget-curl" "$(command -v wget)"; then
if find_busybox; then
wget() { "$BUSYBOX" wget "$@"; }
else
echo "Error: busybox not found." > "$OUTPUT"
exit 1
fi
fi
}
aapt() { "$MODPATH/aapt" "$@"; }
download_webui() {
wget --no-check-certificate -P "$APK_DIR" "$URL"
if [ $? -ne 0 ]; then
echo "Error: APK download failed."
exit 1
fi
}
install_webui() {
pm install -r "$APK_PATH" </dev/null 2>&1 | cat
if [ $? -ne 0 ]; then
echo "Error: APK installation failed."
rm -f "$APK_PATH"
exit 1
fi
}
key_check() {
while true; do
key_check=$(/system/bin/getevent -qlc 1)
key_event=$(echo "$key_check" | awk '{ print $3 }' | grep 'KEY_')
key_status=$(echo "$key_check" | awk '{ print $4 }')
if [[ "$key_event" == *"KEY_"* && "$key_status" == "DOWN" ]]; then
keycheck="$key_event"
break
fi
done
while true; do
key_check=$(/system/bin/getevent -qlc 1)
key_event=$(echo "$key_check" | awk '{ print $3 }' | grep 'KEY_')
key_status=$(echo "$key_check" | awk '{ print $4 }')
if [[ "$key_event" == *"KEY_"* && "$key_status" == "UP" ]]; then
break
fi
done
}
update_script() {
echo "**********************************************"
echo "- Starting script..."
echo ""
if [[ ! -f "$SCRIPT_DIR/UpdateTargetList.sh" ]]; then
echo "! Script missing, please install module again."
echo "**********************************************"
exit 1
else
. "$SCRIPT_DIR/UpdateTargetList.sh"
fi
echo "**********************************************"
echo ""
echo "\(__All set!__)/"
echo "Exiting in 2 seconds..."
sleep 2
}

View File

@@ -5,7 +5,7 @@ TS="/data/adb/modules/tricky_store"
SCRIPT_DIR="/data/adb/tricky_store"
CONFIG_DIR="$SCRIPT_DIR/target_list_config"
MODID=`grep_prop id $TMPDIR/module.prop`
NEW_MODID=.TA_utl
NEW_MODID=".TA_utl"
kb="$COMPATH/.default"
ui_print " ";
@@ -23,21 +23,24 @@ else
abort " ";
fi
if [ ! -d "$TS" ]; then
ui_print "! Tricky store module is not installed"
abort
fi
[ -d "$TS" ] || ui_print "! Warning: Tricky store module not found"
. "$MODPATH/install_func.sh"
ui_print "- Installing..."
initialize
ui_print "- Creating config directory..."
ui_print "- Finalizing..."
find_config
migrate_old_boot_hash
rm -f "$MODPATH/install_func.sh"
ui_print " "
ui_print "! This module is not a part of the Tricky Store module. DO NOT report any issues to Tricky Store if encountered."
ui_print " "
sleep 1
ui_print "- Installation completed successfully! "
ui_print " "
ui_print " "

View File

@@ -1,93 +1,34 @@
initialize() {
if [ -f "$SCRIPT_DIR/UpdateTargetList.sh" ]; then
rm -f "$SCRIPT_DIR/UpdateTargetList.sh"
fi
if [ -f "$CONFIG_DIR/skipwebui" ]; then
rm -f "$CONFIG_DIR/skipwebui"
fi
if [ -d "/data/adb/modules/$NEW_MODID" ]; then
rm -rf "/data/adb/modules/$NEW_MODID"
fi
cp "$MODPATH/module.prop" "$COMPATH/temp/module.prop"
cp "$COMPATH/.default" "$COMPATH/temp/.default"
mv "$COMPATH/UpdateTargetList.sh" "$SCRIPT_DIR/UpdateTargetList.sh"
set_perm $SCRIPT_DIR/UpdateTargetList.sh 0 2000 0755
# Cleanup left over
[ -d "/data/adb/modules/$NEW_MODID" ] && rm -rf "/data/adb/modules/$NEW_MODID"
# Set permission
set_perm $COMPATH/get_extra.sh 0 2000 0755
set_perm $COMPATH/get_WebUI.sh 0 2000 0755
# Handdle Magisk/non-Magisk root manager
if [ "$ACTION" = "false" ]; then
rm -f "$MODPATH/action.sh"
rm -f "$COMPATH/get_WebUI.sh"
echo "**********************************************"
echo "- Tricky Addon's visibility in root manager?"
echo " VOL [+]: Visible"
echo " VOL [-]: Invisible (default)"
echo "**********************************************"
key_check
if [[ "$keycheck" == "KEY_VOLUMEUP" ]]; then
echo "- Setting to visible..."
rm -rf "$COMPATH/temp"
NEW_MODID="$MODID"
fi
NEW_MODID="$MODID"
else
mkdir -p "$COMPATH/update/common"
cp "$COMPATH/.default" "$COMPATH/update/common/.default"
cp "$MODPATH/uninstall.sh" "$COMPATH/update/uninstall.sh"
fi
sed -i "s|\"set-path\"|\"/data/adb/modules/$NEW_MODID/common/\"|" "$MODPATH/webroot/index.js" || {
ui_print "! Failed to set path"
abort
}
sed -i "s|\"set-id\"|\"$NEW_MODID\"|" "$COMPATH/util_func.sh" || {
ui_print "! Failed to set id"
abort
}
#Set specific path
sed -i "s|\"set-path\"|\"/data/adb/modules/$NEW_MODID/\"|" "$MODPATH/webui/scripts/main.js" || abort "! Failed to set path"
# Set aapt binary
cp "$MODPATH/module.prop" "$COMPATH/update/module.prop"
mv "$MODPATH/bin/$(getprop ro.product.cpu.abi)/aapt" "$COMPATH/aapt"
set_perm $COMPATH/aapt 0 2000 0755
rm -rf "$MODPATH/bin"
}
add_exclude() {
EXCLUDE=$(grep -vE '^[[:space:]]*#|^[[:space:]]*$' "$CONFIG_DIR/EXCLUDE")
for app in $EXCLUDE; do
app=$(echo "$app" | tr -d '[:space:]')
if ! grep -Fq "$app" $COMPATH/EXCLUDE; then
echo "$app" >> $COMPATH/EXCLUDE
fi
done
mv "$COMPATH/EXCLUDE" "$CONFIG_DIR/EXCLUDE"
}
add_addition() {
ADDITION=$(grep -vE '^[[:space:]]*#|^[[:space:]]*$' "$CONFIG_DIR/ADDITION")
for app in $ADDITION; do
app=$(echo "$app" | tr -d '[:space:]')
if ! grep -Fq "$app" $COMPATH/ADDITION; then
echo "$app" >> $COMPATH/ADDITION
fi
done
mv "$COMPATH/ADDITION" "$CONFIG_DIR/ADDITION"
}
find_config() {
if [ -d "$CONFIG_DIR" ]; then
if [ ! -f "$CONFIG_DIR/EXCLUDE" ] && [ ! -f "$CONFIG_DIR/ADDITION" ]; then
mv "$COMPATH/EXCLUDE" "$CONFIG_DIR/EXCLUDE"
mv "$COMPATH/ADDITION" "$CONFIG_DIR/ADDITION"
elif [ ! -f "$CONFIG_DIR/ADDITION" ]; then
mv "$COMPATH/ADDITION" "$CONFIG_DIR/ADDITION"
add_exclude
elif [ ! -f "$CONFIG_DIR/EXCLUDE" ]; then
mv "$COMPATH/EXCLUDE" "$CONFIG_DIR/EXCLUDE"
add_addition
else
add_exclude
add_addition
fi
else
mkdir -p "$CONFIG_DIR"
mv "$COMPATH/EXCLUDE" "$CONFIG_DIR/EXCLUDE"
mv "$COMPATH/ADDITION" "$CONFIG_DIR/ADDITION"
fi
# Remove legacy setup
[ -f "$SCRIPT_DIR/UpdateTargetList.sh" ] && rm -f "$SCRIPT_DIR/UpdateTargetList.sh"
[ -d "$CONFIG_DIR" ] && rm -rf "$CONFIG_DIR"
}
migrate_old_boot_hash() {
@@ -97,23 +38,3 @@ migrate_old_boot_hash() {
rm -f "$COMPATH/boot_hash"
fi
}
key_check() {
while true; do
key_check=$(/system/bin/getevent -qlc 1)
key_event=$(echo "$key_check" | awk '{ print $3 }' | grep 'KEY_')
key_status=$(echo "$key_check" | awk '{ print $4 }')
if [[ "$key_event" == *"KEY_"* && "$key_status" == "DOWN" ]]; then
keycheck="$key_event"
break
fi
done
while true; do
key_check=$(/system/bin/getevent -qlc 1)
key_event=$(echo "$key_check" | awk '{ print $3 }' | grep 'KEY_')
key_status=$(echo "$key_check" | awk '{ print $4 }')
if [[ "$key_event" == *"KEY_"* && "$key_status" == "UP" ]]; then
break
fi
done
}

View File

@@ -1,7 +1,7 @@
id=TA_utl
name=Tricky Addon - Update Target List
version=v2.6-beta.2
versionCode=250
version=v2.9
versionCode=290
author=KOWX712
description=A WebUI to conifgure tricky store target.txt
updateJson=https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/update.json
description=A WebUI to conifgure tricky store target.txt
updateJson=https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/update.json

19
module/post-fs-data.sh Normal file
View File

@@ -0,0 +1,19 @@
MODPATH=${0%/*}
TS="/data/adb/modules/tricky_store"
while [ -z "$(ls -A /data/adb/modules/)" ]; do
sleep 1
done
if [ ! -d "$TS" ] || [ -f "$TS/remove" ]; then
if [ -f "$MODPATH/action.sh" ]; then
[ -d "/data/adb/modules/TA_utl" ] && rm -rf "/data/adb/modules/TA_utl"
cp -rf "$MODPATH/common/temp" "/data/adb/modules/TA_utl"
touch "/data/adb/modules/TA_utl/remove"
else
touch "$MODPATH/remove"
fi
fi
rm -f "$TS/action.sh"
rm -rf "$TS/webroot"

View File

@@ -6,6 +6,7 @@ TSPA="/data/adb/modules/tsupport-advance"
aapt() { "$MODPATH/common/aapt" "$@"; }
# Reset verified Boot Hash
hash_value=$(grep -v '^#' "/data/adb/boot_hash" | tr -d '[:space:]')
if [ -n "$hash_value" ]; then
resetprop -n ro.boot.vbmeta.digest "$hash_value"
@@ -18,64 +19,42 @@ elif [ ! -d "$TSPA" ] && [ -f "/storage/emulated/0/stop-tspa-auto-target" ]; the
rm -f "/storage/emulated/0/stop-tspa-auto-target"
fi
if [ -d "$MODPATH/common/temp" ]; then
if [ "$KSU" ] || [ "$APATCH" ]; then
rm -f "$MODPATH/module.prop"
fi
if [ ! -d "$HIDE_DIR" ]; then
# Hide module
if [ -f "$MODPATH/action.sh" ]; then
if [[ "$MODPATH" != "$HIDE_DIR" ]]; then
rm -rf "$HIDE_DIR"
mv "$MODPATH" "$HIDE_DIR"
elif [[ "$MODPATH" != "$HIDE_DIR" ]]; then
rm -rf "$MODPATH"
exit 0
fi
MODPATH="$HIDE_DIR"
elif [ -d "$HIDE_DIR" ]; then
rm -rf "$HIDE_DIR"
fi
rm -f "$MODPATH/module.prop"
OUTPUT_APP="$MODPATH/common/applist"
OUTPUT_SKIP="$MODPATH/common/skiplist"
# Symlink tricky store
[ -f "$MODPATH/action.sh" ] && ln -s "$MODPATH/action.sh" "$TS/action.sh"
ln -s "$MODPATH/webui" "$TS/webroot"
if [ ! -d "$TS" ]; then
if [ -d "$MODPATH/common/temp" ]; then
mkdir -p "/data/adb/modules/TA_utl"
cp -rf "$MODPATH/common/temp/*" "/data/adb/modules/TA_utl/"
touch "/data/adb/modules/TA_utl/remove"
exit 1
# Optimization
OUTPUT_APP="$MODPATH/common/tmp/applist"
OUTPUT_SKIP="$MODPATH/common/tmp/skiplist"
until [ "$(getprop sys.boot_completed)" = "1" ]; do
sleep 1
done
mkdir -p "$MODPATH/common/tmp"
echo "# This file is generated from service.sh to speed up load time" > "$OUTPUT_APP"
echo "# This file is generated from service.sh to speed up load time" > "$OUTPUT_SKIP"
pm list packages -3 </dev/null 2>&1 | cat | awk -F: '{print $2}' | while read -r PACKAGE; do
APK_PATH=$(pm path "$PACKAGE" </dev/null 2>&1 | cat | grep "base.apk" | awk -F: '{print $2}' | tr -d '\r')
if [ -n "$APK_PATH" ]; then
APP_NAME=$(aapt dump badging "$APK_PATH" </dev/null 2>&1 | cat | grep "application-label:" | sed "s/application-label://g; s/'//g")
echo "app-name: $APP_NAME, package-name: $PACKAGE" >> "$OUTPUT_APP"
else
touch "$MODPATH/remove"
exit 1
echo "app-name: Unknown App package-name: $PACKAGE" >> "$OUTPUT_APP"
fi
elif [ -f "$TS/disable" ]; then
exit 1
else
if [ -f "$MODPATH/action.sh" ]; then
if [ -f "$TS/action.sh" ]; then
rm -f "$TS/action.sh"
fi
ln -s "$MODPATH/action.sh" "$TS/action.sh"
else
if [ -d "$TS/webroot" ]; then
rm -rf "$TS/webroot"
fi
if [ -d "$MODPATH/common/temp" ]; then
ln -s "$MODPATH/webroot" "$TS/webroot"
fi
if ! aapt dump xmltree "$APK_PATH" AndroidManifest.xml </dev/null 2>&1 | cat | grep -qE "xposed.category|xposeddescription"; then
echo "$PACKAGE" >> "$OUTPUT_SKIP"
fi
until [ "$(getprop sys.boot_completed)" = "1" ]; do
sleep 1
done
echo "# This file is generated from service.sh to speed up load time" > "$OUTPUT_APP"
echo "# This file is generated from service.sh to speed up load time" > "$OUTPUT_SKIP"
pm list packages -3 </dev/null 2>&1 | cat | awk -F: '{print $2}' | while read -r PACKAGE; do
APK_PATH=$(pm path "$PACKAGE" </dev/null 2>&1 | cat | grep "base.apk" | awk -F: '{print $2}' | tr -d '\r')
if [ -n "$APK_PATH" ]; then
APP_NAME=$(aapt dump badging "$APK_PATH" </dev/null 2>&1 | cat | grep "application-label:" | sed "s/application-label://g; s/'//g")
echo "app-name: $APP_NAME, package-name: $PACKAGE" >> "$OUTPUT_APP"
else
echo "app-name: Unknown App package-name: $PACKAGE" >> "$OUTPUT_APP"
fi
if ! aapt dump xmltree "$APK_PATH" AndroidManifest.xml </dev/null 2>&1 | cat | grep -qE "xposed.category|xposeddescription"; then
echo "$PACKAGE" >> "$OUTPUT_SKIP"
fi
done
. "$SCRIPT_DIR/UpdateTargetList.sh"
fi
done

View File

@@ -8,14 +8,10 @@ if [ -f "/storage/emulated/0/stop-tspa-auto-target" ]; then
fi
# Remove residue and restore aosp keybox.
rm -rf "$SCRIPT_DIR/target_list_config"
rm -f "$SCRIPT_DIR/UpdateTargetList.sh"
rm -rf "/data/adb/modules/.TA_utl"
rm -f "/data/adb/boot_hash"
if [ -d "$TS" ]; then
if [ -f "$TS/action.sh" ]; then
rm -f "$TS/action.sh"
else
rm -rf "$TS/webroot"
fi
rm -f "$TS/action.sh"
rm -rf "$TS/webroot"
fi
xxd -r -p "$MODPATH/common/.default" | base64 -d > "$SCRIPT_DIR/keybox.xml"

View File

@@ -1,141 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title data-i18n="title">Document</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="/styles.css" type="text/css">
<script type="module" crossorigin src="/index.js"></script>
</head>
<body>
<!-- Header -->
<div class="header">
<div id="title" data-i18n="title"></div>
<button id="help-button" class="help-button"><i class="fa fa-question-circle"></i></button>
<div class="no-connection">
<img src="wifi-slash.svg" alt="No Connection Icon" class="wifi-icon">
</div>
<div class="language-dropdown">
<button class="language-button">
<i class="fa fa-compass"></i>
</button>
<div class="language-menu">
<button class="language-option" data-lang="en-US" data-i18n="language_english_us">English</button>
<button class="language-option" data-lang="ru-RU" data-i18n="language_russian">Русский</button>
<button class="language-option" data-lang="tl-PH" data-i18n="language_tagalog">Tagalog</button>
<button class="language-option" data-lang="zh-CN"data-i18n="language_chinese_simplified">中文(简体)</button>
<button class="language-option" data-lang="zh-TW"data-i18n="language_chinese_traditional">中文(繁体)</button>
</div>
</div>
</div>
<!-- Loading Element -->
<div class="loading" data-i18n="loading"></div>
<!-- Prompt Element -->
<div id="prompt" class="prompt"></div>
<!-- Floating Button Element -->
<div class="floating-card">
<button class="floating-btn" id="save" data-i18n="save_and_update_button"></button>
</div>
<!-- Menu Options -->
<div class="search-menu-container">
<div class="search-card">
<span class="search-icon"><i class="fa fa-search"></i></span>
<input type="text" class="search-input" id="search" placeholder="Search" data-i18n="search_placeholder">
<button class="clear-btn" id="clear-btn">&#x2715;</button>
</div>
<div class="menu">
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<label for="menu-toggle" id="menu-button">
<span class="menu-icon"><i class="fa fa-bars"></i></span>
</label>
<div id="menu-options" class="menu-options">
<ul>
<li id="refresh" data-i18n="refresh"></li>
<li id="select-all" data-i18n="select_all"></li>
<li id="deselect-all" data-i18n="deselect_all"></li>
<li id="select-denylist" data-i18n="select_denylist"></li>
<li id="deselect-unnecessary" data-i18n="deselect_unnecessary"></li>
<li id="aospkb" data-i18n="set_aosp_keybox"></li>
<li id="extrakb" data-i18n="set_valid_keybox"></li>
<li id="boot-hash" data-i18n="set_verified_boot_hash"></li>
<li id="about" data-i18n="about"></li>
</ul>
</div>
</div>
</div>
<!-- Applist Display -->
<div id="apps-list"></div>
<template id="app-template">
<div class="card" onclick="toggleCheckbox(event)">
<div class="content" data-package="">
<p class="name"></p>
<input type="checkbox" class="checkbox" checked>
</div>
</div>
</template>
<!-- Help Overlay -->
<div id="help-overlay" class="help-overlay">
<div class="help-menu">
<button id="close-help" class="close-help">&#x2715;</button>
<div class="help-content">
<p data-i18n="help_instructions"></p>
<ul id="help-list"></ul>
</div>
</div>
</div>
<!-- BootHash Input Overlay -->
<div id="boot-hash-overlay" class="boot-hash-overlay"></div>
<div id="boot-hash-card" class="boot-hash-card">
<textarea id="boot-hash-input" class="input-box" placeholder="Paste your verified Boot Hash here"
data-i18n="boot_hash_input_placeholder"></textarea>
<div class="button-container">
<button id="boot-hash-save-button" class="boot-hash-save-button" data-i18n="boot_hash_save_button"></button>
</div>
</div>
<!-- About Overlay -->
<div id="about-overlay" class="about-overlay">
<div id="about-menu" class="about-menu">
<button id="close-about" class="close-about">&#x2715;</button>
<div class="about-content">
<p data-i18n="module_name_line1"></p>
<p data-i18n="module_name_line2"></p>
<p><span data-i18n="by"></span>KOWX712</p>
<br>
<p>
<span data-i18n="telegram_channel"></span>
<br>
<span>t.me/kowchannel</span>
</p>
<br>
<p>
<span data-i18n="github"></span>
<br>
<span>github.com/KOWX712/Tricky-Addon-Update-Target-List</span>
</p>
<br>
<p data-i18n="disclaimer"></p>
<br>
<p data-i18n="acknowledgment"></p>
<p>j-hc/zygisk-detach: WebUI template</p>
</div>
</div>
</div>
<!-- Footer -->
<div class="footer">
<div class="uninstall-container hidden-uninstall">
<i class="fa fa-trash"></i>
<span data-i18n="uninstall_webui"></span>
</div>
</div>
</body>
</html>

View File

@@ -1,757 +0,0 @@
// Header Elements
const title = document.querySelector('.header');
const helpButton = document.getElementById('help-button');
const noConnection = document.querySelector('.no-connection');
const languageButton = document.querySelector('.language-button');
const languageMenu = document.querySelector('.language-menu');
const languageOptions = document.querySelectorAll('.language-option');
// Loading and Prompt Elements
const loadingIndicator = document.querySelector('.loading');
const prompt = document.getElementById('prompt');
// Floating Button
const floatingBtn = document.querySelector('.floating-btn');
// Search and Menu Elements
const searchInput = document.getElementById('search');
const clearBtn = document.getElementById('clear-btn');
const searchMenuContainer = document.querySelector('.search-menu-container');
const searchCard = document.querySelector('.search-card');
const menu = document.querySelector('.menu');
const menuButton = document.getElementById('menu-button');
const menuOptions = document.getElementById('menu-options');
const selectDenylistElement = document.getElementById('select-denylist');
// Applist Elements
const appTemplate = document.getElementById('app-template').content;
const appListContainer = document.getElementById('apps-list');
// Help Overlay Elements
const helpOverlay = document.getElementById('help-overlay');
const closeHelp = document.getElementById('close-help');
const helpList = document.getElementById('help-list');
// BootHash Overlay Elements
const bootHashOverlay = document.getElementById('boot-hash-overlay');
const card = document.getElementById('boot-hash-card');
const inputBox = document.getElementById('boot-hash-input');
const saveButton = document.getElementById('boot-hash-save-button');
const basePath = "set-path";
// Variables
let e = 0;
let excludeList = [];
let isRefreshing = false;
let translations = {};
let currentLang = 'en-US';
// Function to detect user's default language
function detectUserLanguage() {
const userLang = navigator.language || navigator.userLanguage;
const langCode = userLang.split('-')[0];
const availableLanguages = ['en-US', 'ru-RU', 'tl-PH', 'zh-CN', 'zh-TW'];
if (availableLanguages.includes(userLang)) {
return userLang;
}
else if (availableLanguages.includes(langCode)) {
return langCode;
}
else {
return 'en-US';
}
}
// Load translations dynamically based on the selected language
async function loadTranslations(lang) {
try {
const response = await fetch(`/locales/${lang}.json`);
translations = await response.json();
applyTranslations();
} catch (error) {
console.error(`Error loading translations for ${lang}:`, error);
if (lang !== 'en-US') {
console.log("Falling back to English.");
loadTranslations('en-US');
}
}
}
// Function to apply translations to all elements with data-i18n attributes
function applyTranslations() {
document.querySelectorAll("[data-i18n]").forEach((el) => {
const key = el.getAttribute("data-i18n");
if (translations[key]) {
if (el.hasAttribute("placeholder")) {
el.setAttribute("placeholder", translations[key]);
} else {
el.textContent = translations[key];
}
}
});
updateHelpMenu();
}
// Language selection event listener
document.querySelectorAll(".language-option").forEach((button) => {
button.addEventListener("click", (e) => {
const lang = e.target.getAttribute("data-lang");
loadTranslations(lang);
});
});
// Function to dynamically update the help menu
function updateHelpMenu() {
helpList.innerHTML = "";
const helpSections = [
{ title: "save_and_update_button", description: "save_and_update_description" },
{ title: "refresh", description: "refresh_description" },
{ title: "select_deselect", description: "select_description" },
{ title: "select_denylist", description: "select_denylist_description" },
{ title: "deselect_unnecessary", description: "deselect_unnecessary_description" },
{ title: "set_keybox", description: "set_aosp_keybox_description" },
{ title: "set_verified_boot_hash", description: "set_verified_boot_hash_description" }
];
helpSections.forEach((section) => {
const listItem = document.createElement("li");
listItem.innerHTML = `<strong data-i18n="${section.title}">${translations[section.title]}</strong>`;
const description = document.createElement("ul");
const descriptionItem = document.createElement("li");
descriptionItem.textContent = translations[section.description] || `[Missing: ${section.description}]`;
description.appendChild(descriptionItem);
listItem.appendChild(description);
helpList.appendChild(listItem);
const emptyLine = document.createElement("li");
emptyLine.innerHTML = "<br>";
helpList.appendChild(emptyLine);
});
}
// Function to execute shell commands
async function execCommand(command) {
return new Promise((resolve, reject) => {
const callbackName = `exec_callback_${Date.now()}_${e++}`;
window[callbackName] = (errno, stdout, stderr) => {
delete window[callbackName];
if (errno === 0) {
resolve(stdout);
} else {
console.error(`Error executing command: ${stderr}`);
reject(stderr);
}
};
try {
ksu.exec(command, "{}", callbackName);
} catch (error) {
console.error(`Execution error: ${error}`);
reject(error);
}
});
}
// Function to read the EXCLUDE file and return its contents as an array
async function readExcludeFile() {
try {
const result = await execCommand('cat /data/adb/tricky_store/target_list_config/EXCLUDE');
excludeList = result.split("\n").filter(app => app.trim() !== ''); // Filter out empty lines
console.log("Current EXCLUDE list:", excludeList);
} catch (error) {
console.error("Failed to read EXCLUDE file:", error);
}
}
// Helper function to check if an app name should be excluded
function isExcluded(appName) {
return excludeList.some(excludeItem => appName.includes(excludeItem));
}
// Function to fetch, sort, and render the app list with app names
async function fetchAppList() {
try {
await readExcludeFile();
let applistMap = {};
try {
const applistResult = await execCommand(`cat ${basePath}applist`);
applistMap = applistResult
.split("\n")
.reduce((map, line) => {
const match = line.match(/app-name:\s*(.+),\s*package-name:\s*(.+)/);
if (match) {
const appName = match[1].trim();
const packageName = match[2].trim();
map[packageName] = appName;
}
return map;
}, {});
console.log("Applist loaded successfully.");
} catch (error) {
console.warn("Applist file not found or could not be loaded. Skipping applist lookup.");
}
const result = await execCommand("pm list packages -3");
const appEntries = result
.split("\n")
.map(line => {
const packageName = line.replace("package:", "").trim();
const appName = applistMap[packageName] || null;
return { appName, packageName };
})
.filter(entry => entry.packageName);
for (const entry of appEntries) {
if (!entry.appName) {
try {
const apkPath = await execCommand(`pm path ${entry.packageName} | grep "base.apk" | awk -F: '{print $2}' | tr -d '\\r'`);
if (apkPath) {
const appName = await execCommand(`${basePath}aapt dump badging ${apkPath.trim()} 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g"`);
entry.appName = appName.trim() || "Unknown App";
} else {
entry.appName = "Unknown App";
}
} catch (error) {
entry.appName = "Unknown App";
}
}
}
const sortedApps = appEntries.sort((a, b) => {
const aInExclude = isExcluded(a.packageName);
const bInExclude = isExcluded(b.packageName);
return aInExclude === bInExclude ? a.appName.localeCompare(b.appName) : aInExclude ? 1 : -1;
});
appListContainer.innerHTML = "";
sortedApps.forEach(({ appName, packageName }) => {
const appElement = document.importNode(appTemplate, true);
const contentElement = appElement.querySelector(".content");
contentElement.setAttribute("data-package", packageName);
const nameElement = appElement.querySelector(".name");
nameElement.innerHTML = `<strong>${appName || "Unknown App"}</strong><br>${packageName}`;
const checkbox = appElement.querySelector(".checkbox");
checkbox.checked = !isExcluded(packageName);
appListContainer.appendChild(appElement);
});
console.log("App list with names and packages rendered successfully.");
} catch (error) {
console.error("Failed to fetch or render app list with names:", error);
}
floatingBtn.style.transform = "translateY(-120px)";
}
// Function to refresh app list
async function refreshAppList() {
isRefreshing = true;
title.style.transform = 'translateY(0)';
searchMenuContainer.style.transform = 'translateY(0)';
floatingBtn.style.transform = 'translateY(0)';
searchInput.value = '';
clearBtn.style.display = "none";
appListContainer.innerHTML = '';
loadingIndicator.style.display = 'flex';
document.querySelector('.uninstall-container').classList.add('hidden-uninstall');
await new Promise(resolve => setTimeout(resolve, 500));
window.scrollTo(0, 0);
if (noConnection.style.display === "flex") {
await runExtraScript();
}
await fetchAppList();
loadingIndicator.style.display = 'none';
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
isRefreshing = false;
}
// Function to select all visible apps
function selectAllApps() {
document.querySelectorAll(".card").forEach(card => {
if (card.style.display !== "none") {
card.querySelector(".checkbox").checked = true;
}
});
}
// Function to deselect all visible apps
function deselectAllApps() {
document.querySelectorAll(".card").forEach(card => {
if (card.style.display !== "none") {
card.querySelector(".checkbox").checked = false;
}
});
}
// Function to run the extra script
async function runExtraScript() {
try {
const scriptPath = `${basePath}get_extra.sh`;
const output = await execCommand(scriptPath);
console.log("Extra script executed successfully.");
noConnection.style.display = "none";
if (output.includes("update")) {
console.log("Update detected from extra script.");
showPrompt("new_update");
await execCommand(`
su -c "mkdir -p '/data/adb/modules/TA_utl' &&
cp -rf '${basePath}temp/'* '/data/adb/modules/TA_utl/'"
`);
} else {
console.log("No update detected from extra script.");
}
} catch (error) {
console.error("Failed to execute Extra script:", error);
showPrompt("no_internet", false);
noConnection.style.display = "flex";
}
}
// Function to read the exclude list and uncheck corresponding apps
async function deselectUnnecessaryApps() {
try {
const result = await execCommand(`cat ${basePath}exclude-list`);
const UnnecessaryApps = result.split("\n").map(app => app.trim()).filter(Boolean);
const apps = document.querySelectorAll(".card");
apps.forEach(app => {
const contentElement = app.querySelector(".content");
const packageName = contentElement.getAttribute("data-package");
const checkbox = app.querySelector(".checkbox");
if (UnnecessaryApps.includes(packageName)) {
checkbox.checked = false; // Uncheck if found in more-exclude list
}
});
console.log("unnecessary apps deselected successfully.");
} catch (error) {
console.error("Failed to deselect unnecessary apps:", error);
}
}
// Function to check if Magisk
async function checkMagisk() {
try {
const hasDenylistCondition = await execCommand(`
if [ ! -f "/data/adb/apd" ] && [ ! -f "/data/adb/ksud" ]; then
echo "OK"
else
echo ""
fi
`);
if (hasDenylistCondition.trim() === "OK") {
console.log("Denylist conditions met, displaying element.");
selectDenylistElement.style.display = "flex";
} else {
console.log("ksud or apd detected, leaving denylist element hidden.");
}
} catch (error) {
console.error("Error while checking denylist conditions:", error);
}
}
// Function to read the denylist and check corresponding apps
async function selectDenylistApps() {
try {
const result = await execCommand(`
magisk --denylist ls 2>/dev/null | \
awk -F'|' '{print $1}' | \
grep -v "isolated" | \
sort | uniq
`);
const denylistApps = result.split("\n").map(app => app.trim()).filter(Boolean);
const apps = document.querySelectorAll(".card");
await deselectAllApps();
apps.forEach(app => {
const contentElement = app.querySelector(".content");
const packageName = contentElement.getAttribute("data-package");
const checkbox = app.querySelector(".checkbox");
if (denylistApps.includes(packageName)) {
checkbox.checked = true; // Select the app if found in denylist
}
});
console.log("Denylist apps selected successfully.");
} catch (error) {
console.error("Failed to select Denylist apps:", error);
}
}
// Function to replace aosp kb
async function aospkb() {
try {
const sourcePath = `${basePath}.default`;
const destinationPath = "/data/adb/tricky_store/keybox.xml";
await execCommand(`xxd -r -p ${sourcePath} | base64 -d > ${destinationPath}`);
console.log("AOSP keybox copied successfully.");
showPrompt("aosp_key_set");
} catch (error) {
console.error("Failed to copy AOSP keybox:", error);
showPrompt("key_set_error", false);
}
}
// Function to replace valid kb
async function extrakb() {
const sourcePath = `${basePath}.extra`;
const destinationPath = "/data/adb/tricky_store/keybox.xml";
try {
const fileExists = await execCommand(`[ -f ${sourcePath} ] && echo "exists"`);
if (fileExists.trim() !== "exists") {
throw new Error(".extra file not found");
}
await execCommand(`xxd -r -p ${sourcePath} | base64 -d > ${destinationPath}`);
console.log("Valid keybox copied successfully.");
showPrompt("valid_key_set");
} catch (error) {
console.error("Failed to copy valid keybox:", error);
await aospkb();
showPrompt("no_valid_fallback", false);
}
}
// Function to handle Verified Boot Hash
async function setBootHash() {
const showCard = () => {
bootHashOverlay.style.display = "flex";
card.style.display = "flex";
requestAnimationFrame(() => {
bootHashOverlay.classList.add("show");
card.classList.add("show");
});
document.body.style.overflow = "hidden";
};
const closeCard = () => {
bootHashOverlay.classList.remove("show");
card.classList.remove("show");
setTimeout(() => {
bootHashOverlay.style.display = "none";
card.style.display = "none";
document.body.style.overflow = "auto";
}, 200);
};
showCard();
try {
const bootHashContent = await execCommand("cat /data/adb/boot_hash");
const validHash = bootHashContent
.split("\n")
.filter(line => !line.startsWith("#") && line.trim())[0];
inputBox.value = validHash || "";
} catch (error) {
console.warn("Failed to read boot_hash file. Defaulting to empty input.");
inputBox.value = "";
}
saveButton.addEventListener("click", async () => {
const inputValue = inputBox.value.trim();
try {
await execCommand(`echo "${inputValue}" > /data/adb/boot_hash`);
await execCommand(`su -c resetprop -n ro.boot.vbmeta.digest ${inputValue}`);
showPrompt("boot_hash_set");
closeCard();
} catch (error) {
console.error("Failed to update boot_hash:", error);
showPrompt("boot_hash_set_error", false);
}
});
bootHashOverlay.addEventListener("click", (event) => {
if (event.target === bootHashOverlay) closeCard();
});
}
// Function to show about overlay
function aboutMenu() {
const aboutOverlay = document.getElementById('about-overlay');
const menu = document.getElementById('about-menu');
const closeAbout = document.getElementById('close-about');
const showMenu = () => {
aboutOverlay.style.display = 'flex';
setTimeout(() => {
aboutOverlay.style.opacity = '1';
menu.style.opacity = '1';
}, 10);
document.body.style.overflow = 'hidden';
};
const hideMenu = () => {
aboutOverlay.style.opacity = '0';
menu.style.opacity = '0';
setTimeout(() => {
aboutOverlay.style.display = 'none';
document.body.style.overflow = 'auto';
}, 200);
};
showMenu();
closeAbout.addEventListener('click', (event) => {
event.stopPropagation();
hideMenu();
});
aboutOverlay.addEventListener('click', (event) => {
if (!menu.contains(event.target)) {
hideMenu();
}
});
menu.addEventListener('click', (event) => event.stopPropagation());
}
// Function to show the prompt with a success or error message
function showPrompt(key, isSuccess = true) {
const message = translations[key] || key;
prompt.textContent = message;
prompt.classList.toggle('error', !isSuccess);
if (window.promptTimeout) {
clearTimeout(window.promptTimeout);
}
setTimeout(() => {
prompt.classList.add('visible');
prompt.classList.remove('hidden');
window.promptTimeout = setTimeout(() => {
prompt.classList.remove('visible');
prompt.classList.add('hidden');
}, 3000);
}, 500);
}
// Function to toggle menu option
function setupMenuToggle() {
const menuIcon = menuButton.querySelector('.menu-icon');
let menuOpen = false;
let menuAnimating = false;
menuButton.addEventListener('click', (event) => {
if (menuAnimating) return;
event.stopPropagation();
if (menuOptions.classList.contains('visible')) {
closeMenu();
} else {
openMenu();
}
});
document.addEventListener('click', (event) => {
if (!menuOptions.contains(event.target) && event.target !== menuButton) {
closeMenu();
}
});
window.addEventListener('scroll', () => {
if (menuOptions.classList.contains('visible')) {
closeMenu();
}
});
const closeMenuItems = ['refresh', 'select-all', 'deselect-all', 'select-denylist', 'deselect-unnecessary', 'aospkb', 'extrakb', 'boot-hash', 'about'];
closeMenuItems.forEach(id => {
const item = document.getElementById(id);
if (item) {
item.addEventListener('click', (event) => {
event.stopPropagation();
closeMenu();
});
}
});
function openMenu() {
menuAnimating = true;
menuOptions.style.display = 'block';
setTimeout(() => {
menuOptions.classList.remove('hidden');
menuOptions.classList.add('visible');
menuIcon.classList.add('menu-open');
menuIcon.classList.remove('menu-closed');
menuOpen = true;
menuAnimating = false;
}, 10);
}
function closeMenu() {
if (menuOptions.classList.contains('visible')) {
menuAnimating = true;
menuOptions.classList.remove('visible');
menuOptions.classList.add('hidden');
menuIcon.classList.remove('menu-open');
menuIcon.classList.add('menu-closed');
setTimeout(() => {
menuOptions.style.display = 'none';
menuOpen = false;
menuAnimating = false;
}, 200);
}
}
}
// Focus on search input when search card is clicked
searchCard.addEventListener("click", () => {
searchInput.focus();
});
// Search functionality
searchInput.addEventListener("input", (e) => {
const searchQuery = e.target.value.toLowerCase();
const apps = appListContainer.querySelectorAll(".card");
apps.forEach(app => {
const name = app.querySelector(".name").textContent.toLowerCase();
app.style.display = name.includes(searchQuery) ? "block" : "none";
window.scrollTo(0, 0);
});
if (searchQuery !== "") {
clearBtn.style.display = "block";
} else {
clearBtn.style.display = "none";
}
});
// Clear search input
clearBtn.addEventListener("click", () => {
searchInput.value = "";
clearBtn.style.display = "none";
window.scrollTo(0, 0);
const apps = appListContainer.querySelectorAll(".card");
apps.forEach(app => {
app.style.display = "block";
});
});
// Add button click event to update EXCLUDE file and run UpdateTargetList.sh
document.getElementById("save").addEventListener("click", async () => {
await readExcludeFile();
const deselectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:not(:checked)"))
.map(checkbox => checkbox.closest(".card").querySelector(".content").getAttribute("data-package"));
const selectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:checked"))
.map(checkbox => checkbox.closest(".card").querySelector(".content").getAttribute("data-package"));
// Add deselected apps to EXCLUDE list
for (const packageName of deselectedApps) {
if (!excludeList.includes(packageName)) {
excludeList.push(packageName);
console.log("Added to EXCLUDE list:", packageName);
} else {
console.log("Package already in EXCLUDE file, skipping:", packageName);
}
}
// Remove selected apps from EXCLUDE list
if (selectedApps.length > 0) {
selectedApps.forEach(packageName => {
excludeList = excludeList.filter(excludedPackage => excludedPackage !== packageName);
console.log("Removed from EXCLUDE list:", packageName);
});
}
try {
// Save the EXCLUDE file
const updatedExcludeContent = excludeList.join("\n");
await execCommand(`echo "${updatedExcludeContent}" > /data/adb/tricky_store/target_list_config/EXCLUDE`);
console.log("EXCLUDE file updated successfully.");
// Execute UpdateTargetList.sh
try {
await execCommand("/data/adb/tricky_store/UpdateTargetList.sh");
showPrompt("saved_and_updated");
} catch (error) {
console.error("Failed to update target list:", error);
showPrompt("saved_not_updated", false);
}
} catch (error) {
console.error("Failed to update EXCLUDE file:", error);
showPrompt("save_error", false);
}
await readExcludeFile();
await refreshAppList();
});
// Initial load
document.addEventListener('DOMContentLoaded', async () => {
const userLang = detectUserLanguage();
await loadTranslations(userLang);
setupMenuToggle();
document.getElementById("refresh").addEventListener("click", refreshAppList);
document.getElementById("select-all").addEventListener("click", selectAllApps);
document.getElementById("deselect-all").addEventListener("click", deselectAllApps);
document.getElementById("select-denylist").addEventListener("click", selectDenylistApps);
document.getElementById("deselect-unnecessary").addEventListener("click", deselectUnnecessaryApps);
document.getElementById("aospkb").addEventListener("click", aospkb);
document.getElementById("extrakb").addEventListener("click", extrakb);
document.getElementById("boot-hash").addEventListener("click", setBootHash);
document.getElementById("about").addEventListener("click", aboutMenu);
await fetchAppList();
checkMagisk();
loadingIndicator.style.display = "none";
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
runExtraScript();
});
// Toggle the visibility of the language menu when clicking the button
languageButton.addEventListener("click", (event) => {
event.stopPropagation();
const isVisible = languageMenu.classList.contains("show");
if (isVisible) {
languageMenu.classList.remove("show");
} else {
languageMenu.classList.add("show");
}
});
document.addEventListener("click", (event) => {
if (!languageButton.contains(event.target) && !languageMenu.contains(event.target)) {
languageMenu.classList.remove("show");
}
});
languageOptions.forEach(option => {
option.addEventListener("click", () => {
languageMenu.classList.remove("show");
});
});
// Scroll event
let lastScrollY = window.scrollY;
const scrollThreshold = 40;
window.addEventListener('scroll', () => {
if (isRefreshing) return;
if (window.scrollY > lastScrollY && window.scrollY > scrollThreshold) {
title.style.transform = 'translateY(-100%)';
searchMenuContainer.style.transform = 'translateY(-40px)';
floatingBtn.style.transform = 'translateY(0)';
} else if (window.scrollY < lastScrollY) {
title.style.transform = 'translateY(0)';
searchMenuContainer.style.transform = 'translateY(0)';
floatingBtn.style.transform = 'translateY(-120px)';
}
if (languageMenu.classList.contains("show")) {
languageMenu.classList.remove("show");
}
lastScrollY = window.scrollY;
});
// Show help overlay
helpButton.addEventListener("click", () => {
helpOverlay.classList.remove("hide");
helpOverlay.style.display = "flex";
requestAnimationFrame(() => {
helpOverlay.classList.add("show");
});
document.body.classList.add("no-scroll");
});
// Hide help overlay
const hideHelpOverlay = () => {
helpOverlay.classList.remove("show");
helpOverlay.classList.add("hide");
document.body.classList.remove("no-scroll");
setTimeout(() => {
helpOverlay.style.display = "none";
}, 200);
};
// Hide when clicking on close button or outside of the overlay content
closeHelp.addEventListener("click", hideHelpOverlay);
helpOverlay.addEventListener("click", (event) => {
if (event.target === helpOverlay) {
hideHelpOverlay();
}
});
// Uninstall WebUI
document.querySelector(".uninstall-container").addEventListener("click", async () => {
try {
await execCommand(`
su -c "
if [ -d '${basePath}temp/' ]; then
mkdir -p '/data/adb/modules/TA_utl' &&
cp -rf '${basePath}temp/'* '/data/adb/modules/TA_utl/' &&
touch '/data/adb/modules/TA_utl/remove'
else
touch '/data/adb/modules/TA_utl/remove'
fi
"
`);
showPrompt("uninstall_prompt");
} catch (error) {
console.error("Failed to execute uninstall command:", error);
console.log("Error message:", error.message);
showPrompt("uninstall_failed", false);
}
});

View File

@@ -1,52 +0,0 @@
{
"title": "Tricky Addon - Update Target List",
"search_placeholder": "Search",
"save_and_update_button": "Save and Update",
"boot_hash_save_button": "Save",
"loading": "Loading...",
"boot_hash_input_placeholder": "Paste your verified Boot Hash here",
"uninstall_webui": "Uninstall WebUI",
"refresh": "Refresh",
"select_all": "Select All",
"deselect_all": "Deselect All",
"select_denylist": "Select From DenyList",
"deselect_unnecessary": "Deselect Unnecessary",
"set_aosp_keybox": "Set AOSP Keybox",
"set_valid_keybox": "Set Valid Keybox",
"set_verified_boot_hash": "Set Verified Boot Hash",
"about": "About",
"help_instructions": "Instructions",
"save_and_update_description": "Save the current configuration and update target.txt immediately.",
"refresh_description": "Refresh app list and exclude list.",
"select_deselect": "Select & Deselect All",
"select_description": "Select or deselect all apps in the current interface.",
"select_denylist_description": "Available in Magisk only, select apps that are in the DenyList. Recommended.",
"deselect_unnecessary_description": "Unnecessary category: Xposed module, root manager, root-related apps, and general apps that never check bootloader status. This option requires an Internet connection.",
"set_keybox": "Set AOSP & Valid Keybox",
"set_aosp_keybox_description": "Replace tricky store keybox.xml. AOSP keybox will be replaced if there's no more valid keybox. Valid keybox option requires Internet connection.",
"set_verified_boot_hash_description": "Get verifiedBootHash value from Key Attestation Demo. Fix abnormal boot state by resetting ro.boot.vbmeta.digest.",
"module_name_line1": "Tricky Addon",
"module_name_line2": "Update Target List",
"by": "by ",
"telegram_channel": "Telegram Channel",
"github": "GitHub",
"disclaimer": "This WebUI is not a part of Tricky Store, DO NOT report to Tricky Store author if you encounter any issue.",
"acknowledgment": "Acknowledgment",
"no_internet": "Please check your Internet connection",
"aosp_key_set": "AOSP keybox set successfully",
"key_set_error": "Failed to update keybox",
"valid_key_set": "Valid keybox set successfully",
"no_valid_fallback": "No valid keybox found, replaced with AOSP keybox.",
"boot_hash_set": "Verified Boot Hash saved successfully",
"boot_hash_set_error": "Failed to update Verified Boot Hash",
"saved_and_updated": "Config and target.txt updated",
"saved_not_updated": "Config saved, but failed to update target list",
"save_error": "Failed to save config",
"uninstall_prompt": "WebUI will be removed after reboot",
"uninstall_failed": "Failed to uninstall WebUI",
"new_update": "A new update is available!"
}

View File

@@ -1,36 +0,0 @@
# Translation Guide
## Fix Translation Error
1. Fork this repository.
2. Find your language string file in `/module/webroot/locales/`.
3. Edit the string value with translated incorrectly.
4. Create a Pull Request.
---
## Add a New Language
### Simple
- Contact me in Telegram to add a new translation langauge for you.
### Advanced
1. Fork this repository.
2. Make a copy of `/module/webroot/locales/A-template.json`
3. Rename it to `language_code-COUNTRY_CODE.json`, e.g., `en-US.json`.
4. Translate the string value inside.
5. Add `langauge-option` into `/module/webroot/index.html`.
Format:
```xml
<button class="language-option" data-lang="language_code-COUNTRY_CODE" data-i18n="language_languageName">languageName</button>
```
Example:
```xml
<div class="language-menu">
<button class="language-option" data-lang="en-US" data-i18n="language_english_us">English</button>
</div>
```
6. Add language_code-COUNTRY_CODE in `/module/webroot/index.js` under `function detectUserLanguage()`
Format:
```js
function detectUserLanguage() {
const availableLanguages = ['en-US', 'ru-RU', 'tl-PH', 'zh-CN', 'zh-TW'];
}
```
7. Create a Pull Request

View File

@@ -1,52 +0,0 @@
{
"title": "Tricky Addon - Update Target List",
"search_placeholder": "Search",
"save_and_update_button": "Save and Update",
"boot_hash_save_button": "Save",
"loading": "Loading...",
"boot_hash_input_placeholder": "Paste your verified Boot Hash here",
"uninstall_webui": "Uninstall WebUI",
"refresh": "Refresh",
"select_all": "Select All",
"deselect_all": "Deselect All",
"select_denylist": "Select From DenyList",
"deselect_unnecessary": "Deselect Unnecessary",
"set_aosp_keybox": "Set AOSP Keybox",
"set_valid_keybox": "Set Valid Keybox",
"set_verified_boot_hash": "Set Verified Boot Hash",
"about": "About",
"help_instructions": "Instructions",
"save_and_update_description": "Save the current configuration and update target.txt immediately.",
"refresh_description": "Refresh app list and exclude list.",
"select_deselect": "Select & Deselect All",
"select_description": "Select or deselect all apps in the current interface.",
"select_denylist_description": "Available in Magisk only, select apps that are in the DenyList. Recommended.",
"deselect_unnecessary_description": "Unnecessary category: Xposed module, root manager, root-related apps, and general apps that never check bootloader status. This option requires an Internet connection.",
"set_keybox": "Set AOSP & Valid Keybox",
"set_aosp_keybox_description": "Replace tricky store keybox.xml. AOSP keybox will be replaced if there's no more valid keybox. Valid keybox option requires Internet connection.",
"set_verified_boot_hash_description": "Get verifiedBootHash value from Key Attestation Demo. Fix abnormal boot state by resetting ro.boot.vbmeta.digest.",
"module_name_line1": "Tricky Addon",
"module_name_line2": "Update Target List",
"by": "by ",
"telegram_channel": "Telegram Channel",
"github": "GitHub",
"disclaimer": "This WebUI is not a part of Tricky Store, DO NOT report to Tricky Store author if you encounter any issue.",
"acknowledgment": "Acknowledgment",
"no_internet": "Please check your Internet connection",
"aosp_key_set": "AOSP keybox set successfully",
"key_set_error": "Failed to update keybox",
"valid_key_set": "Valid keybox set successfully",
"no_valid_fallback": "No valid keybox found, replaced with AOSP keybox.",
"boot_hash_set": "Verified Boot Hash saved successfully",
"boot_hash_set_error": "Failed to update Verified Boot Hash",
"saved_and_updated": "Config and target.txt updated",
"saved_not_updated": "Config saved, but failed to update target list",
"save_error": "Failed to save config",
"uninstall_prompt": "WebUI will be removed after reboot",
"uninstall_failed": "Failed to uninstall WebUI",
"new_update": "A new update is available!"
}

View File

@@ -1,52 +0,0 @@
{
"title": "Tricky Addon - Обновить список целей",
"search_placeholder": "Поиск",
"save_and_update_button": "Сохранить и обновить",
"boot_hash_save_button": "Сохранить",
"loading": "Загрузка...",
"boot_hash_input_placeholder": "Вставьте свой проверенный Boot Hash сюда",
"uninstall_webui": "Удалить WebUI",
"refresh": "Обновить",
"select_all": "Выбрать все",
"deselect_all": "Отменить выбор всех",
"select_denylist": "Выбрать из DenyList",
"deselect_unnecessary": "Отменить выбор ненужных",
"set_aosp_keybox": "Установить AOSP Keybox",
"set_valid_keybox": "Установить действующий Keybox",
"set_verified_boot_hash": "Установить Verified Boot Hash",
"about": "О программе",
"help_instructions": "Инструкции",
"save_and_update_description": "Сохраните текущую конфигурацию и немедленно обновите target.txt.",
"refresh_description": "Обновить список приложений и список исключений.",
"select_deselect": "Выбрать и отменить выбор всех",
"select_description": "Выбрать или отменить выбор всех приложений в текущем интерфейсе.",
"select_denylist_description": "Доступно только в Magisk, выберите приложения, которые находятся в DenyList. Рекомендуется.",
"deselect_unnecessary_description": "Ненужные категории: модули Xposed, менеджеры root, приложения, связанные с root, и общие приложения, которые никогда не проверяют статус загрузчика. Этот параметр требует подключения к интернету.",
"set_keybox": "Установить AOSP и действующий Keybox",
"set_aosp_keybox_description": "Замените tricky store keybox.xml. AOSP keybox будет заменен, если не будет найден действующий keybox. Опция с действующим keybox требует подключения к интернету.",
"set_verified_boot_hash_description": "Получите значение verifiedBootHash из Key Attestation Demo. Исправьте аномальное состояние загрузки, сбросив ro.boot.vbmeta.digest.",
"module_name_line1": "Tricky Addon",
"module_name_line2": "Обновить список целей",
"by": "от ",
"telegram_channel": "Канал в Telegram",
"github": "GitHub",
"disclaimer": "Этот WebUI не является частью Tricky Store, НЕ сообщайте автору Tricky Store о любых возникающих проблемах.",
"acknowledgment": "Благодарности",
"no_internet": "Пожалуйста, проверьте ваше подключение к интернету",
"aosp_key_set": "AOSP keybox успешно установлен",
"key_set_error": "Не удалось обновить keybox",
"valid_key_set": "Действующий keybox успешно установлен",
"no_valid_fallback": "Не найден действующий keybox, заменен на AOSP keybox.",
"boot_hash_set": "Verified Boot Hash успешно сохранен",
"boot_hash_set_error": "Не удалось обновить Verified Boot Hash",
"saved_and_updated": "Конфигурация и target.txt обновлены",
"saved_not_updated": "Конфигурация сохранена, но не удалось обновить список целей",
"save_error": "Не удалось сохранить конфигурацию",
"uninstall_prompt": "WebUI будет удален после перезагрузки",
"uninstall_failed": "Не удалось удалить WebUI",
"new_update": "Доступно новое обновление!"
}

View File

@@ -1,52 +0,0 @@
{
"title": "Tricky Addon - I-update ang Target List",
"search_placeholder": "Maghanap",
"save_and_update_button": "I-save at I-update",
"boot_hash_save_button": "I-save",
"loading": "Naglo-load...",
"boot_hash_input_placeholder": "I-paste ang iyong verified Boot Hash dito",
"uninstall_webui": "I-uninstall ang WebUI",
"refresh": "I-refresh",
"select_all": "Piliin Lahat",
"deselect_all": "Huwag Pumili ng Lahat",
"select_denylist": "Piliin mula sa DenyList",
"deselect_unnecessary": "Huwag Pumili ng Hindi Kinakailangan",
"set_aosp_keybox": "I-set ang AOSP Keybox",
"set_valid_keybox": "I-set ang Valid Keybox",
"set_verified_boot_hash": "I-set ang Verified Boot Hash",
"about": "Tungkol",
"help_instructions": "Mga Tagubilin",
"save_and_update_description": "I-save ang kasalukuyang configuration at i-update ang target.txt agad.",
"refresh_description": "I-refresh ang listahan ng apps at exclude list.",
"select_deselect": "Piliin & Huwag Pumili ng Lahat",
"select_description": "Piliin o huwag piliin ang lahat ng apps sa kasalukuyang interface.",
"select_denylist_description": "Available lang sa Magisk, piliin ang mga app na nasa DenyList. Inirerekomenda.",
"deselect_unnecessary_description": "Hindi kinakailangang kategorya: Xposed module, root manager, root-related apps, at mga karaniwang apps na hindi kailanman nire-refresh ang bootloader status. Nangangailangan ng koneksyon sa internet.",
"set_keybox": "I-set ang AOSP at Valid Keybox",
"set_aosp_keybox_description": "Palitan ang tricky store keybox.xml. Palitan ang AOSP keybox kung walang valid keybox. Nangangailangan ng koneksyon sa internet ang valid keybox option.",
"set_verified_boot_hash_description": "Kunin ang verifiedBootHash mula sa Key Attestation Demo. Ayusin ang abnormal na boot state sa pamamagitan ng pag-reset ng ro.boot.vbmeta.digest.",
"module_name_line1": "Tricky Addon",
"module_name_line2": "I-update ang Target List",
"by": "ni ",
"telegram_channel": "Telegram Channel",
"github": "GitHub",
"disclaimer": "Ang WebUI na ito ay hindi bahagi ng Tricky Store, HUWAG i-report sa may-akda ng Tricky Store kung makaranas ka ng anumang isyu.",
"acknowledgment": "Pagkilala",
"no_internet": "Pakitingnan ang iyong koneksyon sa Internet",
"aosp_key_set": "Matagumpay na na-set ang AOSP Keybox",
"key_set_error": "Nabigong i-update ang keybox",
"valid_key_set": "Matagumpay na na-set ang Valid Keybox",
"no_valid_fallback": "Walang valid na keybox na natagpuan, pinalitan ng AOSP keybox.",
"boot_hash_set": "Matagumpay na na-save ang Verified Boot Hash",
"boot_hash_set_error": "Nabigong i-update ang Verified Boot Hash",
"saved_and_updated": "Na-save ang config at na-update ang target.txt",
"saved_not_updated": "Na-save ang config, ngunit nabigong i-update ang target list",
"save_error": "Nabigong i-save ang config",
"uninstall_prompt": "Mawawala ang WebUI pagkatapos ng reboot",
"uninstall_failed": "Nabigong i-uninstall ang WebUI",
"new_update": "May bagong update na available!"
}

View File

@@ -1,52 +0,0 @@
{
"title": "TS插件 - 更新目标列表",
"search_placeholder": "搜索",
"save_and_update_button": "保存并更新",
"boot_hash_save_button": "保存",
"loading": "加载中...",
"boot_hash_input_placeholder": "在此粘贴您的哈希值",
"uninstall_webui": "卸载 WebUI",
"refresh": "刷新",
"select_all": "全选",
"deselect_all": "取消全选",
"select_denylist": "从排除列表中选择",
"deselect_unnecessary": "取消选择非必应用",
"set_aosp_keybox": "设置 AOSP 密钥",
"set_valid_keybox": "设置有效密钥",
"set_verified_boot_hash": "设置哈希值",
"about": "关于",
"help_instructions": "使用指南",
"save_and_update_description": "保存当前配置并立即更新目标列表target.txt。",
"refresh_description": "刷新应用列表和排除列表。",
"select_deselect": "全选 & 取消全选",
"select_description": "选择或取消选择当前界面中的所有应用。",
"select_denylist_description": "仅适用于 Magisk选择在排除列表中的应用。推荐使用。",
"deselect_unnecessary_description": "非必要分类Xposed 模块、root 管理器、与 root 相关的应用,以及从不检查 bootloader 状态的通用应用。此功能需连网使用。",
"set_keybox": "设置 AOSP & 有效密钥",
"set_aosp_keybox_description": "替换 Tricky Store 的密钥keybox.xml。如果没有有效密钥将替换为 AOSP 密钥。有效密钥选项需连网使用。",
"set_verified_boot_hash_description": "从 Key Attestation Demo 获取 verifiedBootHash哈希值。通过重置 ro.boot.vbmeta.digest 修复异常 boot 状态。",
"module_name_line1": "TS插件",
"module_name_line2": "更新目标列表",
"by": "作者:",
"telegram_channel": "TG频道",
"github": "GitHub",
"disclaimer": "此 WebUI 不是 Tricky Store 的一部分,遇到任何问题请勿向 Tricky Store 作者反馈。",
"acknowledgment": "特别鸣谢",
"no_internet": "请检查您的网络连接",
"aosp_key_set": "成功设置 AOSP 密钥",
"key_set_error": "更新密钥失败",
"valid_key_set": "成功设置有效密钥",
"no_valid_fallback": "未找到有效密钥,已替换为 AOSP 密钥。",
"boot_hash_set": "哈希值重置成功",
"boot_hash_set_error": "哈希值重置失败",
"saved_and_updated": "成功保存配置和更新目标列表",
"saved_not_updated": "配置已保存,但更新目标列表失败",
"save_error": "保存配置失败",
"uninstall_prompt": "WebUI 将在重启后被移除",
"uninstall_failed": "卸载 WebUI 失败",
"new_update": "发现新的版本!"
}

View File

@@ -1,52 +0,0 @@
{
"title": "TS插件 - 更新目標列表",
"search_placeholder": "搜尋",
"save_and_update_button": "保存並更新",
"boot_hash_save_button": "保存",
"loading": "加載中...",
"boot_hash_input_placeholder": "在此粘貼您的哈希值",
"uninstall_webui": "卸載 WebUI",
"refresh": "刷新",
"select_all": "全選",
"deselect_all": "取消全選",
"select_denylist": "從排除列表中選擇",
"deselect_unnecessary": "取消選擇非必應用",
"set_aosp_keybox": "設置 AOSP 密鑰",
"set_valid_keybox": "設置有效密鑰",
"set_verified_boot_hash": "設置哈希值",
"about": "關於",
"help_instructions": "使用指南",
"save_and_update_description": "保存當前配置並立即更新目標列表target.txt。",
"refresh_description": "刷新應用列表和排除列表。",
"select_deselect": "全選 & 取消全選",
"select_description": "選擇或取消選擇當前界面中的所有應用。",
"select_denylist_description": "僅適用於 Magisk選擇在排除列表中的應用。推薦使用。",
"deselect_unnecessary_description": "非必要分類Xposed 模塊、root 管理器、與 root 相關的應用,以及從不檢查 bootloader 狀態的通用應用。此功能需連網使用。",
"set_keybox": "設置 AOSP & 有效密鑰",
"set_aosp_keybox_description": "替換 Tricky Store 的密鑰keybox.xml。如果沒有有效密鑰將替換為 AOSP 密鑰。有效密鑰選項需連網使用。",
"set_verified_boot_hash_description": "從 Key Attestation Demo 獲取 verifiedBootHash哈希值。通過重置 ro.boot.vbmeta.digest 修復異常 boot 狀態。",
"module_name_line1": "TS插件",
"module_name_line2": "更新目標列表",
"by": "作者:",
"telegram_channel": "TG頻道",
"github": "GitHub",
"disclaimer": "此 WebUI 不是 Tricky Store 的一部分,遇到任何問題請勿向 Tricky Store 作者反饋。",
"acknowledgment": "特別鳴謝",
"no_internet": "請檢查您的網路連接",
"aosp_key_set": "成功設置 AOSP 密鑰",
"key_set_error": "更新密鑰失敗",
"valid_key_set": "成功設置有效密鑰",
"no_valid_fallback": "未找到有效密鑰,已替換為 AOSP 密鑰。",
"boot_hash_set": "哈希值重置成功",
"boot_hash_set_error": "哈希值重置失敗",
"saved_and_updated": "成功保存配置和更新目標列表",
"saved_not_updated": "配置已保存,但更新目標列表失敗",
"save_error": "保存配置失敗",
"uninstall_prompt": "WebUI 將在重啟後被移除",
"uninstall_failed": "卸載 WebUI 失敗",
"new_update": "發現新的版本!"
}

View File

@@ -1,658 +0,0 @@
body {
background-color: #F5F5F5;
}
.no-scroll {
overflow: hidden;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
position: fixed;
top: 0;
height: 40px;
width: 100%;
background-color: #F5F5F5;
transition: transform 0.3s ease;
z-index: 1100;
}
#title {
font-size: 16.5px;
font-weight: bold;
}
.no-connection {
padding-bottom: 2px;
display: none;
position: relative;
margin-right: 0px;
color: #7E7E7E;
}
.no-connection .wifi-icon {
width: 22px;
height: 22px;
filter: invert(0.6) sepia(0) saturate(0) hue-rotate(180deg) brightness(0.8) contrast(1);
}
.language-dropdown {
position: relative;
display: inline-block;
margin-right: 15px;
}
.language-button {
background: none;
border: none;
font-size: 23px;
color: #333;
}
.language-menu {
display: flex;
padding: 5px;
flex-direction: column;
position: absolute;
right: 0;
background-color: #fff;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
z-index: 2000;
border: 1px solid #ccc;
border-radius: 8px;
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
}
.language-menu.show {
display: block;
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.language-option {
padding: 10px;
text-align: left;
background: none;
border: none;
width: 100%;
font-size: 16px;
color: #333;
width: auto;
white-space: nowrap;
}
.help-button {
margin-right: auto;
background: none;
border: none;
font-size: 22px;
align-items: center;
justify-content: center;
}
.help-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index: 2000;
justify-content: center;
align-items: center;
opacity: 0;
transition: opacity 0.2s ease;
}
.help-overlay.show {
display: flex;
opacity: 1;
}
.help-overlay.hide {
opacity: 0;
}
.help-menu {
position: relative;
width: 75vw;
max-width: 800px;
background-color: white;
padding: 0 10px;
border-radius: 15px;
text-align: left;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
.close-help {
position: absolute;
top: 15px;
right: 12px;
background: none;
border: none;
font-size: 20px;
color: #ccc;
}
.help-content {
max-height: 85vh;
padding: 0 20px;
overflow-y: auto;
}
.help-content p {
font-size: 26px;
}
.help-content ul {
padding-left: 0;
list-style-type: none;
}
.help-content ul li {
font-weight: bold;
font-size: 18px;
}
.help-content ul ul li {
font-weight: normal;
font-size: 16px;
}
.help-content ul ul ul li {
color: #777777;
font-weight: normal;
font-size: 14px;
}
.help-content ul ul ul li a {
color: inherit;
}
.boot-hash-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1200;
justify-content: center;
align-items: center;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease, visibility 0.2s ease;
}
.boot-hash-card {
position: fixed;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
width: 80vw;
max-width: 600px;
background-color: #fff;
border-radius: 18px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
z-index: 1200;
padding: 20px;
display: none;
flex-direction: column;
gap: 15px;
opacity: 0;
transition: opacity 0.2s ease;
}
.boot-hash-overlay.show {
visibility: visible;
opacity: 1;
}
.boot-hash-card.show {
display: flex;
opacity: 1;
}
.input-box {
width: calc(100% - 20px);
height: 100px;
resize: none;
padding: 9px;
font-size: 16px;
background-color: #FFF;
border: 1px solid #ccc;
border-radius: 10px;
}
.button-container {
display: flex;
justify-content: flex-start;
}
.boot-hash-save-button {
padding: 10px 20px;
border: none;
border-radius: 38px;
font-size: 18px;
background-color: #007bff;
color: white;
margin-left: auto;
}
.about-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1100;
display: none;
justify-content: center;
align-items: center;
opacity: 0;
transition: opacity 0.2s ease;
}
.about-menu {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #fff;
border-radius: 8px;
padding: 25px 30px;
z-index: 1200;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
opacity: 0;
display: flex;
flex-direction: column;
gap: 15px;
transition: opacity 0.2s ease;
}
.close-about {
position: absolute;
top: 15px;
right: 12px;
background: none;
border: none;
font-size: 18px;
color: #ccc;
}
.about-content p {
margin: 0;
font-size: 16px;
text-align: left;
}
.about-content p[data-i18n="module_name_line1"] {
font-size: 26px;
}
.about-content p[data-i18n="module_name_line2"] {
font-size: 22px;
}
.about-content p span[data-i18n="by"] {
font-size: 14px;
}
.about-content p span[data-i18n="telegram_channel"] {
font-weight: bold;
}
.about-content p span[data-i18n="github"] {
font-weight: bold;
}
.about-content p[data-i18n="acknowledgment"] {
font-size: 18px;
text-align: left;
}
.about-content p:not([data-i18n]) {
font-size: 16px;
}
#apps-list {
margin-top: 100px;
}
.search-menu-container {
display: flex;
position: fixed;
top: 40px;
height: 50px;
width: calc(100% - 17px);
z-index: 1000;
transition: transform 0.3s ease;
}
.search-card {
background-color: white;
border: 1px solid #ccc;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
display: flex;
align-items: center;
border-radius: 50px;
left: 0;
height: calc(100% - 2px);
width: calc(100% - 60px);
position: absolute;
}
.search-icon {
position: absolute;
left: 18px;
font-size: 15px;
z-index: 1000;
}
.search-input {
position: absolute;
border: none;
font-size: 17px;
outline: none;
left: 10px;
padding: 0 30px;
width: calc(100% - 10);
}
.clear-btn {
position: absolute;
color: #ccc;
right: 10px;
border: none;
background: none;
font-size: 18px;
cursor: pointer;
display: none;
z-index: 10;
}
.menu {
display: flex;
right: 0;
position: absolute;
height: 100%;
}
.menu-toggle {
display: none;
}
#menu-button {
background-color: white;
border: 1px solid #ccc;
border-radius: 50%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
width: 48px;
display: flex;
justify-content: center;
align-items: center;
}
.menu-icon {
display: inline-block;
transition: transform 0.2s ease;
}
.menu-icon.menu-open {
transform: rotate(90deg);
}
.menu-icon.menu-closed {
transform: rotate(0deg);
}
.menu-options {
background-color: white;
border: 1px solid #ccc;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
display: none;
position: absolute;
padding: 5px;
top: 110%;
right: 0;
transform: translateX(120%);
transition: transform 0.2s ease;
width: auto;
white-space: nowrap;
}
#select-denylist {
display: none;
}
.menu-options.visible {
display: block;
transform: translateX(0);
}
.menu-options.hidden {
transform: translateX(140%);
}
.menu-options ul {
list-style: none;
margin: 0;
padding: 0;
}
.menu-options li {
cursor: default;
padding: 13px 12px;
text-align: left;
}
.card {
background-color: white;
border: none;
border-radius: 8px;
margin-bottom: 10px;
outline: none;
padding: 15px;
}
.content {
display: flex;
justify-content: space-between;
align-items: center;
}
.name {
display: inline-block;
margin: 0;
max-width: calc(100% - 30px);
overflow-wrap: break-word;
word-break: break-word;
}
.checkbox {
margin-left: auto;
}
.prompt {
position: fixed;
bottom: 0;
left: 10px;
background-color: #4CAF50;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
color: white;
font-size: 15px;
padding: 5px 15px;
z-index: 1000;
transform: translateY(100%);
transition: transform 0.5s ease;
white-space: nowrap;
}
.prompt.visible {
animation: YbounceIn 0.4s forwards;
}
.prompt.hidden {
animation: YbounceOut 0.4s forwards;
}
.prompt.error {
background-color: #f44336;
}
@keyframes YbounceIn {
0% {
transform: translateY(100%);
}
50% {
transform: translateY(-80%);
}
100% {
transform: translateY(-60%);
}
}
@keyframes YbounceOut {
0% {
transform: translateY(-60%);
}
50% {
transform: translateY(-80%);
}
100% {
transform: translateY(100%);
}
}
.floating-card {
display: flex;
justify-content: center;
position: fixed;
bottom: -70px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
}
.floating-btn {
flex-shrink: 0;
background-color: #007bff;
border: none;
box-shadow: 0 4px 8px #0003;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
padding: 12px 17px;
font-size: 17px;
transition: transform 0.3s ease-in-out;
border-top-left-radius: 50px;
border-top-right-radius: 50px;
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
}
.loading {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
color: #6E6E6E;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
z-index: 1000;
}
.footer {
padding: 25px;
position: relative;
}
.uninstall-container {
padding: 10px 10px;
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
display: flex;
align-items: center;
border-radius: 8px;
background-color: #B10000;
}
.uninstall-container i {
margin-right: 5px;
font-size: 18px;
color: #fff;
}
.uninstall-container span {
font-size: 16px;
font-weight: bold;
color: #fff;
}
.uninstall-container.hidden-uninstall {
display: none;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #121212;
color: #eee;
}
.header {
background-color: #121212;
}
.language-button,
.language-option,
.input-box,
.help-button {
color: #fff;
}
.help-menu,
.about-menu,
.boot-hash-card,
.card,
.search-input,
.search-card {
background-color: #343434;
}
.search-card {
border: 1px solid #6E6E6E;
}
.search-input {
color: white;
}
.language-menu,
.input-box,
.menu-options,
#menu-button {
background-color: #343434;
border: 1px solid #6E6E6E;
}
}

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.92,5.51h0L3.71,2.29A1,1,0,0,0,2.29,3.71L4.56,6A15.21,15.21,0,0,0,1.4,8.39a1,1,0,0,0,0,1.41,1,1,0,0,0,.71.3,1,1,0,0,0,.7-.29A13.07,13.07,0,0,1,6.05,7.46L7.54,9a10.78,10.78,0,0,0-3.32,2.27,1,1,0,1,0,1.42,1.4,8.8,8.8,0,0,1,3.45-2.12l1.62,1.61a7.07,7.07,0,0,0-3.66,1.94,1,1,0,1,0,1.42,1.4A5,5,0,0,1,12,14a4.13,4.13,0,0,1,.63.05l7.66,7.66a1,1,0,0,0,1.42,0,1,1,0,0,0,0-1.42ZM12,16a3,3,0,1,0,3,3A3,3,0,0,0,12,16Zm0,4a1,1,0,1,1,1-1A1,1,0,0,1,12,20ZM22.61,8.39A15,15,0,0,0,10.29,4.1a1,1,0,1,0,.22,2A13.07,13.07,0,0,1,21.2,9.81a1,1,0,0,0,1.41-1.42Zm-4.25,4.24a1,1,0,0,0,1.42-1.4,10.75,10.75,0,0,0-4.84-2.82,1,1,0,1,0-.52,1.92A8.94,8.94,0,0,1,18.36,12.63Z"/></svg>

Before

Width:  |  Height:  |  Size: 725 B

210
module/webui/index.html Normal file
View File

@@ -0,0 +1,210 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title data-i18n="title">TrickyAddon</title>
<link rel="stylesheet" href="styles/global.css" type="text/css">
<link rel="stylesheet" href="styles/about.css" type="text/css">
<link rel="stylesheet" href="styles/applist.css" type="text/css">
<link rel="stylesheet" href="styles/boot-hash.css" type="text/css">
<link rel="stylesheet" href="styles/header.css" type="text/css">
<link rel="stylesheet" href="styles/search_menu.css" type="text/css">
<link rel="stylesheet" type="text/css" href="/mmrl/insets.css" />
<script type="module" crossorigin src="scripts/main.js"></script>
</head>
<body>
<!-- Header -->
<div class="header-block"></div>
<div class="header">
<div id="title" data-i18n="header.title"></div>
<button id="help-button" class="help-button">
<svg xmlns="http://www.w3.org/2000/svg" height="21px" viewBox="0 -1060 960 990" width="21px" fill="#6E6E6E"><path d="M478-240q21 0 35.5-14.5T528-290q0-21-14.5-35.5T478-340q-21 0-35.5 14.5T428-290q0 21 14.5 35.5T478-240Zm-36-154h74q0-33 7.5-52t42.5-52q26-26 41-49.5t15-56.5q0-56-41-86t-97-30q-57 0-92.5 30T342-618l66 26q5-18 22.5-39t53.5-21q32 0 48 17.5t16 38.5q0 20-12 37.5T506-526q-44 39-54 59t-10 73Zm38 314q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z" /></svg>
</button>
<div class="no-connection">
<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -920 960 960" width="20px" fill="#6E6E6E"><path d="M790-56 414-434q-47 11-87.5 33T254-346l-84-86q32-32 69-56t79-42l-90-90q-41 21-76.5 46.5T84-516L0-602q32-32 66.5-57.5T140-708l-84-84 56-56 736 736-58 56Zm-310-64q-42 0-71-29.5T380-220q0-42 29-71t71-29q42 0 71 29t29 71q0 41-29 70.5T480-120Zm236-238-29-29-29-29-144-144q81 8 151.5 41T790-432l-74 74Zm160-158q-77-77-178.5-120.5T480-680q-21 0-40.5 1.5T400-674L298-776q44-12 89.5-18t92.5-6q142 0 265 53t215 145l-84 86Z" /></svg>
</div>
<div class="language-dropdown">
<button class="language-button">
<i class="language-icon">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="M480-80q-82 0-155-31.5t-127.5-86Q143-252 111.5-325T80-480q0-83 31.5-155.5t86-127Q252-817 325-848.5T480-880q83 0 155.5 31.5t127 86q54.5 54.5 86 127T880-480q0 82-31.5 155t-86 127.5q-54.5 54.5-127 86T480-80Zm0-82q26-36 45-75t31-83H404q12 44 31 83t45 75Zm-104-16q-18-33-31.5-68.5T322-320H204q29 50 72.5 87t99.5 55Zm208 0q56-18 99.5-55t72.5-87H638q-9 38-22.5 73.5T584-178ZM170-400h136q-3-20-4.5-39.5T300-480q0-21 1.5-40.5T306-560H170q-5 20-7.5 39.5T160-480q0 21 2.5 40.5T170-400Zm216 0h188q3-20 4.5-39.5T580-480q0-21-1.5-40.5T574-560H386q-3 20-4.5 39.5T380-480q0 21 1.5 40.5T386-400Zm268 0h136q5-20 7.5-39.5T800-480q0-21-2.5-40.5T790-560H654q3 20 4.5 39.5T660-480q0 21-1.5 40.5T654-400Zm-16-240h118q-29-50-72.5-87T584-782q18 33 31.5 68.5T638-640Zm-234 0h152q-12-44-31-83t-45-75q-26 36-45 75t-31 83Zm-200 0h118q9-38 22.5-73.5T376-782q-56 18-99.5 55T204-640Z"/></svg>
</i>
</button>
<div class="language-menu"></div>
<div id="language-overlay" class="language-overlay"></div>
</div>
</div>
<!-- Loading Element -->
<div class="loading" data-i18n="loading.loading"></div>
<!-- Prompt Element -->
<div id="prompt" class="prompt"></div>
<!-- Floating Button Element -->
<div class="floating-card">
<button class="floating-btn" id="save" data-i18n="functional_button.save_and_update_button"></button>
</div>
<!-- Menu Options -->
<div class="search-menu-container">
<div class="search-card">
<span class="search-icon">
<svg xmlns="http://www.w3.org/2000/svg" height="19px" viewBox="0 -960 960 960" width="24px" fill="#6E6E6E"><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z" /></svg>
</span>
<input type="text" class="search-input" id="search" placeholder="" data-i18n="search_bar.search_placeholder">
<button class="clear-btn" id="clear-btn">&#x2715;</button>
</div>
<div class="menu">
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<label for="menu-toggle" id="menu-button">
<i class="menu-icon">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -1060 960 960" width="24px"><path d="M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z"/></svg>
</i>
</label>
<div id="menu-options" class="menu-options">
<ul>
<li id="refresh" data-i18n="menu.refresh"></li>
<li id="select-all" data-i18n="menu.select_all"></li>
<li id="deselect-all" data-i18n="menu.deselect_all"></li>
<li id="select-denylist" data-i18n="menu.select_denylist"></li>
<li id="deselect-unnecessary" data-i18n="menu.deselect_unnecessary"></li>
<li id="aospkb" data-i18n="menu.set_aosp_keybox"></li>
<li id="extrakb" data-i18n="menu.set_valid_keybox"></li>
<li id="boot-hash" data-i18n="menu.set_verified_boot_hash"></li>
<li id="about" data-i18n="menu.about"></li>
</ul>
</div>
</div>
<div id="menu-overlay" class="menu-overlay"></div>
</div>
<!-- Applist Display -->
<div id="apps-list"></div>
<div class="update-card" id="update-card">
<p id="update-available" data-i18n="update_banner.update_available"></p>
<p id="redirect-to-release" data-i18n="update_banner.redirect_to_release"></p>
</div>
<template id="app-template">
<div class="card-box">
<div class="card">
<div class="content" data-package="">
<p class="name"></p>
<input type="checkbox" class="checkbox">
</div>
</div>
</div>
</template>
<!-- Help Overlay -->
<div id="help-overlay" class="help-overlay">
<div class="help-menu">
<button id="close-help" class="close-help">&#x2715;</button>
<div class="help-content">
<p data-i18n="help.help_instructions"></p>
<ul id="helpList">
<li id="save_and_update_button">
<strong data-i18n="help.save_and_update"></strong>
<ul>
<li data-i18n="help.save_and_update_description"></li>
</ul>
</li>
<br>
<li id="refresh">
<strong data-i18n="help.refresh"></strong>
<ul>
<li data-i18n="help.refresh_description"></li>
</ul>
</li>
<br>
<li id="select_deselect">
<strong data-i18n="help.select_deselect"></strong>
<ul>
<li data-i18n="help.select_description"></li>
</ul>
</li>
<br>
<li id="select_denylist">
<strong data-i18n="help.select_denylist"></strong>
<ul>
<li data-i18n="help.select_denylist_description"></li>
</ul>
</li>
<br>
<li id="deselect_unnecessary">
<strong data-i18n="help.deselect_unnecessary"></strong>
<ul>
<li data-i18n="help.deselect_unnecessary_description"></li>
</ul>
</li>
<br>
<li id="set_keybox">
<strong data-i18n="help.set_keybox"></strong>
<ul>
<li data-i18n="help.set_keybox_description"></li>
</ul>
</li>
<br>
<li id="set_verified_boot_hash">
<strong data-i18n="help.set_verified_boot_hash"></strong>
<ul>
<li data-i18n="help.set_verified_boot_hash_description"></li>
</ul>
</li>
<br>
</ul>
</div>
</div>
</div>
<!-- BootHash Input Overlay -->
<div id="boot-hash-overlay" class="boot-hash-overlay"></div>
<div id="boot-hash-card" class="boot-hash-card">
<textarea id="boot-hash-input" class="input-box" placeholder="Paste your verified Boot Hash here" data-i18n="reset_vbmeta.boot_hash_input_placeholder"></textarea>
<div class="button-container">
<button id="boot-hash-save-button" class="boot-hash-save-button" data-i18n="reset_vbmeta.boot_hash_save_button"></button>
</div>
</div>
<!-- About Overlay -->
<div id="about-overlay" class="about-overlay">
<div id="about-menu" class="about-menu">
<button id="close-about" class="close-about">&#x2715;</button>
<div class="about-content">
<p id="module_name_line1" data-i18n="about.module_name_line1"></p>
<p id="module_name_line2" data-i18n="about.module_name_line2"></p>
<p><span id="authored" data-i18n="about.by"></span> KOWX712</p>
<br>
<p id="disclaimer" data-i18n="about.disclaimer"></p>
<br>
<p>
<div class="link">
<i class="link-icon" id="telegram" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 0 496 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M248 8C111 8 0 119 0 256S111 504 248 504 496 393 496 256 385 8 248 8zM363 176.7c-3.7 39.2-19.9 134.4-28.1 178.3-3.5 18.6-10.3 24.8-16.9 25.4-14.4 1.3-25.3-9.5-39.3-18.7-21.8-14.3-34.2-23.2-55.3-37.2-24.5-16.1-8.6-25 5.3-39.5 3.7-3.8 67.1-61.5 68.3-66.7 .2-.7 .3-3.1-1.2-4.4s-3.6-.8-5.1-.5q-3.3 .7-104.6 69.1-14.8 10.2-26.9 9.9c-8.9-.2-25.9-5-38.6-9.1-15.5-5-27.9-7.7-26.8-16.3q.8-6.7 18.5-13.7 108.4-47.2 144.6-62.3c68.9-28.6 83.2-33.6 92.5-33.8 2.1 0 6.6 .5 9.6 2.9a10.5 10.5 0 0 1 3.5 6.7A43.8 43.8 0 0 1 363 176.7z"/></svg>
<span id="link-text" data-i18n="about.telegram_channel"></span>
</i>
<i class="link-icon" id="github" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 0 496 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
<span id="link-text" data-i18n="about.github"></span>
</i>
</div>
</p>
<br>
<p id="acknowledgment" data-i18n="about.acknowledgment"></p>
<p>j-hc/zygisk-detach: WebUI template</p>
</div>
</div>
</div>
<!-- Footer -->
<div class="footer">
<div class="uninstall-container hidden-uninstall">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#FFFFFF"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z" /></svg>
<span data-i18n="functional_button.uninstall_webui"></span>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,75 @@
{
"language": "English",
"header": {
"title": "Tricky Addon - Update Target List"
},
"help": {
"help_instructions": "Instructions",
"save_and_update": "Save",
"save_and_update_description": "Save current configure to target.txt.",
"refresh": "Refresh",
"refresh_description": "Refresh app list and exclude list.",
"select_deselect": "Select & Deselect All",
"select_description": "Select or deselect all apps in the current interface.",
"select_denylist": "Select From DenyList",
"select_denylist_description": "Available in Magisk only, select apps that are in the DenyList. Recommended.",
"deselect_unnecessary": "Deselect Unnecessary",
"deselect_unnecessary_description": "Unnecessary category: Xposed module, root manager, root-related apps, and general apps that never check bootloader status. This option requires an Internet connection.",
"set_keybox": "Set AOSP & Valid Keybox",
"set_keybox_description": "Replace tricky store keybox.xml. AOSP keybox will be replaced if there's no more valid keybox. Valid keybox option requires Internet connection.",
"set_verified_boot_hash": "Set Verified Boot Hash",
"set_verified_boot_hash_description": "Get verifiedBootHash value from Key Attestation Demo. Fix abnormal boot state by resetting ro.boot.vbmeta.digest."
},
"update_banner": {
"update_available": "A new version is ready",
"redirect_to_release": "tap to download the latest version"
},
"search_bar": {
"search_placeholder": "Search"
},
"functional_button": {
"save_and_update_button": "Save",
"uninstall_webui": "Uninstall WebUI"
},
"loading": {
"loading": "Loading..."
},
"menu": {
"refresh": "Refresh",
"select_all": "Select All",
"deselect_all": "Deselect All",
"select_denylist": "Select From DenyList",
"deselect_unnecessary": "Deselect Unnecessary",
"set_aosp_keybox": "Set AOSP Keybox",
"set_valid_keybox": "Set Valid Keybox",
"set_verified_boot_hash": "Set Verified Boot Hash",
"about": "About"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Paste your verified Boot Hash here",
"boot_hash_save_button": "Save"
},
"about": {
"module_name_line1": "Tricky Addon",
"module_name_line2": "Update Target List",
"by": "by",
"telegram_channel": "Telegram Channel",
"github": "GitHub",
"disclaimer": "This module is not a part of the Tricky Store module. DO NOT report any issues to Tricky Store if encountered.",
"acknowledgment": "Acknowledgment"
},
"prompt": {
"no_internet": "Please check your Internet connection",
"aosp_key_set": "AOSP keybox set successfully",
"key_set_error": "Failed to update keybox",
"valid_key_set": "Valid keybox set successfully",
"no_valid_fallback": "No valid keybox found, replaced with AOSP keybox.",
"boot_hash_set": "Verified Boot Hash saved successfully",
"boot_hash_set_error": "Failed to update Verified Boot Hash",
"saved_target": "Config saved to target.txt",
"save_error": "Failed to save config",
"uninstall_prompt": "WebUI will be removed after reboot",
"uninstall_failed": "Failed to uninstall WebUI",
"new_update": "A new update is available!"
}
}

View File

@@ -0,0 +1,18 @@
# Translation Guide
## Fix Bad Translation
1. Fork this repository.
2. Find your language string file in `/module/webroot/locales/`.
3. Edit the string value with translated incorrectly.
4. Create a Pull Request.
---
## Add a New Language
### Simple
- Contact me in Telegram to add a new translation langauge.
### Advanced
1. Fork this repository.
2. Make a copy of `/module/webroot/locales/A-template.json`
3. Rename it to `language_code-COUNTRY_CODE.json`, e.g., `en-US.json`.
4. Translate the string value inside.
6. Create a Pull Request.

View File

@@ -0,0 +1,75 @@
{
"language": "English",
"header": {
"title": "Tricky Addon - Update Target List"
},
"help": {
"help_instructions": "Instructions",
"save_and_update": "Save",
"save_and_update_description": "Save current configure to target.txt.",
"refresh": "Refresh",
"refresh_description": "Refresh app list and exclude list.",
"select_deselect": "Select & Deselect All",
"select_description": "Select or deselect all apps in the current interface.",
"select_denylist": "Select From DenyList",
"select_denylist_description": "Available in Magisk only, select apps that are in the DenyList. Recommended.",
"deselect_unnecessary": "Deselect Unnecessary",
"deselect_unnecessary_description": "Unnecessary category: Xposed module, root manager, root-related apps, and general apps that never check bootloader status. This option requires an Internet connection.",
"set_keybox": "Set AOSP & Valid Keybox",
"set_keybox_description": "Replace tricky store keybox.xml. AOSP keybox will be replaced if there's no more valid keybox. Valid keybox option requires Internet connection.",
"set_verified_boot_hash": "Set Verified Boot Hash",
"set_verified_boot_hash_description": "Get verifiedBootHash value from Key Attestation Demo. Fix abnormal boot state by resetting ro.boot.vbmeta.digest."
},
"update_banner": {
"update_available": "A new version is ready",
"redirect_to_release": "tap to download the latest version"
},
"search_bar": {
"search_placeholder": "Search"
},
"functional_button": {
"save_and_update_button": "Save",
"uninstall_webui": "Uninstall WebUI"
},
"loading": {
"loading": "Loading..."
},
"menu": {
"refresh": "Refresh",
"select_all": "Select All",
"deselect_all": "Deselect All",
"select_denylist": "Select From DenyList",
"deselect_unnecessary": "Deselect Unnecessary",
"set_aosp_keybox": "Set AOSP Keybox",
"set_valid_keybox": "Set Valid Keybox",
"set_verified_boot_hash": "Set Verified Boot Hash",
"about": "About"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Paste your verified Boot Hash here",
"boot_hash_save_button": "Save"
},
"about": {
"module_name_line1": "Tricky Addon",
"module_name_line2": "Update Target List",
"by": "by",
"telegram_channel": "Telegram Channel",
"github": "GitHub",
"disclaimer": "This module is not a part of the Tricky Store module. DO NOT report any issues to Tricky Store if encountered.",
"acknowledgment": "Acknowledgment"
},
"prompt": {
"no_internet": "Please check your Internet connection",
"aosp_key_set": "AOSP keybox set successfully",
"key_set_error": "Failed to update keybox",
"valid_key_set": "Valid keybox set successfully",
"no_valid_fallback": "No valid keybox found, replaced with AOSP keybox.",
"boot_hash_set": "Verified Boot Hash saved successfully",
"boot_hash_set_error": "Failed to update Verified Boot Hash",
"saved_target": "Config saved to target.txt",
"save_error": "Failed to save config",
"uninstall_prompt": "WebUI will be removed after reboot",
"uninstall_failed": "Failed to uninstall WebUI",
"new_update": "A new update is available!"
}
}

View File

@@ -0,0 +1,75 @@
{
"language": "Español",
"header": {
"title": "Tricky Addon - Update Target List"
},
"help": {
"help_instructions": "Instrucciones",
"save_and_update": "Guardar",
"save_and_update_description": "Guardar la configuración actual en target.txt.",
"refresh": "Actualizar",
"refresh_description": "Actualizar lista de aplicaciones y lista de exclusión.",
"select_deselect": "Seleccionar y Deseleccionar Todo",
"select_description": "Seleccionar o deseleccionar todas las aplicaciones en la interfaz actual.",
"select_denylist": "Seleccionar desde DenyList",
"select_denylist_description": "Disponible solo en Magisk, selecciona aplicaciones que están en la DenyList. Recomendado.",
"deselect_unnecessary": "Deseleccionar innecesarios",
"deselect_unnecessary_description": "Categorías innecesarias: módulos Xposed, gestores de root, aplicaciones relacionadas con root y aplicaciones generales que nunca verifican el estado del bootloader. Esta opción requiere conexión a Internet.",
"set_keybox": "Configurar AOSP y Keybox Válido",
"set_keybox_description": "Reemplazar el archivo keybox.xml de Tricky Store. El AOSP Keybox será reemplazado si no hay un keybox válido. Esta opción requiere conexión a Internet.",
"set_verified_boot_hash": "Configurar Boot Hash Verificado",
"set_verified_boot_hash_description": "Obtén el valor de verifiedBootHash del Key Attestation Demo. Corrige un estado de arranque anormal reiniciando ro.boot.vbmeta.digest."
},
"update_banner": {
"update_available": "Una nueva versión está lista",
"redirect_to_release": "toca para descargar la última versión"
},
"search_bar": {
"search_placeholder": "Buscar"
},
"functional_button": {
"save_and_update_button": "Guardar",
"uninstall_webui": "Desinstalar WebUI"
},
"loading": {
"loading": "Cargando..."
},
"menu": {
"refresh": "Actualizar",
"select_all": "Seleccionar Todo",
"deselect_all": "Deseleccionar Todo",
"select_denylist": "Seleccionar desde DenyList",
"deselect_unnecessary": "Deseleccionar innecesarios",
"set_aosp_keybox": "Configurar AOSP Keybox",
"set_valid_keybox": "Configurar Keybox Válido",
"set_verified_boot_hash": "Configurar Boot Hash Verificado",
"about": "Acerca de"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Pega aquí tu Boot Hash verificado",
"boot_hash_save_button": "Guardar"
},
"about": {
"module_name_line1": "Tricky Addon",
"module_name_line2": "Update Target List",
"by": "por",
"telegram_channel": "Canal de Telegram",
"github": "GitHub",
"disclaimer": "Este módulo no es parte del módulo Tricky Store. NO reportes problemas al autor de Tricky Store si los encuentras.",
"acknowledgment": "Agradecimientos"
},
"prompt": {
"no_internet": "Por favor, verifica tu conexión a Internet",
"aosp_key_set": "AOSP Keybox configurado correctamente",
"key_set_error": "Error al actualizar el Keybox",
"valid_key_set": "Keybox válido configurado correctamente",
"no_valid_fallback": "No se encontró un keybox válido, reemplazado con AOSP Keybox.",
"boot_hash_set": "Boot Hash verificado guardado correctamente",
"boot_hash_set_error": "Error al actualizar el Boot Hash verificado",
"saved_target": "Configuración guardada en target.txt",
"save_error": "Error al guardar la configuración",
"uninstall_prompt": "El WebUI se eliminará después de reiniciar",
"uninstall_failed": "Error al desinstalar el WebUI",
"new_update": "¡Una nueva actualización está disponible!"
}
}

View File

@@ -0,0 +1,75 @@
{
"language": "日本語",
"header": {
"title": "Tricky Addon - Update Target List"
},
"help": {
"help_instructions": "使い方",
"save_and_update": "保存",
"save_and_update_description": "現在の設定を target.txt に保存します。",
"refresh": "更新",
"refresh_description": "アプリリストと除外リストを更新します。",
"select_deselect": "すべてを選択と解除",
"select_description": "現在のインターフェースのすべてのアプリを選択または解除します。",
"select_denylist": "DenyList から選択",
"select_denylist_description": "Magisk の環境でのみ使用可能です。Deny List 内のアプリを選択します(推奨)。",
"deselect_unnecessary": "不要な選択を解除",
"deselect_unnecessary_description": "不要なカテゴリー: Xposed モジュール、root マネージャー、root 関連アプリ、Bootloader の状態を確認しない一般的なアプリです。このオプションはインターネット接続が必要です。",
"set_keybox": "AOSP と 有効な Keybox",
"set_keybox_description": "Tricky Store の keybox.xml を置き換えます。有効な Keybox がなくなった場合は、AOSP Keybox に置き換えられます。インターネット接続が必要です。",
"set_verified_boot_hash": "確認付きブートハッシュを設定",
"set_verified_boot_hash_description": "Key Attestation Demo から確認付きブートハッシュの値を取得します。ro.boot.vbmeta.digest をリセットして異常なブート状態を修正します。"
},
"update_banner": {
"update_available": "新しいバージョンの準備完了",
"redirect_to_release": "タップで最新のバージョンをダウンロード"
},
"search_bar": {
"search_placeholder": "検索"
},
"functional_button": {
"save_and_update_button": "保存",
"uninstall_webui": "WebUI をアンインストール"
},
"loading": {
"loading": "読み込み中..."
},
"menu": {
"refresh": "更新",
"select_all": "すべて選択",
"deselect_all": "すべての選択を解除",
"select_denylist": "DenyList から選択",
"deselect_unnecessary": "不要な選択を解除",
"set_aosp_keybox": "AOSP Keybox を設定",
"set_valid_keybox": "有効な Keybox を設定",
"set_verified_boot_hash": "確認付きブートハッシュを設定",
"about": "このアドオンについて"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "確認付きブートハッシュをここに貼り付け",
"boot_hash_save_button": "保存"
},
"about": {
"module_name_line1": "Tricky Addon",
"module_name_line2": "Update Target List",
"by": "開発者: ",
"telegram_channel": "Telegram チャンネル",
"github": "GitHub",
"disclaimer": "このモジュールは、Tricky Store モジュールの一部ではありません。Tricky Store 公式に問題を報告しないでください。",
"acknowledgment": "謝辞"
},
"prompt": {
"no_internet": "インターネット接続を確認してください。",
"aosp_key_set": "AOSP Keybox の設定に成功しました。",
"key_set_error": "Keybox の更新に失敗しました。",
"valid_key_set": "有効な Keybox の設定に成功しました。",
"no_valid_fallback": "有効な Keybox がありません。AOSP Keybox に置き換えます。",
"boot_hash_set": "確認付きブートハッシュの更新に成功しました。",
"boot_hash_set_error": "確認付きブートハッシュの更新に失敗しました。",
"saved_target": "設定を target.txt に保存しました。",
"save_error": "設定の保存に失敗しました。",
"uninstall_prompt": "WebUI は再起動後に削除されます。",
"uninstall_failed": "WebUI のアンインストールに失敗しました。",
"new_update": "新しいバージョンがあります!"
}
}

View File

@@ -0,0 +1,75 @@
{
"language": "Русский",
"header": {
"title": "Tricky Addon - Обновить список целей"
},
"help": {
"help_instructions": "Инструкции",
"save_and_update": "Сохранить",
"save_and_update_description": "Сохранить текущую конфигурацию в target.txt.",
"refresh": "Обновить",
"refresh_description": "Обновить список приложений и список исключений.",
"select_deselect": "Выбрать и отменить выбор всех",
"select_description": "Выбрать или отменить выбор всех приложений в текущем интерфейсе.",
"select_denylist": "Выбрать из DenyList",
"select_denylist_description": "Доступно только в Magisk, выберите приложения, которые находятся в DenyList. Рекомендуется.",
"deselect_unnecessary": "Отменить выбор ненужных",
"deselect_unnecessary_description": "Ненужные категории: модули Xposed, менеджеры root, приложения, связанные с root, и общие приложения, которые никогда не проверяют статус загрузчика. Этот параметр требует подключения к интернету.",
"set_keybox": "Установить AOSP и действующий Keybox",
"set_keybox_description": "Замените tricky store keybox.xml. AOSP keybox будет заменен, если не будет найден действующий keybox. Опция с действующим keybox требует подключения к интернету.",
"set_verified_boot_hash": "Установить Verified Boot Hash",
"set_verified_boot_hash_description": "Получите значение verifiedBootHash из Key Attestation Demo. Исправьте аномальное состояние загрузки, сбросив ro.boot.vbmeta.digest."
},
"update_banner": {
"update_available": "Доступна новая версия",
"redirect_to_release": "нажмите, чтобы скачать последнюю версию"
},
"search_bar": {
"search_placeholder": "Поиск"
},
"functional_button": {
"save_and_update_button": "Сохранить",
"uninstall_webui": "Удалить WebUI"
},
"loading": {
"loading": "Загрузка..."
},
"menu": {
"refresh": "Обновить",
"select_all": "Выбрать все",
"deselect_all": "Отменить выбор всех",
"select_denylist": "Выбрать из DenyList",
"deselect_unnecessary": "Отменить выбор ненужных",
"set_aosp_keybox": "Установить AOSP Keybox",
"set_valid_keybox": "Установить действующий Keybox",
"set_verified_boot_hash": "Установить Verified Boot Hash",
"about": "О программе"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Вставьте свой проверенный Boot Hash сюда",
"boot_hash_save_button": "Сохранить"
},
"about": {
"module_name_line1": "Tricky Addon",
"module_name_line2": "Обновить список целей",
"by": "от",
"telegram_channel": "Канал в Telegram",
"github": "GitHub",
"disclaimer": "Этот WebUI не является частью Tricky Store, НЕ сообщайте автору Tricky Store о любых возникающих проблемах.",
"acknowledgment": "Благодарности"
},
"prompt": {
"no_internet": "Пожалуйста, проверьте ваше подключение к интернету",
"aosp_key_set": "AOSP keybox успешно установлен",
"key_set_error": "Не удалось обновить keybox",
"valid_key_set": "Действующий keybox успешно установлен",
"no_valid_fallback": "Не найден действующий keybox, заменен на AOSP keybox.",
"boot_hash_set": "Verified Boot Hash успешно сохранен",
"boot_hash_set_error": "Не удалось обновить Verified Boot Hash",
"saved_target": "Конфигурация сохранена в target.txt",
"save_error": "Не удалось сохранить конфигурацию",
"uninstall_prompt": "WebUI будет удален после перезагрузки",
"uninstall_failed": "Не удалось удалить WebUI",
"new_update": "Доступно новое обновление!"
}
}

View File

@@ -0,0 +1,75 @@
{
"language": "Tagalog",
"header": {
"title": "Tricky Addon - I-update ang Target List"
},
"help": {
"help_instructions": "Mga Tagubilin",
"save_and_update": "I-save",
"save_and_update_description": "I-save ang kasalukuyang configuration sa target.txt.",
"refresh": "I-refresh",
"refresh_description": "I-refresh ang listahan ng apps at exclude list.",
"select_deselect": "Piliin & Huwag Pumili ng Lahat",
"select_description": "Piliin o huwag piliin ang lahat ng apps sa kasalukuyang interface.",
"select_denylist": "Piliin mula sa DenyList",
"select_denylist_description": "Available lang sa Magisk, piliin ang mga app na nasa DenyList. Inirerekomenda.",
"deselect_unnecessary": "Huwag Pumili ng Hindi Kinakailangan",
"deselect_unnecessary_description": "Hindi kinakailangang kategorya: Xposed module, root manager, root-related apps, at mga karaniwang apps na hindi kailanman nire-refresh ang bootloader status. Nangangailangan ng koneksyon sa internet.",
"set_keybox": "I-set ang AOSP at Valid Keybox",
"set_keybox_description": "Palitan ang tricky store keybox.xml. Palitan ang AOSP keybox kung walang valid keybox. Nangangailangan ng koneksyon sa internet ang valid keybox option.",
"set_verified_boot_hash": "I-set ang Verified Boot Hash",
"set_verified_boot_hash_description": "Kunin ang verifiedBootHash mula sa Key Attestation Demo. Ayusin ang abnormal na boot state sa pamamagitan ng pag-reset ng ro.boot.vbmeta.digest."
},
"update_banner": {
"update_available": "Handa na ang bagong bersyon",
"redirect_to_release": "i-tap para i-download ang pinakabagong bersyon"
},
"search_bar": {
"search_placeholder": "Maghanap"
},
"functional_button": {
"save_and_update_button": "I-save",
"uninstall_webui": "I-uninstall ang WebUI"
},
"loading": {
"loading": "Naglo-load..."
},
"menu": {
"refresh": "I-refresh",
"select_all": "Piliin Lahat",
"deselect_all": "Huwag Pumili ng Lahat",
"select_denylist": "Piliin mula sa DenyList",
"deselect_unnecessary": "Huwag Pumili ng Hindi Kinakailangan",
"set_aosp_keybox": "I-set ang AOSP Keybox",
"set_valid_keybox": "I-set ang Valid Keybox",
"set_verified_boot_hash": "I-set ang Verified Boot Hash",
"about": "Tungkol"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "I-paste ang iyong verified Boot Hash dito",
"boot_hash_save_button": "I-save"
},
"about": {
"module_name_line1": "Tricky Addon",
"module_name_line2": "I-update ang Target List",
"by": "ni",
"telegram_channel": "Telegram Channel",
"github": "GitHub",
"disclaimer": "Ang WebUI na ito ay hindi bahagi ng Tricky Store, HUWAG i-report sa may-akda ng Tricky Store kung makaranas ka ng anumang isyu.",
"acknowledgment": "Pagkilala"
},
"prompt": {
"no_internet": "Pakitingnan ang iyong koneksyon sa Internet",
"aosp_key_set": "Matagumpay na na-set ang AOSP Keybox",
"key_set_error": "Nabigong i-update ang keybox",
"valid_key_set": "Matagumpay na na-set ang Valid Keybox",
"no_valid_fallback": "Walang valid na keybox na natagpuan, pinalitan ng AOSP keybox.",
"boot_hash_set": "Matagumpay na na-save ang Verified Boot Hash",
"boot_hash_set_error": "Nabigong i-update ang Verified Boot Hash",
"saved_target": "Na-save ang configuration sa target.txt",
"save_error": "Nabigong i-save ang config",
"uninstall_prompt": "Mawawala ang WebUI pagkatapos ng reboot",
"uninstall_failed": "Nabigong i-uninstall ang WebUI",
"new_update": "May bagong update na available!"
}
}

View File

@@ -0,0 +1,75 @@
{
"language": "中文(简体)",
"header": {
"title": "TS插件 - 更新目标列表"
},
"help": {
"help_instructions": "使用指南",
"save_and_update": "保存",
"save_and_update_description": "保存当前配置到目标列表target.txt。",
"refresh": "刷新",
"refresh_description": "刷新应用列表和排除列表。",
"select_deselect": "全选 & 取消全选",
"select_description": "选择或取消选择当前界面中的所有应用。",
"select_denylist": "从排除列表中选择",
"select_denylist_description": "仅适用于 Magisk选择在排除列表中的应用。推荐使用。",
"deselect_unnecessary": "取消选择非必应用",
"deselect_unnecessary_description": "非必要分类Xposed 模块、root 管理器、与 root 相关的应用,以及从不检查 bootloader 状态的通用应用。此功能需连网使用。",
"set_keybox": "设置 AOSP & 有效密钥",
"set_keybox_description": "替换 Tricky Store 的密钥keybox.xml。如果没有有效密钥将替换为 AOSP 密钥。有效密钥选项需连网使用。",
"set_verified_boot_hash": "设置哈希值",
"set_verified_boot_hash_description": "从 Key Attestation Demo 获取 verifiedBootHash哈希值。通过重置 ro.boot.vbmeta.digest 修复异常 boot 状态。"
},
"update_banner": {
"update_available": "发现新的版本",
"redirect_to_release": "点击跳转 GitHub 下载最新版本"
},
"search_bar": {
"search_placeholder": "搜索"
},
"functional_button": {
"save_and_update_button": "保存",
"uninstall_webui": "卸载 WebUI"
},
"loading": {
"loading": "加载中..."
},
"menu": {
"refresh": "刷新",
"select_all": "全选",
"deselect_all": "取消全选",
"select_denylist": "从排除列表中选择",
"deselect_unnecessary": "取消选择非必应用",
"set_aosp_keybox": "设置 AOSP 密钥",
"set_valid_keybox": "设置有效密钥",
"set_verified_boot_hash": "设置哈希值",
"about": "关于"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "在此粘贴您的哈希值",
"boot_hash_save_button": "保存"
},
"about": {
"module_name_line1": "TS插件",
"module_name_line2": "更新目标列表",
"by": "作者:",
"telegram_channel": "TG频道",
"github": "GitHub",
"disclaimer": "此 WebUI 不是 Tricky Store 的一部分,遇到任何问题请勿向 Tricky Store 作者反馈。",
"acknowledgment": "特别鸣谢"
},
"prompt": {
"no_internet": "请检查您的网络连接",
"aosp_key_set": "成功设置 AOSP 密钥",
"key_set_error": "更新密钥失败",
"valid_key_set": "成功设置有效密钥",
"no_valid_fallback": "未找到有效密钥,已替换为 AOSP 密钥。",
"boot_hash_set": "哈希值重置成功",
"boot_hash_set_error": "哈希值重置失败",
"saved_target": "成功保存配置",
"save_error": "保存配置失败",
"uninstall_prompt": "WebUI 将在重启后被移除",
"uninstall_failed": "卸载 WebUI 失败",
"new_update": "发现新的版本!"
}
}

View File

@@ -0,0 +1,75 @@
{
"language": "中文(繁体)",
"header": {
"title": "TS插件 - 更新目標列表"
},
"help": {
"help_instructions": "使用指南",
"save_and_update": "保存",
"save_and_update_description": "保存當前配置到目標列表target.txt。",
"refresh": "刷新",
"refresh_description": "刷新應用列表和排除列表。",
"select_deselect": "全選 & 取消全選",
"select_description": "選擇或取消選擇當前界面中的所有應用。",
"select_denylist": "從排除列表中選擇",
"select_denylist_description": "僅適用於 Magisk選擇在排除列表中的應用。推薦使用。",
"deselect_unnecessary": "取消選擇非必應用",
"deselect_unnecessary_description": "非必要分類Xposed 模塊、root 管理器、與 root 相關的應用,以及從不檢查 bootloader 狀態的通用應用。此功能需連網使用。",
"set_keybox": "設置 AOSP & 有效密鑰",
"set_keybox_description": "替換 Tricky Store 的密鑰keybox.xml。如果沒有有效密鑰將替換為 AOSP 密鑰。有效密鑰選項需連網使用。",
"set_verified_boot_hash": "設置哈希值",
"set_verified_boot_hash_description": "從 Key Attestation Demo 獲取 verifiedBootHash哈希值。通過重置 ro.boot.vbmeta.digest 修復異常 boot 狀態。"
},
"update_banner": {
"update_available": "發現新的版本",
"redirect_to_release": "點擊跳轉至 GitHub 下載最新版本"
},
"search_bar": {
"search_placeholder": "搜尋"
},
"functional_button": {
"save_and_update_button": "保存",
"uninstall_webui": "卸載 WebUI"
},
"loading": {
"loading": "加載中..."
},
"menu": {
"refresh": "刷新",
"select_all": "全選",
"deselect_all": "取消全選",
"select_denylist": "從排除列表中選擇",
"deselect_unnecessary": "取消選擇非必應用",
"set_aosp_keybox": "設置 AOSP 密鑰",
"set_valid_keybox": "設置有效密鑰",
"set_verified_boot_hash": "設置哈希值",
"about": "關於"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "在此粘貼您的哈希值",
"boot_hash_save_button": "保存"
},
"about": {
"module_name_line1": "TS插件",
"module_name_line2": "更新目標列表",
"by": "作者:",
"telegram_channel": "TG頻道",
"github": "GitHub",
"disclaimer": "此 WebUI 不是 Tricky Store 的一部分,遇到任何問題請勿向 Tricky Store 作者反饋。",
"acknowledgment": "特別鳴謝"
},
"prompt": {
"no_internet": "請檢查您的網路連接",
"aosp_key_set": "成功設置 AOSP 密鑰",
"key_set_error": "更新密鑰失敗",
"valid_key_set": "成功設置有效密鑰",
"no_valid_fallback": "未找到有效密鑰,已替換為 AOSP 密鑰。",
"boot_hash_set": "哈希值重置成功",
"boot_hash_set_error": "哈希值重置失敗",
"saved_target": "成功保存配置",
"save_error": "保存配置失敗",
"uninstall_prompt": "WebUI 將在重啟後被移除",
"uninstall_failed": "卸載 WebUI 失敗",
"new_update": "發現新的版本!"
}
}

View File

@@ -0,0 +1,54 @@
import { execCommand } from './main.js';
const telegramLink = document.getElementById('telegram');
const githubLink = document.getElementById('github');
// Function to show about overlay
export function aboutMenu() {
const aboutOverlay = document.getElementById('about-overlay');
const aboutMenu = document.getElementById('about-menu');
const closeAbout = document.getElementById('close-about');
const showMenu = () => {
aboutOverlay.style.display = 'flex';
setTimeout(() => {
aboutOverlay.style.opacity = '1';
aboutMenu.style.opacity = '1';
}, 10);
document.body.style.overflow = 'hidden';
};
const hideMenu = () => {
aboutOverlay.style.opacity = '0';
aboutMenu.style.opacity = '0';
setTimeout(() => {
aboutOverlay.style.display = 'none';
document.body.style.overflow = 'auto';
}, 200);
};
showMenu();
closeAbout.addEventListener('click', (event) => {
event.stopPropagation();
hideMenu();
});
aboutOverlay.addEventListener('click', (event) => {
if (!aboutMenu.contains(event.target)) {
hideMenu();
}
});
menu.addEventListener('click', (event) => event.stopPropagation());
}
// Event listener for link redirect
telegramLink.addEventListener('click', async () => {
try {
await execCommand('am start -a android.intent.action.VIEW -d https://t.me/kowchannel');
} catch (error) {
console.error('Error opening Telegram link:', error);
}
});
githubLink.addEventListener('click', async () => {
try {
await execCommand('am start -a android.intent.action.VIEW -d https://github.com/KOWX712/Tricky-Addon-Update-Target-List');
} catch (error) {
console.error('Error opening GitHub link:', error);
}
});

View File

@@ -0,0 +1,127 @@
import { basePath, execCommand, floatingBtn, appsWithExclamation, appsWithQuestion } from './main.js';
const appTemplate = document.getElementById('app-template').content;
export const appListContainer = document.getElementById('apps-list');
export const updateCard = document.getElementById('update-card');
// Fetch and render applist
export async function fetchAppList() {
try {
let targetList = [];
try {
const targetFileContent = await execCommand('cat /data/adb/tricky_store/target.txt');
targetList = processTargetList(targetFileContent);
console.log("Current target list:", targetList);
} catch (error) {
console.error("Failed to read target.txt file:", error);
}
let applistMap = {};
try {
const applistResult = await execCommand(`cat ${basePath}common/tmp/applist`);
applistMap = applistResult
.split("\n")
.reduce((map, line) => {
const match = line.match(/app-name:\s*(.+),\s*package-name:\s*(.+)/);
if (match) {
const appName = match[1].trim();
const packageName = match[2].trim();
map[packageName] = appName;
}
return map;
}, {});
console.log("Applist loaded successfully.");
} catch (error) {
console.warn("Applist file not found or could not be loaded. Skipping applist lookup.");
}
const result = await execCommand("pm list packages -3");
const appEntries = result
.split("\n")
.map(line => {
const packageName = line.replace("package:", "").trim();
const appName = applistMap[packageName] || null;
return { appName, packageName };
})
.filter(entry => entry.packageName);
for (const entry of appEntries) {
if (!entry.appName) {
try {
const apkPath = await execCommand(`pm path ${entry.packageName} | grep "base.apk" | awk -F: '{print $2}' | tr -d '\\r'`);
if (apkPath) {
const appName = await execCommand(`${basePath}common/aapt dump badging ${apkPath.trim()} 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g"`);
entry.appName = appName.trim() || "Unknown App";
} else {
entry.appName = "Unknown App";
}
} catch (error) {
entry.appName = "Unknown App";
}
}
}
// Sort
const sortedApps = appEntries.sort((a, b) => {
const aChecked = targetList.includes(a.packageName);
const bChecked = targetList.includes(b.packageName);
if (aChecked !== bChecked) {
return aChecked ? -1 : 1;
}
return (a.appName || "").localeCompare(b.appName || "");
});
// Render
appListContainer.innerHTML = "";
sortedApps.forEach(({ appName, packageName }) => {
const appElement = document.importNode(appTemplate, true);
const contentElement = appElement.querySelector(".content");
contentElement.setAttribute("data-package", packageName);
const nameElement = appElement.querySelector(".name");
nameElement.innerHTML = `<strong>${appName || "Unknown App"}</strong><br>${packageName}`;
const checkbox = appElement.querySelector(".checkbox");
checkbox.checked = targetList.includes(packageName);
appListContainer.appendChild(appElement);
});
console.log("App list with names and packages rendered successfully.");
} catch (error) {
console.error("Failed to fetch or render app list with names:", error);
}
floatingBtn.style.transform = "translateY(-120px)";
toggleableCheckbox();
if (appListContainer.firstChild !== updateCard) {
appListContainer.insertBefore(updateCard, appListContainer.firstChild);
}
}
// Function to save app with ! and ? then process target list
function processTargetList(targetFileContent) {
appsWithExclamation.length = 0;
appsWithQuestion.length = 0;
const targetList = targetFileContent
.split("\n")
.map(app => {
const trimmedApp = app.trim();
if (trimmedApp.endsWith('!')) {
appsWithExclamation.push(trimmedApp.slice(0, -1));
} else if (trimmedApp.endsWith('?')) {
appsWithQuestion.push(trimmedApp.slice(0, -1));
}
return trimmedApp.replace(/[!?]/g, '');
})
.filter(app => app.trim() !== '');
return targetList;
}
// Make checkboxes toggleable
function toggleableCheckbox() {
const appElements = appListContainer.querySelectorAll(".card");
appElements.forEach(card => {
const content = card.querySelector(".content");
const checkbox = content.querySelector(".checkbox");
content.addEventListener("click", (event) => {
if (event.target !== checkbox) {
checkbox.checked = !checkbox.checked;
}
});
});
}

View File

@@ -0,0 +1,30 @@
const helpButton = document.getElementById('help-button');
const helpOverlay = document.getElementById('help-overlay');
const closeHelp = document.getElementById('close-help');
const helpList = document.getElementById('help-list');
// Function to setup the help menu
export function setupHelpOverlay() {
helpButton.addEventListener("click", () => {
helpOverlay.classList.remove("hide");
helpOverlay.style.display = "flex";
requestAnimationFrame(() => {
helpOverlay.classList.add("show");
});
document.body.classList.add("no-scroll");
});
const hideHelpOverlay = () => {
helpOverlay.classList.remove("show");
helpOverlay.classList.add("hide");
document.body.classList.remove("no-scroll");
setTimeout(() => {
helpOverlay.style.display = "none";
}, 200);
};
closeHelp.addEventListener("click", hideHelpOverlay);
helpOverlay.addEventListener("click", (event) => {
if (event.target === helpOverlay) {
hideHelpOverlay();
}
});
}

View File

@@ -0,0 +1,132 @@
import { basePath, execCommand } from './main.js';
const languageButton = document.querySelector('.language-button');
const languageMenu = document.querySelector('.language-menu');
const languageOptions = document.querySelectorAll('.language-option');
const languageOverlay = document.getElementById('language-overlay');
export let translations = {};
let currentLang = 'en-US';
let availableLanguages = ['en-US'];
// Function to check for available language
export async function initializeAvailableLanguages() {
try {
const multiLang = await execCommand(`find ${basePath}webui/locales -type f -name "*.json" ! -name "A-template.json" -exec basename -s .json {} \\;`);
availableLanguages = multiLang.trim().split('\n');
generateLanguageMenu();
} catch (error) {
console.error('Failed to fetch available languages:', error);
availableLanguages = ['en-US'];
}
}
// Function to detect user's default language
export function detectUserLanguage() {
const userLang = navigator.language || navigator.userLanguage;
const langCode = userLang.split('-')[0];
if (availableLanguages.includes(userLang)) {
return userLang;
} else if (availableLanguages.includes(langCode)) {
return langCode;
} else {
return 'en-US';
}
}
// Load translations dynamically based on the selected language
export async function loadTranslations(lang) {
try {
const response = await fetch(`/locales/${lang}.json`);
translations = await response.json();
applyTranslations();
} catch (error) {
console.error(`Error loading translations for ${lang}:`, error);
if (lang !== 'en-US') {
console.log("Falling back to English.");
loadTranslations('en-US');
}
}
}
// Function to apply translations to all elements with data-i18n attributes
function applyTranslations() {
document.querySelectorAll("[data-i18n]").forEach((el) => {
const keyString = el.getAttribute("data-i18n");
const translation = keyString.split('.').reduce((acc, key) => acc && acc[key], translations);
if (translation) {
if (el.hasAttribute("placeholder")) {
el.setAttribute("placeholder", translation);
} else {
el.textContent = translation;
}
}
});
}
// Function to setup the language menu
export function setupLanguageMenu() {
languageButton.addEventListener("click", (event) => {
event.stopPropagation();
const isVisible = languageMenu.classList.contains("show");
if (isVisible) {
closeLanguageMenu();
} else {
openLanguageMenu();
}
});
document.addEventListener("click", (event) => {
if (!languageButton.contains(event.target) && !languageMenu.contains(event.target)) {
closeLanguageMenu();
}
});
languageOptions.forEach(option => {
option.addEventListener("click", () => {
closeLanguageMenu();
});
});
window.addEventListener('scroll', () => {
if (languageMenu.classList.contains("show")) {
closeLanguageMenu();
}
});
function openLanguageMenu() {
languageMenu.classList.add("show");
languageOverlay.style.display = 'flex';
}
function closeLanguageMenu() {
languageMenu.classList.remove("show");
languageOverlay.style.display = 'none';
}
languageMenu.addEventListener("click", (e) => {
if (e.target.classList.contains("language-option")) {
const lang = e.target.getAttribute("data-lang");
loadTranslations(lang);
closeLanguageMenu();
}
});
}
// Function to generate the language menu dynamically
async function generateLanguageMenu() {
languageMenu.innerHTML = '';
const languagePromises = availableLanguages.map(async (lang) => {
try {
const response = await fetch(`/locales/${lang}.json`);
const data = await response.json();
return { lang, name: data.language || lang };
} catch (error) {
console.error(`Error fetching language name for ${lang}:`, error);
return { lang, name: lang };
}
});
const languageData = await Promise.all(languagePromises);
const sortedLanguages = languageData.sort((a, b) => a.name.localeCompare(b.name));
sortedLanguages.forEach(({ lang, name }) => {
const button = document.createElement('button');
button.classList.add('language-option');
button.setAttribute('data-lang', lang);
button.textContent = name;
languageMenu.appendChild(button);
});
}

View File

@@ -0,0 +1,245 @@
import { aboutMenu } from './about.js';
import { appListContainer, updateCard, fetchAppList } from './applist.js';
import { setupHelpOverlay } from './help.js';
import { initializeAvailableLanguages, detectUserLanguage, loadTranslations, setupLanguageMenu, translations } from './language.js';
import { selectAllApps, deselectAllApps, selectDenylistApps, deselectUnnecessaryApps, aospkb, extrakb } from './menu_option.js';
import { searchMenuContainer, searchInput, clearBtn, setupMenuToggle } from './search_menu.js';
import { setBootHash } from './vbmeta-digest.js';
// Header Elements
const headerBlock = document.querySelector('.header-block');
const title = document.querySelector('.header');
const noConnection = document.querySelector('.no-connection');
// Menu Elements
const selectDenylistElement = document.getElementById('select-denylist');
// Loading, Save and Prompt Elements
const loadingIndicator = document.querySelector('.loading');
const prompt = document.getElementById('prompt');
export const floatingBtn = document.querySelector('.floating-btn');
export const basePath = "set-path";
export const appsWithExclamation = [];
export const appsWithQuestion = [];
const ADDITIONAL_APPS = [ "com.google.android.gms", "io.github.vvb2060.keyattestation", "io.github.vvb2060.mahoshojo", "icu.nullptr.nativetest" ];
// Variables
let e = 0;
let isRefreshing = false;
// Function to refresh app list
async function refreshAppList() {
isRefreshing = true;
title.style.transform = 'translateY(0)';
searchMenuContainer.style.transform = 'translateY(0)';
floatingBtn.style.transform = 'translateY(0)';
searchInput.value = '';
clearBtn.style.display = "none";
appListContainer.innerHTML = '';
loadingIndicator.style.display = 'flex';
document.querySelector('.uninstall-container').classList.add('hidden-uninstall');
await new Promise(resolve => setTimeout(resolve, 500));
window.scrollTo(0, 0);
if (noConnection.style.display === "flex") {
try {
await updateCheck();
await execCommand(`[ -f ${basePath}common/tmp/exclude-list ] && rm -f "${basePath}common/tmp/exclude-list"`);
} catch (error) {
console.error("Error occurred:", error);
}
}
await fetchAppList();
loadingIndicator.style.display = 'none';
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
isRefreshing = false;
}
// Function to run the update check
async function updateCheck() {
try {
const scriptPath = `sh ${basePath}common/get_extra.sh --update`;
const output = await execCommand(scriptPath);
console.log("update script executed successfully.");
noConnection.style.display = "none";
if (output.includes("update")) {
console.log("Update detected from extra script.");
showPrompt("prompt.new_update");
updateCard.style.display = "flex";
} else {
console.log("No update detected from extra script.");
}
} catch (error) {
console.error("Failed to execute update script:", error);
showPrompt("prompt.no_internet", false);
noConnection.style.display = "flex";
}
}
// Function to check if Magisk
async function checkMagisk() {
try {
const magiskEnv = await execCommand(`command -v magisk >/dev/null 2>&1 && echo "OK"`);
if (magiskEnv.trim() === "OK") {
console.log("Denylist conditions met, displaying element.");
selectDenylistElement.style.display = "flex";
} else {
console.log("ksud or apd detected, leaving denylist element hidden.");
}
} catch (error) {
console.error("Error while checking denylist conditions:", error);
}
}
// Function to show the prompt with a success or error message
export function showPrompt(key, isSuccess = true) {
const message = key.split('.').reduce((acc, k) => acc && acc[k], translations) || key;
prompt.textContent = message;
prompt.classList.toggle('error', !isSuccess);
if (window.promptTimeout) {
clearTimeout(window.promptTimeout);
}
setTimeout(() => {
prompt.classList.add('visible');
prompt.classList.remove('hidden');
window.promptTimeout = setTimeout(() => {
prompt.classList.remove('visible');
prompt.classList.add('hidden');
}, 3000);
}, 200);
}
// Save configure and preserve ! and ? in target.txt
document.getElementById("save").addEventListener("click", async () => {
const selectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:checked"))
.map(checkbox => checkbox.closest(".card").querySelector(".content").getAttribute("data-package"));
let finalAppsList = new Set(selectedApps);
ADDITIONAL_APPS.forEach(app => {
finalAppsList.add(app);
});
finalAppsList = Array.from(finalAppsList);
try {
const modifiedAppsList = finalAppsList.map(app => {
if (appsWithExclamation.includes(app)) {
return `${app}!`;
} else if (appsWithQuestion.includes(app)) {
return `${app}?`;
}
return app;
});
const updatedTargetContent = modifiedAppsList.join("\n");
await execCommand(`echo "${updatedTargetContent}" > /data/adb/tricky_store/target.txt`);
console.log("target.txt updated successfully.");
showPrompt("prompt.saved_target");
for (const app of appsWithExclamation) {
await execCommand(`sed -i 's/^${app}$/${app}!/' /data/adb/tricky_store/target.txt`);
}
for (const app of appsWithQuestion) {
await execCommand(`sed -i 's/^${app}$/${app}?/' /data/adb/tricky_store/target.txt`);
}
console.log("App names modified in target.txt.");
} catch (error) {
console.error("Failed to update target.txt:", error);
showPrompt("prompt.save_error", false);
}
await refreshAppList();
});
// Uninstall WebUI
document.querySelector(".uninstall-container").addEventListener("click", async () => {
try {
await execCommand(`sh ${basePath}common/get_extra.sh --uninstall`);
console.log("uninstall script executed successfully.");
showPrompt("prompt.uninstall_prompt");
} catch (error) {
console.error("Failed to execute uninstall command:", error);
showPrompt("prompt.uninstall_failed", false);
}
});
// Function to check if running in MMRL
function adjustHeaderForMMRL() {
if (typeof ksu !== 'undefined' && ksu.mmrl) {
console.log("Running in MMRL");
title.style.top = 'var(--window-inset-top)';
const insetTop = getComputedStyle(document.documentElement).getPropertyValue('--window-inset-top');
const insetTopValue = parseInt(insetTop, 10);
searchMenuContainer.style.top = `${insetTopValue + 40}px`;
headerBlock.style.display = 'block';
}
}
// Scroll event
let lastScrollY = window.scrollY;
const scrollThreshold = 40;
window.addEventListener('scroll', () => {
if (isRefreshing) return;
if (window.scrollY > lastScrollY && window.scrollY > scrollThreshold) {
title.style.transform = 'translateY(-80px)';
headerBlock.style.transform = 'translateY(-80px)';
searchMenuContainer.style.transform = 'translateY(-40px)';
floatingBtn.style.transform = 'translateY(0)';
} else if (window.scrollY < lastScrollY) {
headerBlock.style.transform = 'translateY(0)';
title.style.transform = 'translateY(0)';
searchMenuContainer.style.transform = 'translateY(0)';
floatingBtn.style.transform = 'translateY(-120px)';
}
lastScrollY = window.scrollY;
});
// Initial load
document.addEventListener('DOMContentLoaded', async () => {
adjustHeaderForMMRL();
await initializeAvailableLanguages();
const userLang = detectUserLanguage();
await loadTranslations(userLang);
setupMenuToggle();
setupLanguageMenu();
setupHelpOverlay();
document.getElementById("refresh").addEventListener("click", refreshAppList);
document.getElementById("select-all").addEventListener("click", selectAllApps);
document.getElementById("deselect-all").addEventListener("click", deselectAllApps);
document.getElementById("select-denylist").addEventListener("click", selectDenylistApps);
document.getElementById("deselect-unnecessary").addEventListener("click", deselectUnnecessaryApps);
document.getElementById("aospkb").addEventListener("click", aospkb);
document.getElementById("extrakb").addEventListener("click", extrakb);
document.getElementById("boot-hash").addEventListener("click", setBootHash);
document.getElementById("about").addEventListener("click", aboutMenu);
await fetchAppList();
checkMagisk();
updateCheck();
loadingIndicator.style.display = "none";
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
});
// Redirect to GitHub release page
updateCard.addEventListener('click', async () => {
try {
await execCommand('am start -a android.intent.action.VIEW -d https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/latest');
} catch (error) {
console.error('Error opening GitHub Release link:', error);
}
});
// Function to execute shell commands
export async function execCommand(command) {
return new Promise((resolve, reject) => {
const callbackName = `exec_callback_${Date.now()}_${e++}`;
window[callbackName] = (errno, stdout, stderr) => {
delete window[callbackName];
if (errno === 0) {
resolve(stdout);
} else {
console.error(`Error executing command: ${stderr}`);
reject(stderr);
}
};
try {
ksu.exec(command, "{}", callbackName);
} catch (error) {
console.error(`Execution error: ${error}`);
reject(error);
}
});
}

View File

@@ -0,0 +1,111 @@
import { basePath, execCommand, showPrompt } from './main.js';
// Function to check or uncheck all app
function toggleCheckboxes(shouldCheck) {
document.querySelectorAll(".card").forEach(card => {
if (card.style.display !== "none") {
card.querySelector(".checkbox").checked = shouldCheck;
}
});
}
// Function to select all visible apps
export function selectAllApps() {
toggleCheckboxes(true);
}
// Function to deselect all visible apps
export function deselectAllApps() {
toggleCheckboxes(false);
}
// Function to read the denylist and check corresponding apps
export async function selectDenylistApps() {
try {
const result = await execCommand(`magisk --denylist ls 2>/dev/null | awk -F'|' '{print $1}' | grep -v "isolated" | sort | uniq`);
const denylistApps = result.split("\n").map(app => app.trim()).filter(Boolean);
const apps = document.querySelectorAll(".card");
await deselectAllApps();
apps.forEach(app => {
const contentElement = app.querySelector(".content");
const packageName = contentElement.getAttribute("data-package");
const checkbox = app.querySelector(".checkbox");
if (denylistApps.includes(packageName)) {
checkbox.checked = true;
}
});
console.log("Denylist apps selected successfully.");
} catch (error) {
console.error("Failed to select Denylist apps:", error);
}
}
// Function to read the exclude list and uncheck corresponding apps
export async function deselectUnnecessaryApps() {
try {
const fileCheck = await execCommand(`test -f ${basePath}common/tmp/exclude-list && echo "exists" || echo "not found"`);
if (fileCheck.trim() === "not found") {
setTimeout(async () => {
await execCommand(`sh ${basePath}common/get_extra.sh --unnecessary`);
}, 0);
console.log("Exclude list not found. Running the unnecessary apps script.");
} else {
setTimeout(async () => {
await execCommand(`sh ${basePath}common/get_extra.sh --xposed`);
}, 0);
console.log("Exclude list found. Running xposed script.");
}
await new Promise(resolve => setTimeout(resolve, 100));
const result = await execCommand(`cat ${basePath}common/tmp/exclude-list`);
const UnnecessaryApps = result.split("\n").map(app => app.trim()).filter(Boolean);
const apps = document.querySelectorAll(".card");
apps.forEach(app => {
const contentElement = app.querySelector(".content");
const packageName = contentElement.getAttribute("data-package");
const checkbox = app.querySelector(".checkbox");
if (UnnecessaryApps.includes(packageName)) {
checkbox.checked = false;
}
});
console.log("Unnecessary apps deselected successfully.");
} catch (error) {
console.error("Failed to deselect unnecessary apps:", error);
}
}
// Function to replace aosp kb
export async function aospkb() {
try {
const sourcePath = `${basePath}common/.default`;
const destinationPath = "/data/adb/tricky_store/keybox.xml";
await execCommand(`xxd -r -p ${sourcePath} | base64 -d > ${destinationPath}`);
console.log("AOSP keybox copied successfully.");
showPrompt("prompt.aosp_key_set");
} catch (error) {
console.error("Failed to copy AOSP keybox:", error);
showPrompt("prompt.key_set_error", false);
}
}
// Function to replace valid kb
export async function extrakb() {
setTimeout(async () => {
await execCommand(`sh ${basePath}common/get_extra.sh --kb`);
}, 100);
const sourcePath = `${basePath}common/tmp/.extra`;
const destinationPath = "/data/adb/tricky_store/keybox.xml";
try {
await new Promise(resolve => setTimeout(resolve, 300));
const fileExists = await execCommand(`[ -f ${sourcePath} ] && echo "exists"`);
if (fileExists.trim() !== "exists") {
throw new Error(".extra file not found");
}
await execCommand(`xxd -r -p ${sourcePath} | base64 -d > ${destinationPath}`);
console.log("Valid keybox copied successfully.");
showPrompt("prompt.valid_key_set");
} catch (error) {
console.error("Failed to copy valid keybox:", error);
await aospkb();
showPrompt("prompt.no_valid_fallback", false);
}
}

View File

@@ -0,0 +1,103 @@
import { appListContainer } from './applist.js';
const searchCard = document.querySelector('.search-card');
export const searchInput = document.getElementById('search');
export const clearBtn = document.getElementById('clear-btn');
export const searchMenuContainer = document.querySelector('.search-menu-container');
const menu = document.querySelector('.menu');
const menuButton = document.getElementById('menu-button');
const menuOptions = document.getElementById('menu-options');
const menuOverlay = document.getElementById('menu-overlay');
const menuIcon = menuButton.querySelector('.menu-icon');
// Focus on search input when search card is clicked
searchCard.addEventListener("click", () => {
searchInput.focus();
});
// Search functionality
searchInput.addEventListener("input", (e) => {
const searchQuery = e.target.value.toLowerCase();
const apps = appListContainer.querySelectorAll(".card");
apps.forEach(app => {
const name = app.querySelector(".name").textContent.toLowerCase();
app.style.display = name.includes(searchQuery) ? "block" : "none";
window.scrollTo(0, 0);
});
if (searchQuery !== "") {
clearBtn.style.display = "block";
} else {
clearBtn.style.display = "none";
}
});
// Clear search input
clearBtn.addEventListener("click", () => {
searchInput.value = "";
clearBtn.style.display = "none";
window.scrollTo(0, 0);
const apps = appListContainer.querySelectorAll(".card");
apps.forEach(app => {
app.style.display = "block";
});
});
// Function to toggle menu option
export function setupMenuToggle() {
let menuOpen = false;
let menuAnimating = false;
menuButton.addEventListener('click', (event) => {
if (menuAnimating) return;
event.stopPropagation();
if (menuOptions.classList.contains('visible')) {
closeMenu();
} else {
openMenu();
}
});
document.addEventListener('click', (event) => {
if (!menuOptions.contains(event.target) && event.target !== menuButton) {
closeMenu();
}
});
window.addEventListener('scroll', () => {
if (menuOptions.classList.contains('visible')) {
closeMenu();
}
});
const menuOptionsList = document.querySelectorAll('#menu-options li');
menuOptionsList.forEach(option => {
option.addEventListener('click', (event) => {
event.stopPropagation();
closeMenu();
});
});
function openMenu() {
menuAnimating = true;
menuOptions.style.display = 'block';
setTimeout(() => {
menuOptions.classList.remove('hidden');
menuOptions.classList.add('visible');
menuIcon.classList.add('menu-open');
menuIcon.classList.remove('menu-closed');
menuOverlay.style.display = 'flex';
menuOpen = true;
menuAnimating = false;
}, 10);
}
function closeMenu() {
if (menuOptions.classList.contains('visible')) {
menuAnimating = true;
menuOptions.classList.remove('visible');
menuOptions.classList.add('hidden');
menuIcon.classList.remove('menu-open');
menuIcon.classList.add('menu-closed');
menuOverlay.style.display = 'none';
setTimeout(() => {
menuOptions.style.display = 'none';
menuOpen = false;
menuAnimating = false;
}, 200);
}
}
}

View File

@@ -0,0 +1,54 @@
import { execCommand, showPrompt } from './main.js';
const bootHashOverlay = document.getElementById('boot-hash-overlay');
const card = document.getElementById('boot-hash-card');
const inputBox = document.getElementById('boot-hash-input');
const saveButton = document.getElementById('boot-hash-save-button');
// Function to handle Verified Boot Hash
export async function setBootHash() {
const showCard = () => {
bootHashOverlay.style.display = "flex";
card.style.display = "flex";
requestAnimationFrame(() => {
bootHashOverlay.classList.add("show");
card.classList.add("show");
});
document.body.style.overflow = "hidden";
};
const closeCard = () => {
bootHashOverlay.classList.remove("show");
card.classList.remove("show");
setTimeout(() => {
bootHashOverlay.style.display = "none";
card.style.display = "none";
document.body.style.overflow = "auto";
}, 200);
};
showCard();
try {
const bootHashContent = await execCommand("cat /data/adb/boot_hash");
const validHash = bootHashContent
.split("\n")
.filter(line => !line.startsWith("#") && line.trim())[0];
inputBox.value = validHash || "";
} catch (error) {
console.warn("Failed to read boot_hash file. Defaulting to empty input.");
inputBox.value = "";
}
saveButton.addEventListener("click", async () => {
const inputValue = inputBox.value.trim();
try {
await execCommand(`echo "${inputValue}" > /data/adb/boot_hash`);
await execCommand(`su -c resetprop -n ro.boot.vbmeta.digest ${inputValue}`);
showPrompt("prompt.boot_hash_set");
closeCard();
} catch (error) {
console.error("Failed to update boot_hash:", error);
showPrompt("prompt.boot_hash_set_error", false);
}
});
bootHashOverlay.addEventListener("click", (event) => {
if (event.target === bootHashOverlay) closeCard();
});
}

View File

@@ -0,0 +1,124 @@
.about-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1100;
display: none;
justify-content: center;
align-items: center;
opacity: 0;
transition: opacity 0.2s ease;
}
.about-menu {
position: fixed;
top: 50%;
left: 50%;
width: 90vw;
max-width: 800px;
transform: translate(-50%, -50%);
background: #fff;
border-radius: 15px;
padding: 30px 0;
z-index: 1200;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
z-index: 1200;
opacity: 0;
display: flex;
flex-direction: column;
gap: 15px;
transition: opacity 0.2s ease;
}
.close-about {
position: absolute;
top: 15px;
right: 12px;
background: none;
border: none;
font-size: 18px;
color: #ccc;
}
.link,
.about-content p {
margin: 0;
padding: 0 30px;
font-size: 16px;
text-align: left;
}
#module_name_line1 {
font-size: 26px;
}
#module_name_line2 {
font-size: 22px;
}
#authored {
font-size: 14px;
}
#disclaimer {
font-style: italic;
}
#acknowledgment {
font-weight: bold;
font-size: 18px;
}
.link-icon {
display: inline-block;
font-style: normal;
border-radius: 8px;
box-sizing: border-box;
margin-bottom: 5px;
transition: background-color 0.2s ease;
}
.link-icon svg {
padding-bottom: 3px;
vertical-align: bottom;
height: 17px;
}
#telegram {
font-size: 18px;
padding: 3px 10px;
background-color: #38A7ED;
color: #fff;
fill: #fff;
}
#telegram:active {
background-color: #1A78B3;
}
#github {
font-size: 18px;
padding: 3px 10px;
background-color: #606060;
color: #fff;
fill: #fff;
}
#github:active {
background-color: #4D4D4D;
}
#link-text {
font-size: 17px;
font-weight: bold;
}
@media (prefers-color-scheme: dark) {
.about-menu {
background-color: #343434;
}
}

View File

@@ -0,0 +1,92 @@
.card-box {
display: flex;
justify-content: center;
align-items: center;
}
#apps-list {
margin-top: 100px;
flex-direction: column;
}
.update-card {
display: none;
flex-direction: column;
justify-content: space-between;
align-items: center;
background-color: #DCDCDC;
border: none;
border-radius: 10px;
margin: 0 auto;
margin-bottom: 10px;
outline: none;
padding: 12px;
width: calc(100% - 30px);
max-width: 900px;
transition: background-color 0.2s ease;
}
#update-available {
font-size: 20px;
font-weight: bold;
margin-top: 15px;
margin-bottom: 0;
}
#redirect-to-release {
margin-top: 5px;
margin-bottom: 15px;
}
.card {
background-color: white;
border: none;
border-radius: 12px;
margin: 0 auto;
margin-bottom: 10px;
outline: none;
padding: 12px;
width: calc(100% - 30px);
max-width: 900px;
transition: background-color 0.2s ease;
}
.card:active,
.update-card:active {
background-color: #C8C8C8;
}
.content {
display: flex;
justify-content: space-between;
align-items: center;
}
.name {
display: inline-block;
margin: 0;
font-size: 15.5px;
max-width: calc(100% - 30px);
overflow-wrap: break-word;
word-break: break-word;
}
.checkbox {
margin-left: auto;
transform: scale(1.15);
}
@media (prefers-color-scheme: dark) {
.card {
background-color: #343434;
}
.update-card {
background-color: #4D4D4D;
}
.card:active,
.update-card:active {
background-color: #616161;
}
}

View File

@@ -0,0 +1,87 @@
.boot-hash-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1200;
justify-content: center;
align-items: center;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease, visibility 0.2s ease;
}
.boot-hash-card {
position: fixed;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
width: 80vw;
max-width: 600px;
background-color: #fff;
border-radius: 18px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
z-index: 1200;
padding: 20px;
display: none;
flex-direction: column;
gap: 15px;
opacity: 0;
transition: opacity 0.2s ease;
}
.boot-hash-overlay.show {
visibility: visible;
opacity: 1;
}
.boot-hash-card.show {
display: flex;
opacity: 1;
}
.input-box {
width: calc(100% - 20px);
height: 100px;
resize: none;
padding: 9px;
font-size: 16px;
background-color: #FFF;
border: 1px solid #ccc;
border-radius: 10px;
}
.button-container {
display: flex;
justify-content: flex-start;
}
.boot-hash-save-button {
padding: 10px 20px;
border: none;
border-radius: 38px;
font-size: 18px;
font-weight: bold;
background-color: #007bff;
color: white;
margin-left: auto;
transition: background-color 0.2s ease;
}
.boot-hash-save-button:active {
background-color: #003d80;
}
@media (prefers-color-scheme: dark) {
.boot-hash-card {
background-color: #343434;
}
.input-box {
color: #fff;
background-color: #343434;
border: 1px solid #6E6E6E;
}
}

View File

@@ -0,0 +1,161 @@
body {
background-color: #F5F5F5;
padding-top: var(--window-inset-top);
padding-bottom: var(--window-inset-bottom);
}
.no-scroll {
overflow: hidden;
}
.floating-card {
display: flex;
justify-content: center;
position: fixed;
bottom: -70px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
}
.floating-btn {
flex-shrink: 0;
background-color: #007bff;
border: none;
box-shadow: 0 4px 8px #0003;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
padding: 10px 20px;
font-size: 20px;
font-weight: bold;
transition: transform 0.3s ease-in-out, background-color 0.2s ease;
border-radius: 50px 50px;
}
.floating-btn:active {
background-color: #003d80;
}
.prompt {
position: fixed;
bottom: 0;
left: 10px;
background-color: #4CAF50;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
color: white;
font-size: 15px;
padding: 5px 10px;
z-index: 2000;
width: auto;
max-width: calc(100% - 40px);
transform: translateY(100%);
transition: transform 0.5s ease;
}
.prompt.visible {
animation: YbounceIn 0.4s forwards;
}
.prompt.hidden {
animation: YbounceOut 0.4s forwards;
}
.prompt.error {
background-color: #f44336;
}
@keyframes YbounceIn {
0% {
transform: translateY(100%);
}
50% {
transform: translateY(-80%);
}
100% {
transform: translateY(-60%);
}
}
@keyframes YbounceOut {
0% {
transform: translateY(-60%);
}
50% {
transform: translateY(-80%);
}
100% {
transform: translateY(100%);
}
}
.loading {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
color: #6E6E6E;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
z-index: 1000;
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
width: calc(100% - 10px);
max-width: 1100px;
padding: 25px 0;
position: relative;
margin-left: auto;
margin-right: auto;
}
.uninstall-container {
padding: 10px 10px;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
display: flex;
align-items: center;
border-radius: 8px;
background-color: #CE0000;
white-space: nowrap;
transition: background-color 0.2s ease;
}
.uninstall-container:active {
background-color: #830000;
}
.uninstall-container i {
margin-right: 5px;
}
.uninstall-container span {
font-size: 16px;
font-weight: bold;
color: #fff;
}
.uninstall-container.hidden-uninstall {
display: none;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #121212;
color: #fff;
}
}

View File

@@ -0,0 +1,236 @@
.header {
display: flex;
align-items: center;
justify-content: space-between;
position: fixed;
top: 0;
height: 40px;
width: calc(100% - 10px);
max-width: 1100px;
background-color: #F5F5F5;
transition: transform 0.3s ease;
z-index: 1100;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
}
.header-block {
background-color: #F5F5F5;
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 1100;
transition: transform 0.3s ease;
height: var(--window-inset-top);
}
#title {
padding-left: 5px;
font-size: 16.5px;
font-weight: bold;
}
.no-connection {
padding: 0;
display: none;
margin-right: 0px;
background: none;
border: none;
}
.language-dropdown {
position: relative;
display: inline-block;
}
.language-button {
padding-top: 5px;
background: none;
border: none;
}
.language-icon {
fill: #000;
}
.language-menu {
display: flex;
padding: 3px 10px;
flex-direction: column;
position: absolute;
right: 0;
background-color: #fff;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
z-index: 1800;
border: 1px solid #ccc;
border-radius: 8px;
opacity: 0;
visibility: hidden;
max-height: calc(100vh - 50px);
overflow-y: auto;
transform: translateY(-10px);
transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
}
.language-menu.show {
display: block;
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.language-option {
padding: 8px 5px;
text-align: left;
background: none;
border: none;
font-size: 16px;
color: #333;
width: 100%;
white-space: nowrap;
border-bottom: 1px solid #ccc;
transition: background-color 0.2s ease;
}
.language-option:last-child {
border-bottom: none;
}
.language-option:active {
background-color: #C8C8C8;
}
.language-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: none;
z-index: 1100;
display: none;
}
.help-button {
padding-left: 5px;
margin-right: auto;
background: none;
border: none;
}
.help-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index: 2000;
justify-content: center;
align-items: center;
opacity: 0;
transition: opacity 0.2s ease;
}
.help-overlay.show {
display: flex;
opacity: 1;
}
.help-overlay.hide {
opacity: 0;
}
.help-menu {
position: relative;
width: 90vw;
max-width: 800px;
background-color: white;
padding: 10px 0;
border-radius: 15px;
text-align: left;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
.close-help {
position: absolute;
top: 15px;
right: 12px;
background: none;
border: none;
font-size: 20px;
color: #ccc;
}
.help-content {
max-height: 85vh;
padding: 0 30px;
overflow-y: auto;
}
.help-content p {
font-size: 26px;
}
.help-content ul {
padding-left: 0;
list-style-type: none;
}
.help-content ul li {
font-weight: bold;
font-size: 18px;
}
.help-content ul ul li {
font-weight: normal;
font-size: 16px;
}
.help-content ul ul ul li {
color: #777777;
font-weight: normal;
font-size: 14px;
}
.help-content ul ul ul li a {
color: inherit;
}
@media (prefers-color-scheme: dark) {
.header-block,
.header {
background-color: #121212;
}
.language-option,
.help-button {
color: #fff;
}
.language-icon {
fill: #eee;
}
.help-menu {
background-color: #343434;
}
.language-menu {
background-color: #343434;
border: 1px solid #6E6E6E;
}
.language-option {
border-bottom: 1px solid #6E6E6E;
}
.language-option:active {
background-color: #616161;
}
}

View File

@@ -0,0 +1,191 @@
.search-menu-container {
display: flex;
position: fixed;
top: 40px;
height: 50px;
width: calc(100% - 20px);
max-width: 1100px;
z-index: 1000;
transition: transform 0.3s ease;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
}
.search-card {
background-color: white;
border: 1px solid #ccc;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
display: flex;
align-items: center;
border-radius: 50px;
left: 0;
height: calc(100% - 2px);
width: calc(100% - 60px);
position: absolute;
}
.search-icon {
position: absolute;
padding-top: 5px;
left: 15px;
z-index: 1000;
}
.search-input {
position: absolute;
border: none;
font-size: 17px;
outline: none;
left: 10px;
padding: 0 30px;
width: calc(100% - 10);
}
.clear-btn {
position: absolute;
color: #ccc;
padding-bottom: 3px;
right: 10px;
border: none;
background: none;
font-size: 18px;
cursor: pointer;
display: none;
z-index: 10;
}
.menu {
display: flex;
right: 0;
position: absolute;
height: 100%;
}
.menu-toggle {
display: none;
}
#menu-button {
background-color: white;
border: 1px solid #ccc;
border-radius: 50%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
width: 48px;
display: flex;
justify-content: center;
align-items: center;
}
.menu-icon {
display: inline-block;
fill: #000;
transition: transform 0.2s ease;
}
.menu-icon.menu-open {
transform: rotate(90deg);
}
.menu-icon.menu-closed {
transform: rotate(0deg);
}
.menu-options {
background-color: white;
border: 1px solid #ccc;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
display: none;
position: absolute;
padding: 5px 12px;
top: 110%;
right: 0;
z-index: 1200;
transform: translateX(120%);
transition: transform 0.2s ease;
width: auto;
max-height: calc(100vh - 120px);
overflow-y: auto;
white-space: nowrap;
}
#select-denylist {
display: none;
}
.menu-options.visible {
display: block;
transform: translateX(0);
}
.menu-options.hidden {
transform: translateX(140%);
}
.menu-options ul {
list-style: none;
margin: 0;
padding: 0;
}
.menu-options li {
cursor: default;
padding: 12px 4px;
text-align: left;
border-bottom: 1px solid #ccc;
transition: background-color 0.2s ease;
}
.menu-options li:active {
background-color: #C8C8C8;
}
.menu-options li:last-child {
border-bottom: none;
}
.menu-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: none;
z-index: 1000;
display: none;
}
@media (prefers-color-scheme: dark) {
.menu-icon {
fill: #eee;
}
.search-input,
.search-card {
background-color: #343434;
}
.search-card {
border: 1px solid #6E6E6E;
}
.search-input {
color: white;
}
.menu-options,
#menu-button {
background-color: #343434;
border: 1px solid #6E6E6E;
}
.menu-options li {
border-bottom: 1px solid #6E6E6E;
}
.menu-options li:active {
background-color: #616161;
}
}

View File

@@ -1,7 +1,7 @@
{
"description": "Unnecessary app list",
"repo-link": "https://github.com/KOWX712/Tricky-Addon-Update-Target-List",
"json-link": "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/more-excldue.json",
"json-link": "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/more-exclude.json",
"data": [
{
"info": "Root manager",
@@ -58,6 +58,14 @@
{
"name": "KSUWebUI",
"package-name": "io.github.a13e300.ksuwebui"
},
{
"name": "Shizuku",
"package-name": "moe.shizuku.privileged.api"
},
{
"name": "MMRL",
"package-name": "com.dergoogler.mmrl"
}
]
},

View File

@@ -1,6 +1,6 @@
{
"versionCode": 250,
"version": "v2.5",
"zipUrl": "https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/download/v2.5/TrickyAddonModule-v2.5.zip",
"changelog": "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/changelog.md"
"versionCode": 290,
"version": "v2.9",
"zipUrl": "https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/download/v2.9/TrickyAddonModule-v2.9.zip",
"changelog": "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/changelog.md"
}