You've already forked Tricky-Addon-Update-Target-List
mirror of
https://github.com/KOWX712/Tricky-Addon-Update-Target-List.git
synced 2025-09-06 06:37:09 +00:00
Compare commits
320 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
533bdf8fa5 | ||
|
|
a9eab165a0 | ||
|
|
5bbbe4bc08 | ||
|
|
df255096c8 | ||
|
|
b1a52ee173 | ||
|
|
3b355ac5ff | ||
|
|
98ed78cebb | ||
|
|
294a7bf214 | ||
|
|
8f87642319 | ||
|
|
e939f11a72 | ||
|
|
92e654614e | ||
|
|
6b15a09381 | ||
|
|
63c10043dd | ||
|
|
487b2ed434 | ||
|
|
6ed1ec07a8 | ||
|
|
7a07476598 | ||
|
|
5e8d806237 | ||
|
|
ab65ed6520 | ||
|
|
dd786643dc | ||
|
|
c273f1823a | ||
|
|
3d3c47aab4 | ||
|
|
b11fe1dd61 | ||
|
|
6a26150e50 | ||
|
|
1c93287b69 | ||
|
|
d739bc2751 | ||
|
|
defef34bc3 | ||
|
|
e704bda0f7 | ||
|
|
530f006154 | ||
|
|
7a8e5979cd | ||
|
|
48637a0fdb | ||
|
|
ad4cc31c29 | ||
|
|
d5c2fe2cbd | ||
|
|
36ea5f4f99 | ||
|
|
dc84087b33 | ||
|
|
0191078fe5 | ||
|
|
80ffdd3e0d | ||
|
|
9f6faf4e17 | ||
|
|
6419f5e3b9 | ||
|
|
0c659675c5 | ||
|
|
37fce96a11 | ||
|
|
3e36abdbc4 | ||
|
|
9e59a30129 | ||
|
|
b4cd5467ef | ||
|
|
a119c58279 | ||
|
|
1db0259f36 | ||
|
|
4176bd9ce1 | ||
|
|
c879dfa428 | ||
|
|
355c0444c7 | ||
|
|
293f9e1266 | ||
|
|
8e9c7f0db8 | ||
|
|
de5a8b8b87 | ||
|
|
c20e8cde1f | ||
|
|
93e2e8c8ba | ||
|
|
bf726bf863 | ||
|
|
9f859dc488 | ||
|
|
9bed9c0c41 | ||
|
|
211f3d732b | ||
|
|
41ce39be2a | ||
|
|
56ca7ec7a1 | ||
|
|
2784072fb4 | ||
|
|
2a3890e5fb | ||
|
|
59e79b33b7 | ||
|
|
fe76f01439 | ||
|
|
37d78b790e | ||
|
|
30c70d01d6 | ||
|
|
c09f43ab5b | ||
|
|
058ac8dfdc | ||
|
|
735444d8a3 | ||
|
|
6a806ac588 | ||
|
|
3ffe75a1f3 | ||
|
|
4fdc057162 | ||
|
|
b7b5c2c1f0 | ||
|
|
ddeb13c5e2 | ||
|
|
410629fad5 | ||
|
|
7424ed325a | ||
|
|
f1128cd55b | ||
|
|
e5dcc62fdf | ||
|
|
ee169eb2cd | ||
|
|
a9d6833342 | ||
|
|
a8e388d4cf | ||
|
|
09f6f522de | ||
|
|
f2483efc6e | ||
|
|
6ed4df7d9c | ||
|
|
ac4ff62cce | ||
|
|
b6c81362fe | ||
|
|
5f70249003 | ||
|
|
16f1cde2d7 | ||
|
|
96ea764aa0 | ||
|
|
c44a101776 | ||
|
|
581d81d5dd | ||
|
|
d0882dfa57 | ||
|
|
3050ecf84c | ||
|
|
83cd9a0ac8 | ||
|
|
bf8fdb8419 | ||
|
|
edfe2986e7 | ||
|
|
473bd64770 | ||
|
|
68ed991d98 | ||
|
|
553df593ae | ||
|
|
dfc6726e10 | ||
|
|
5a66cba009 | ||
|
|
f8dfe50a0c | ||
|
|
24c00f124d | ||
|
|
5e3836f41f | ||
|
|
41b434f2bb | ||
|
|
5441eb0830 | ||
|
|
046af031d8 | ||
|
|
4977695022 | ||
|
|
0427153ea6 | ||
|
|
2980bda649 | ||
|
|
0821e88fdc | ||
|
|
25ecc49a77 | ||
|
|
42f0b6df77 | ||
|
|
006ca27100 | ||
|
|
f36f5bf7db | ||
|
|
41430b4386 | ||
|
|
6ee2b65b75 | ||
|
|
1a50c322d9 | ||
|
|
83469179e6 | ||
|
|
d534185d48 | ||
|
|
7324d92aeb | ||
|
|
6cd29416ec | ||
|
|
39c303e04e | ||
|
|
8d67689d76 | ||
|
|
2886b7e742 | ||
|
|
2447312286 | ||
|
|
895b3ff1bd | ||
|
|
e18871754f | ||
|
|
a4c08ba08c | ||
|
|
66e048d5a1 | ||
|
|
b81d95d31f | ||
|
|
bb7573f5dd | ||
|
|
ccffd2eaed | ||
|
|
d9c1cdc11d | ||
|
|
e1f9c8904a | ||
|
|
3b98a88c77 | ||
|
|
0b8dcd4503 | ||
|
|
913118ac60 | ||
|
|
cb4276643a | ||
|
|
0087575117 | ||
|
|
5f01b4fed1 | ||
|
|
1f7a4c174b | ||
|
|
19f6b156f6 | ||
|
|
63874eeb8b | ||
|
|
2c5082acbc | ||
|
|
1cb810405a | ||
|
|
142dfdbe81 | ||
|
|
5ef6293924 | ||
|
|
a6b35e8d85 | ||
|
|
51747f261e | ||
|
|
aa7147d115 | ||
|
|
5e9463d8d2 | ||
|
|
d1313d743c | ||
|
|
2542e1a18a | ||
|
|
aa0837ec49 | ||
|
|
684b38afef | ||
|
|
e348fbdd6f | ||
|
|
bb167b760d | ||
|
|
8909a73b59 | ||
|
|
d8848fe5c3 | ||
|
|
2d2cdd7672 | ||
|
|
c1818b6ba2 | ||
|
|
c69337501a | ||
|
|
12a39ce60a | ||
|
|
ec330a4b0b | ||
|
|
7e2c185c5c | ||
|
|
f641f388ad | ||
|
|
f7aee9dc34 | ||
|
|
c19b93ffa3 | ||
|
|
2dc69abea4 | ||
|
|
75ff61e4d2 | ||
|
|
bb3b0abb30 | ||
|
|
502e6f6ea6 | ||
|
|
1d5428e683 | ||
|
|
fe64f37361 | ||
|
|
24548025fe | ||
|
|
d3885966b2 | ||
|
|
ae32ccf973 | ||
|
|
77a6e06631 | ||
|
|
940d809ac5 | ||
|
|
1861e43a81 | ||
|
|
10c02a6924 | ||
|
|
b07c9f8f5a | ||
|
|
dad4bed07e | ||
|
|
a7214cfa81 | ||
|
|
82c489f787 | ||
|
|
de43439200 | ||
|
|
5347ac29bf | ||
|
|
37467411cf | ||
|
|
4fd5b47817 | ||
|
|
610f106913 | ||
|
|
dc46e5f12e | ||
|
|
f46cc964e4 | ||
|
|
a7963c53dc | ||
|
|
7c5b144492 | ||
|
|
4230929dc9 | ||
|
|
437237e3d4 | ||
|
|
cfb51e28fb | ||
|
|
6bdfff7f92 | ||
|
|
4146f09062 | ||
|
|
d223b39e29 | ||
|
|
6bf5009cb8 | ||
|
|
22bdb3986a | ||
|
|
2a04b7426d | ||
|
|
a03b785323 | ||
|
|
d307c57171 | ||
|
|
c6339f4e5d | ||
|
|
4c9e56c1db | ||
|
|
9302d39910 | ||
|
|
06d2edf57f | ||
|
|
ff6244b140 | ||
|
|
dfe4a23f8a | ||
|
|
5dd1496ca7 | ||
|
|
8c831cea39 | ||
|
|
42a8f6baae | ||
|
|
befa011c15 | ||
|
|
f576b4bb2f | ||
|
|
a2b2da27f8 | ||
|
|
b3282816cb | ||
|
|
15f975ee67 | ||
|
|
11d3b34657 | ||
|
|
ad905cb6e0 | ||
|
|
5b966f5626 | ||
|
|
c500e7476a | ||
|
|
1b2a1701f4 | ||
|
|
4563a3399d | ||
|
|
873354b11c | ||
|
|
3d8ca67a6a | ||
|
|
f13e4ecca5 | ||
|
|
878a5faacf | ||
|
|
504918a289 | ||
|
|
6f9d4482a7 | ||
|
|
765444fcd5 | ||
|
|
7905ebcca5 | ||
|
|
030f48f8ce | ||
|
|
27b932ed82 | ||
|
|
d839e3ea4d | ||
|
|
119e0aa2cf | ||
|
|
d17ca1d7ef | ||
|
|
3f5832608e | ||
|
|
b06ffda6bf | ||
|
|
8f6dc6523d | ||
|
|
552758a01f | ||
|
|
6a21702f25 | ||
|
|
31a229e52b | ||
|
|
c7fa970158 | ||
|
|
9e569421cd | ||
|
|
13f020ebd0 | ||
|
|
f1ca044c4f | ||
|
|
227cbeeb5b | ||
|
|
951ae11bcd | ||
|
|
410576094a | ||
|
|
20747caa66 | ||
|
|
879735e33a | ||
|
|
a44941d482 | ||
|
|
3504ec15ce | ||
|
|
ba2e699ca5 | ||
|
|
785250d748 | ||
|
|
b227ad990c | ||
|
|
cb2d8c0192 | ||
|
|
f12fe49d17 | ||
|
|
a0b0c5ca15 | ||
|
|
69198fa458 | ||
|
|
2198313a4a | ||
|
|
85998d76fe | ||
|
|
a399c4a69a | ||
|
|
18e3048028 | ||
|
|
9b5293f7b0 | ||
|
|
375af46292 | ||
|
|
017491b652 | ||
|
|
aea3e9fff3 | ||
|
|
84b7bd9f4e | ||
|
|
9fa022bad6 | ||
|
|
ec024a2936 | ||
|
|
72d505dec5 | ||
|
|
0e06ea4902 | ||
|
|
45657574d2 | ||
|
|
315f254123 | ||
|
|
4772755965 | ||
|
|
18968a4fcb | ||
|
|
457c771cfa | ||
|
|
c5804fabdc | ||
|
|
60ae2e42f9 | ||
|
|
04394ca65d | ||
|
|
3f8ef22b83 | ||
|
|
71e6d7ec8b | ||
|
|
01300c9524 | ||
|
|
8747df3969 | ||
|
|
792e5a15a1 | ||
|
|
df7167dc55 | ||
|
|
ffa0aa461d | ||
|
|
3926980b28 | ||
|
|
a92928838b | ||
|
|
fd837d41e8 | ||
|
|
ce2164b6c2 | ||
|
|
1c1333d0c8 | ||
|
|
561de52bf7 | ||
|
|
6fe8d30ccf | ||
|
|
101bb6abd0 | ||
|
|
b7341c80bc | ||
|
|
5460a2fa5d | ||
|
|
d6d890ef10 | ||
|
|
8801513684 | ||
|
|
db6e591010 | ||
|
|
ad5e2ca551 | ||
|
|
7f431f13f3 | ||
|
|
ed379dfde5 | ||
|
|
3dd007882b | ||
|
|
0607f2d223 | ||
|
|
6a5fb6c717 | ||
|
|
6561ea861b | ||
|
|
f4085f8cf0 | ||
|
|
336efb8d3e | ||
|
|
9e57c81a66 | ||
|
|
cfa17eea26 | ||
|
|
dbed7f9f90 | ||
|
|
5352e8604e | ||
|
|
ff18585543 | ||
|
|
b50e9aa086 | ||
|
|
213c4a2f13 | ||
|
|
f4860d1a00 |
8
.gitattributes
vendored
8
.gitattributes
vendored
@@ -1,9 +1,5 @@
|
||||
# Declare files that will always have LF line endings on checkout.
|
||||
*.sh text eol=lf
|
||||
*.prop text eol=lf
|
||||
*.md text eol=lf
|
||||
*.xml text eol=lf
|
||||
META-INF/** text eol=lf
|
||||
** text eol=lf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
common/addon/**/tools/** binary
|
||||
module/bin/**/** binary
|
||||
127
.github/workflows/build.yml
vendored
Normal file
127
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'module/**'
|
||||
pull_request:
|
||||
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: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Extract Module Info
|
||||
id: extract_info
|
||||
run: |
|
||||
MODULE_VERSION=$(grep '^version=' module/module.prop | sed 's/version=//')
|
||||
COMMIT_NUM=$(git rev-list --count HEAD)
|
||||
BUILD_COUNT=${{ github.run_number }}
|
||||
ARTIFACT_NAME="TrickyAddonModule-${MODULE_VERSION}-${COMMIT_NUM}${BUILD_COUNT}-canary"
|
||||
sed -i "s/^version=.*/& (${COMMIT_NUM}${BUILD_COUNT}-canary)/" module/module.prop
|
||||
echo "MODULE_VERSION=${MODULE_VERSION}" >> $GITHUB_ENV
|
||||
echo "ARTIFACT_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV
|
||||
echo "VERSION=${MODULE_VERSION}" >> $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: |
|
||||
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||
echo "version_tag_exists=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
git fetch --tags
|
||||
VERSION=${{ env.VERSION }}
|
||||
if git tag | grep -qx "^${VERSION}"; then
|
||||
echo "version_tag_exists=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version_tag_exists=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
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")
|
||||
FILES="TrickyAddonModule-${VERSION}.zip"
|
||||
fi
|
||||
|
||||
echo "CURRENT_TAG=$CURRENT_TAG" >> $GITHUB_ENV
|
||||
echo "ZIP_NAME=TrickyAddonModule-${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: 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 }}
|
||||
31
.github/workflows/json-lint.yml
vendored
Normal file
31
.github/workflows/json-lint.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
name: pr_jsonlint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'module/webui/locales/*.json'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install JSON linter
|
||||
run: npm install -g jsonlint
|
||||
|
||||
- name: Lint JSON files
|
||||
run: |
|
||||
for file in $(find module/webui/locales -name "*.json"); do
|
||||
echo "Checking $file"
|
||||
if ! jsonlint "$file"; then
|
||||
echo "Error in $file"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
__MACOSX
|
||||
.DS_Store
|
||||
applist.json
|
||||
61
README.md
61
README.md
@@ -1,41 +1,48 @@
|
||||
# **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 is **not** a necessary module for root hide but for those who lazy to do it manually
|
||||
[](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/latest)
|
||||
[](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](https://github.com/5ec1cff/KsuWebUIStandalone) and [MMRL](https://github.com/MMRLApp/MMRL)
|
||||
- Automatic KSUWebUIStandalone install 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 | ✅ |
|
||||
| Long press to choose `!` or `?` mode for the app. [Auto](https://github.com/5ec1cff/TrickyStore/releases/tag/1.1.0)<br>Use this only when the app cannot work without this. | ✅ |
|
||||
| Select apps from Magisk DenyList `optional` | ✅ |
|
||||
| Deselect [unnecessary apps](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/blob/main/more-exclude.json) `optional` | ✅ |
|
||||
| Set verifiedBootHash `optional` | ✅ |
|
||||
| Auto config [security patch](https://github.com/5ec1cff/TrickyStore?tab=readme-ov-file#customize-security-patch-level-121), customizable in WebUI | ✅ |
|
||||
| Provide AOSP Keybox `optional` | ✅ |
|
||||
| Import custom Keybox from device storage | ✅ |
|
||||
| Add system apps `not recommended` | ✅ |
|
||||
| Valid Keybox `not guaranteed` | ❌ |
|
||||
| Periodically add all app to target.txt | ❌ |
|
||||
|
||||
## More
|
||||
**Support to pass abnormal boot state**
|
||||
- Paste Verfied Boot Hash to `boot_hash` in `/data/adb/`, reboot.
|
||||
## 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
|
||||
- [markedjs/marked](https://github.com/markedjs/marked) - Markdown Support
|
||||
|
||||
## Links
|
||||
Download: [GitHub release](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases)
|
||||
|
||||
Telegram channel: [KOW's Little World](https://t.me/kowchannel)
|
||||
[](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases)
|
||||
[](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/issues)
|
||||
[](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/blob/main/changelog.md)
|
||||
[](https://t.me/kowchannel)
|
||||
|
||||
132
changelog.md
132
changelog.md
@@ -1,17 +1,131 @@
|
||||
### Tricky Addon: Update Target List
|
||||
A **KSU WebUI** to configure tricky store target.txt
|
||||
|
||||
Requirement: Tricky Store module installed
|
||||
|
||||
Manually add VerifiedBootHash to /data/adb/boot_hash (optional)
|
||||
*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)
|
||||
|
||||
Starting from v2.4, WebUI will take longer time to load due to reading app name from every base.apk. The more apps installed, the longer time it takes to load the WebUI.
|
||||
|
||||
## Changelog
|
||||
### v3.8.1
|
||||
- **WebUI:** Fixed missing aosp key fallback when no valid key is available.
|
||||
|
||||
### v3.8
|
||||
- **WebUI:** Optimized UI.
|
||||
- **WebUI:** Added mirror link fallback to fetch content from raw.githubusercontent.com
|
||||
- **WebUI:** Added French translation (#31, @anaelle-dev)
|
||||
- **WebUI:** Added Arabic Translation (#32, @ZG089)
|
||||
- **WebUI:** Added Azerbaijani Translation (#34, @mnasibzade)
|
||||
|
||||
### v3.7
|
||||
- **WebUI:** Optimized UI.
|
||||
- **WebUI:** Added uninstall confirmation dialog.
|
||||
- **WebUI:** Sanitize text content (#23, @totalolage)
|
||||
- **WebUI:** Added selected language memory.
|
||||
- **WebUI:** Fixed Chinese translation (#26 #27, @xiaokuqwq)
|
||||
- **WebUI:** Added Indonesian translation (#28, @ChiseWaguri)
|
||||
- **WebUI:** Added Italian translation (#30, @luigimak)
|
||||
- **MMRL:** Added monet theme suport.
|
||||
- **MMRL:** Fixed fail to display guide when permission is not granted.
|
||||
- No longer add Play Store by default.
|
||||
|
||||
### v3.6
|
||||
- **WebUI:** Option to add system apps.
|
||||
- **WebUI:** Fixed abnormal gap between content and header in MMRL.
|
||||
- Handle some vbmeta related prop, enforce boot hash to lowercase.
|
||||
- No longer auto config security patch by default (old user will remain current setup).
|
||||
- Fixed issue with disable sucompat.
|
||||
- More minor improvements.
|
||||
|
||||
### v3.5
|
||||
- **Script:** Set `system=prop` in auto config.
|
||||
- **WebUI:** Option to fetch secuirty patch date.
|
||||
- **WebUI:** Fixed `Failed to fetch app list` issue in vanilla rom.
|
||||
- **WebUI:** Added Polish translation (#18, @Bladius2024)
|
||||
- **WebUI:** Update Japanese translation (#20, @reindex-ot)
|
||||
- **WebUI:** Minor UI improvements.
|
||||
|
||||
### v3.4
|
||||
- **WebUI:** Allow import custom keybox from device storage.
|
||||
- **WebUI:** Allow custom config security patch in WebUI, save empty to disable auto config.
|
||||
- **WebUI:** Update Turkish translation (#16, @berkmirsatk)
|
||||
- **WebUI:** Fix wrong changelog version displayed in update changelog.
|
||||
- **MMRL:** Display a guide to enable the JavaScript API in MMRL. Directly request API permission on v33045+
|
||||
- More minor improvements
|
||||
|
||||
### v3.3.1
|
||||
- Fixed security patch logic, use pif.json to get security patch date.
|
||||
- No auto config `security_patch.txt` for security patch lesser than one year.
|
||||
|
||||
### v3.3
|
||||
- Support auto config `security_patch.txt` for Tricky Store v1.2.1 or higher.
|
||||
- No longer need to add `!` to Play Store for devices that have security patch older than one year to get strong integrity in new A13+ check.
|
||||
- **Magisk:** automatically add apps from DenyList to `target.txt` on boot. To enable this feature, click "Select from DenyList" once in WebUI after update.
|
||||
|
||||
### v3.2
|
||||
- Add `android` and `com.android.vending` by default.
|
||||
- Handle `ro.vendor.build.security_patch` if the value is different.
|
||||
- Updated Japanese translation (#11, @reindex-ot)
|
||||
- Added Turkish translation (@berkmirsatk)
|
||||
|
||||
### v3.1
|
||||
- Added `com.google.android.gsf` and `com.android.vending` into WebUI app list. (#10, @ChiseWaguri)
|
||||
- Fixed multiple instances of GMS appeared in the app list when GMS isn't a system app.
|
||||
- Added auto backup `keybox.xml` to `keybox.xml.bak` before replacing it.
|
||||
- Minor animation improvements and code optimizations.
|
||||
- [Markdown support](https://github.com/markedjs/marked) for future update changelog in WebUI.
|
||||
|
||||
### v3.0
|
||||
- Animation improvement: new checkbox animation, new touch ripple animation, and more.
|
||||
- Adjust save button and prompt position in MMRL.
|
||||
- Long press on app to select `!` and `?` mode, use this only when the app cannot work without this.
|
||||
- Display gms in app list.
|
||||
- Show module version in header.
|
||||
- Rewrite update method, you can now update module directly in WebUI.
|
||||
|
||||
### 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 restriction 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, integrate action button & WebUI on Tricky Store card. You can still use visible option if you found any issue with invisible 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).
|
||||
|
||||
### v2.6-beta.1
|
||||
- Check in [release notes](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/tag/v2.6-beta.1).
|
||||
|
||||
### v2.5
|
||||
- Remove kb prompt on installation, moved into WebUI
|
||||
- Restore to AOSP keybox during uninstallation
|
||||
@@ -19,7 +133,7 @@ Starting from v2.4, WebUI will take longer time to load due to reading app name
|
||||
### v2.4
|
||||
- Added aapt binary for app name display
|
||||
|
||||
**KSU WebUI**
|
||||
- **KSU WebUI:**
|
||||
- Added app name display
|
||||
|
||||
### v2.3
|
||||
@@ -29,13 +143,13 @@ Starting from v2.4, WebUI will take longer time to load due to reading app name
|
||||
- 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
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
## Tricky Addon Lite: Update Target List Script
|
||||
## Tricky Addon Lite: Update Target List Script (EOL)
|
||||
- Script only, **NOT Module**
|
||||
- Run with root priviledge
|
||||
- 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)
|
||||
|
||||
[](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases)
|
||||
[](https://github.com/KOWX712/Tricky-Addon-Update-Target-List/issues)
|
||||
[](https://t.me/kowchannel)
|
||||
|
||||
@@ -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="
|
||||
@@ -21,6 +21,8 @@ me.garfieldhan.apatch.next"
|
||||
|
||||
ADDITION="
|
||||
com.google.android.gms
|
||||
com.google.android.gsf
|
||||
com.android.vending
|
||||
io.github.vvb2060.keyattestation
|
||||
io.github.vvb2060.mahoshojo
|
||||
icu.nullptr.nativetest"
|
||||
@@ -39,7 +41,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
|
||||
|
||||
@@ -1,33 +1,60 @@
|
||||
MODPATH="${0%/*}"
|
||||
COMPATH="$MODPATH/common"
|
||||
###########################################
|
||||
## This file is NOT a part of Tricky Store
|
||||
###########################################
|
||||
|
||||
MODPATH="/data/adb/modules/.TA_utl"
|
||||
ORG_PATH="$PATH"
|
||||
TMP_DIR="$MODPATH/common/tmp"
|
||||
SCRIPT_DIR="/data/adb/tricky_store"
|
||||
APK_PATH="$TMP_DIR/base.apk"
|
||||
|
||||
. "$COMPATH/util_func.sh"
|
||||
manual_download() {
|
||||
echo "$1"
|
||||
sleep 3
|
||||
am start -a android.intent.action.VIEW -d "https://github.com/5ec1cff/KsuWebUIStandalone/releases"
|
||||
exit 1
|
||||
}
|
||||
|
||||
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"
|
||||
else
|
||||
echo "- Skipping WebUI installation..."
|
||||
touch "$SKIP_FILE"
|
||||
echo "- Skip WebUI check until next installation."
|
||||
echo ""
|
||||
update_script
|
||||
fi
|
||||
download() {
|
||||
PATH=/data/adb/magisk:/data/data/com.termux/files/usr/bin:$PATH
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
timeout 10 curl -Ls "$1"
|
||||
else
|
||||
update_script
|
||||
timeout 10 busybox wget --no-check-certificate -qO- "$1"
|
||||
fi
|
||||
fi
|
||||
PATH="$ORG_PATH"
|
||||
}
|
||||
|
||||
get_webui() {
|
||||
echo "- Downloading KSU WebUI Standalone..."
|
||||
API="https://api.github.com/repos/5ec1cff/KsuWebUIStandalone/releases/latest"
|
||||
ping -c 1 -w 5 raw.githubusercontent.com &>/dev/null || manual_download "! Error: Unable to connect to raw.githubusercontent.com, please download manually."
|
||||
URL=$(download "$API" | grep -o '"browser_download_url": "[^"]*"' | cut -d '"' -f 4) || manual_download "! Error: Unable to get latest version, please download manually."
|
||||
download "$URL" > "$APK_PATH" || manual_download "! Error: APK download failed, please download manually."
|
||||
|
||||
echo "- Installing..."
|
||||
pm install -r "$APK_PATH" || {
|
||||
rm -f "$APK_PATH"
|
||||
manual_download "! Error: APK installation failed, please download manually.."
|
||||
}
|
||||
|
||||
echo "- Done."
|
||||
rm -f "$APK_PATH"
|
||||
|
||||
echo "- Launching WebUI..."
|
||||
am start -n "io.github.a13e300.ksuwebui/.WebUIActivity" -e id "tricky_store"
|
||||
}
|
||||
|
||||
# Launch KSUWebUI standalone or MMRL, install KSUWebUI standalone if both are not installed
|
||||
if pm path io.github.a13e300.ksuwebui >/dev/null 2>&1; then
|
||||
echo "- Launching WebUI in KSUWebUIStandalone..."
|
||||
am start -n "io.github.a13e300.ksuwebui/.WebUIActivity" -e id "tricky_store"
|
||||
elif pm path com.dergoogler.mmrl >/dev/null 2>&1; then
|
||||
echo "- Launching WebUI in MMRL WebUI..."
|
||||
am start -n "com.dergoogler.mmrl/.ui.activity.webui.WebUIActivity" -e MOD_ID "tricky_store"
|
||||
else
|
||||
echo "! No WebUI app found"
|
||||
get_webui
|
||||
fi
|
||||
|
||||
echo "- WebUI launched successfully."
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 " "
|
||||
@@ -1,6 +0,0 @@
|
||||
# This file is to pass Minotaur native test 'Partition Check Fail'
|
||||
# Download Key Attestation (chiteroman fork recommended)
|
||||
# Link: https://github.com/chiteroman/KeyAttestation/releases
|
||||
# Get your VerifiedBootHash value from Key Attestation app
|
||||
# Ask here if you don't know how to do: https://t.me/kowchannelchat
|
||||
# Paste verifiedBootHash value on next line and save
|
||||
@@ -1,28 +0,0 @@
|
||||
URL="https://github.com/5ec1cff/KsuWebUIStandalone/releases/download/v1.0/KsuWebUI-1.0-34-release.apk"
|
||||
APK_DIR="$COMPATH"
|
||||
LOG_FILE="$COMPATH/webuiError.log"
|
||||
|
||||
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."
|
||||
@@ -1,32 +1,167 @@
|
||||
#!/system/bin/sh
|
||||
|
||||
#!/bin/sh
|
||||
MODPATH=${0%/*}
|
||||
OUTPUT="$MODPATH/exclude-list"
|
||||
KBOUTPUT="$MODPATH/.extra"
|
||||
ORG_PATH="$PATH"
|
||||
SKIPLIST="$MODPATH/tmp/skiplist"
|
||||
XPOSED="$MODPATH/tmp/xposed"
|
||||
|
||||
. $MODPATH/util_func.sh
|
||||
|
||||
find_busybox
|
||||
check_wget
|
||||
|
||||
# Fetch Xposed module package names
|
||||
wget --no-check-certificate -q -O - "https://modules.lsposed.org/modules.json" 2>/dev/null | \
|
||||
grep -o '"name":"[^"]*","description":' | \
|
||||
awk -F'"' '{print $4}' > "$OUTPUT"
|
||||
|
||||
# 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
|
||||
echo "Error: Failed to fetch data." > "$OUTPUT"
|
||||
rm -f "$KBOUTPUT"
|
||||
exit 1
|
||||
if [ "$MODPATH" = "/data/adb/modules/.TA_utl/common" ]; then
|
||||
MODDIR="/data/adb/modules/.TA_utl"
|
||||
MAGISK="true"
|
||||
else
|
||||
MODDIR="/data/adb/modules/TA_utl"
|
||||
fi
|
||||
|
||||
wget --no-check-certificate -qO "$KBOUTPUT" "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/.extra"
|
||||
aapt() { "$MODPATH/aapt" "$@"; }
|
||||
|
||||
if [ ! -s "$KBOUTPUT" ]; then
|
||||
rm -f "$KBOUTPUT"
|
||||
fi
|
||||
# probe for downloaders
|
||||
# wget = low pref, no ssl.
|
||||
# curl, has ssl on android, we use it if found
|
||||
download() {
|
||||
PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:/data/data/com.termux/files/usr/bin:$PATH
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
timeout 10 curl -Ls "$1"
|
||||
else
|
||||
timeout 10 busybox wget --no-check-certificate -qO- "$1"
|
||||
fi
|
||||
PATH="$ORG_PATH"
|
||||
}
|
||||
|
||||
get_xposed() {
|
||||
touch "$XPOSED"
|
||||
pm list packages -3 | cut -d':' -f2 | grep -vxF -f "$SKIPLIST" | grep -vxF -f "$XPOSED" | 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" >> "$XPOSED"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
cat "$XPOSED"
|
||||
}
|
||||
|
||||
check_update() {
|
||||
[ -f "$MODDIR/disable" ] && rm -f "$MODDIR/disable"
|
||||
LOCAL_VERSION=$(grep '^versionCode=' "$MODPATH/update/module.prop" | awk -F= '{print $2}')
|
||||
if [ "$REMOTE_VERSION" -gt "$LOCAL_VERSION" ] && [ ! -f "/data/adb/modules/TA_utl/update" ]; then
|
||||
if [ "$MAGISK" = "true" ]; 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
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
if [ "$MAGISK" = "true" ]; then
|
||||
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"
|
||||
}
|
||||
|
||||
get_update() {
|
||||
download "$ZIP_URL" > "$MODPATH/tmp/module.zip"
|
||||
[ -s "$MODPATH/tmp/module.zip" ] || exit 1
|
||||
}
|
||||
|
||||
install_update() {
|
||||
PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH
|
||||
if command -v magisk >/dev/null 2>&1; then
|
||||
magisk --install-module "$MODPATH/tmp/module.zip" || exit 1
|
||||
elif command -v apd >/dev/null 2>&1; then
|
||||
apd module install "$MODPATH/tmp/module.zip" || exit 1
|
||||
elif command -v ksud >/dev/null 2>&1; then
|
||||
ksud module install "$MODPATH/tmp/module.zip" || exit 1
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f "$MODPATH/tmp/module.zip"
|
||||
rm -f "$MODPATH/tmp/changelog.md"
|
||||
rm -f "$MODPATH/tmp/version"
|
||||
}
|
||||
|
||||
release_note() {
|
||||
awk -v header="### $VERSION" '
|
||||
$0 == header {
|
||||
print;
|
||||
found = 1;
|
||||
next
|
||||
}
|
||||
found && /^###/ { exit }
|
||||
found { print }
|
||||
' "$MODPATH/tmp/changelog.md"
|
||||
}
|
||||
|
||||
set_security_patch() {
|
||||
# Find pif.json
|
||||
[ -f "/data/adb/modules/playintegrityfix/pif.json" ] && PIF="/data/adb/modules/playintegrityfix/pif.json"
|
||||
[ -f "/data/adb/pif.json" ] && PIF="/data/adb/pif.json"
|
||||
[ -f "/data/adb/modules/playintegrityfix/custom.pif.json" ] && PIF="/data/adb/modules/playintegrityfix/custom.pif.json"
|
||||
|
||||
security_patch=$(grep '"SECURITY_PATCH"' "$PIF" | sed 's/.*: "//; s/".*//')
|
||||
[ -z "$security_patch" ] && security_patch=$(getprop ro.build.version.security_patch) # Fallback
|
||||
|
||||
formatted_security_patch=$(echo "$security_patch" | sed 's/-//g')
|
||||
security_patch_after_1y=$(echo "$formatted_security_patch + 10000" | bc)
|
||||
TODAY=$(date +%Y%m%d)
|
||||
if [ -n "$formatted_security_patch" ] && [ "$TODAY" -lt "$security_patch_after_1y" ]; then
|
||||
TS_version=$(grep "versionCode=" "/data/adb/modules/tricky_store/module.prop" | cut -d'=' -f2)
|
||||
if [ "$TS_version" -lt 158 ]; then
|
||||
resetprop ro.vendor.build.security_patch "$security_patch"
|
||||
resetprop ro.build.version.security_patch "$security_patch"
|
||||
else
|
||||
SECURITY_PATCH_FILE="/data/adb/tricky_store/security_patch.txt"
|
||||
printf "system=prop\nboot=%s\nvendor=%s\n" "$security_patch" "$security_patch" > "$SECURITY_PATCH_FILE"
|
||||
chmod 644 "$SECURITY_PATCH_FILE"
|
||||
fi
|
||||
else
|
||||
echo "not set"
|
||||
fi
|
||||
}
|
||||
|
||||
get_latest_security_patch() {
|
||||
security_patch=$(download "https://source.android.com/docs/security/bulletin/pixel" | grep -o "<td>[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}</td>" | head -n 1 | sed 's/<td>\(.*\)<\/td>/\1/')
|
||||
[ -n "$security_patch" ] && echo "$security_patch" || exit 1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
--xposed)
|
||||
get_xposed
|
||||
exit
|
||||
;;
|
||||
--check-update)
|
||||
REMOTE_VERSION="$2"
|
||||
check_update
|
||||
exit
|
||||
;;
|
||||
--uninstall)
|
||||
uninstall
|
||||
exit
|
||||
;;
|
||||
--get-update)
|
||||
ZIP_URL="$2"
|
||||
get_update
|
||||
exit
|
||||
;;
|
||||
--install-update)
|
||||
install_update
|
||||
exit
|
||||
;;
|
||||
--release-note)
|
||||
VERSION="$2"
|
||||
release_note
|
||||
exit
|
||||
;;
|
||||
--security-patch)
|
||||
set_security_patch
|
||||
exit
|
||||
;;
|
||||
--get-security-patch)
|
||||
get_latest_security_patch
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
11
module/common/repo.json
Normal file
11
module/common/repo.json
Normal 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"
|
||||
}
|
||||
3
module/common/update/service.sh
Normal file
3
module/common/update/service.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
MODPATH=${0%/*}
|
||||
|
||||
rm -rf "$MODPATH"
|
||||
@@ -1,84 +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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -5,39 +5,46 @@ 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`
|
||||
ORG_DIR="/data/adb/modules/$MODID"
|
||||
NEW_MODID=".TA_utl"
|
||||
kb="$COMPATH/.default"
|
||||
|
||||
ui_print " ";
|
||||
ui_print " "
|
||||
if [ "$APATCH" ]; then
|
||||
ui_print "- APatch:$APATCH_VER│$APATCH_VER_CODE"
|
||||
ACTION=false
|
||||
elif [ "$KSU" ]; then
|
||||
ui_print "- KSU:$KSU_KERNEL_VER_CODE│$KSU_VER_CODE"
|
||||
if [ "$KSU_NEXT" ]; then
|
||||
ui_print "- KernelSU Next:$KSU_KERNEL_VER_CODE│$KSU_VER_CODE"
|
||||
else
|
||||
ui_print "- KernelSU:$KSU_KERNEL_VER_CODE│$KSU_VER_CODE"
|
||||
fi
|
||||
ACTION=false
|
||||
elif [ "$MAGISK_VER_CODE" ]; then
|
||||
ui_print "- Magisk:$MAGISK_VER│$MAGISK_VER_CODE"
|
||||
else
|
||||
ui_print " ";
|
||||
ui_print "! recovery is not supported";
|
||||
abort " ";
|
||||
ui_print " "
|
||||
ui_print "! recovery is not supported"
|
||||
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
|
||||
migrate_config
|
||||
|
||||
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 " "
|
||||
|
||||
@@ -1,96 +1,62 @@
|
||||
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
|
||||
cp "$MODPATH/module.prop" "$COMPATH/module.prop.orig"
|
||||
mv "$COMPATH/UpdateTargetList.sh" "$SCRIPT_DIR/UpdateTargetList.sh"
|
||||
# Cleanup left over
|
||||
[ -d "/data/adb/modules/$NEW_MODID" ] && rm -rf "/data/adb/modules/$NEW_MODID"
|
||||
|
||||
sed -i "s|\"set-path\"|\"/data/adb/modules/$MODID/common/\"|" "$MODPATH/webroot/index.js" || {
|
||||
ui_print "! Failed to set path"
|
||||
abort
|
||||
}
|
||||
sed -i "s|\"set-id\"|\"$MODID\"|" "$COMPATH/util_func.sh" || {
|
||||
ui_print "! Failed to set id"
|
||||
abort
|
||||
}
|
||||
|
||||
mkdir -p "$MODPATH/system/bin"
|
||||
mv "$MODPATH/bin/$(getprop ro.product.cpu.abi)/aapt" "$COMPATH/aapt"
|
||||
rm -rf "$MODPATH/bin"
|
||||
|
||||
set_perm $COMPATH/aapt 0 2000 0755
|
||||
set_perm $SCRIPT_DIR/UpdateTargetList.sh 0 2000 0755
|
||||
# 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"
|
||||
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
|
||||
}
|
||||
|
||||
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"
|
||||
# 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"
|
||||
}
|
||||
|
||||
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() {
|
||||
if [ ! -f "/data/adb/boot_hash" ]; then
|
||||
if [ -f "$ORG_DIR/boot_hash" ]; then
|
||||
mv "$ORG_DIR/boot_hash" "/data/adb/boot_hash"
|
||||
fi
|
||||
mv "$COMPATH/boot_hash" "/data/adb/boot_hash"
|
||||
else
|
||||
rm -f "$COMPATH/boot_hash"
|
||||
migrate_config() {
|
||||
# remove empty file
|
||||
if [ -f "/data/adb/boot_hash" ]; then
|
||||
hash_value=$(grep -v '^#' "/data/adb/boot_hash" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')
|
||||
[ -z "$hash_value" ] && rm -f /data/adb/boot_hash || echo "$hash_value" > /data/adb/boot_hash
|
||||
fi
|
||||
|
||||
# Migrate from old version setup
|
||||
if [ -f "$ORG_DIR/system.prop" ]; then
|
||||
hash_value=$(sed -n 's/^ro.boot.vbmeta.digest=//p' "$ORG_DIR/system.prop")
|
||||
if [ -n "$hash_value" ]; then
|
||||
echo -e "\n$hash_value" >> "/data/adb/boot_hash"
|
||||
# Migrate security_patch config*
|
||||
if [ -f "/data/adb/security_patch" ]; then
|
||||
if grep -q "^auto_config=1" "/data/adb/security_patch"; then
|
||||
touch "/data/adb/tricky_store/security_patch_auto_config"
|
||||
fi
|
||||
rm -f "/data/adb/security_patch"
|
||||
fi
|
||||
}
|
||||
|
||||
# Additional system app
|
||||
if [ ! -f "/data/adb/tricky_store/system_app" ]; then
|
||||
SYSTEM_APP="
|
||||
com.google.android.gms
|
||||
com.google.android.gsf
|
||||
com.android.vending
|
||||
com.oplus.deepthinker
|
||||
com.heytap.speechassist
|
||||
com.coloros.sceneservice"
|
||||
touch "/data/adb/tricky_store/system_app"
|
||||
for app in $SYSTEM_APP; do
|
||||
if pm list packages -s | grep -q "$app"; then
|
||||
echo "$app" >> "/data/adb/tricky_store/system_app"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
id=TA_utl
|
||||
name=Tricky Addon - Update Target List
|
||||
version=v2.5
|
||||
versionCode=250
|
||||
version=v3.8.1
|
||||
versionCode=381
|
||||
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
19
module/post-fs-data.sh
Normal 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
|
||||
|
||||
[ -L "$TS/webroot" ] && rm -f "$TS/webroot"
|
||||
[ -L "$TS/action.sh" ] && rm -f "$TS/action.sh"
|
||||
@@ -1,13 +1,48 @@
|
||||
MODPATH=${0%/*}
|
||||
HIDE_DIR="/data/adb/modules/.TA_utl"
|
||||
TS="/data/adb/modules/tricky_store"
|
||||
SCRIPT_DIR="/data/adb/tricky_store"
|
||||
TSPA="/data/adb/modules/tsupport-advance"
|
||||
|
||||
hash_value=$(grep -v '^#' "/data/adb/boot_hash" | tr -d '[:space:]')
|
||||
if [ -n "$hash_value" ]; then
|
||||
resetprop -n ro.boot.vbmeta.digest "$hash_value"
|
||||
aapt() { "$MODPATH/common/aapt" "$@"; }
|
||||
|
||||
add_denylist_to_target() {
|
||||
exclamation_target=$(grep '!' "/data/adb/tricky_store/target.txt" | sed 's/!$//')
|
||||
question_target=$(grep '?' "/data/adb/tricky_store/target.txt" | sed 's/?$//')
|
||||
target=$(sed 's/[!?]$//' /data/adb/tricky_store/target.txt)
|
||||
denylist=$(magisk --denylist ls 2>/dev/null | awk -F'|' '{print $1}' | grep -v "isolated")
|
||||
|
||||
printf "%s\n" "$target" "$denylist" | sort -u > "/data/adb/tricky_store/target.txt"
|
||||
|
||||
for target in $exclamation_target; do
|
||||
sed -i "s/^$target$/$target!/" "/data/adb/tricky_store/target.txt"
|
||||
done
|
||||
|
||||
for target in $question_target; do
|
||||
sed -i "s/^$target$/$target?/" "/data/adb/tricky_store/target.txt"
|
||||
done
|
||||
}
|
||||
|
||||
resetprop_if_empty() {
|
||||
CURRENT=$(getprop "$1")
|
||||
[ -z "$CURRENT" ] && resetprop -n "$1" "$2"
|
||||
}
|
||||
|
||||
# Spoof security patch
|
||||
if [ -f "/data/adb/tricky_store/security_patch_auto_config" ]; then
|
||||
sh "$MODPATH/common/get_extra.sh" --security-patch
|
||||
fi
|
||||
|
||||
# Reset vbmeta related prop
|
||||
if [ -f "/data/adb/boot_hash" ]; then
|
||||
hash_value=$(grep -v '^#' "/data/adb/boot_hash" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')
|
||||
[ -z "$hash_value" ] && rm -f /data/adb/boot_hash || resetprop -n ro.boot.vbmeta.digest "$hash_value"
|
||||
fi
|
||||
resetprop_if_empty "ro.boot.vbmeta.device_state" "locked"
|
||||
resetprop_if_empty "ro.boot.vbmeta.invalidate_on_error" "yes"
|
||||
resetprop_if_empty "ro.boot.vbmeta.avb_version" "1.0"
|
||||
resetprop_if_empty "ro.boot.vbmeta.hash_alg" "sha256"
|
||||
resetprop_if_empty "ro.boot.vbmeta.size" "10496"
|
||||
|
||||
# Disable TSupport-A auto update target to prevent overwrite
|
||||
if [ -d "$TSPA" ]; then
|
||||
touch "/storage/emulated/0/stop-tspa-auto-target"
|
||||
@@ -15,25 +50,82 @@ elif [ ! -d "$TSPA" ] && [ -f "/storage/emulated/0/stop-tspa-auto-target" ]; the
|
||||
rm -f "/storage/emulated/0/stop-tspa-auto-target"
|
||||
fi
|
||||
|
||||
if [ ! -f "$MODPATH/common/module.prop.orig" ]; then
|
||||
sed -i 's/^description=.*/description=Module is corrupted, please reinstall module./' "$MODPATH/module.prop"
|
||||
touch "$MODPATH/disable"
|
||||
exit 1
|
||||
# Magisk operation
|
||||
if [ -f "$MODPATH/action.sh" ]; then
|
||||
# Hide module from Magisk manager
|
||||
if [ "$MODPATH" != "$HIDE_DIR" ]; then
|
||||
rm -rf "$HIDE_DIR"
|
||||
mkdir -p "$HIDE_DIR"
|
||||
busybox chcon --reference="$MODPATH" "$HIDE_DIR"
|
||||
cp -af "$MODPATH/." "$HIDE_DIR/"
|
||||
fi
|
||||
MODPATH="$HIDE_DIR"
|
||||
|
||||
# Add target from denylist
|
||||
# To trigger this, choose "Select from DenyList" in WebUI once
|
||||
[ -f "/data/adb/tricky_store/target_from_denylist" ] && add_denylist_to_target
|
||||
else
|
||||
[ -d "$HIDE_DIR" ] && rm -rf "$HIDE_DIR"
|
||||
fi
|
||||
|
||||
if [ ! -d "$TS" ]; then
|
||||
sed -i 's/^description=.*/description=Tricky store is not installed/' "$MODPATH/module.prop"
|
||||
touch "$MODPATH/disable"
|
||||
elif [ -f "$TS/disable" ]; then
|
||||
sed -i 's/^description=.*/description=Tricky store is disabled/' "$MODPATH/module.prop"
|
||||
touch "$MODPATH/disable"
|
||||
elif [ ! -f "$SCRIPT_DIR/UpdateTargetList.sh" ]; then
|
||||
sed -i 's/^description=.*/description=Script missing, please install module again/' "$MODPATH/module.prop"
|
||||
touch "$MODPATH/disable"
|
||||
# Hide module from APatch, KernelSU, KSUWebUIStandalone, MMRL
|
||||
rm -f "$MODPATH/module.prop"
|
||||
|
||||
# Symlink tricky store
|
||||
if [ -f "$MODPATH/action.sh" ] && [ ! -e "$TS/action.sh" ]; then
|
||||
ln -s "$MODPATH/action.sh" "$TS/action.sh"
|
||||
fi
|
||||
if [ ! -e "$TS/webroot" ]; then
|
||||
ln -s "$MODPATH/webui" "$TS/webroot"
|
||||
fi
|
||||
|
||||
# Optimization
|
||||
OUTPUT_APP="$MODPATH/webui/applist.json"
|
||||
OUTPUT_SKIP="$MODPATH/common/tmp/skiplist"
|
||||
OUTPUT_XPOSED="$MODPATH/common/tmp/xposed"
|
||||
|
||||
until [ "$(getprop sys.boot_completed)" = "1" ]; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Create temporary directory
|
||||
mkdir -p "$MODPATH/common/tmp"
|
||||
|
||||
# Additional system apps
|
||||
if [ -f "/data/adb/tricky_store/system_app" ]; then
|
||||
SYSTEM_APP=$(cat "/data/adb/tricky_store/system_app" | tr '\n' '|' | sed 's/|*$//')
|
||||
else
|
||||
cat "$MODPATH/common/module.prop.orig" > "$MODPATH/module.prop"
|
||||
until [ "$(getprop sys.boot_completed)" = "1" ]; do
|
||||
sleep 1
|
||||
done
|
||||
. "$SCRIPT_DIR/UpdateTargetList.sh"
|
||||
fi
|
||||
SYSTEM_APP=""
|
||||
fi
|
||||
|
||||
# Initialize cache files to save app list and skip list
|
||||
echo "[" > "$OUTPUT_APP"
|
||||
echo "# This file is generated from service.sh to speed up load time" > "$OUTPUT_SKIP"
|
||||
|
||||
# Get list of third party apps and specific system apps, then cache app name
|
||||
# Check Xposed module
|
||||
{
|
||||
pm list packages -3 2>/dev/null
|
||||
pm list packages -s | grep -E "$SYSTEM_APP" 2>/dev/null || true
|
||||
} | awk -F: '{print $2}' | while read -r PACKAGE; do
|
||||
# Get APK path for the package
|
||||
APK_PATH=$(pm path "$PACKAGE" 2>/dev/null | grep "base.apk" | awk -F: '{print $2}')
|
||||
[ -z "$APK_PATH" ] && APK_PATH=$(pm path "$PACKAGE" 2>/dev/null | grep ".apk" | awk -F: '{print $2}')
|
||||
|
||||
APP_NAME=$(aapt dump badging "$APK_PATH" 2>/dev/null | grep "application-label:" | sed "s/application-label://g; s/'//g")
|
||||
[ -z "$APP_NAME" ] && APP_NAME="$PACKAGE"
|
||||
echo " {\"app_name\": \"$APP_NAME\", \"package_name\": \"$PACKAGE\"}," >> "$OUTPUT_APP"
|
||||
|
||||
# Check if app is Xposed module and add to skip list if not
|
||||
touch "$OUTPUT_XPOSED"
|
||||
if aapt dump xmltree "$APK_PATH" AndroidManifest.xml 2>/dev/null | grep -qE "xposed.category|xposeddescription"; then
|
||||
echo "$PACKAGE" >> "$OUTPUT_XPOSED"
|
||||
else
|
||||
echo "$PACKAGE" >> "$OUTPUT_SKIP"
|
||||
fi
|
||||
done
|
||||
|
||||
sed -i '$ s/,$//' "$OUTPUT_APP"
|
||||
echo "]" >> "$OUTPUT_APP"
|
||||
|
||||
[ -f "$MODPATH/action.sh" ] && rm -rf "/data/adb/modules/TA_utl"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
MODPATH=${0%/*}
|
||||
TS="/data/adb/modules/tricky_store"
|
||||
SCRIPT_DIR="/data/adb/tricky_store"
|
||||
|
||||
# Enable back TSupport-A auto update
|
||||
@@ -7,7 +8,14 @@ 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"
|
||||
rm -f "/data/adb/tricky_store/security_patch_auto_config"
|
||||
rm -f "/data/adb/tricky_store/target_from_denylist"
|
||||
rm -f "/data/adb/tricky_store/system_app"
|
||||
if [ -d "$TS" ]; then
|
||||
[ -L "$TS/webroot" ] && rm -f "$TS/webroot"
|
||||
[ -L "$TS/action.sh" ] && rm -f "$TS/action.sh"
|
||||
fi
|
||||
mv -f "$SCRIPT_DIR/keybox.xml" "$SCRIPT_DIR/keybox.xml.bak"
|
||||
xxd -r -p "$MODPATH/common/.default" | base64 -d > "$SCRIPT_DIR/keybox.xml"
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<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>
|
||||
<div class="title-container">
|
||||
<div id="title">Tricky Addon - Update Target List</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>
|
||||
<div id="help-overlay" class="help-overlay">
|
||||
<div class="help-menu">
|
||||
<button id="close-help" class="close-help">✕</button>
|
||||
<div class="help-content">
|
||||
<p>Instructions</p>
|
||||
<ul>
|
||||
<li>Save and Update
|
||||
<ul>
|
||||
<li>Save the current configuration and update target.txt immediately.</li>
|
||||
<li><br></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Refresh
|
||||
<ul>
|
||||
<li>Refresh app list and exclude list.</li>
|
||||
<li><br></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Select All & Deselect All
|
||||
<ul>
|
||||
<li>Select or deselect all apps in the current interface.</li>
|
||||
<li><br></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Select From DenyList
|
||||
<ul>
|
||||
<li>Available in Magisk only, select apps that in the DenyList. Recommended.</li>
|
||||
<li><br></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Deselect Unnecessary
|
||||
<ul>
|
||||
<li>Unnecessary category: Xposed module, root manager, root-related apps, and general apps
|
||||
that never check bootloader status. This option requrie Internet connection.</li>
|
||||
<ul>
|
||||
<li>Contribute to <a
|
||||
href="https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/more-excldue.json"
|
||||
target="_blank">unnecessary app list</a>? Create an <a
|
||||
href="https://github.com/KOWX712/Tricky-Addon-Update-Target-List/issues"
|
||||
target="_blank">issue</a> or <a
|
||||
href="https://github.com/KOWX712/Tricky-Addon-Update-Target-List/pulls"
|
||||
target="_blank">pull request</a>.</li>
|
||||
</ul>
|
||||
<li><br></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Set AOSP & Valid Keybox
|
||||
<ul>
|
||||
<li>Replace tricky store keybox.xml<br><strong>AOSP keybox:</strong> Device
|
||||
Integrity.<br><strong>Valid keybox:</strong> Strong Integrity, fallback to Basic
|
||||
Integrity if revoked.<br>AOSP keybox will be replaced if there's no more valid keybox.
|
||||
Valid keybox option require Internet connection.</li>
|
||||
<li><br></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
<button class="clear-btn" id="clear-btn">✕</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">Refresh</li>
|
||||
<li id="select-all">Select All</li>
|
||||
<li id="deselect-all">Deselect All</li>
|
||||
<li id="select-denylist">Select From DenyList</li>
|
||||
<li id="deselect-unnecessary">Deselect Unnecessary</li>
|
||||
<li id="aospkb">Set AOSP Keybox</li>
|
||||
<li id="extrakb">Set Valid Keybox</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="apps-list"></div>
|
||||
<div class="floating-card">
|
||||
<button class="floating-btn" id="save">Save and Update</button>
|
||||
</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>
|
||||
<div class="loading">Loading...</div>
|
||||
<div class="acknowledgment">Credit to j-hc/zygisk-detach WebUI</div>
|
||||
<div id="prompt" class="prompt"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,479 +0,0 @@
|
||||
let e = 0;
|
||||
const appTemplate = document.getElementById("app-template").content;
|
||||
const appListContainer = document.getElementById("apps-list");
|
||||
const loadingIndicator = document.querySelector(".loading");
|
||||
const searchMenuContainer = document.querySelector('.search-menu-container');
|
||||
const searchInput = document.getElementById("search");
|
||||
const clearBtn = document.getElementById("clear-btn");
|
||||
const title = document.querySelector('.title-container');
|
||||
const noConnection = document.querySelector(".no-connection");
|
||||
const helpButton = document.getElementById("help-button");
|
||||
const helpOverlay = document.getElementById("help-overlay");
|
||||
const closeHelp = document.getElementById("close-help");
|
||||
const searchCard = document.querySelector('.search-card');
|
||||
const menu = document.querySelector('.menu');
|
||||
const selectDenylistElement = document.getElementById("select-denylist");
|
||||
const floatingBtn = document.querySelector('.floating-btn');
|
||||
const basePath = "set-path";
|
||||
let excludeList = [];
|
||||
let isRefreshing = false;
|
||||
|
||||
// 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();
|
||||
const result = await execCommand(`
|
||||
pm list packages -3 | while read -r line; do
|
||||
PACKAGE=$(echo "$line" | awk -F: '{print $2}')
|
||||
APK_PATH=$(pm path "$PACKAGE" | grep "base.apk" | awk -F: '{print $2}' | tr -d '\\r')
|
||||
if [ -n "$APK_PATH" ]; then
|
||||
APP_NAME=$( ${basePath}aapt dump badging "$APK_PATH" 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g" )
|
||||
echo "$APP_NAME|$PACKAGE"
|
||||
else
|
||||
echo "Unknown App|$PACKAGE"
|
||||
fi
|
||||
done
|
||||
`);
|
||||
const appEntries = result.split("\n").map(line => {
|
||||
const [appName, packageName] = line.split("|").map(item => item.trim());
|
||||
return { appName, packageName };
|
||||
}).filter(entry => entry.packageName); // Remove invalid entries
|
||||
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 = ""; // Clear the container before rendering
|
||||
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(-100px)";
|
||||
}
|
||||
|
||||
// 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';
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
window.scrollTo(0, 0);
|
||||
if (noConnection.style.display === "flex") {
|
||||
await runExtraScript();
|
||||
}
|
||||
await fetchAppList();[]
|
||||
loadingIndicator.style.display = 'none';
|
||||
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`;
|
||||
await execCommand(scriptPath);
|
||||
console.log("Extra script executed successfully.");
|
||||
noConnection.style.display = "none";
|
||||
} catch (error) {
|
||||
console.error("Failed to execute Extra script:", error);
|
||||
showPrompt("Please check your Internet connection", 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 keybox set successfully.");
|
||||
} catch (error) {
|
||||
console.error("Failed to copy AOSP keybox:", error);
|
||||
showPrompt("Failed to update keybox.", 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 keybox set successfully.");
|
||||
} catch (error) {
|
||||
console.error("Failed to copy valid keybox:", error);
|
||||
await aospkb();
|
||||
showPrompt("No valid keybox found, replaced with AOSP keybox.", false);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to show the prompt with a success or error message
|
||||
function showPrompt(message, isSuccess = true) {
|
||||
const prompt = document.getElementById('prompt');
|
||||
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 menuButton = document.getElementById('menu-button');
|
||||
const menuIcon = menuButton.querySelector('.menu-icon');
|
||||
const menuOptions = document.getElementById('menu-options');
|
||||
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'];
|
||||
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("Config and target.txt updated");
|
||||
} catch (error) {
|
||||
console.error("Failed to update target list:", error);
|
||||
showPrompt("Config saved, but failed to update target list", false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to update EXCLUDE file:", error);
|
||||
showPrompt("Failed to save config", false);
|
||||
}
|
||||
await readExcludeFile();
|
||||
await refreshAppList();
|
||||
});
|
||||
|
||||
// Initial load
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
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);
|
||||
await fetchAppList();
|
||||
checkMagisk();
|
||||
runExtraScript();
|
||||
loadingIndicator.style.display = "none";
|
||||
});
|
||||
|
||||
// Scroll event
|
||||
let lastScrollY = window.scrollY;
|
||||
const scrollThreshold = 35;
|
||||
window.addEventListener('scroll', () => {
|
||||
if (isRefreshing) return;
|
||||
if (window.scrollY > lastScrollY && window.scrollY > scrollThreshold) {
|
||||
title.style.transform = 'translateY(-100%)';
|
||||
searchMenuContainer.style.transform = 'translateY(-35px)';
|
||||
floatingBtn.style.transform = 'translateY(0)';
|
||||
} else if (window.scrollY < lastScrollY) {
|
||||
title.style.transform = 'translateY(0)';
|
||||
searchMenuContainer.style.transform = 'translateY(0)';
|
||||
floatingBtn.style.transform = 'translateY(-100px)';
|
||||
}
|
||||
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();
|
||||
}
|
||||
});
|
||||
@@ -1,424 +0,0 @@
|
||||
body {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.no-scroll {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
height: 40px;
|
||||
width: calc(100% - 17px);
|
||||
background-color: #F5F5F5;
|
||||
transition: transform 0.3s ease;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.no-connection {
|
||||
display: none;
|
||||
align-items: center;
|
||||
color: #7E7E7E;
|
||||
}
|
||||
|
||||
.no-connection .wifi-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
filter: invert(0.6) sepia(0) saturate(0) hue-rotate(180deg) brightness(0.8) contrast(1);
|
||||
}
|
||||
|
||||
.help-button {
|
||||
margin-right: auto;
|
||||
padding: 0 10px;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
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;
|
||||
}
|
||||
|
||||
#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: 15px 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: -50px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.floating-btn {
|
||||
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 {
|
||||
color: #6E6E6E;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: calc(100vh - 164px);
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.acknowledgment {
|
||||
color: #6E6E6E;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #121212;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.title-container {
|
||||
background-color: #121212;
|
||||
}
|
||||
|
||||
.help-button {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.help-menu,
|
||||
.card,
|
||||
.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;
|
||||
}
|
||||
}
|
||||
@@ -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 |
360
module/webui/index.html
Normal file
360
module/webui/index.html
Normal file
@@ -0,0 +1,360 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<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/file_selector.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" href="styles/security_patch.css" type="text/css">
|
||||
<link rel="stylesheet" href="styles/system_app.css" type="text/css">
|
||||
<script type="module" crossorigin src="scripts/main.js"></script>
|
||||
<script type="module" crossorigin src="scripts/about.js"></script>
|
||||
<script type="module" crossorigin src="scripts/help.js"></script>
|
||||
<script type="module" crossorigin src="scripts/boot_hash.js"></script>
|
||||
<script type="module" crossorigin src="scripts/security_patch.js"></script>
|
||||
<script src="scripts/marked.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<div id="title" data-i18n="header.title"></div><span id="module-version"></span>
|
||||
<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="22px" viewBox="0 -960 960 960" width="22px"><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 ripple-element" id="save" data-i18n="functional_button.save_and_update_button"></button>
|
||||
</div>
|
||||
|
||||
<!-- Menu Options -->
|
||||
<div class="search-menu-container">
|
||||
<div class="search-card ripple-element">
|
||||
<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">✕</button>
|
||||
</div>
|
||||
<div class="menu">
|
||||
<input type="checkbox" id="menu-toggle" class="menu-toggle">
|
||||
<label for="menu-toggle" class="menu-button ripple-element" 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 class="ripple-element" id="refresh" data-i18n="menu.refresh"></li>
|
||||
<li class="ripple-element" id="select-all" data-i18n="menu.select_all"></li>
|
||||
<li class="ripple-element" id="deselect-all" data-i18n="menu.deselect_all"></li>
|
||||
<li class="ripple-element" id="select-denylist" data-i18n="menu.select_denylist"></li>
|
||||
<li class="ripple-element" id="deselect-unnecessary" data-i18n="menu.deselect_unnecessary"></li>
|
||||
<li class="ripple-element" id="add-system-app" data-i18n="menu.add_system_app"></li>
|
||||
<li class="ripple-element" id="aospkb" data-i18n="menu.set_aosp_keybox"></li>
|
||||
<li class="ripple-element" id="validkb" data-i18n="menu.set_valid_keybox"></li>
|
||||
<li class="ripple-element" id="customkb" data-i18n="menu.set_custom_keybox"></li>
|
||||
<li class="ripple-element" id="boot-hash" data-i18n="menu.set_verified_boot_hash"></li>
|
||||
<li class="ripple-element" id="security-patch" data-i18n="menu.set_security_patch"></li>
|
||||
<li class="ripple-element" 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 ripple-element" id="update-card">
|
||||
<p id="update-available" data-i18n="update.update_available"></p>
|
||||
<p id="redirect-to-release" data-i18n="update.redirect_to_release"></p>
|
||||
</div>
|
||||
<div class="mode-overlay"></div>
|
||||
<template id="app-template">
|
||||
<div class="card-box">
|
||||
<div class="card ripple-element" id="card">
|
||||
<div class="content" data-package="">
|
||||
<div class="mode">
|
||||
<label class="mode-switch" id="normal">
|
||||
<input type="radio" class="mode-input" id="normal-mode">
|
||||
<i class="mode-icon">
|
||||
<div class="status-indicator ripple-element" id="normal-indicator">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#ffffff"><path d="M480-480Zm0 280q-116 0-198-82t-82-198q0-116 82-198t198-82q116 0 198 82t82 198q0 116-82 198t-198 82Zm0-80q83 0 141.5-58.5T680-480q0-83-58.5-141.5T480-680q-83 0-141.5 58.5T280-480q0 83 58.5 141.5T480-280Z"/></svg>
|
||||
</div>
|
||||
</i>
|
||||
</label>
|
||||
<label class="mode-switch" id="generate">
|
||||
<input type="radio" class="mode-input" id="generate-mode">
|
||||
<i class="mode-icon">
|
||||
<div class="status-indicator ripple-element" id="generate-indicator">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 -960 960 960" width="18px" fill="#ffffff"><path d="M480-120q-33 0-56.5-23.5T400-200q0-33 23.5-56.5T480-280q33 0 56.5 23.5T560-200q0 33-23.5 56.5T480-120Zm-80-240v-480h160v480H400Z"/></svg>
|
||||
</div>
|
||||
</i>
|
||||
</label>
|
||||
<label class="mode-switch" id="hack">
|
||||
<input type="radio" class="mode-input" id="hack-mode">
|
||||
<i class="mode-icon">
|
||||
<div class="status-indicator ripple-element" id="hack-indicator">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="19px" viewBox="0 -960 960 960" width="19px" fill="#ffffff"><path d="M424-320q0-81 14.5-116.5T500-514q41-36 62.5-62.5T584-637q0-41-27.5-68T480-732q-51 0-77.5 31T365-638l-103-44q21-64 77-111t141-47q105 0 161.5 58.5T698-641q0 50-21.5 85.5T609-475q-49 47-59.5 71.5T539-320H424Zm56 240q-33 0-56.5-23.5T400-160q0-33 23.5-56.5T480-240q33 0 56.5 23.5T560-160q0 33-23.5 56.5T480-80Z"/></svg>
|
||||
</div>
|
||||
</i>
|
||||
</label>
|
||||
</div>
|
||||
<p class="name"></p>
|
||||
<div class="checkbox-wrapper">
|
||||
<input type="checkbox" class="checkbox" id="checkbox1" disabled />
|
||||
<label for="checkbox1" class="custom-checkbox">
|
||||
<span class="tick-symbol">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -3 26 26" width="16px" height="16px" fill="#fff"><path d="M 22.566406 4.730469 L 20.773438 3.511719 C 20.277344 3.175781 19.597656 3.304688 19.265625 3.796875 L 10.476563 16.757813 L 6.4375 12.71875 C 6.015625 12.296875 5.328125 12.296875 4.90625 12.71875 L 3.371094 14.253906 C 2.949219 14.675781 2.949219 15.363281 3.371094 15.789063 L 9.582031 22 C 9.929688 22.347656 10.476563 22.613281 10.96875 22.613281 C 11.460938 22.613281 11.957031 22.304688 12.277344 21.839844 L 22.855469 6.234375 C 23.191406 5.742188 23.0625 5.066406 22.566406 4.730469 Z"/></svg>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Help Overlay -->
|
||||
<div id="help-overlay" class="help-overlay overlay">
|
||||
<div class="help-menu overlay-content">
|
||||
<button id="close-help" class="close-btn">✕</button>
|
||||
<div class="help-content">
|
||||
<div class="help-content-header" data-i18n="help.help_instructions"></div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.save_and_update"></strong>
|
||||
<p data-i18n="help.save_and_update_description"></p>
|
||||
</div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.refresh"></strong>
|
||||
<p data-i18n="help.refresh_description"></p>
|
||||
</div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.select_deselect"></strong>
|
||||
<p data-i18n="help.select_description"></p>
|
||||
</div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.select_denylist"></strong>
|
||||
<p data-i18n="help.select_denylist_description"></p>
|
||||
</div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.deselect_unnecessary"></strong>
|
||||
<p data-i18n="help.deselect_unnecessary_description"></p>
|
||||
</div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.add_system_app"></strong>
|
||||
<p data-i18n="help.add_system_app_description"></p>
|
||||
</div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.set_keybox"></strong>
|
||||
<p data-i18n="help.set_keybox_description"></p>
|
||||
</div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.set_custom_keybox"></strong>
|
||||
<p data-i18n="help.set_custom_keybox_description"></p>
|
||||
</div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.set_security_patch"></strong>
|
||||
<p data-i18n="help.set_security_patch_description"></p>
|
||||
</div>
|
||||
<div class="instruction">
|
||||
<strong data-i18n="help.set_verified_boot_hash"></strong>
|
||||
<p data-i18n="help.set_verified_boot_hash_description"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- BootHash Input Overlay -->
|
||||
<div id="boot-hash-overlay" class="boot-hash-overlay overlay">
|
||||
<div id="boot-hash-card" class="boot-hash-card overlay-content">
|
||||
<div class="boot-hash-title" data-i18n="boot_hash.title"></div>
|
||||
<textarea id="boot-hash-input" class="boot-hash-input" placeholder="Paste your verified Boot Hash here" data-i18n="boot_hash.input_placeholder" oninput="window.trimInput(this)"></textarea>
|
||||
<button id="boot-hash-save-button" class="boot-hash-save-button ripple-element" data-i18n="boot_hash.save_button"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- About Overlay -->
|
||||
<div id="about-overlay" class="about-overlay overlay">
|
||||
<div class="about-menu overlay-content">
|
||||
<button id="close-about" class="close-btn">✕</button>
|
||||
<div class="about-title">
|
||||
<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>
|
||||
</div>
|
||||
<div id="disclaimer" data-i18n="about.disclaimer"></div>
|
||||
<div class="link">
|
||||
<i class="link-icon ripple-element" 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 ripple-element" 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>
|
||||
<div class="acknowledgment">
|
||||
<p id="acknowledgment" data-i18n="about.acknowledgment"></p>
|
||||
<p>j-hc/zygisk-detach: WebUI template</p>
|
||||
<p>markedjs/marked: Markdown Support</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Update Overlay -->
|
||||
<div class="update-overlay overlay">
|
||||
<div class="update-menu overlay-content">
|
||||
<button id="close-update" class="close-btn">✕</button>
|
||||
<div class="update-content">
|
||||
<h1 data-i18n="update.changelog"></h1>
|
||||
<div class="changelog"></div>
|
||||
<div class="update-button-container">
|
||||
<button class="install ripple-element" data-i18n="update.install"></button>
|
||||
<button class="reboot ripple-element" data-i18n="update.reboot"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MMRL Permission Request Overlay -->
|
||||
<div id="permission-popup" class="permission-popup overlay">
|
||||
<div class="permission-content">
|
||||
<h2 id="permission-title">Please allow JavaScript API in MMRL settings</h2>
|
||||
<div class="permission-steps">
|
||||
<ol>
|
||||
<li>Settings</li>
|
||||
<li>Security</li>
|
||||
<li>Allow JavaScript API</li>
|
||||
<li>Tricky Store</li>
|
||||
<li>Enable "Allow Advanced KernelSU API"</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- File Selector Overlay -->
|
||||
<div class="file-selector-overlay overlay">
|
||||
<div class="file-selector overlay-content">
|
||||
<div class="file-selector-header">
|
||||
<button class="back-button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="22px" viewBox="40 -1050 900 960" width="22px"><path d="M400-93.85 13.85-480 400-866.15l56.77 56.77L127.38-480l329.39 329.38L400-93.85Z"/></svg>
|
||||
</button>
|
||||
<div class="current-path">/storage/emulated/0/Download</div>
|
||||
<button class="close-selector">✕</button>
|
||||
</div>
|
||||
<div class="file-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Security Patch Overlay -->
|
||||
<div id="security-patch-overlay" class="security-patch-overlay overlay">
|
||||
<div id="security-patch-card" class="security-patch-card overlay-content">
|
||||
<div class="security-patch-header" data-i18n="security_patch.title"></div>
|
||||
<div class="security-patch-content">
|
||||
<div id="normal-mode-inputs" class="normal-mode-inputs">
|
||||
<div class="input-group">
|
||||
<label id="security_patch-all">All</label>
|
||||
<input type="text" id="all-patch" placeholder="20250101" maxlength="8" autocapitalize="none">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="advanced-mode-inputs" class="advanced-mode-inputs hidden">
|
||||
<div class="input-group">
|
||||
<label id="security_patch-system">System</label>
|
||||
<input type="text" id="system-patch" placeholder="202501" maxlength="6" autocapitalize="none">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label id="security_patch-boot">Boot</label>
|
||||
<input type="text" id="boot-patch" placeholder="2025-01-01" autocapitalize="none" oninput="formatDate(this, 'boot')" maxlength="10">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label id="security_patch-vendor">Vendor</label>
|
||||
<input type="text" id="vendor-patch" placeholder="2025-01-01" autocapitalize="none" oninput="formatDate(this, 'vendor')" maxlength="10">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="advanced-toggle">
|
||||
<input type="checkbox" class="checkbox" id="advanced-mode" />
|
||||
<label for="advanced-mode" class="custom-checkbox">
|
||||
<span class="tick-symbol">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -3 26 26" width="16px" height="16px" fill="#fff">
|
||||
<path d="M 22.566406 4.730469 L 20.773438 3.511719 C 20.277344 3.175781 19.597656 3.304688 19.265625 3.796875 L 10.476563 16.757813 L 6.4375 12.71875 C 6.015625 12.296875 5.328125 12.296875 4.90625 12.71875 L 3.371094 14.253906 C 2.949219 14.675781 2.949219 15.363281 3.371094 15.789063 L 9.582031 22 C 9.929688 22.347656 10.476563 22.613281 10.96875 22.613281 C 11.460938 22.613281 11.957031 22.304688 12.277344 21.839844 L 22.855469 6.234375 C 23.191406 5.742188 23.0625 5.066406 22.566406 4.730469 Z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</label>
|
||||
<label for="advanced-mode" data-i18n="security_patch.advanced_mode"></label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button id="get-patch" class="get-button ripple-element" data-i18n="security_patch.get_date"></button>
|
||||
<div class="button-container">
|
||||
<button id="auto-config" class="auto-button ripple-element" data-i18n="security_patch.auto"></button>
|
||||
<button id="save-patch" class="save-button ripple-element" data-i18n="security_patch.save"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add System App Overlay -->
|
||||
<div id="add-system-app-overlay" class="add-system-app-overlay overlay">
|
||||
<div id="add-system-app-card" class="add-system-app-card overlay-content">
|
||||
<div class="add-system-app-title" data-i18n="add_system_app.title"></div>
|
||||
<div class="add-system-app-content">
|
||||
<input type="text" id="system-app-input" placeholder="com.example.app" autocapitalize="none">
|
||||
<button id="add-system-app-button" class="add-system-app-button ripple-element" data-i18n="add_system_app.add"></button>
|
||||
<h3 class="current-system-app-list" data-i18n="add_system_app.current_list"></h3>
|
||||
<div class="current-system-app-list-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Uninstall Confirmation Overlay -->
|
||||
<div class="uninstall-confirmation-overlay overlay" id="uninstall-confirmation-overlay">
|
||||
<div class="uninstall-confirmation overlay-content">
|
||||
<div class="uninstall-confirmation-title" data-i18n="confirmation.uninstall_title"></div>
|
||||
<p data-i18n="confirmation.uninstall_message"></p>
|
||||
<div class="uninstall-confirmation-button-container">
|
||||
<button class="uninstall-confirmation-button ripple-element" id="cancel-uninstall" data-i18n="confirmation.uninstall_cancel"></button>
|
||||
<button class="uninstall-confirmation-button ripple-element" id="confirm-uninstall" data-i18n="confirmation.uninstall_confirm"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="footer">
|
||||
<div class="uninstall-container ripple-element hidden-uninstall">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><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>
|
||||
132
module/webui/locales/A-template.json
Normal file
132
module/webui/locales/A-template.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "English",
|
||||
"system_default": "System Default",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"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 Internet connection.",
|
||||
"add_system_app": "Add System App",
|
||||
"add_system_app_description": "Add specific system app to app list.",
|
||||
"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_custom_keybox": "Set Custom Keybox",
|
||||
"set_custom_keybox_description": "Import keybox from your device storage. Only support xml file.",
|
||||
"set_security_patch": "Set Security Patch",
|
||||
"set_security_patch_description": "Set custom security patch spoof. Auto config will use security patch from PIF module, enabled by default. Leave blank and save to disable auto config.",
|
||||
"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": {
|
||||
"update_available": "A new version is ready",
|
||||
"redirect_to_release": "tap to download the latest version",
|
||||
"changelog": "Changelog",
|
||||
"install": "Install",
|
||||
"reboot": "Reboot"
|
||||
},
|
||||
"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",
|
||||
"add_system_app": "Add System App",
|
||||
"set_aosp_keybox": "Set AOSP Keybox",
|
||||
"set_valid_keybox": "Set Valid Keybox",
|
||||
"set_custom_keybox": "Set Custom Keybox",
|
||||
"set_verified_boot_hash": "Set Verified Boot Hash",
|
||||
"set_security_patch": "Set Security Patch",
|
||||
"about": "About"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Boot Hash",
|
||||
"input_placeholder": "Paste your verified Boot Hash here",
|
||||
"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!",
|
||||
"downloading": "Downloading new update...",
|
||||
"downloaded": "Download completed",
|
||||
"download_fail": "Fail to download update",
|
||||
"installing": "Installing update...",
|
||||
"installed": "Installed successfully, reboot now.",
|
||||
"install_fail": "Fail to install, please update manually",
|
||||
"rebooting": "Rebooting...",
|
||||
"reboot_fail": "Fail to reboot, please reboot manually",
|
||||
"custom_key_set": "Custom keybox set successfully",
|
||||
"custom_key_set_error": "Failed to set custom keybox",
|
||||
"no_file_selected": "No file selected",
|
||||
"system_app_not_found": "System app not found",
|
||||
"system_app_error": "Failed to add system app"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Security Patch",
|
||||
"advanced_mode": "Advanced",
|
||||
"get_date": "Get Security Patch Date",
|
||||
"auto": "Auto",
|
||||
"save": "Save",
|
||||
"fetching": "Fetching...",
|
||||
"fetched": "Done",
|
||||
"get_failed": "Failed to fetch security patch date",
|
||||
"auto_success": "Auto config enabled successfully",
|
||||
"auto_failed": "Failed to enable auto config",
|
||||
"save_success": "Security patch saved successfully",
|
||||
"save_failed": "Failed to save security patch",
|
||||
"value_empty": "Security patch configuration is disabled",
|
||||
"invalid_all": "Invalid format",
|
||||
"invalid_boot": "Invalid boot format",
|
||||
"invalid_system": "Invalid system format",
|
||||
"invalid_vendor": "Invalid vendor format"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Add System App",
|
||||
"add": "Add",
|
||||
"current_list": "Current System App List"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Confirm Uninstall?",
|
||||
"uninstall_message": "Are you sure you want to uninstall Tricky Addon",
|
||||
"uninstall_cancel": "Cancel",
|
||||
"uninstall_confirm": "Confirm"
|
||||
}
|
||||
}
|
||||
19
module/webui/locales/A-translate.md
Normal file
19
module/webui/locales/A-translate.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Translation Guide
|
||||
## Fix Bad Translation
|
||||
1. Fork this repository.
|
||||
2. Find your language string file in `/module/webui/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/webui/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 the language code to `/module/webui/locales/available-lang.json`, this step is necessary for displaying the language in the WebUI.
|
||||
6. Create a Pull Request.
|
||||
132
module/webui/locales/ar-EG.json
Normal file
132
module/webui/locales/ar-EG.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "العربية",
|
||||
"system_default": "الإعدادات الافتراضية للنظام",
|
||||
"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": "تحديد من قائمة الرفض",
|
||||
"select_denylist_description": "متاح في Magisk فقط، حدد التطبيقات الموجودة في قائمة الرفض. موصى به.",
|
||||
"deselect_unnecessary": "إلغاء تحديد غير الضروري",
|
||||
"deselect_unnecessary_description": "فئة غير ضرورية: وحدة Xposed، مدير الجذر، التطبيقات المتعلقة بالجذر، والتطبيقات العامة التي لا تتحقق أبدًا من حالة bootloader. يتطلب هذا الخيار اتصالاً بالإنترنت.",
|
||||
"add_system_app": "إضافة تطبيق نظام",
|
||||
"add_system_app_description": "إضافة تطبيق نظام محدد إلى قائمة التطبيقات.",
|
||||
"set_keybox": "تعيين AOSP و Keybox صالح",
|
||||
"set_keybox_description": "استبدال tricky store keybox.xml. سيتم استبدال keybox AOSP إذا لم يكن هناك keybox صالح آخر. يتطلب خيار keybox الصالح اتصالاً بالإنترنت.",
|
||||
"set_custom_keybox": "تعيين Keybox مخصص",
|
||||
"set_custom_keybox_description": "استيراد keybox من تخزين جهازك. يدعم فقط ملف xml.",
|
||||
"set_security_patch": "تعيين تصحيح الأمان",
|
||||
"set_security_patch_description": "تعيين تصحيح أمان مخصص. سيستخدم التكوين التلقائي تصحيح الأمان من وحدة PIF، مفعل بشكل افتراضي. اتركه فارغًا واحفظه لتعطيل التكوين التلقائي.",
|
||||
"set_verified_boot_hash": "تعيين تجزئة التمهيد الموثوق",
|
||||
"set_verified_boot_hash_description": "احصل على قيمة verifiedBootHash من عرض إثبات المفتاح. إصلاح حالة التمهيد غير الطبيعية عن طريق إعادة تعيين ro.boot.vbmeta.digest."
|
||||
},
|
||||
"update": {
|
||||
"update_available": "إصدار جديد جاهز",
|
||||
"redirect_to_release": "اضغط لتنزيل أحدث إصدار",
|
||||
"changelog": "سجل التغييرات",
|
||||
"install": "تثبيت",
|
||||
"reboot": "إعادة تشغيل"
|
||||
},
|
||||
"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": "إلغاء تحديد غير الضروري",
|
||||
"add_system_app": "إضافة تطبيق نظام",
|
||||
"set_aosp_keybox": "تعيين Keybox AOSP",
|
||||
"set_valid_keybox": "تعيين Keybox صالح",
|
||||
"set_custom_keybox": "تعيين Keybox مخصص",
|
||||
"set_verified_boot_hash": "تعيين تجزئة التمهيد الموثوق",
|
||||
"set_security_patch": "تعيين تصحيح الأمان",
|
||||
"about": "حول"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "تجزئة التمهيد",
|
||||
"input_placeholder": "الصق تجزئة التمهيد الموثوق هنا",
|
||||
"save_button": "حفظ"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "Tricky Addon",
|
||||
"module_name_line2": "تحديث قائمة الأهداف",
|
||||
"by": "بواسطة",
|
||||
"telegram_channel": "قناة التليجرام",
|
||||
"github": "GitHub",
|
||||
"disclaimer": "هذه الوحدة ليست جزءًا من وحدة Tricky Store. لا تقم بالإبلاغ عن أي مشاكل إلى Tricky Store إذا واجهت أيًا منها.",
|
||||
"acknowledgment": "شكر وتقدير"
|
||||
},
|
||||
"prompt": {
|
||||
"no_internet": "يرجى التحقق من اتصالك بالإنترنت",
|
||||
"aosp_key_set": "تم تعيين keybox AOSP بنجاح",
|
||||
"key_set_error": "فشل في تحديث keybox",
|
||||
"valid_key_set": "تم تعيين keybox صالح بنجاح",
|
||||
"no_valid_fallback": "لم يتم العثور على keybox صالح، تم الاستبدال بـ keybox AOSP.",
|
||||
"boot_hash_set": "تم حفظ تجزئة التمهيد الموثوق بنجاح",
|
||||
"boot_hash_set_error": "فشل في تحديث تجزئة التمهيد الموثوق",
|
||||
"saved_target": "تم حفظ التكوين إلى target.txt",
|
||||
"save_error": "فشل في حفظ التكوين",
|
||||
"uninstall_prompt": "سيتم إزالة WebUI بعد إعادة التشغيل",
|
||||
"uninstall_failed": "فشل في إلغاء تثبيت WebUI",
|
||||
"new_update": "تحديث جديد متاح!",
|
||||
"downloading": "جارٍ تنزيل التحديث الجديد...",
|
||||
"downloaded": "اكتمل التنزيل",
|
||||
"download_fail": "فشل في تنزيل التحديث",
|
||||
"installing": "جارٍ تثبيت التحديث...",
|
||||
"installed": "تم التثبيت بنجاح، أعد التشغيل الآن.",
|
||||
"install_fail": "فشل في التثبيت، يرجى التحديث يدويًا",
|
||||
"rebooting": "جارٍ إعادة التشغيل...",
|
||||
"reboot_fail": "فشل في إعادة التشغيل، يرجى إعادة التشغيل يدويًا",
|
||||
"custom_key_set": "تم تعيين keybox مخصص بنجاح",
|
||||
"custom_key_set_error": "فشل في تعيين keybox مخصص",
|
||||
"no_file_selected": "لم يتم اختيار أي ملف",
|
||||
"system_app_not_found": "لم يتم العثور على تطبيق النظام",
|
||||
"system_app_error": "فشل في إضافة تطبيق النظام"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "تصحيح الأمان",
|
||||
"advanced_mode": "متقدم",
|
||||
"get_date": "الحصول على تاريخ تصحيح الأمان",
|
||||
"auto": "تلقائي",
|
||||
"save": "حفظ",
|
||||
"fetching": "جارٍ التحميل...",
|
||||
"fetched": "تم",
|
||||
"get_failed": "فشل في جلب تاريخ تصحيح الأمان",
|
||||
"auto_success": "تم تفعيل التكوين التلقائي بنجاح",
|
||||
"auto_failed": "فشل في تفعيل التكوين التلقائي",
|
||||
"save_success": "تم حفظ تصحيح الأمان بنجاح",
|
||||
"save_failed": "فشل في حفظ تصحيح الأمان",
|
||||
"value_empty": "تم تعطيل تكوين تصحيح الأمان",
|
||||
"invalid_all": "تنسيق غير صالح",
|
||||
"invalid_boot": "تنسيق تمهيد غير صالح",
|
||||
"invalid_system": "تنسيق نظام غير صالح",
|
||||
"invalid_vendor": "تنسيق بائع غير صالح"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "إضافة تطبيق نظام",
|
||||
"add": "إضافة",
|
||||
"current_list": "قائمة تطبيقات النظام الحالية"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "تأكيد إلغاء التثبيت؟",
|
||||
"uninstall_message": "هل أنت متأكد أنك تريد إلغاء تثبيت Tricky Addon",
|
||||
"uninstall_cancel": "إلغاء",
|
||||
"uninstall_confirm": "تأكيد"
|
||||
}
|
||||
}
|
||||
18
module/webui/locales/available-lang.json
Normal file
18
module/webui/locales/available-lang.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"languages": [
|
||||
"ar-EG",
|
||||
"en-US",
|
||||
"es-ES",
|
||||
"fr-FR",
|
||||
"id-ID",
|
||||
"it-IT",
|
||||
"ja-JP",
|
||||
"pl-PL",
|
||||
"ru-RU",
|
||||
"tl-PH",
|
||||
"tr-TR",
|
||||
"az-AZ",
|
||||
"zh-CN",
|
||||
"zh-TW"
|
||||
]
|
||||
}
|
||||
132
module/webui/locales/az-AZ.json
Normal file
132
module/webui/locales/az-AZ.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "Azərbaycanca",
|
||||
"system_default": "Sistem Varsayılanı",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"help": {
|
||||
"help_instructions": "Təlimatlar",
|
||||
"save_and_update": "Yadda saxla",
|
||||
"save_and_update_description": "Cari konfiqurasiyanı target.txt faylına yadda saxla.",
|
||||
"refresh": "Təzələ",
|
||||
"refresh_description": "Proqram siyahısını və istisna siyahısını təzələ.",
|
||||
"select_deselect": "Hamısını seç və seçimi ləğv et",
|
||||
"select_description": "Cari interfeysdəki bütün tətbiqləri seç və ya seçimdən çıxar.",
|
||||
"select_denylist": "DenyList-dən seç",
|
||||
"select_denylist_description": "Yalnız Magisk-də mövcuddur, DenyList-də olan tətbiqləri seçin. Tövsiyə olunur.",
|
||||
"deselect_unnecessary": "Lazımsızları seçmə",
|
||||
"deselect_unnecessary_description": "Lazımsız kateqoriya: Xposed modulu, kök meneceri, kök ilə əlaqəli tətbiqlər və heç vaxt bootloader statusunu yoxlamayan ümumi tətbiqlər. Bu seçim İnternet bağlantısı tələb edir.",
|
||||
"add_system_app": "Sistem Tətbiqi Əlavə et",
|
||||
"add_system_app_description": "Müəyyən bir sistem tətbiqini tətbiq siyahısına əlavə et.",
|
||||
"set_keybox": "AOSP & Etibarlı Keybox təyin et",
|
||||
"set_keybox_description": "Tricky store keybox.xml-ni dəyişdir. Əgər etibarlı keybox yoxdursa, AOSP keybox dəyişdiriləcək. Etibarlı keybox seçimi İnternet bağlantısı tələb edir.",
|
||||
"set_custom_keybox": "Özəl Keybox təyin et",
|
||||
"set_custom_keybox_description": "Keybox-u cihaz yaddaşından idxal et. Yalnız xml faylını dəstəkləyir.",
|
||||
"set_security_patch": "Təhlükəsizlik Təkmilləşdirməsini təyin et",
|
||||
"set_security_patch_description": "Xüsusi təhlükəsizlik təkmilləşdirməsini dəyişdir. Avtomatik konfiqurasiya, PIF modulundan təhlükəsizlik təkmilləşdirməsini istifadə edəcək, bu seçimi aktivdir. Avtomatik konfiqurasiyanı dayandırmaq üçün boş buraxın və yadda saxlayın.",
|
||||
"set_verified_boot_hash": "Təsdiqlənmiş Boot Hash təyin et",
|
||||
"set_verified_boot_hash_description": "Key Attestation Demo-dan verifiedBootHash dəyərini əldə et. ro.boot.vbmeta.digest-ni sıfırlayaraq qeyri-adi boot vəziyyətini düzəlt."
|
||||
},
|
||||
"update": {
|
||||
"update_available": "Yeni versiya mövcuddur",
|
||||
"redirect_to_release": "Ən son versiyanı yükləmək üçün klikləyin",
|
||||
"changelog": "Dəyişikliklər",
|
||||
"install": "Yüklə",
|
||||
"reboot": "Yenidən başladın"
|
||||
},
|
||||
"search_bar": {
|
||||
"search_placeholder": "Axtar"
|
||||
},
|
||||
"functional_button": {
|
||||
"save_and_update_button": "Yadda saxla",
|
||||
"uninstall_webui": "WebUI-ni sil"
|
||||
},
|
||||
"loading": {
|
||||
"loading": "Yüklənir..."
|
||||
},
|
||||
"menu": {
|
||||
"refresh": "Təzələ",
|
||||
"select_all": "Hamısını seç",
|
||||
"deselect_all": "Hamısının seçimini ləğv et",
|
||||
"select_denylist": "DenyList-dən seç",
|
||||
"deselect_unnecessary": "Lazımsızları seçmə",
|
||||
"add_system_app": "Sistem Tətbiqi Əlavə et",
|
||||
"set_aosp_keybox": "AOSP Keybox təyin et",
|
||||
"set_valid_keybox": "Etibarlı Keybox təyin et",
|
||||
"set_custom_keybox": "Özəl Keybox təyin et",
|
||||
"set_verified_boot_hash": "Təsdiqlənmiş Boot Hash təyin et",
|
||||
"set_security_patch": "Təhlükəsizlik Təkmilləşdirməsini təyin et",
|
||||
"about": "Haqqında"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Boot Hash",
|
||||
"input_placeholder": "Təsdiqlənmiş Boot Hash-ı buraya yapışdırın",
|
||||
"save_button": "Yadda saxla"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "Tricky Addon",
|
||||
"module_name_line2": "Hədəf Siyahısını Yenilə",
|
||||
"by": "tərəfindən",
|
||||
"telegram_channel": "Telegram Kanalı",
|
||||
"github": "GitHub",
|
||||
"disclaimer": "Bu mod, Tricky Store modulunun bir hissəsi deyil. Qarşılaşılan hər hansı bir problemi Tricky Store-a bildirməyin.",
|
||||
"acknowledgment": "Təşəkkür"
|
||||
},
|
||||
"prompt": {
|
||||
"no_internet": "İnternet bağlantınızı yoxlayın",
|
||||
"aosp_key_set": "AOSP keybox uğurla təyin olundu",
|
||||
"key_set_error": "Keybox-u yeniləmək mümkün olmadı",
|
||||
"valid_key_set": "Etibarlı keybox uğurla təyin olundu",
|
||||
"no_valid_fallback": "Etibarlı keybox tapılmadı, AOSP keybox ilə dəyişdirildi.",
|
||||
"boot_hash_set": "Təsdiqlənmiş Boot Hash uğurla yadda saxlanıldı",
|
||||
"boot_hash_set_error": "Təsdiqlənmiş Boot Hash yenilənə bilmədi",
|
||||
"saved_target": "Konfiqurasiya target.txt-yə yadda saxlanıldı",
|
||||
"save_error": "Konfiqurasiyanı yadda saxlamaq mümkün olmadı",
|
||||
"uninstall_prompt": "WebUI yenidən başladıqdan sonra silinəcək",
|
||||
"uninstall_failed": "WebUI-ni silmək mümkün olmadı",
|
||||
"new_update": "Yeni bir yeniləmə mövcuddur!",
|
||||
"downloading": "Yeni yeniləməni yükləyir...",
|
||||
"downloaded": "Yükləmə tamamlandı",
|
||||
"download_fail": "Yeniləməni yükləmək mümkün olmadı",
|
||||
"installing": "Yeniləmə quraşdırılır...",
|
||||
"installed": "Uğurla quraşdırıldı, indi yenidən başladın.",
|
||||
"install_fail": "Quraşdırmaq mümkün olmadı, zəhmət olmasa əl ilə yeniləyin",
|
||||
"rebooting": "Yenidən başladılır...",
|
||||
"reboot_fail": "Yenidən başlatmaq mümkün olmadı, zəhmət olmasa əl ilə yenidən başlayın",
|
||||
"custom_key_set": "Özəl keybox uğurla təyin olundu",
|
||||
"custom_key_set_error": "Özəl keybox təyin oluna bilmədi",
|
||||
"no_file_selected": "Fayl seçilməyib",
|
||||
"system_app_not_found": "Sistem tətbiqi tapılmadı",
|
||||
"system_app_error": "Sistem tətbiqini əlavə etmək mümkün olmadı"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Təhlükəsizlik Təkmilləşdirməsi",
|
||||
"advanced_mode": "Ətraflı",
|
||||
"get_date": "Təhlükəsizlik Təkmilləşdirməsinin Tarixini Al",
|
||||
"auto": "Avtomatik",
|
||||
"save": "Yadda saxla",
|
||||
"fetching": "Yığılır...",
|
||||
"fetched": "Tamam",
|
||||
"get_failed": "Təhlükəsizlik təkmilləşdirməsinin tarixini almaq mümkün olmadı",
|
||||
"auto_success": "Avtomatik konfiqurasiya uğurla aktivləşdirildi",
|
||||
"auto_failed": "Avtomatik konfiqurasiyanı aktivləşdirmək mümkün olmadı",
|
||||
"save_success": "Təhlükəsizlik təkmilləşdirməsi uğurla yadda saxlanıldı",
|
||||
"save_failed": "Təhlükəsizlik təkmilləşdirməsini yadda saxlamaq mümkün olmadı",
|
||||
"value_empty": "Təhlükəsizlik təkmilləşdirməsi konfiqurasiyası deaktivdir",
|
||||
"invalid_all": "Yanlış format",
|
||||
"invalid_boot": "Yanlış boot formatı",
|
||||
"invalid_system": "Yanlış sistem formatı",
|
||||
"invalid_vendor": "Yanlış vendor formatı"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Sistem Tətbiqi Əlavə et",
|
||||
"add": "Əlavə et",
|
||||
"current_list": "Cari Sistem Tətbiqi Siyahısı"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Silinməni Təsdiqləyirsiniz?",
|
||||
"uninstall_message": "Tricky Addon-u silmək istədiyinizə əminsinizmi?",
|
||||
"uninstall_cancel": "İmtina et",
|
||||
"uninstall_confirm": "Təsdiqlə"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/en-US.json
Normal file
132
module/webui/locales/en-US.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "English",
|
||||
"system_default": "System Default",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"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 Internet connection.",
|
||||
"add_system_app": "Add System App",
|
||||
"add_system_app_description": "Add specific system app to app list.",
|
||||
"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_custom_keybox": "Set Custom Keybox",
|
||||
"set_custom_keybox_description": "Import keybox from your device storage. Only support xml file.",
|
||||
"set_security_patch": "Set Security Patch",
|
||||
"set_security_patch_description": "Set custom security patch spoof. Auto config will use security patch from PIF module, enabled by default. Leave blank and save to disable auto config.",
|
||||
"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": {
|
||||
"update_available": "A new version is ready",
|
||||
"redirect_to_release": "tap to download the latest version",
|
||||
"changelog": "Changelog",
|
||||
"install": "Install",
|
||||
"reboot": "Reboot"
|
||||
},
|
||||
"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",
|
||||
"add_system_app": "Add System App",
|
||||
"set_aosp_keybox": "Set AOSP Keybox",
|
||||
"set_valid_keybox": "Set Valid Keybox",
|
||||
"set_custom_keybox": "Set Custom Keybox",
|
||||
"set_verified_boot_hash": "Set Verified Boot Hash",
|
||||
"set_security_patch": "Set Security Patch",
|
||||
"about": "About"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Boot Hash",
|
||||
"input_placeholder": "Paste your verified Boot Hash here",
|
||||
"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!",
|
||||
"downloading": "Downloading new update...",
|
||||
"downloaded": "Download completed",
|
||||
"download_fail": "Fail to download update",
|
||||
"installing": "Installing update...",
|
||||
"installed": "Installed successfully, reboot now.",
|
||||
"install_fail": "Fail to install, please update manually",
|
||||
"rebooting": "Rebooting...",
|
||||
"reboot_fail": "Fail to reboot, please reboot manually",
|
||||
"custom_key_set": "Custom keybox set successfully",
|
||||
"custom_key_set_error": "Failed to set custom keybox",
|
||||
"no_file_selected": "No file selected",
|
||||
"system_app_not_found": "System app not found",
|
||||
"system_app_error": "Failed to add system app"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Security Patch",
|
||||
"advanced_mode": "Advanced",
|
||||
"get_date": "Get Security Patch Date",
|
||||
"auto": "Auto",
|
||||
"save": "Save",
|
||||
"fetching": "Fetching...",
|
||||
"fetched": "Done",
|
||||
"get_failed": "Failed to fetch security patch date",
|
||||
"auto_success": "Auto config enabled successfully",
|
||||
"auto_failed": "Failed to enable auto config",
|
||||
"save_success": "Security patch saved successfully",
|
||||
"save_failed": "Failed to save security patch",
|
||||
"value_empty": "Security patch configuration is disabled",
|
||||
"invalid_all": "Invalid format",
|
||||
"invalid_boot": "Invalid boot format",
|
||||
"invalid_system": "Invalid system format",
|
||||
"invalid_vendor": "Invalid vendor format"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Add System App",
|
||||
"add": "Add",
|
||||
"current_list": "Current System App List"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Confirm Uninstall?",
|
||||
"uninstall_message": "Are you sure you want to uninstall Tricky Addon",
|
||||
"uninstall_cancel": "Cancel",
|
||||
"uninstall_confirm": "Confirm"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/es-ES.json
Normal file
132
module/webui/locales/es-ES.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "Español",
|
||||
"system_default": "Predeterminado del sistema",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"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.",
|
||||
"add_system_app": "Agregar Aplicación del Sistema",
|
||||
"add_system_app_description": "Agregar una aplicación del sistema específica a la lista de aplicaciones.",
|
||||
"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_custom_keybox": "Establecer Keybox Personalizado",
|
||||
"set_custom_keybox_description": "Importar keybox desde el almacenamiento de tu dispositivo. Solo soporta archivos xml.",
|
||||
"set_security_patch": "Configurar Parche de Seguridad",
|
||||
"set_security_patch_description": "Configurar parche de seguridad personalizado. La configuración automática usará el parche de seguridad de PIF, habilitado por defecto. Deja en blanco y guarda para deshabilitar la configuración automática.",
|
||||
"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": {
|
||||
"update_available": "Una nueva versión está lista",
|
||||
"redirect_to_release": "toca para descargar la última versión",
|
||||
"changelog": "Registro de cambios",
|
||||
"install": "Instalar",
|
||||
"reboot": "Reiniciar"
|
||||
},
|
||||
"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",
|
||||
"add_system_app": "Agregar Aplicación del Sistema",
|
||||
"set_aosp_keybox": "Configurar AOSP Keybox",
|
||||
"set_valid_keybox": "Configurar Keybox Válido",
|
||||
"set_custom_keybox": "Establecer Keybox Personalizado",
|
||||
"set_security_patch": "Configurar Parche de Seguridad",
|
||||
"set_verified_boot_hash": "Configurar Boot Hash Verificado",
|
||||
"about": "Acerca de"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Boot Hash",
|
||||
"input_placeholder": "Pega aquí tu Boot Hash verificado",
|
||||
"save_button": "Guardar"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "Tricky Addon",
|
||||
"module_name_line2": "Actualizar Lista de Objetivos",
|
||||
"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!",
|
||||
"downloading": "Descargando nueva actualización...",
|
||||
"downloaded": "Descarga completada",
|
||||
"download_fail": "Error al descargar la actualización",
|
||||
"installing": "Instalando actualización...",
|
||||
"installed": "Instalado con éxito, reinicia ahora.",
|
||||
"install_fail": "Error al instalar, actualiza manualmente",
|
||||
"rebooting": "Reiniciando...",
|
||||
"reboot_fail": "Error al reiniciar, reinicia manualmente",
|
||||
"custom_key_set": "Keybox personalizado establecido con éxito",
|
||||
"custom_key_set_error": "Error al establecer el keybox personalizado",
|
||||
"no_file_selected": "Ningún archivo seleccionado",
|
||||
"system_app_not_found": "Aplicación del sistema no encontrada",
|
||||
"system_app_error": "Error al agregar la aplicación del sistema"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Parche de Seguridad",
|
||||
"advanced_mode": "Avanzado",
|
||||
"get_date": "Obtener Fecha del Parche de Seguridad",
|
||||
"auto": "Automático",
|
||||
"save": "Guardar",
|
||||
"fetching": "Obteniendo...",
|
||||
"fetched": "Completado",
|
||||
"get_failed": "Error al obtener la fecha del parche de seguridad",
|
||||
"auto_success": "Configuración automática habilitada con éxito",
|
||||
"auto_failed": "Error al habilitar la configuración automática",
|
||||
"save_success": "Parche de seguridad guardado con éxito",
|
||||
"save_failed": "Error al guardar el parche de seguridad",
|
||||
"value_empty": "La configuración del parche de seguridad está deshabilitada",
|
||||
"invalid_all": "Formato inválido",
|
||||
"invalid_boot": "Formato de boot inválido",
|
||||
"invalid_system": "Formato de system inválido",
|
||||
"invalid_vendor": "Formato de vendor inválido"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Añadir aplicación del sistema",
|
||||
"add": "Añadir",
|
||||
"current_list": "Lista actual de aplicaciones del sistema"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "¿Confirmar desinstalación?",
|
||||
"uninstall_message": "¿Está seguro de que desea desinstalar Tricky Addon",
|
||||
"uninstall_cancel": "Cancelar",
|
||||
"uninstall_confirm": "Confirmar"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/fr-FR.json
Normal file
132
module/webui/locales/fr-FR.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "Français",
|
||||
"system_default": "Langage système",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"help": {
|
||||
"help_instructions": "Instructions",
|
||||
"save_and_update": "Enregistrer",
|
||||
"save_and_update_description": "Enregistrer la configuration actuelle dans target.txt.",
|
||||
"refresh": "Actualiser",
|
||||
"refresh_description": "Actualiser la liste des applications et la liste d'exclusions.",
|
||||
"select_deselect": "Tout sélectionner & désélectionner",
|
||||
"select_description": "Sélectionner ou désélectionner toutes les applications de l'interface actuelle.",
|
||||
"select_DenyList": "Sélectionner depuis la DenyList",
|
||||
"select_DenyList_description": "Disponible uniquement sur Magisk, sélectionner les applications présentes dans la DenyList. Recommandé.",
|
||||
"deselect_unnecessary": "Désélectionner les applications inutiles",
|
||||
"deselect_unnecessary_description": "Catégorie inutile : module Xposed, gestionnaire root, applications liées au root et applications générales ne vérifiant jamais l'état du bootloader. Cette option nécessite une connexion Internet.",
|
||||
"add_system_app": "Ajouter une application système",
|
||||
"add_system_app_description": "Ajouter une application système spécifique à la liste.",
|
||||
"set_keybox": "Définir une Keybox AOSP & Valide",
|
||||
"set_keybox_description": "Remplacer le fichier keybox.xml de Tricky Store. La keybox AOSP sera remplacée s'il n'y a plus de keybox valide. L'option keybox valide nécessite une connexion Internet.",
|
||||
"set_custom_keybox": "Définir une Keybox personnalisée",
|
||||
"set_custom_keybox_description": "Importer une keybox depuis le stockage de votre appareil. Seuls les fichiers XML sont pris en charge.",
|
||||
"set_security_patch": "Définir le patch de sécurité",
|
||||
"set_security_patch_description": "Définir un patch de sécurité personnalisé. La configuration automatique utilisera le patch de sécurité du module PIF, activée par défaut. Laisser vide et enregistrer pour désactiver la configuration automatique.",
|
||||
"set_verified_boot_hash": "Définir le hash Verified Boot",
|
||||
"set_verified_boot_hash_description": "Obtenir la valeur verifiedBootHash depuis Key Attestation Demo. Corriger un état de démarrage anormal en réinitialisant ro.boot.vbmeta.digest."
|
||||
},
|
||||
"update": {
|
||||
"update_available": "Une nouvelle version est disponible",
|
||||
"redirect_to_release": "appuyer pour télécharger la dernière version",
|
||||
"changelog": "Journal des modifications",
|
||||
"install": "Installer",
|
||||
"reboot": "Redémarrer"
|
||||
},
|
||||
"search_bar": {
|
||||
"search_placeholder": "Rechercher"
|
||||
},
|
||||
"functional_button": {
|
||||
"save_and_update_button": "Enregistrer",
|
||||
"uninstall_webui": "Désinstaller la WebUI"
|
||||
},
|
||||
"loading": {
|
||||
"loading": "Chargement…"
|
||||
},
|
||||
"menu": {
|
||||
"refresh": "Actualiser",
|
||||
"select_all": "Tout sélectionner",
|
||||
"deselect_all": "Tout désélectionner",
|
||||
"select_DenyList": "Sélectionner depuis la DenyList",
|
||||
"deselect_unnecessary": "Désélectionner les applications inutiles",
|
||||
"add_system_app": "Ajouter une application système",
|
||||
"set_aosp_keybox": "Définir une Keybox AOSP",
|
||||
"set_valid_keybox": "Définir une Keybox valide",
|
||||
"set_custom_keybox": "Définir une Keybox personnalisée",
|
||||
"set_verified_boot_hash": "Définir le hash Verified Boot",
|
||||
"set_security_patch": "Définir le patch de sécurité",
|
||||
"about": "À propos"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Hash de démarrage",
|
||||
"input_placeholder": "Collez votre hash Verified Boot ici",
|
||||
"save_button": "Enregistrer"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "Tricky Addon",
|
||||
"module_name_line2": "Mettre à jour la liste cible",
|
||||
"by": "par",
|
||||
"telegram_channel": "Canal Telegram",
|
||||
"github": "GitHub",
|
||||
"disclaimer": "Ce module ne fait pas partie du module Tricky Store. NE signalez PAS de problèmes à Tricky Store en cas d'erreur.",
|
||||
"acknowledgment": "Remerciements"
|
||||
},
|
||||
"prompt": {
|
||||
"no_internet": "Veuillez vérifier votre connexion Internet",
|
||||
"aosp_key_set": "Keybox AOSP définie avec succès",
|
||||
"key_set_error": "Échec de la mise à jour de la Keybox",
|
||||
"valid_key_set": "Keybox valide définie avec succès",
|
||||
"no_valid_fallback": "Aucune Keybox valide trouvée, remplacée par le Keybox AOSP.",
|
||||
"boot_hash_set": "Hash Verified Boot enregistré avec succès",
|
||||
"boot_hash_set_error": "Échec de la mise à jour du hash Verified Boot",
|
||||
"saved_target": "Configuration enregistrée dans target.txt",
|
||||
"save_error": "Échec de l'enregistrement de la configuration",
|
||||
"uninstall_prompt": "La WebUI sera supprimée après le redémarrage",
|
||||
"uninstall_failed": "Échec de la désinstallation de la WebUI",
|
||||
"new_update": "Une nouvelle mise à jour est disponible !",
|
||||
"downloading": "Téléchargement de la mise à jour…",
|
||||
"downloaded": "Téléchargement terminé",
|
||||
"download_fail": "Échec du téléchargement de la mise à jour",
|
||||
"installing": "Installation de la mise à jour…",
|
||||
"installed": "Installation réussie, redémarrez maintenant.",
|
||||
"install_fail": "Échec de l'installation, veuillez mettre à jour manuellement",
|
||||
"rebooting": "Redémarrage…",
|
||||
"reboot_fail": "Échec du redémarrage, veuillez redémarrer manuellement",
|
||||
"custom_key_set": "Keybox personnalisée définie avec succès",
|
||||
"custom_key_set_error": "Échec de la définition de la Keybox personnalisée",
|
||||
"no_file_selected": "Aucun fichier sélectionné",
|
||||
"system_app_not_found": "Application système introuvable",
|
||||
"system_app_error": "Échec de l'ajout de l'application système"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Patch de sécurité",
|
||||
"advanced_mode": "Avancé",
|
||||
"get_date": "Obtenir la date du patch de sécurité",
|
||||
"auto": "Automatique",
|
||||
"save": "Enregistrer",
|
||||
"fetching": "Récupération…",
|
||||
"fetched": "Terminé",
|
||||
"get_failed": "Échec de la récupération de la date du patch de sécurité",
|
||||
"auto_success": "Configuration automatique activée avec succès",
|
||||
"auto_failed": "Échec de l'activation de la configuration automatique",
|
||||
"save_success": "Patch de sécurité enregistré avec succès",
|
||||
"save_failed": "Échec de l'enregistrement du patch de sécurité",
|
||||
"value_empty": "Configuration du patch de sécurité désactivée",
|
||||
"invalid_all": "Format invalide",
|
||||
"invalid_boot": "Format de démarrage invalide",
|
||||
"invalid_system": "Format du système invalide",
|
||||
"invalid_vendor": "Format du fournisseur invalide"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Ajouter une application système",
|
||||
"add": "Ajouter",
|
||||
"current_list": "Liste des applications système actuelles"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Confirmer la désinstallation ?",
|
||||
"uninstall_message": "Êtes-vous sûr(e) de vouloir désinstaller Tricky Addon",
|
||||
"uninstall_cancel": "Annuler",
|
||||
"uninstall_confirm": "Confirmer"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/id-ID.json
Normal file
132
module/webui/locales/id-ID.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "Bahasa Indonesia",
|
||||
"system_default": "Default Sistem",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"help": {
|
||||
"help_instructions": "Panduan",
|
||||
"save_and_update": "Simpan",
|
||||
"save_and_update_description": "Simpan konfigurasi saat ini ke target.txt.",
|
||||
"refresh": "Segarkan",
|
||||
"refresh_description": "Perbarui daftar aplikasi dan daftar pengecualian.",
|
||||
"select_deselect": "Pilih & Batalkan Pilihan Semua",
|
||||
"select_description": "Pilih atau batalkan pilihan semua aplikasi yang ditampilkan.",
|
||||
"select_denylist": "Pilih dari Denylist",
|
||||
"select_denylist_description": "Hanya untuk Magisk, pilih aplikasi yang ada di Denylist. Disarankan.",
|
||||
"deselect_unnecessary": "Batalkan Pilihan yang Tidak Perlu",
|
||||
"deselect_unnecessary_description": "Kategori tidak perlu: Modul Xposed, pengelola root, aplikasi terkait root, dan aplikasi yang tidak pernah memeriksa status bootloader. Opsi ini memerlukan koneksi internet.",
|
||||
"add_system_app": "Tambahkan Aplikasi Sistem",
|
||||
"add_system_app_description": "Tambahkan aplikasi sistem tertentu ke daftar aplikasi.",
|
||||
"set_keybox": "Ganti Keybox AOSP & Valid",
|
||||
"set_keybox_description": "Ganti file keybox.xml bawaan. Jika tidak ada keybox valid, maka keybox AOSP akan digunakan. Opsi ini memerlukan koneksi internet.",
|
||||
"set_custom_keybox": "Gunakan Keybox Kustom",
|
||||
"set_custom_keybox_description": "Impor keybox dari penyimpanan perangkat. Hanya mendukung file XML.",
|
||||
"set_security_patch": "Atur Patch Keamanan",
|
||||
"set_security_patch_description": "Sesuaikan patch keamanan. Konfigurasi otomatis akan menggunakan patch dari modul PIF dan aktif secara default. Kosongkan dan simpan untuk menonaktifkan konfigurasi otomatis.",
|
||||
"set_verified_boot_hash": "Atur Verified Boot Hash",
|
||||
"set_verified_boot_hash_description": "Ambil nilai verifiedBootHash dari aplikasi Key Attestation Demo. Perbaiki status boot yang bermasalah dengan mereset ro.boot.vbmeta.digest."
|
||||
},
|
||||
"update": {
|
||||
"update_available": "Versi baru tersedia!",
|
||||
"redirect_to_release": "Ketuk untuk mengunduh versi terbaru",
|
||||
"changelog": "Catatan Perubahan",
|
||||
"install": "Pasang",
|
||||
"reboot": "Mulai Ulang"
|
||||
},
|
||||
"search_bar": {
|
||||
"search_placeholder": "Cari"
|
||||
},
|
||||
"functional_button": {
|
||||
"save_and_update_button": "Simpan",
|
||||
"uninstall_webui": "Copot Pemasangan WebUI"
|
||||
},
|
||||
"loading": {
|
||||
"loading": "Memuat..."
|
||||
},
|
||||
"menu": {
|
||||
"refresh": "Segarkan",
|
||||
"select_all": "Pilih Semua",
|
||||
"deselect_all": "Batalkan Semua Pilihan",
|
||||
"select_denylist": "Pilih dari Denylist",
|
||||
"deselect_unnecessary": "Batalkan Pilihan yang Tidak Perlu",
|
||||
"add_system_app": "Tambahkan Aplikasi Sistem",
|
||||
"set_aosp_keybox": "Gunakan Keybox AOSP",
|
||||
"set_valid_keybox": "Gunakan Keybox Valid",
|
||||
"set_custom_keybox": "Gunakan Keybox Kustom",
|
||||
"set_verified_boot_hash": "Atur Verified Boot Hash",
|
||||
"set_security_patch": "Atur Patch Keamanan",
|
||||
"about": "Tentang"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Verified Boot Hash",
|
||||
"input_placeholder": "Tempel Verified Boot Hash Anda di sini",
|
||||
"save_button": "Simpan"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "Tricky Addon",
|
||||
"module_name_line2": "Perbarui Daftar Target",
|
||||
"by": "oleh",
|
||||
"telegram_channel": "Saluran Telegram",
|
||||
"github": "GitHub",
|
||||
"disclaimer": "Modul ini bukan bagian dari Tricky Store. Jangan laporkan masalah ke Tricky Store jika mengalami kendala.",
|
||||
"acknowledgment": "Pengakuan"
|
||||
},
|
||||
"prompt": {
|
||||
"no_internet": "Periksa koneksi internet Anda",
|
||||
"aosp_key_set": "Keybox AOSP berhasil digunakan",
|
||||
"key_set_error": "Gagal memperbarui keybox",
|
||||
"valid_key_set": "Keybox valid berhasil digunakan",
|
||||
"no_valid_fallback": "Tidak ada keybox valid, menggunakan keybox AOSP.",
|
||||
"boot_hash_set": "Verified Boot Hash berhasil disimpan",
|
||||
"boot_hash_set_error": "Gagal memperbarui Verified Boot Hash",
|
||||
"saved_target": "Konfigurasi disimpan ke target.txt",
|
||||
"save_error": "Gagal menyimpan konfigurasi",
|
||||
"uninstall_prompt": "WebUI akan dicopot setelah perangkat dimulai ulang",
|
||||
"uninstall_failed": "Gagal mencopot pemasangan WebUI",
|
||||
"new_update": "Pembaruan baru tersedia!",
|
||||
"downloading": "Mengunduh pembaruan...",
|
||||
"downloaded": "Unduhan selesai",
|
||||
"download_fail": "Gagal mengunduh pembaruan",
|
||||
"installing": "Memasang pembaruan...",
|
||||
"installed": "Pembaruan berhasil dipasang, mulai ulang sekarang.",
|
||||
"install_fail": "Gagal memasang, silakan perbarui secara manual",
|
||||
"rebooting": "Memulai ulang...",
|
||||
"reboot_fail": "Gagal memulai ulang, silakan lakukan secara manual",
|
||||
"custom_key_set": "Keybox kustom berhasil digunakan",
|
||||
"custom_key_set_error": "Gagal menggunakan keybox kustom",
|
||||
"no_file_selected": "Tidak ada file yang dipilih",
|
||||
"system_app_not_found": "Aplikasi sistem tidak ditemukan",
|
||||
"system_app_error": "Gagal menambahkan aplikasi sistem"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Patch Keamanan",
|
||||
"advanced_mode": "Mode Lanjutan",
|
||||
"get_date": "Ambil Tanggal Patch Keamanan",
|
||||
"auto": "Otomatis",
|
||||
"save": "Simpan",
|
||||
"fetching": "Mengambil...",
|
||||
"fetched": "Selesai",
|
||||
"get_failed": "Gagal mengambil tanggal patch keamanan",
|
||||
"auto_success": "Konfigurasi otomatis berhasil diaktifkan",
|
||||
"auto_failed": "Gagal mengaktifkan konfigurasi otomatis",
|
||||
"save_success": "Patch keamanan berhasil disimpan",
|
||||
"save_failed": "Gagal menyimpan patch keamanan",
|
||||
"value_empty": "Konfigurasi patch keamanan dinonaktifkan",
|
||||
"invalid_all": "Format tidak valid",
|
||||
"invalid_boot": "Format boot tidak valid",
|
||||
"invalid_system": "Format sistem tidak valid",
|
||||
"invalid_vendor": "Format vendor tidak valid"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Tambah Aplikasi Sistem",
|
||||
"add": "Tambah",
|
||||
"current_list": "Daftar Aplikasi Sistem Saat Ini"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Konfirmasi Hapus?",
|
||||
"uninstall_message": "Apakah Anda yakin ingin menghapus Tricky Addon",
|
||||
"uninstall_cancel": "Batal",
|
||||
"uninstall_confirm": "Konfirmasi"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/it-IT.json
Normal file
132
module/webui/locales/it-IT.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "Italiano",
|
||||
"system_default": "Predefinito di sistema",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"help": {
|
||||
"help_instructions": "Istruzioni",
|
||||
"save_and_update": "Salva",
|
||||
"save_and_update_description": "Salva la configurazione corrente in target.txt.",
|
||||
"refresh": "Aggiorna",
|
||||
"refresh_description": "Aggiorna l'elenco delle app e l'elenco delle esclusioni.",
|
||||
"select_deselect": "Seleziona & Deseleziona Tutto",
|
||||
"select_description": "Seleziona o deseleziona tutte le app nell'interfaccia corrente.",
|
||||
"select_denylist": "Seleziona da DenyList",
|
||||
"select_denylist_description": "Disponibile solo in Magisk, seleziona le app presenti nella DenyList. Consigliato.",
|
||||
"deselect_unnecessary": "Deseleziona Non necessari",
|
||||
"deselect_unnecessary_description": "Categoria non necessaria: modulo Xposed, root manager, app correlate al root e app generali che non controllano mai lo stato del bootloader. Questa opzione richiede una connessione a Internet.",
|
||||
"add_system_app": "Aggiungi App di Sistema",
|
||||
"add_system_app_description": "Aggiungi app di sistema specifiche all'elenco delle app.",
|
||||
"set_keybox": "Imposta AOSP & Keybox Valida",
|
||||
"set_keybox_description": "Sostituisci tricky store keybox.xml. La keybox AOSP verrà sostituita se non ci sono più keybox valide. L'opzione valida per la keybox richiede una connessione Internet.",
|
||||
"set_custom_keybox": "Imposta Keybox Personalizzata",
|
||||
"set_custom_keybox_description": "Importa keybox dalla memoria del tuo dispositivo. Supporta solo file xml.",
|
||||
"set_security_patch": "Imposta Patch di Sicurezza",
|
||||
"set_security_patch_description": "Imposta spoofing patch di sicurezza personalizzato. La configurazione automatica utilizzerà la patch di sicurezza dal modulo PIF, abilitato di default. Lascia vuoto e salva per disabilitare la configurazione automatica.",
|
||||
"set_verified_boot_hash": "Imposta Boot Hash Verificato",
|
||||
"set_verified_boot_hash_description": "Ottieni il valore verifiedBootHash da Key Attestation Demo. Correggi lo stato di avvio anomalo reimpostando ro.boot.vbmeta.digest."
|
||||
},
|
||||
"update": {
|
||||
"update_available": "È pronta una nuova versione",
|
||||
"redirect_to_release": "tocca per scaricare l'ultima versione",
|
||||
"changelog": "Changelog",
|
||||
"install": "Installa",
|
||||
"reboot": "Riavvio"
|
||||
},
|
||||
"search_bar": {
|
||||
"search_placeholder": "Ricerca"
|
||||
},
|
||||
"functional_button": {
|
||||
"save_and_update_button": "Salva",
|
||||
"uninstall_webui": "Disinstalla WebUI"
|
||||
},
|
||||
"loading": {
|
||||
"loading": "Caricamento..."
|
||||
},
|
||||
"menu": {
|
||||
"refresh": "Aggiorna",
|
||||
"select_all": "Seleziona Tutto",
|
||||
"deselect_all": "Deseleziona tutto",
|
||||
"select_denylist": "Seleziona da DenyList",
|
||||
"deselect_unnecessary": "Deseleziona Non necessari",
|
||||
"add_system_app": "Aggiungi App di Sistema",
|
||||
"set_aosp_keybox": "Imposta Keybox AOSP",
|
||||
"set_valid_keybox": "Imposta Keybox Valida",
|
||||
"set_custom_keybox": "Imposta Keybox Personalizzata",
|
||||
"set_verified_boot_hash": "Imposta Boot Hash Verificato",
|
||||
"set_security_patch": "Imposta Patch di Sicurezza",
|
||||
"about": "About"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Boot Hash",
|
||||
"input_placeholder": "Incolla qui il tuo Boot Hash verificato",
|
||||
"save_button": "Salva"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "Tricky Addon",
|
||||
"module_name_line2": "Aggiorna Target List",
|
||||
"by": "by",
|
||||
"telegram_channel": "Canale Telegram",
|
||||
"github": "GitHub",
|
||||
"disclaimer": "Questo modulo non fa parte del modulo Tricky Store. NON segnalare eventuali problemi a Tricky Store se riscontrati.",
|
||||
"acknowledgment": "Riconoscimento"
|
||||
},
|
||||
"prompt": {
|
||||
"no_internet": "Controlla la tua connessione Internet",
|
||||
"aosp_key_set": "Keybox AOSP impostata correttamente",
|
||||
"key_set_error": "Impossibile aggiornare keybox",
|
||||
"valid_key_set": "Keybox valida impostata correttamente",
|
||||
"no_valid_fallback": "Nessuna keybox valida trovata, sostituito con keybox AOSP.",
|
||||
"boot_hash_set": "Boot Hash Verificato salvato correttamente",
|
||||
"boot_hash_set_error": "Impossibile aggiornare Boot Hash Verificato",
|
||||
"saved_target": "Configurazione salvata in target.txt",
|
||||
"save_error": "Impossibile salvare la configurazione",
|
||||
"uninstall_prompt": "WebUI verrà rimosso dopo il riavvio",
|
||||
"uninstall_failed": "Impossibile disinstallare WebUI",
|
||||
"new_update": "È disponibile un nuovo aggiornamento!",
|
||||
"downloading": "Download nuovo aggiornamento...",
|
||||
"downloaded": "Download completato",
|
||||
"download_fail": "Impossibile scaricare l'aggiornamento",
|
||||
"installing": "Installazione aggiornamento...",
|
||||
"installed": "Installato correttamente, riavvia ora.",
|
||||
"install_fail": "Installazione non riuscita, aggiorna manualmente",
|
||||
"rebooting": "Riavvio...",
|
||||
"reboot_fail": "Impossibile riavviare, riavvia manualmente",
|
||||
"custom_key_set": "Keybox personalizzata impostata correttamente",
|
||||
"custom_key_set_error": "Impossibile impostare keybox personalizzata",
|
||||
"no_file_selected": "Nessun file selezionato",
|
||||
"system_app_not_found": "App di sistema non trovata",
|
||||
"system_app_error": "Impossibile aggiungere l'app di sistema"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Patch di sicurezza",
|
||||
"advanced_mode": "Avanzato",
|
||||
"get_date": "Ottieni data patch di sicurezza",
|
||||
"auto": "Auto",
|
||||
"save": "Salva",
|
||||
"fetching": "Recupero...",
|
||||
"fetched": "Fatto",
|
||||
"get_failed": "Impossibile recuperare la data della patch di sicurezza",
|
||||
"auto_success": "Configurazione automatica abilitata correttamente",
|
||||
"auto_failed": "Impossibile abilitare la configurazione automatica",
|
||||
"save_success": "Patch di sicurezza salvata correttamente",
|
||||
"save_failed": "Impossibile salvare la patch di sicurezza",
|
||||
"value_empty": "La configurazione della patch di sicurezza è disabilitata",
|
||||
"invalid_all": "Formato non valido",
|
||||
"invalid_boot": "Formato boot non valido",
|
||||
"invalid_system": "Formato system non valido",
|
||||
"invalid_vendor": "Formato vendor non valido"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Aggiungi app di sistema",
|
||||
"add": "Aggiungi",
|
||||
"current_list": "Elenco attuale delle app di sistema"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Confermi disinstallazione?",
|
||||
"uninstall_message": "Sei sicuro di voler disinstallare Tricky Addon",
|
||||
"uninstall_cancel": "Annulla",
|
||||
"uninstall_confirm": "Conferma"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/ja-JP.json
Normal file
132
module/webui/locales/ja-JP.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "日本語",
|
||||
"system_default": "システムデフォルト",
|
||||
"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 の環境でのみ使用可能です。Deny List 内のアプリを選択します(推奨)。",
|
||||
"deselect_unnecessary": "不要な選択を解除",
|
||||
"deselect_unnecessary_description": "不要なカテゴリー: Xposed モジュール、root マネージャー、root 関連アプリ、Bootloader の状態を確認しない一般的なアプリです。このオプションはインターネット接続が必要です。",
|
||||
"add_system_app": "システムアプリを追加",
|
||||
"add_system_app_description": "特定のシステムアプリをアプリリストに追加します。",
|
||||
"set_keybox": "AOSP と 有効な Keybox",
|
||||
"set_keybox_description": "Tricky Store の keybox.xml を置き換えます。有効な Keybox がなくなった場合は、AOSP Keybox に置き換えられます。インターネット接続が必要です。",
|
||||
"set_custom_keybox": "カスタム Keybox を設定",
|
||||
"set_custom_keybox_description": "デバイスのストレージからカスタム Keybox ファイルをインポートします。xml ファイルのみ対応。",
|
||||
"set_security_patch": "セキュリティパッチを設定",
|
||||
"set_security_patch_description": "カスタムセキュリティパッチの設定。自動設定は PIF モジュールのセキュリティパッチを使用します。空白のまま保存すると自動設定を無効にします。",
|
||||
"set_verified_boot_hash": "確認付きブートハッシュを設定",
|
||||
"set_verified_boot_hash_description": "Key Attestation Demo から確認付きブートハッシュの値を取得します。ro.boot.vbmeta.digest をリセットして異常なブート状態を修正します。"
|
||||
},
|
||||
"update": {
|
||||
"update_available": "新しいバージョンの準備完了",
|
||||
"redirect_to_release": "タップで最新のバージョンをダウンロード",
|
||||
"changelog": "変更履歴",
|
||||
"install": "インストール",
|
||||
"reboot": "再起動"
|
||||
},
|
||||
"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": "不要な選択を解除",
|
||||
"add_system_app": "システムアプリを追加",
|
||||
"set_aosp_keybox": "AOSP Keybox を設定",
|
||||
"set_valid_keybox": "有効な Keybox を設定",
|
||||
"set_custom_keybox": "カスタム Keybox を設定",
|
||||
"set_verified_boot_hash": "確認付きブートハッシュを設定",
|
||||
"set_security_patch": "セキュリティパッチを設定",
|
||||
"about": "このアドオンについて"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "ブートハッシュ",
|
||||
"input_placeholder": "確認付きブートハッシュをここに貼り付け",
|
||||
"save_button": "保存"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "Tricky Addon",
|
||||
"module_name_line2": "ターゲットリストを更新",
|
||||
"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": "新しいバージョンがあります!",
|
||||
"downloading": "新しい更新をダウンロード中...",
|
||||
"downloaded": "ダウンロードが完了しました",
|
||||
"download_fail": "更新のダウンロードに失敗しました",
|
||||
"installing": "更新をインストール中...",
|
||||
"installed": "正常にインストールされました。再起動してください。",
|
||||
"install_fail": "インストールに失敗しました。手動で更新してください。",
|
||||
"rebooting": "再起動中...",
|
||||
"reboot_fail": "再起動に失敗しました。手動で再起動してください。",
|
||||
"custom_key_set": "カスタム Keybox の設定に成功しました",
|
||||
"custom_key_set_error": "カスタム Keybox の設定に失敗しました",
|
||||
"no_file_selected": "ファイルが選択されていません",
|
||||
"system_app_not_found": "システムアプリが見つかりません",
|
||||
"system_app_error": "システムアプリの追加に失敗しました"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "セキュリティパッチ",
|
||||
"advanced_mode": "高度",
|
||||
"get_date": "セキュリティパッチの日付を取得",
|
||||
"auto": "自動",
|
||||
"save": "保存",
|
||||
"fetching": "取得中...",
|
||||
"fetched": "完了",
|
||||
"get_failed": "セキュリティパッチの日付を取得できませんでした",
|
||||
"auto_success": "自動設定が有効化されました",
|
||||
"auto_failed": "自動設定が有効化できませんでした",
|
||||
"save_success": "セキュリティパッチが正常に保存されました",
|
||||
"save_failed": "セキュリティパッチの保存に失敗しました",
|
||||
"value_empty": "セキュリティパッチの設定は無効です",
|
||||
"invalid_all": "無効な形式です",
|
||||
"invalid_boot": "無効な boot 形式です",
|
||||
"invalid_system": "無効な system 形式です",
|
||||
"invalid_vendor": "無効な vendor 形式です"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "システムアプリを追加",
|
||||
"add": "追加",
|
||||
"current_list": "現在のシステムアプリリスト"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "アンインストールの確認",
|
||||
"uninstall_message": "Tricky Addonをアンインストールしてもよろしいですか",
|
||||
"uninstall_cancel": "キャンセル",
|
||||
"uninstall_confirm": "確認"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/pl-PL.json
Normal file
132
module/webui/locales/pl-PL.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "Polski",
|
||||
"system_default": "Domyślne systemowe",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"help": {
|
||||
"help_instructions": "Instrukcja",
|
||||
"save_and_update": "Zapisz",
|
||||
"save_and_update_description": "Zapisz bieżącą konfigurację do target.txt.",
|
||||
"refresh": "Odśwież",
|
||||
"refresh_description": "Odśwież listę aplikacji i listę wykluczeń.",
|
||||
"select_deselect": "Zaznacz i odznacz wszystko",
|
||||
"select_description": "Zaznacz lub odznacz wszystkie aplikacje w bieżącym interfejsie.",
|
||||
"select_denylist": "Wybierz z listy odrzuconych",
|
||||
"select_denylist_description": "Dostępne tylko w Magisk, wybrane aplikacje, które są na DenyList. Zalecane.",
|
||||
"deselect_unnecessary": "Odznacz niepotrzebne",
|
||||
"deselect_unnecessary_description": "Kategoria niepotrzebna: moduł Xposed, menedżer root, aplikacje związane z rootem i ogólne aplikacje, które nigdy nie sprawdzają stanu bootloadera. Ta opcja wymaga połączenia internetowego.",
|
||||
"add_system_app": "Dodaj aplikację systemową",
|
||||
"add_system_app_description": "Dodaj konkretną aplikację systemową do listy aplikacji.",
|
||||
"set_keybox": "Ustaw AOSP i prawidłowy klucz",
|
||||
"set_keybox_description": "Zastąp tricky store keybox.xml. Klucz AOSP zostanie zastąpiony, jeśli nie będzie już prawidłowego klucza. Opcja pobrania prawidłowego klucza wymaga połączenia internetowego.",
|
||||
"set_custom_keybox": "Ustaw niestandardowy klucz",
|
||||
"set_custom_keybox_description": "Importuj klucz z pamięci urządzenia. Obsługuje tylko pliki xml.",
|
||||
"set_security_patch": "Ustaw poprawkę bezpieczeństwa",
|
||||
"set_security_patch_description": "Ustaw niestandardową poprawkę bezpieczeństwa. Automatyczna konfiguracja użyje poprawki bezpieczeństwa z modułu PIF, domyślnie włączonego. Pozostaw puste i zapisz, aby wyłączyć automatyczną konfigurację.",
|
||||
"set_verified_boot_hash": "Ustaw zweryfikowany skrót rozruchowy",
|
||||
"set_verified_boot_hash_description": "Pobierz wartość verifiedBootHash z Key Attestation Demo. Napraw nieprawidłowy stan rozruchu, resetując ro.boot.vbmeta.digest."
|
||||
},
|
||||
"update": {
|
||||
"update_available": "Nowa wersja jest gotowa",
|
||||
"redirect_to_release": "dotknij, aby pobrać najnowszą wersję",
|
||||
"changelog": "Dziennik zmian",
|
||||
"install": "Zainstaluj",
|
||||
"reboot": "Odśwież"
|
||||
},
|
||||
"search_bar": {
|
||||
"search_placeholder": "Szukaj"
|
||||
},
|
||||
"functional_button": {
|
||||
"save_and_update_button": "Zapisz",
|
||||
"uninstall_webui": "Odinstaluj WebUI"
|
||||
},
|
||||
"loading": {
|
||||
"loading": "Ładowanie..."
|
||||
},
|
||||
"menu": {
|
||||
"refresh": "Odśwież ",
|
||||
"select_all": "Zaznacz wszystko",
|
||||
"deselect_all": "Odznacz wszystko",
|
||||
"select_denylist": "Wybierz z listy odrzuconych",
|
||||
"deselect_unnecessary": "Odznacz niepotrzebne",
|
||||
"add_system_app": "Dodaj aplikację systemową",
|
||||
"set_aosp_keybox": "Ustaw klucz AOSP",
|
||||
"set_valid_keybox": "Ustaw ważny klucz",
|
||||
"set_custom_keybox": "Ustaw niestandardowy klucz ",
|
||||
"set_verified_boot_hash": "Ustaw zweryfikowany skrót rozruchowy",
|
||||
"set_security_patch": "Ustaw poprawkę bezpieczeństwa",
|
||||
"about": "O"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Hash rozruchu",
|
||||
"input_placeholder": "Wklej tutaj zweryfikowany skrót rozruchowy",
|
||||
"save_button": "Zapisz"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "Tricky Addon",
|
||||
"module_name_line2": "Aktualizacja listy celów",
|
||||
"by": "wydany przez:",
|
||||
"telegram_channel": "Kanał Telegram",
|
||||
"github": "GitHub",
|
||||
"disclaimer": "Ten moduł nie jest częścią modułu Tricky Store. NIE zgłaszaj żadnych problemów do Tricky Store, jeśli je napotkasz.",
|
||||
"acknowledgment": "Podziękowania dla:"
|
||||
},
|
||||
"prompt": {
|
||||
"no_internet": "Sprawdź swoje połączenie internetowe",
|
||||
"aosp_key_set": "Klucz AOSP ustawiony pomyślnie",
|
||||
"key_set_error": "Nie udało się zaktualizować klucza",
|
||||
"valid_key_set": "Prawidłowy klucz został pomyślnie ustawiony",
|
||||
"no_valid_fallback": "Nie znaleziono prawidłowego klucza. Zastąpiono kluczem AOSP.",
|
||||
"boot_hash_set": "Zweryfikowano skrót rozruchowy, który został pomyślnie zapisany",
|
||||
"boot_hash_set_error": "Nie udało się zaktualizować zweryfikowanego skrótu rozruchowego",
|
||||
"saved_target": "Konfiguracja zapisana w pliku target.txt",
|
||||
"save_error": "Nie udało się zapisać konfiguracji",
|
||||
"uninstall_prompt": "WebUI zostanie usunięty po ponownym uruchomieniu",
|
||||
"uninstall_failed": "Nie udało się odinstalować WebUI",
|
||||
"new_update": "Dostępna jest nowa aktualizacja!",
|
||||
"downloading": "Pobieranie nowej aktualizacji...",
|
||||
"downloaded": "Pobieranie ukończone",
|
||||
"download_fail": "Nie udało się pobrać aktualizacji",
|
||||
"installing": "Instalowanie aktualizacji...",
|
||||
"installed": "Instalacja przebiegła pomyślnie, uruchom ponownie.",
|
||||
"install_fail": "Nie udało się zainstalować, zaktualizuj instrukcję",
|
||||
"rebooting": "Ponowne uruchomienie...",
|
||||
"reboot_fail": "Nie udało się ponownie uruchomić, proszę ponownie uruchomić ręcznie",
|
||||
"custom_key_set": "Niestandardowe klucz został pomyślnie ustawiony",
|
||||
"custom_key_set_error": "Nie udało się ustawić niestandardowego klucza",
|
||||
"no_file_selected": "Nie wybrano pliku",
|
||||
"system_app_not_found": "Aplikacja systemowa nie znaleziona",
|
||||
"system_app_error": "Nie udało się dodać aplikacji systemowej"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Poprawka bezpieczeństwa",
|
||||
"advanced_mode": "Zaawansowany",
|
||||
"get_date": "Pobierz datę poprawki zabezpieczeń",
|
||||
"auto": "Automatyczny",
|
||||
"save": "Zapisz",
|
||||
"fetching": "Pobieranie...",
|
||||
"fetched": "Zrobione",
|
||||
"get_failed": "Nie udało się pobrać daty poprawki zabezpieczeń",
|
||||
"auto_success": "Konfiguracja automatyczna włączona pomyślnie",
|
||||
"auto_failed": "Nie udało się włączyć automatycznej konfiguracji",
|
||||
"save_success": "Poprawka zabezpieczeń została pomyślnie zapisana",
|
||||
"save_failed": "Nie udało się zapisać poprawki zabezpieczeń",
|
||||
"value_empty": "Konfiguracja poprawki zabezpieczeń jest wyłączona",
|
||||
"invalid_all": "Nieprawidłowy format",
|
||||
"invalid_boot": "Nieprawidłowy format rozruchu",
|
||||
"invalid_system": "Nieprawidłowy format systemu",
|
||||
"invalid_vendor": "Nieprawidłowy format dostawcy"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Dodaj aplikację systemową",
|
||||
"add": "Dodaj",
|
||||
"current_list": "Aktualna lista aplikacji systemowych"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Potwierdzić odinstalowanie?",
|
||||
"uninstall_message": "Czy na pewno chcesz odinstalować Tricky Addon",
|
||||
"uninstall_cancel": "Anuluj",
|
||||
"uninstall_confirm": "Potwierdź"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/ru-RU.json
Normal file
132
module/webui/locales/ru-RU.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "Русский",
|
||||
"system_default": "Системный по умолчанию",
|
||||
"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, и общие приложения, которые никогда не проверяют статус загрузчика. Этот параметр требует подключения к интернету.",
|
||||
"add_system_app": "Добавить системное приложение",
|
||||
"add_system_app_description": "Добавить конкретное системное приложение в список приложений.",
|
||||
"set_keybox": "Установить AOSP и действующий Keybox",
|
||||
"set_keybox_description": "Замените tricky store keybox.xml. AOSP keybox будет заменен, если не будет найден действующий keybox. Опция с действующим keybox требует подключения к интернету.",
|
||||
"set_custom_keybox": "Установить пользовательский Keybox",
|
||||
"set_custom_keybox_description": "Импортируйте файл keybox из вашего устройства в хранилище. Поддерживаются только xml файлы.",
|
||||
"set_security_patch": "Установить Security Patch",
|
||||
"set_security_patch_description": "Установите пользовательский патч безопасности. Автоматическая настройка будет использовать патч безопасности из модуля PIF, включен по умолчанию. Оставьте пустым и сохраните, чтобы отключить автоматическую настройку.",
|
||||
"set_verified_boot_hash": "Установить Verified Boot Hash",
|
||||
"set_verified_boot_hash_description": "Получите значение verifiedBootHash из Key Attestation Demo. Исправьте аномальное состояние загрузки, сбросив ro.boot.vbmeta.digest."
|
||||
},
|
||||
"update": {
|
||||
"update_available": "Доступна новая версия",
|
||||
"redirect_to_release": "нажмите, чтобы скачать последнюю версию",
|
||||
"changelog": "Список изменений",
|
||||
"install": "Установить",
|
||||
"reboot": "Перезагрузить"
|
||||
},
|
||||
"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": "Отменить выбор ненужных",
|
||||
"add_system_app": "Добавить системное приложение",
|
||||
"set_aosp_keybox": "Установить AOSP Keybox",
|
||||
"set_valid_keybox": "Установить действующий Keybox",
|
||||
"set_custom_keybox": "Установить пользовательский Keybox",
|
||||
"set_security_patch": "Установить Security Patch",
|
||||
"set_verified_boot_hash": "Установить Verified Boot Hash",
|
||||
"about": "О программе"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Boot Hash",
|
||||
"input_placeholder": "Вставьте свой проверенный 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": "Доступно новое обновление!",
|
||||
"downloading": "Загрузка нового обновления...",
|
||||
"downloaded": "Загрузка завершена",
|
||||
"download_fail": "Не удалось загрузить обновление",
|
||||
"installing": "Установка обновления...",
|
||||
"installed": "Успешно установлено, перезагрузите устройство.",
|
||||
"install_fail": "Не удалось установить, обновите вручную",
|
||||
"rebooting": "Перезагрузка...",
|
||||
"reboot_fail": "Не удалось перезагрузить, перезагрузите вручную",
|
||||
"custom_key_set": "Пользовательский keybox успешно установлен",
|
||||
"custom_key_set_error": "Не удалось установить пользовательский keybox",
|
||||
"no_file_selected": "Файл не выбран",
|
||||
"system_app_not_found": "Системное приложение не найдено",
|
||||
"system_app_error": "Не удалось добавить системное приложение"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Патч безопасности",
|
||||
"advanced_mode": "Расширенный",
|
||||
"get_date": "Получить дату патча безопасности",
|
||||
"auto": "Авто",
|
||||
"save": "Сохранить",
|
||||
"fetching": "Получение...",
|
||||
"fetched": "Готово",
|
||||
"get_failed": "Не удалось получить дату патча безопасности",
|
||||
"auto_success": "Автоматическая конфигурация успешно включена",
|
||||
"auto_failed": "Не удалось включить автоматическую конфигурацию",
|
||||
"save_success": "Патч безопасности успешно сохранен",
|
||||
"save_failed": "Не удалось сохранить патч безопасности",
|
||||
"value_empty": "Конфигурация патча безопасности отключена",
|
||||
"invalid_all": "Неверный формат",
|
||||
"invalid_boot": "Неверный формат boot",
|
||||
"invalid_system": "Неверный формат system",
|
||||
"invalid_vendor": "Неверный формат vendor"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Добавить системное приложение",
|
||||
"add": "Добавить",
|
||||
"current_list": "Текущий список системных приложений"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Подтвердить удаление?",
|
||||
"uninstall_message": "Вы уверены, что хотите удалить Tricky Addon",
|
||||
"uninstall_cancel": "Отмена",
|
||||
"uninstall_confirm": "Подтвердить"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/tl-PH.json
Normal file
132
module/webui/locales/tl-PH.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "Filipino",
|
||||
"system_default": "Default ng Sistema",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"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.",
|
||||
"add_system_app": "Magdagdag ng System App",
|
||||
"add_system_app_description": "Magdagdag ng tiyak na system app sa listahan ng apps.",
|
||||
"set_keybox": "I-set ang AOSP at Valid Keybox",
|
||||
"set_keybox_description": "Palitan ang tricky store keybox. Palitan ang AOSP keybox kung walang valid keybox. Nangangailangan ng koneksyon sa internet ang valid keybox option.",
|
||||
"set_custom_keybox": "I-set ang Custom Keybox",
|
||||
"set_custom_keybox_description": "Mag-import ng custom keybox mula sa iyong device storage. Sumusuporta lamang ng xml file.",
|
||||
"set_security_patch": "I-set ang Security Patch",
|
||||
"set_security_patch_description": "I-set ang custom security patch. Ang auto config ay mag-use ng security patch mula sa PIF module, default enabled. I-leave blank at i-save para i-disable ang auto config.",
|
||||
"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": {
|
||||
"update_available": "Handa na ang bagong bersyon",
|
||||
"redirect_to_release": "i-tap para i-download ang pinakabagong bersyon",
|
||||
"changelog": "Mga Pagbabago",
|
||||
"install": "I-install",
|
||||
"reboot": "I-reboot"
|
||||
},
|
||||
"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",
|
||||
"add_system_app": "Magdagdag ng System App",
|
||||
"set_aosp_keybox": "I-set ang AOSP Keybox",
|
||||
"set_valid_keybox": "I-set ang Valid Keybox",
|
||||
"set_custom_keybox": "I-set ang Custom Keybox",
|
||||
"set_verified_boot_hash": "I-set ang Verified Boot Hash",
|
||||
"set_security_patch": "I-set ang Security Patch",
|
||||
"about": "Tungkol"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Boot Hash",
|
||||
"input_placeholder": "I-paste ang iyong verified Boot Hash dito",
|
||||
"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!",
|
||||
"downloading": "Nagda-download ng bagong update...",
|
||||
"downloaded": "Natapos ang pag-download",
|
||||
"download_fail": "Nabigo ang pag-download ng update",
|
||||
"installing": "Nag-i-install ng update...",
|
||||
"installed": "Matagumpay na na-install, mag-reboot na ngayon.",
|
||||
"install_fail": "Nabigo ang pag-install, pakisubukang mag-update nang manu-mano",
|
||||
"rebooting": "Nag-re-reboot...",
|
||||
"reboot_fail": "Nabigo ang pag-reboot, pakisubukang mag-reboot nang manu-mano",
|
||||
"custom_key_set": "Matagumpay na na-set ang Custom Keybox",
|
||||
"custom_key_set_error": "Nabigong i-set ang Custom Keybox",
|
||||
"no_file_selected": "Walang napiling file",
|
||||
"system_app_not_found": "Walang natagpuan na system app",
|
||||
"system_app_error": "Nabigong dagdag ang system app"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Security Patch",
|
||||
"advanced_mode": "Advanced",
|
||||
"get_date": "Kunin ang Petsa ng Security Patch",
|
||||
"auto": "Auto",
|
||||
"save": "I-save",
|
||||
"fetching": "Kumukuha...",
|
||||
"fetched": "Tapos na",
|
||||
"get_failed": "Hindi makuha ang petsa ng security patch",
|
||||
"auto_success": "Matagumpay na na-enable ang auto config",
|
||||
"auto_failed": "Nabigong i-enable ang auto config",
|
||||
"save_success": "Matagumpay na na-save ang security patch",
|
||||
"save_failed": "Nabigong i-save ang security patch",
|
||||
"value_empty": "Naka-disable ang configuration ng security patch",
|
||||
"invalid_all": "Invalid format",
|
||||
"invalid_boot": "Invalid boot format",
|
||||
"invalid_system": "Invalid system format",
|
||||
"invalid_vendor": "Invalid vendor format"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Magdagdag ng System App",
|
||||
"add": "Idagdag",
|
||||
"current_list": "Kasalukuyang Listahan ng System App"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Kumpirmahin ang Pag-uninstall?",
|
||||
"uninstall_message": "Sigurado ka bang gusto mong i-uninstall ang Tricky Addon",
|
||||
"uninstall_cancel": "Kanselahin",
|
||||
"uninstall_confirm": "Kumpirmahin"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/tr-TR.json
Normal file
132
module/webui/locales/tr-TR.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "Türkçe",
|
||||
"system_default": "Sistem Varsayılanı",
|
||||
"header": {
|
||||
"title": "Tricky Addon"
|
||||
},
|
||||
"help": {
|
||||
"help_instructions": "Talimatlar",
|
||||
"save_and_update": "Kaydet",
|
||||
"save_and_update_description": "Mevcut yapılandırmayı target.txt dosyasına kaydet.",
|
||||
"refresh": "Yenile",
|
||||
"refresh_description": "Uygulama ve hariç tutma listesini yenile.",
|
||||
"select_deselect": "Tümünü Seç & Seçimi Kaldır",
|
||||
"select_description": "Mevcut arayüzdeki tüm uygulamaları seç veya seçimini kaldır.",
|
||||
"select_denylist": "Reddetme Listesinden Seç",
|
||||
"select_denylist_description": "Yalnızca Magisk'te mevcut, Reddetme Listesindeki uygulamaları seç. Tavsiye edilir.",
|
||||
"deselect_unnecessary": "Gereksizleri Seçme",
|
||||
"deselect_unnecessary_description": "Gereksiz kategori: Xposed modülü, root yöneticisi, root ile ilgili uygulamalar ve asla bootloader durumunu kontrol etmeyen genel uygulamalar. Bu seçenek internet bağlantısı gerektirir.",
|
||||
"add_system_app": "Sistem Uygulaması Ekle",
|
||||
"add_system_app_description": "Belirli bir sistem uygulamasını uygulama listesine ekleyin.",
|
||||
"set_keybox": "AOSP & Geçerli Keybox Ayarla",
|
||||
"set_keybox_description": "Tricky Store'daki keybox.xml dosyasını değiştirir. Eğer geçerli bir keybox yoksa AOSP keybox ile değiştirilecektir. Geçerli keybox seçeneği internet bağlantısı gerektirir.",
|
||||
"set_custom_keybox": "Özel Keybox Ayarla",
|
||||
"set_custom_keybox_description": "Cihaz depolamasından bir keybox dosyasını içe aktarın. Sadece xml dosyaları desteklenir.",
|
||||
"set_security_patch": "Güvenlik Yaması Ayarla",
|
||||
"set_security_patch_description": "Özel güvenlik yamasını ayarlayın. Otomatik yapılandırma PIF modülünün güvenlik yamasını kullanacaktır. Boş bırakın ve kaydedin ki otomatik yapılandırma devre dışı bırakılsın.",
|
||||
"set_verified_boot_hash": "Doğrulanmış Boot Hash Ayarla",
|
||||
"set_verified_boot_hash_description": "Key Attestation Demo'dan verifiedBootHash değerini alın. Abnormal boot durumunu ro.boot.vbmeta.digest'i sıfırlayarak düzeltin."
|
||||
},
|
||||
"update": {
|
||||
"update_available": "Yeni bir sürüm hazır",
|
||||
"redirect_to_release": "Son sürümü indirmek için dokunun",
|
||||
"changelog": "Değişiklik Günlüğü",
|
||||
"install": "Yükle",
|
||||
"reboot": "Yeniden Başlat"
|
||||
},
|
||||
"search_bar": {
|
||||
"search_placeholder": "Ara"
|
||||
},
|
||||
"functional_button": {
|
||||
"save_and_update_button": "Kaydet",
|
||||
"uninstall_webui": "WebUI'ı Kaldır"
|
||||
},
|
||||
"loading": {
|
||||
"loading": "Yükleniyor..."
|
||||
},
|
||||
"menu": {
|
||||
"refresh": "Yenile",
|
||||
"select_all": "Tümünü Seç",
|
||||
"deselect_all": "Tüm Seçimleri Kaldır",
|
||||
"select_denylist": "Reddetme Listesinden Seç",
|
||||
"deselect_unnecessary": "Gereksizleri Seçme",
|
||||
"add_system_app": "Sistem Uygulaması Ekle",
|
||||
"set_aosp_keybox": "AOSP Keybox Ayarla",
|
||||
"set_valid_keybox": "Geçerli Keybox Ayarla",
|
||||
"set_custom_keybox": "Özel Keybox Ayarla",
|
||||
"set_security_patch": "Güvenlik Yaması Ayarla",
|
||||
"set_verified_boot_hash": "Doğrulanmış Boot Hash Ayarla",
|
||||
"about": "Hakkında"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "Boot Hash",
|
||||
"input_placeholder": "Doğrulanmış Boot Hash'inizi buraya yapıştırın",
|
||||
"save_button": "Kaydet"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "Tricky Addon",
|
||||
"module_name_line2": "Target List'i Güncelle",
|
||||
"by": "tarafından",
|
||||
"telegram_channel": "Telegram Kanalı",
|
||||
"github": "GitHub",
|
||||
"disclaimer": "Bu modül, Tricky Store modülünün bir parçası değildir. Herhangi bir sorun yaşarsanız, lütfen bunu Tricky Store'a rapor etmeyin.",
|
||||
"acknowledgment": "Teşekkürler"
|
||||
},
|
||||
"prompt": {
|
||||
"no_internet": "Lütfen internet bağlantınızı kontrol edin",
|
||||
"aosp_key_set": "AOSP keybox başarıyla ayarlandı",
|
||||
"key_set_error": "Keybox güncellenemedi",
|
||||
"valid_key_set": "Geçerli keybox başarıyla ayarlandı",
|
||||
"no_valid_fallback": "Geçerli keybox bulunamadı, AOSP keybox ile değiştirildi.",
|
||||
"boot_hash_set": "Doğrulanmış Boot Hash başarıyla kaydedildi",
|
||||
"boot_hash_set_error": "Doğrulanmış Boot Hash güncellenemedi",
|
||||
"saved_target": "Yapılandırma target.txt dosyasına kaydedildi",
|
||||
"save_error": "Yapılandırma kaydedilemedi",
|
||||
"uninstall_prompt": "WebUI yeniden başlatma sonrasında kaldırılacak",
|
||||
"uninstall_failed": "WebUI kaldırılamadı",
|
||||
"new_update": "Yeni bir güncelleme mevcut!",
|
||||
"downloading": "Yeni güncelleme indiriliyor...",
|
||||
"downloaded": "İndirme tamamlandı",
|
||||
"download_fail": "Güncelleme indirilemedi",
|
||||
"installing": "Güncelleme yükleniyor...",
|
||||
"installed": "Başarıyla yüklendi, şimdi yeniden başlatın.",
|
||||
"install_fail": "Yükleme başarısız oldu, lütfen manuel olarak güncelleyin",
|
||||
"rebooting": "Yeniden başlatılıyor...",
|
||||
"reboot_fail": "Yeniden başlatma başarısız, lütfen manuel olarak yeniden başlatın",
|
||||
"custom_key_set": "Özel keybox başarıyla ayarlandı",
|
||||
"custom_key_set_error": "Özel keybox ayarlanamadı",
|
||||
"no_file_selected": "Dosya seçilmedi",
|
||||
"system_app_not_found": "Sistem uygulaması bulunamadı",
|
||||
"system_app_error": "Sistem uygulaması ekleme hatası"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "Güvenlik Yaması",
|
||||
"advanced_mode": "Gelişmiş",
|
||||
"get_date": "Güvenlik Yaması Tarihini Al",
|
||||
"auto": "Otomatik",
|
||||
"save": "Kaydet",
|
||||
"fetching": "Alınıyor...",
|
||||
"fetched": "Tamamlandı",
|
||||
"get_failed": "Güvenlik yaması tarihi alınamadı",
|
||||
"auto_success": "Otomatik yapılandırma başarıyla etkinleştirildi",
|
||||
"auto_failed": "Otomatik yapılandırma etkinleştirilemedi",
|
||||
"save_success": "Güvenlik yaması başarıyla kaydedildi",
|
||||
"save_failed": "Güvenlik yaması kaydedilemedi",
|
||||
"value_empty": "Güvenlik yaması yapılandırması devre dışı bırakıldı",
|
||||
"invalid_all": "Geçersiz format",
|
||||
"invalid_boot": "Geçersiz boot formatı",
|
||||
"invalid_system": "Geçersiz system formatı",
|
||||
"invalid_vendor": "Geçersiz vendor formatı"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "Sistem Uygulaması Ekle",
|
||||
"add": "Ekle",
|
||||
"current_list": "Mevcut Sistem Uygulamaları Listesi"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "Kaldırma İşlemi Onaylansın mı?",
|
||||
"uninstall_message": "Tricky Addon'u kaldırmak istediğinizden emin misiniz",
|
||||
"uninstall_cancel": "İptal",
|
||||
"uninstall_confirm": "Onayla"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/zh-CN.json
Normal file
132
module/webui/locales/zh-CN.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "简体中文",
|
||||
"system_default": "系统默认",
|
||||
"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 状态的通用应用。此功能需连网使用。",
|
||||
"add_system_app": "添加系统应用",
|
||||
"add_system_app_description": "添加特定系统应用到应用列表。",
|
||||
"set_keybox": "设置 AOSP & 有效密钥",
|
||||
"set_keybox_description": "替换 Tricky Store 的密钥(keybox.xml)。如果没有有效密钥,将替换为 AOSP 密钥。有效密钥选项需连网使用。",
|
||||
"set_custom_keybox": "设置自定义密钥",
|
||||
"set_custom_keybox_description": "从设备存储导入自定义密钥。仅支持 xml 文件。",
|
||||
"set_security_patch": "设置安全补丁",
|
||||
"set_security_patch_description": "设置自定义安全补丁。自动配置将使用 PIF 模块的安全补丁,默认启用。留空保存则禁用自动配置。",
|
||||
"set_verified_boot_hash": "设置哈希值",
|
||||
"set_verified_boot_hash_description": "从 Key Attestation Demo 获取 verifiedBootHash(哈希值)。通过重置 ro.boot.vbmeta.digest 修复异常 boot 状态。"
|
||||
},
|
||||
"update": {
|
||||
"update_available": "发现新的版本",
|
||||
"redirect_to_release": "点击下载最新版本",
|
||||
"changelog": "更新日志",
|
||||
"install": "安装",
|
||||
"reboot": "重启"
|
||||
},
|
||||
"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": "取消选择非必要应用",
|
||||
"add_system_app": "添加系统应用",
|
||||
"set_aosp_keybox": "设置 AOSP 密钥",
|
||||
"set_valid_keybox": "设置有效密钥",
|
||||
"set_custom_keybox": "设置自定义密钥",
|
||||
"set_security_patch": "设置安全补丁",
|
||||
"set_verified_boot_hash": "设置哈希值",
|
||||
"about": "关于"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "哈希值",
|
||||
"input_placeholder": "在此粘贴您的哈希值",
|
||||
"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": "发现新的版本!",
|
||||
"downloading": "正在下载...",
|
||||
"downloaded": "下载完成",
|
||||
"download_fail": "下载失败",
|
||||
"installing": "正常安装...",
|
||||
"installed": "安装完成,重启生效",
|
||||
"install_fail": "安装失败,请手动更新",
|
||||
"rebooting": "正在重启...",
|
||||
"reboot_fail": "重启失败,请手动重启",
|
||||
"custom_key_set": "成功设置自定义密钥",
|
||||
"custom_key_set_error": "设置自定义密钥失败",
|
||||
"no_file_selected": "未选择文件",
|
||||
"system_app_not_found": "未找到该系统应用",
|
||||
"system_app_error": "系统应用添加失败"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "安全补丁",
|
||||
"advanced_mode": "高级",
|
||||
"get_date": "获取安全补丁日期",
|
||||
"auto": "自动",
|
||||
"save": "保存",
|
||||
"fetching": "获取中...",
|
||||
"fetched": "完成",
|
||||
"get_failed": "获取安全补丁日期失败",
|
||||
"auto_success": "自动配置成功启用",
|
||||
"auto_failed": "无法启用自动配置",
|
||||
"save_success": "安全补丁成功保存",
|
||||
"save_failed": "保存安全补丁失败",
|
||||
"value_empty": "安全补丁配置已禁用",
|
||||
"invalid_all": "无效格式",
|
||||
"invalid_boot": "无效 boot 格式",
|
||||
"invalid_system": "无效 system 格式",
|
||||
"invalid_vendor": "无效 vendor 格式"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "添加系统应用",
|
||||
"add": "添加",
|
||||
"current_list": "当前系统应用列表"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "确认卸载?",
|
||||
"uninstall_message": "您确定要卸载 TS 插件吗",
|
||||
"uninstall_cancel": "取消",
|
||||
"uninstall_confirm": "确认"
|
||||
}
|
||||
}
|
||||
132
module/webui/locales/zh-TW.json
Normal file
132
module/webui/locales/zh-TW.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"language": "繁體中文",
|
||||
"system_default": "系統預設",
|
||||
"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 狀態的通用應用。此功能需連網使用。",
|
||||
"add_system_app": "添加系統應用",
|
||||
"add_system_app_description": "添加特定系統應用到應用列表。",
|
||||
"set_keybox": "設置 AOSP & 有效密鑰",
|
||||
"set_keybox_description": "替換 Tricky Store 的密鑰(keybox.xml)。如果沒有有效密鑰,將替換為 AOSP 密鑰。有效密鑰選項需連網使用。",
|
||||
"set_custom_keybox": "設置自定義密鑰",
|
||||
"set_custom_keybox_description": "從設備存儲導入自定義密鑰。僅支持 xml 文件。",
|
||||
"set_security_patch": "設置安全補丁",
|
||||
"set_security_patch_description": "設置自定義安全補丁。自動配置將使用 PIF 模組的安全補丁,預設啟用。留空保存則禁用自動配置。",
|
||||
"set_verified_boot_hash": "設置哈希值",
|
||||
"set_verified_boot_hash_description": "從 Key Attestation Demo 獲取 verifiedBootHash(哈希值)。通過重置 ro.boot.vbmeta.digest 修復異常 boot 狀態。"
|
||||
},
|
||||
"update": {
|
||||
"update_available": "發現新版本",
|
||||
"redirect_to_release": "點擊下載最新版本",
|
||||
"changelog": "更新日誌",
|
||||
"install": "安裝",
|
||||
"reboot": "重啟"
|
||||
},
|
||||
"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": "取消選擇非必要應用",
|
||||
"add_system_app": "添加系統應用",
|
||||
"set_aosp_keybox": "設置 AOSP 密鑰",
|
||||
"set_valid_keybox": "設置有效密鑰",
|
||||
"set_custom_keybox": "設置自定義密鑰",
|
||||
"set_security_patch": "設置安全補丁",
|
||||
"set_verified_boot_hash": "設置哈希值",
|
||||
"about": "關於"
|
||||
},
|
||||
"boot_hash": {
|
||||
"title": "哈希值",
|
||||
"input_placeholder": "在此貼上您的哈希值",
|
||||
"save_button": "保存"
|
||||
},
|
||||
"about": {
|
||||
"module_name_line1": "TS 插件",
|
||||
"module_name_line2": "更新目標列表",
|
||||
"by": "作者:",
|
||||
"telegram_channel": "Telegram 頻道",
|
||||
"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": "發現新版本!",
|
||||
"downloading": "正在下載...",
|
||||
"downloaded": "下載完成",
|
||||
"download_fail": "下載失敗",
|
||||
"installing": "正在安裝...",
|
||||
"installed": "安裝完成,重啟生效",
|
||||
"install_fail": "安裝失敗,請手動更新",
|
||||
"rebooting": "正在重啟...",
|
||||
"reboot_fail": "重啟失敗,請手動重啟",
|
||||
"custom_key_set": "成功設置自定義密鑰",
|
||||
"custom_key_set_error": "設置自定義密鑰失敗",
|
||||
"no_file_selected": "未選擇文件",
|
||||
"system_app_not_found": "未找到該系統應用",
|
||||
"system_app_error": "系統應用添加失敗"
|
||||
},
|
||||
"security_patch": {
|
||||
"title": "安全補丁",
|
||||
"advanced_mode": "進階",
|
||||
"get_date": "獲取安全補丁日期",
|
||||
"auto": "自動",
|
||||
"save": "保存",
|
||||
"fetching": "獲取中...",
|
||||
"fetched": "完成",
|
||||
"get_failed": "獲取安全補丁日期失敗",
|
||||
"auto_success": "自動配置成功啟用",
|
||||
"auto_failed": "無法啟用自動配置",
|
||||
"save_success": "安全補丁成功保存",
|
||||
"save_failed": "保存安全補丁失敗",
|
||||
"value_empty": "安全補丁配置已禁用",
|
||||
"invalid_all": "無效格式",
|
||||
"invalid_boot": "無效 boot 格式",
|
||||
"invalid_system": "無效 system 格式",
|
||||
"invalid_vendor": "無效 vendor 格式"
|
||||
},
|
||||
"add_system_app": {
|
||||
"title": "添加系統應用",
|
||||
"add": "添加",
|
||||
"current_list": "當前系統應用列表"
|
||||
},
|
||||
"confirmation": {
|
||||
"uninstall_title": "確認卸載?",
|
||||
"uninstall_message": "您確定要卸載 TS 插件嗎",
|
||||
"uninstall_cancel": "取消",
|
||||
"uninstall_confirm": "確認"
|
||||
}
|
||||
}
|
||||
40
module/webui/scripts/about.js
Normal file
40
module/webui/scripts/about.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import { linkRedirect } from './main.js';
|
||||
|
||||
// Function to show about overlay
|
||||
document.getElementById("about").addEventListener("click", () => {
|
||||
const aboutOverlay = document.getElementById('about-overlay');
|
||||
const aboutContent = document.querySelector('.about-menu');
|
||||
const closeAbout = document.getElementById('close-about');
|
||||
|
||||
// Show about menu
|
||||
setTimeout(() => {
|
||||
document.body.classList.add("no-scroll");
|
||||
aboutOverlay.style.display = 'flex';
|
||||
setTimeout(() => {
|
||||
aboutOverlay.style.opacity = '1';
|
||||
aboutContent.classList.add('open');
|
||||
}, 10);
|
||||
}, 80);
|
||||
|
||||
const hideMenu = () => {
|
||||
document.body.classList.remove("no-scroll");
|
||||
aboutOverlay.style.opacity = '0';
|
||||
aboutContent.classList.remove('open');
|
||||
setTimeout(() => {
|
||||
aboutOverlay.style.display = 'none';
|
||||
}, 200);
|
||||
};
|
||||
|
||||
closeAbout.addEventListener("click", hideMenu);
|
||||
aboutOverlay.addEventListener('click', (event) => {
|
||||
if (event.target === aboutOverlay) hideMenu();
|
||||
});
|
||||
});
|
||||
|
||||
// Event listener for link redirect
|
||||
document.getElementById('telegram').addEventListener('click', function() {
|
||||
linkRedirect('https://t.me/kowchannel');
|
||||
});
|
||||
document.getElementById('github').addEventListener('click', function() {
|
||||
linkRedirect('https://github.com/KOWX712/Tricky-Addon-Update-Target-List');
|
||||
});
|
||||
260
module/webui/scripts/applist.js
Normal file
260
module/webui/scripts/applist.js
Normal file
@@ -0,0 +1,260 @@
|
||||
import { basePath, execCommand, hideFloatingBtn, appsWithExclamation, appsWithQuestion, toast } from './main.js';
|
||||
|
||||
const appTemplate = document.getElementById('app-template').content;
|
||||
const modeOverlay = document.querySelector('.mode-overlay');
|
||||
export const appListContainer = document.getElementById('apps-list');
|
||||
export const updateCard = document.getElementById('update-card');
|
||||
|
||||
// Fetch and render applist
|
||||
export async function fetchAppList() {
|
||||
try {
|
||||
// fetch target list
|
||||
let targetList = [];
|
||||
try {
|
||||
const targetFileContent = await execCommand('cat /data/adb/tricky_store/target.txt');
|
||||
targetList = processTargetList(targetFileContent);
|
||||
} catch (error) {
|
||||
toast("Failed to read target.txt!");
|
||||
console.error("Failed to read target.txt file:", error);
|
||||
}
|
||||
|
||||
// fetch applist
|
||||
const response = await fetch('applist.json');
|
||||
const appList = await response.json();
|
||||
const appNameMap = appList.reduce((map, app) => {
|
||||
map[app.package_name] = app.app_name;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
// Get installed packages first
|
||||
let appEntries = [], installedPackages = [];
|
||||
try {
|
||||
installedPackages = await execCommand(`
|
||||
pm list packages -3 | awk -F: '{print $2}'
|
||||
[ -s "/data/adb/tricky_store/system_app" ] && SYSTEM_APP=$(cat "/data/adb/tricky_store/system_app" | tr '\n' '|' | sed 's/|*$//') || SYSTEM_APP=""
|
||||
[ -z "$SYSTEM_APP" ] || pm list packages -s | awk -F: '{print $2}' | grep -Ex "$SYSTEM_APP" 2>/dev/null || true
|
||||
`)
|
||||
installedPackages = installedPackages.split("\n").map(line => line.trim()).filter(Boolean);
|
||||
appEntries = await Promise.all(installedPackages.map(async packageName => {
|
||||
if (appNameMap[packageName]) {
|
||||
return {
|
||||
appName: appNameMap[packageName],
|
||||
packageName
|
||||
};
|
||||
}
|
||||
const appName = await execCommand(`
|
||||
base_apk=$(pm path ${packageName} | grep "base.apk" | awk -F: '{print $2}')
|
||||
[ -n "$base_apk" ] || base_apk=$(pm path ${packageName} | grep ".apk" | awk -F: '{print $2}')
|
||||
${basePath}/common/aapt dump badging $base_apk 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g"
|
||||
`);
|
||||
return {
|
||||
appName: appName.trim() || packageName,
|
||||
packageName
|
||||
};
|
||||
}));
|
||||
} catch (error) {
|
||||
appEntries = appList.map(app => ({
|
||||
appName: app.app_name,
|
||||
packageName: app.package_name
|
||||
}));
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Set unique names for radio button groups
|
||||
const radioButtons = appElement.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach((radio) => {
|
||||
radio.name = `mode-radio-${packageName}`;
|
||||
});
|
||||
|
||||
// Preselect the radio button based on the package name
|
||||
const generateRadio = appElement.querySelector('#generate-mode');
|
||||
const hackRadio = appElement.querySelector('#hack-mode');
|
||||
const normalRadio = appElement.querySelector('#normal-mode');
|
||||
|
||||
if (appsWithExclamation.includes(packageName)) {
|
||||
generateRadio.checked = true;
|
||||
} else if (appsWithQuestion.includes(packageName)) {
|
||||
hackRadio.checked = true;
|
||||
} else {
|
||||
normalRadio.checked = true;
|
||||
}
|
||||
|
||||
const nameElement = appElement.querySelector(".name");
|
||||
nameElement.innerHTML = `
|
||||
<div class="app-info">
|
||||
<div class="app-name"><strong>${appName}</strong></div>
|
||||
<div class="package-name">${packageName}</div>
|
||||
</div>
|
||||
`;
|
||||
const checkbox = appElement.querySelector(".checkbox");
|
||||
checkbox.checked = targetList.includes(packageName);
|
||||
appListContainer.appendChild(appElement);
|
||||
});
|
||||
} catch (error) {
|
||||
toast("Failed to fetch app list!");
|
||||
console.error("Failed to fetch or render app list with names:", error);
|
||||
}
|
||||
hideFloatingBtn(false);
|
||||
toggleableCheckbox();
|
||||
if (appListContainer.firstChild !== updateCard) {
|
||||
appListContainer.insertBefore(updateCard, appListContainer.firstChild);
|
||||
}
|
||||
const checkboxes = appListContainer.querySelectorAll(".checkbox");
|
||||
setupRadioButtonListeners();
|
||||
setupModeMenu();
|
||||
updateCheckboxColor();
|
||||
}
|
||||
|
||||
// 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) => {
|
||||
checkbox.checked = !checkbox.checked;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add eventlistener to mode button
|
||||
function setupRadioButtonListeners() {
|
||||
const radioButtons = appListContainer.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach((radioButton) => {
|
||||
radioButton.addEventListener('change', (event) => {
|
||||
const card = radioButton.closest(".card");
|
||||
const packageName = card.querySelector(".content").getAttribute("data-package");
|
||||
if (radioButton.id === 'generate-mode') {
|
||||
if (!appsWithExclamation.includes(packageName)) {
|
||||
appsWithExclamation.push(packageName);
|
||||
}
|
||||
const indexInQuestion = appsWithQuestion.indexOf(packageName);
|
||||
if (indexInQuestion > -1) {
|
||||
appsWithQuestion.splice(indexInQuestion, 1);
|
||||
}
|
||||
} else if (radioButton.id === 'hack-mode') {
|
||||
if (!appsWithQuestion.includes(packageName)) {
|
||||
appsWithQuestion.push(packageName);
|
||||
}
|
||||
const indexInExclamation = appsWithExclamation.indexOf(packageName);
|
||||
if (indexInExclamation > -1) {
|
||||
appsWithExclamation.splice(indexInExclamation, 1);
|
||||
}
|
||||
} else if (radioButton.id === 'normal-mode') {
|
||||
const indexInExclamation = appsWithExclamation.indexOf(packageName);
|
||||
if (indexInExclamation > -1) {
|
||||
appsWithExclamation.splice(indexInExclamation, 1);
|
||||
}
|
||||
const indexInQuestion = appsWithQuestion.indexOf(packageName);
|
||||
if (indexInQuestion > -1) {
|
||||
appsWithQuestion.splice(indexInQuestion, 1);
|
||||
}
|
||||
}
|
||||
updateCheckboxColor();
|
||||
console.log("Updated appsWithExclamation:", appsWithExclamation);
|
||||
console.log("Updated appsWithQuestion:", appsWithQuestion);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Hold to open menu
|
||||
function setupModeMenu() {
|
||||
let holdTimeout;
|
||||
function showMode(card) {
|
||||
const modeElement = card.querySelector(".mode");
|
||||
if (modeElement) {
|
||||
modeElement.style.display = "flex";
|
||||
modeOverlay.style.display = "flex";
|
||||
setTimeout(() => {
|
||||
modeElement.classList.add('show');
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
function hideAllModes() {
|
||||
const allModeElements = appListContainer.querySelectorAll(".mode");
|
||||
allModeElements.forEach((modeElement) => {
|
||||
modeElement.classList.remove('show');
|
||||
modeOverlay.style.display = "none";
|
||||
setTimeout(() => {
|
||||
modeElement.style.display = "none";
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
|
||||
const cards = appListContainer.querySelectorAll(".card");
|
||||
cards.forEach((card) => {
|
||||
card.addEventListener("pointerdown", () => {
|
||||
const checkbox = card.querySelector(".checkbox");
|
||||
if (checkbox && checkbox.checked) {
|
||||
holdTimeout = setTimeout(() => {
|
||||
showMode(card);
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
card.addEventListener("pointerup", () => clearTimeout(holdTimeout));
|
||||
card.addEventListener("pointercancel", () => clearTimeout(holdTimeout));
|
||||
});
|
||||
|
||||
document.addEventListener("click", (event) => {
|
||||
if (!event.target.closest(".mode") || modeOverlay.contains(event.target)) {
|
||||
hideAllModes();
|
||||
} else if (event.target.closest(".status-indicator")) {
|
||||
setTimeout(() => {
|
||||
hideAllModes();
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
window.addEventListener("scroll", hideAllModes);
|
||||
}
|
||||
|
||||
// Function to update card borders color
|
||||
function updateCheckboxColor() {
|
||||
const cards = appListContainer.querySelectorAll(".card");
|
||||
cards.forEach((card) => {
|
||||
const packageName = card.querySelector(".content").getAttribute("data-package");
|
||||
const checkbox = card.querySelector(".checkbox");
|
||||
checkbox.classList.remove("checkbox-checked-generate", "checkbox-checked-hack");
|
||||
if (appsWithExclamation.includes(packageName)) {
|
||||
checkbox.classList.add("checkbox-checked-generate");
|
||||
} else if (appsWithQuestion.includes(packageName)) {
|
||||
checkbox.classList.add("checkbox-checked-hack");
|
||||
} else if (checkbox.checked) {
|
||||
checkbox.classList.remove("checkbox-checked-generate", "checkbox-checked-hack");
|
||||
}
|
||||
});
|
||||
}
|
||||
69
module/webui/scripts/boot_hash.js
Normal file
69
module/webui/scripts/boot_hash.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import { execCommand, showPrompt } from './main.js';
|
||||
|
||||
const bootHashOverlay = document.getElementById('boot-hash-overlay');
|
||||
const bootHash = document.querySelector('.boot-hash-card');
|
||||
const inputBox = document.getElementById('boot-hash-input');
|
||||
const saveButton = document.getElementById('boot-hash-save-button');
|
||||
|
||||
// Remove empty spaces from input and convert to lowercase
|
||||
window.trimInput = (input) => {
|
||||
input.value = input.value.replace(/\s+/g, '').toLowerCase();
|
||||
};
|
||||
|
||||
// Function to handle Verified Boot Hash
|
||||
document.getElementById("boot-hash").addEventListener("click", async () => {
|
||||
// Display boot hash menu
|
||||
document.body.classList.add("no-scroll");
|
||||
bootHashOverlay.style.display = "flex";
|
||||
setTimeout(() => {
|
||||
bootHashOverlay.style.opacity = 1;
|
||||
bootHash.classList.add('open');
|
||||
}, 10);
|
||||
|
||||
const closeBootHashMenu = () => {
|
||||
document.body.classList.remove("no-scroll");
|
||||
bootHashOverlay.style.opacity = 0;
|
||||
bootHash.classList.remove('open');
|
||||
setTimeout(() => {
|
||||
bootHashOverlay.style.display = "none";
|
||||
}, 200);
|
||||
};
|
||||
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(`
|
||||
PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH
|
||||
resetprop -n ro.boot.vbmeta.digest ${inputValue}
|
||||
[ -z "${inputValue}" ] && rm -f /data/adb/boot_hash || {
|
||||
echo "${inputValue}" > /data/adb/boot_hash
|
||||
chmod 644 /data/adb/boot_hash
|
||||
}
|
||||
`);
|
||||
showPrompt("prompt.boot_hash_set");
|
||||
closeBootHashMenu();
|
||||
} 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) closeBootHashMenu();
|
||||
});
|
||||
|
||||
// Enter to save
|
||||
inputBox.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
saveButton.click();
|
||||
}
|
||||
});
|
||||
});
|
||||
31
module/webui/scripts/help.js
Normal file
31
module/webui/scripts/help.js
Normal file
@@ -0,0 +1,31 @@
|
||||
const helpButton = document.getElementById('help-button');
|
||||
const helpOverlay = document.getElementById('help-overlay');
|
||||
const helpContent = document.querySelector('.help-menu');
|
||||
const closeHelp = document.getElementById('close-help');
|
||||
|
||||
// Open help menu
|
||||
helpButton.addEventListener("click", () => {
|
||||
document.body.classList.add("no-scroll");
|
||||
helpOverlay.style.display = "flex";
|
||||
setTimeout(() => {
|
||||
helpOverlay.style.opacity = 1;
|
||||
helpContent.classList.add('open');
|
||||
}, 10);
|
||||
});
|
||||
|
||||
const hideHelpOverlay = () => {
|
||||
helpOverlay.style.opacity = 0;
|
||||
helpContent.classList.remove('open');
|
||||
document.body.classList.remove("no-scroll");
|
||||
setTimeout(() => {
|
||||
helpOverlay.style.display = "none";
|
||||
}, 200);
|
||||
};
|
||||
|
||||
// Close help menu
|
||||
closeHelp.addEventListener("click", hideHelpOverlay);
|
||||
helpOverlay.addEventListener("click", (event) => {
|
||||
if (event.target === helpOverlay) {
|
||||
hideHelpOverlay();
|
||||
}
|
||||
});
|
||||
156
module/webui/scripts/language.js
Normal file
156
module/webui/scripts/language.js
Normal file
@@ -0,0 +1,156 @@
|
||||
import { applyRippleEffect } 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 availableLanguages = ['en-US'];
|
||||
|
||||
/**
|
||||
* Detect user's default language
|
||||
* @returns {Promise<string>} - Detected language code
|
||||
*/
|
||||
async function detectUserLanguage() {
|
||||
const userLang = navigator.language || navigator.userLanguage;
|
||||
const langCode = userLang.split('-')[0];
|
||||
|
||||
try {
|
||||
// Fetch available languages
|
||||
const availableResponse = await fetch('locales/available-lang.json');
|
||||
const availableData = await availableResponse.json();
|
||||
availableLanguages = availableData.languages;
|
||||
await generateLanguageMenu();
|
||||
|
||||
// Fetch preferred language
|
||||
const prefered_language_code = localStorage.getItem('trickyAddonLanguage');
|
||||
|
||||
// Check if preferred language is valid
|
||||
if (prefered_language_code !== 'default' && availableLanguages.includes(prefered_language_code)) {
|
||||
return prefered_language_code;
|
||||
} else if (availableLanguages.includes(userLang)) {
|
||||
return userLang;
|
||||
} else if (availableLanguages.includes(langCode)) {
|
||||
return langCode;
|
||||
} else {
|
||||
return 'en-US';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error detecting user language:', error);
|
||||
return 'en-US';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load translations dynamically based on the selected language
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function loadTranslations() {
|
||||
const lang = await detectUserLanguage();
|
||||
const response = await fetch(`locales/${lang}.json`);
|
||||
translations = await response.json();
|
||||
applyTranslations();
|
||||
applyRippleEffect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply translations to all elements with data-i18n attributes
|
||||
* @returns {void}
|
||||
*/
|
||||
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
|
||||
* @returns {void}
|
||||
*/
|
||||
export function setupLanguageMenu() {
|
||||
languageButton.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
const isVisible = languageMenu.classList.contains("show");
|
||||
if (isVisible) {
|
||||
closeLanguageMenu();
|
||||
} else {
|
||||
languageOverlay.style.display = 'flex';
|
||||
setTimeout(() => languageMenu.classList.add("show"), 10);
|
||||
}
|
||||
});
|
||||
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();
|
||||
}
|
||||
});
|
||||
const closeLanguageMenu = () => {
|
||||
setTimeout(() => {
|
||||
languageMenu.classList.remove("show");
|
||||
languageOverlay.style.display = 'none';
|
||||
}, 80)
|
||||
}
|
||||
languageMenu.addEventListener("click", async (e) => {
|
||||
if (e.target.classList.contains("language-option")) {
|
||||
const lang = e.target.getAttribute("data-lang");
|
||||
localStorage.setItem('trickyAddonLanguage', lang);
|
||||
closeLanguageMenu();
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
loadTranslations(lang);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the language menu dynamically
|
||||
* Refer available-lang.json in ./locales for list of languages
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function generateLanguageMenu() {
|
||||
languageMenu.innerHTML = '';
|
||||
|
||||
// Add System Default option
|
||||
const defaultButton = document.createElement('button');
|
||||
defaultButton.classList.add('language-option', 'ripple-element');
|
||||
defaultButton.setAttribute('data-lang', 'default');
|
||||
defaultButton.setAttribute('data-i18n', 'system_default');
|
||||
languageMenu.appendChild(defaultButton);
|
||||
|
||||
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', 'ripple-element');
|
||||
button.setAttribute('data-lang', lang);
|
||||
button.textContent = name;
|
||||
languageMenu.appendChild(button);
|
||||
});
|
||||
}
|
||||
379
module/webui/scripts/main.js
Normal file
379
module/webui/scripts/main.js
Normal file
@@ -0,0 +1,379 @@
|
||||
import { appListContainer, fetchAppList } from './applist.js';
|
||||
import { loadTranslations, setupLanguageMenu, translations } from './language.js';
|
||||
import { setupSystemAppMenu } from './menu_option.js';
|
||||
import { searchMenuContainer, searchInput, clearBtn, setupMenuToggle } from './search_menu.js';
|
||||
import { updateCheck } from './update.js';
|
||||
import { securityPatch } from './security_patch.js';
|
||||
|
||||
// Header Elements
|
||||
const title = document.querySelector('.header');
|
||||
export const noConnection = document.querySelector('.no-connection');
|
||||
|
||||
// Loading, Save and Prompt Elements
|
||||
const permissionPopup = document.getElementById('permission-popup');
|
||||
const loadingIndicator = document.querySelector('.loading');
|
||||
const prompt = document.getElementById('prompt');
|
||||
const floatingCard = document.querySelector('.floating-card');
|
||||
const floatingBtn = document.querySelector('.floating-btn');
|
||||
|
||||
export let basePath;
|
||||
export const appsWithExclamation = [];
|
||||
export const appsWithQuestion = [];
|
||||
const ADDITIONAL_APPS = [ "android", "com.google.android.gms", "io.github.vvb2060.keyattestation", "io.github.vvb2060.mahoshojo", "icu.nullptr.nativetest" ]; // Always keep default apps in target.txt
|
||||
|
||||
// Variables
|
||||
let e = 0;
|
||||
let isRefreshing = false;
|
||||
let MMRL_API = true;
|
||||
|
||||
// Function to set basePath
|
||||
async function getBasePath() {
|
||||
try {
|
||||
await execCommand('[ -d /data/adb/modules/.TA_utl ]');
|
||||
basePath = "/data/adb/modules/.TA_utl"
|
||||
} catch (error) {
|
||||
basePath = "/data/adb/modules/TA_utl"
|
||||
}
|
||||
}
|
||||
|
||||
// Function to load the version from module.prop
|
||||
async function getModuleVersion() {
|
||||
const moduleVersion = document.getElementById('module-version');
|
||||
try {
|
||||
const version = await execCommand(`grep '^version=' ${basePath}/common/update/module.prop | cut -d'=' -f2`);
|
||||
moduleVersion.textContent = version;
|
||||
} catch (error) {
|
||||
console.error("Failed to read version from module.prop:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to refresh app list
|
||||
export async function refreshAppList() {
|
||||
isRefreshing = true;
|
||||
title.style.transform = 'translateY(0)';
|
||||
searchMenuContainer.style.transform = 'translateY(0)';
|
||||
hideFloatingBtn();
|
||||
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 {
|
||||
updateCheck();
|
||||
await execCommand(`[ -f ${basePath}/common/tmp/exclude-list ] && rm -f "${basePath}/common/tmp/exclude-list"`);
|
||||
} catch (error) {
|
||||
toast("Failed!");
|
||||
console.error("Error occurred:", error);
|
||||
}
|
||||
}
|
||||
await fetchAppList();
|
||||
applyRippleEffect();
|
||||
loadingIndicator.style.display = 'none';
|
||||
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
|
||||
isRefreshing = false;
|
||||
}
|
||||
|
||||
// Function to check tricky store version
|
||||
async function checkTrickyStoreVersion() {
|
||||
const securityPatchElement = document.getElementById('security-patch');
|
||||
try {
|
||||
const version = await execCommand(`
|
||||
TS_version=$(grep "versionCode=" "/data/adb/modules/tricky_store/module.prop" | cut -d'=' -f2)
|
||||
[ "$TS_version" -ge 158 ] || echo "NO"
|
||||
`);
|
||||
if (version.trim() !== "NO") securityPatchElement.style.display = "flex";
|
||||
} catch (error) {
|
||||
toast("Failed to check Tricky Store version!");
|
||||
console.error("Error while checking Tricky Store version:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if Magisk
|
||||
async function checkMagisk() {
|
||||
const selectDenylistElement = document.getElementById('select-denylist');
|
||||
try {
|
||||
const magiskEnv = await execCommand(`command -v magisk >/dev/null 2>&1 || echo "NO"`);
|
||||
if (magiskEnv.trim() !== "NO") selectDenylistElement.style.display = "flex";
|
||||
} catch (error) {
|
||||
toast("Failed to check Magisk!");
|
||||
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, duration = 3000) {
|
||||
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.style.transform = 'translateY(calc((var(--window-inset-bottom, 0px) + 60%) * -1))';
|
||||
window.promptTimeout = setTimeout(() => {
|
||||
prompt.style.transform = 'translateY(100%)';
|
||||
}, duration);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Function to redirect link on external browser
|
||||
export async function linkRedirect(link) {
|
||||
try {
|
||||
await execCommand(`am start -a android.intent.action.VIEW -d ${link}`);
|
||||
} catch (error) {
|
||||
toast("Failed!");
|
||||
console.error('Error redirect link:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 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}" | sort -u > /data/adb/tricky_store/target.txt`);
|
||||
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`);
|
||||
}
|
||||
} 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", () => {
|
||||
const uninstallOverlay = document.getElementById("uninstall-confirmation-overlay");
|
||||
const uninstallContent = document.querySelector('.uninstall-confirmation');
|
||||
const cancelButton = document.getElementById("cancel-uninstall");
|
||||
const confirmButton = document.getElementById("confirm-uninstall")
|
||||
|
||||
uninstallOverlay.style.display = 'flex';
|
||||
document.body.classList.add('no-scroll');
|
||||
setTimeout(() => {
|
||||
uninstallOverlay.style.opacity = 1;
|
||||
uninstallContent.classList.add('open');
|
||||
}, 10)
|
||||
|
||||
const closeuninstallOverlay = () => {
|
||||
document.body.classList.remove('no-scroll');
|
||||
uninstallOverlay.style.opacity = 0;
|
||||
uninstallContent.classList.remove('open');
|
||||
setTimeout(() => {
|
||||
uninstallOverlay.style.display = 'none';
|
||||
}, 200)
|
||||
}
|
||||
cancelButton.addEventListener('click', () => closeuninstallOverlay());
|
||||
uninstallOverlay.addEventListener('click', (e) => {
|
||||
if (e.target === uninstallOverlay) closeuninstallOverlay();
|
||||
})
|
||||
confirmButton.addEventListener('click', () => {
|
||||
closeuninstallOverlay();
|
||||
uninstallWebUI();
|
||||
})
|
||||
});
|
||||
async function uninstallWebUI() {
|
||||
try {
|
||||
await execCommand(`sh ${basePath}/common/get_extra.sh --uninstall`);
|
||||
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
|
||||
async function checkMMRL() {
|
||||
if (typeof ksu !== 'undefined' && ksu.mmrl) {
|
||||
// Set status bars theme based on device theme
|
||||
try {
|
||||
$tricky_store.setLightStatusBars(!window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
} catch (error) {
|
||||
console.error("Error setting status bars theme:", error)
|
||||
}
|
||||
|
||||
// Request API permission, supported version: 33045+
|
||||
try {
|
||||
$tricky_store.requestAdvancedKernelSUAPI();
|
||||
} catch (error) {
|
||||
console.error("Error requesting API:", error);
|
||||
}
|
||||
|
||||
// Check permissions
|
||||
try {
|
||||
await execCommand('ls /data/adb/modules');
|
||||
MMRL_API = true;
|
||||
} catch (error) {
|
||||
console.error('Permission check failed:', error);
|
||||
permissionPopup.style.display = 'flex';
|
||||
MMRL_API = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Funtion to adapt floating button hide in MMRL
|
||||
export function hideFloatingBtn(hide = true) {
|
||||
if (!hide) floatingCard.style.transform = 'translateY(0)';
|
||||
else floatingCard.style.transform = 'translateY(calc(var(--window-inset-bottom, 0px) + 120px))';
|
||||
}
|
||||
|
||||
// Function to apply ripple effect
|
||||
export function applyRippleEffect() {
|
||||
document.querySelectorAll('.ripple-element').forEach(element => {
|
||||
if (element.dataset.rippleListener !== "true") {
|
||||
element.addEventListener("pointerdown", async (event) => {
|
||||
const handlePointerUp = () => {
|
||||
ripple.classList.add("end");
|
||||
setTimeout(() => {
|
||||
ripple.classList.remove("end");
|
||||
ripple.remove();
|
||||
}, duration * 1000);
|
||||
element.removeEventListener("pointerup", handlePointerUp);
|
||||
element.removeEventListener("pointercancel", handlePointerUp);
|
||||
};
|
||||
element.addEventListener("pointerup", () => setTimeout(handlePointerUp, 80));
|
||||
element.addEventListener("pointercancel", () => setTimeout(handlePointerUp, 80));
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 80));
|
||||
if (isScrolling) return;
|
||||
const ripple = document.createElement("span");
|
||||
ripple.classList.add("ripple");
|
||||
|
||||
// Calculate ripple size and position
|
||||
const rect = element.getBoundingClientRect();
|
||||
const width = rect.width;
|
||||
const size = Math.max(rect.width, rect.height);
|
||||
const x = event.clientX - rect.left - size / 2;
|
||||
const y = event.clientY - rect.top - size / 2;
|
||||
|
||||
// Determine animation duration
|
||||
let duration = 0.2 + (width / 800) * 0.4;
|
||||
duration = Math.min(0.8, Math.max(0.2, duration));
|
||||
|
||||
// Set ripple styles
|
||||
ripple.style.width = ripple.style.height = `${size}px`;
|
||||
ripple.style.left = `${x}px`;
|
||||
ripple.style.top = `${y}px`;
|
||||
ripple.style.animationDuration = `${duration}s`;
|
||||
ripple.style.transition = `opacity ${duration}s ease`;
|
||||
|
||||
// Adaptive color
|
||||
const computedStyle = window.getComputedStyle(element);
|
||||
const bgColor = computedStyle.backgroundColor || "rgba(0, 0, 0, 0)";
|
||||
const textColor = computedStyle.color;
|
||||
const isDarkColor = (color) => {
|
||||
const rgb = color.match(/\d+/g);
|
||||
if (!rgb) return false;
|
||||
const [r, g, b] = rgb.map(Number);
|
||||
return (r * 0.299 + g * 0.587 + b * 0.114) < 96; // Luma formula
|
||||
};
|
||||
ripple.style.backgroundColor = isDarkColor(bgColor) ? "rgba(255, 255, 255, 0.2)" : "";
|
||||
|
||||
// Append ripple and handle cleanup
|
||||
element.appendChild(ripple);
|
||||
});
|
||||
element.dataset.rippleListener = "true";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Scroll event
|
||||
let lastScrollY = window.scrollY;
|
||||
let isScrolling = false;
|
||||
let scrollTimeout;
|
||||
const scrollThreshold = 40;
|
||||
window.addEventListener('scroll', () => {
|
||||
isScrolling = true;
|
||||
clearTimeout(scrollTimeout);
|
||||
scrollTimeout = setTimeout(() => {
|
||||
isScrolling = false;
|
||||
}, 200);
|
||||
if (isRefreshing) return;
|
||||
if (window.scrollY > lastScrollY && window.scrollY > scrollThreshold) {
|
||||
title.style.transform = 'translateY(-100%)';
|
||||
searchMenuContainer.style.transform = 'translateY(-40px)';
|
||||
hideFloatingBtn();
|
||||
} else if (window.scrollY < lastScrollY) {
|
||||
title.style.transform = 'translateY(0)';
|
||||
searchMenuContainer.style.transform = 'translateY(0)';
|
||||
hideFloatingBtn(false);
|
||||
}
|
||||
lastScrollY = window.scrollY;
|
||||
});
|
||||
|
||||
// Initial load
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
await loadTranslations();
|
||||
await checkMMRL();
|
||||
if (!MMRL_API) return;
|
||||
await getBasePath();
|
||||
hideFloatingBtn();
|
||||
getModuleVersion();
|
||||
setupMenuToggle();
|
||||
setupLanguageMenu();
|
||||
setupSystemAppMenu();
|
||||
await fetchAppList();
|
||||
applyRippleEffect();
|
||||
checkTrickyStoreVersion();
|
||||
checkMagisk();
|
||||
updateCheck();
|
||||
securityPatch();
|
||||
loadingIndicator.style.display = "none";
|
||||
floatingBtn.style.display = 'block';
|
||||
hideFloatingBtn(false);
|
||||
document.getElementById("refresh").addEventListener("click", refreshAppList);
|
||||
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
|
||||
});
|
||||
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to toast message
|
||||
export function toast(message) {
|
||||
try {
|
||||
ksu.toast(message);
|
||||
} catch (error) {
|
||||
console.error("Failed to show toast:", error);
|
||||
}
|
||||
}
|
||||
6
module/webui/scripts/marked.min.js
vendored
Normal file
6
module/webui/scripts/marked.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
430
module/webui/scripts/menu_option.js
Normal file
430
module/webui/scripts/menu_option.js
Normal file
@@ -0,0 +1,430 @@
|
||||
import { basePath, execCommand, showPrompt, toast, applyRippleEffect, refreshAppList } 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
|
||||
document.getElementById("select-all").addEventListener("click", () => toggleCheckboxes(true));
|
||||
|
||||
// Function to deselect all visible apps
|
||||
document.getElementById("deselect-all").addEventListener("click", () => toggleCheckboxes(false));
|
||||
|
||||
// Function to read the denylist and check corresponding apps
|
||||
document.getElementById("select-denylist").addEventListener("click", async () => {
|
||||
try {
|
||||
const result = await execCommand(`magisk --denylist ls 2>/dev/null | awk -F'|' '{print $1}' | grep -v "isolated" | sort -u`);
|
||||
const denylistApps = 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 (denylistApps.includes(packageName)) {
|
||||
checkbox.checked = true;
|
||||
}
|
||||
});
|
||||
await execCommand('touch "/data/adb/tricky_store/target_from_denylist"');
|
||||
console.log("Denylist apps selected successfully.");
|
||||
} catch (error) {
|
||||
toast("Failed to read DenyList!");
|
||||
console.error("Failed to select Denylist apps:", error);
|
||||
}
|
||||
});
|
||||
|
||||
// Function to read the exclude list and uncheck corresponding apps
|
||||
document.getElementById("deselect-unnecessary").addEventListener("click", async () => {
|
||||
try {
|
||||
const excludeList = await fetch("https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/more-exclude.json")
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
return response.json();
|
||||
})
|
||||
.catch(async () => {
|
||||
return fetch("https://raw.gitmirror.com/KOWX712/Tricky-Addon-Update-Target-List/main/more-exclude.json")
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
return response.json();
|
||||
});
|
||||
})
|
||||
.then(data => {
|
||||
return data.data
|
||||
.flatMap(category => category.apps)
|
||||
.map(app => app['package-name'])
|
||||
.join('\n');
|
||||
})
|
||||
.catch(error => {
|
||||
toast("Failed to download unnecessary apps!");
|
||||
throw error;
|
||||
});
|
||||
const xposed = await execCommand(`sh ${basePath}/common/get_extra.sh --xposed`);
|
||||
const UnnecessaryApps = excludeList.split("\n").map(app => app.trim()).filter(Boolean).concat(xposed.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) {
|
||||
toast("Failed to get unnecessary apps!");
|
||||
console.error("Failed to get unnecessary apps:", error);
|
||||
}
|
||||
});
|
||||
|
||||
// Function to add system app
|
||||
export async function setupSystemAppMenu() {
|
||||
document.getElementById("add-system-app").addEventListener("click", () => setTimeout(() => openSystemAppOverlay(), 80));
|
||||
document.getElementById("add-system-app-overlay").addEventListener("click", (event) => {
|
||||
if (event.target === event.currentTarget) closeSystemAppOverlay();
|
||||
});
|
||||
const systemAppOverlay = document.getElementById("add-system-app-overlay");
|
||||
const systemAppContent = document.querySelector('.add-system-app-card');
|
||||
const systemAppInput = document.getElementById("system-app-input");
|
||||
function openSystemAppOverlay() {
|
||||
renderSystemAppList();
|
||||
document.body.classList.add("no-scroll");
|
||||
systemAppOverlay.style.display = "flex";
|
||||
setTimeout(() => {
|
||||
systemAppOverlay.style.opacity = "1";
|
||||
systemAppContent.classList.add('open');
|
||||
}, 10);
|
||||
systemAppInput.value = "";
|
||||
}
|
||||
function closeSystemAppOverlay() {
|
||||
document.body.classList.remove("no-scroll");
|
||||
systemAppOverlay.style.opacity = "0";
|
||||
systemAppContent.classList.remove('open');
|
||||
setTimeout(() => {
|
||||
systemAppOverlay.style.display = "none";
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// Add system app button
|
||||
document.getElementById("add-system-app-button").addEventListener("click", async () => {
|
||||
const input = document.getElementById("system-app-input");
|
||||
const packageName = input.value.trim();
|
||||
if (packageName) {
|
||||
try {
|
||||
const result = await execCommand(`pm list packages -s | grep -q ${packageName} || echo "false"`);
|
||||
if (result.includes("false")) {
|
||||
showPrompt("prompt.system_app_not_found", false);
|
||||
} else {
|
||||
await execCommand(`
|
||||
touch "/data/adb/tricky_store/system_app"
|
||||
echo "${packageName}" >> "/data/adb/tricky_store/system_app"
|
||||
echo "${packageName}" >> "/data/adb/tricky_store/target.txt"
|
||||
`);
|
||||
systemAppInput.value = "";
|
||||
closeSystemAppOverlay();
|
||||
refreshAppList();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error adding system app:", error);
|
||||
showPrompt("prompt.add_system_app_error", false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Display current system app list and remove button
|
||||
async function renderSystemAppList() {
|
||||
const currentSystemAppList = document.querySelector(".current-system-app-list");
|
||||
const currentSystemAppListContent = document.querySelector(".current-system-app-list-content");
|
||||
currentSystemAppListContent.innerHTML = "";
|
||||
try {
|
||||
const systemAppList = await execCommand(`[ -f "/data/adb/tricky_store/system_app" ] && cat "/data/adb/tricky_store/system_app" | sed '/^$/d' || echo "false"`);
|
||||
if (systemAppList.trim() === 'false' || systemAppList.trim() === '') {
|
||||
currentSystemAppList.style.display = "none";
|
||||
} else {
|
||||
systemAppList.split("\n").forEach(app => {
|
||||
currentSystemAppListContent.innerHTML += `
|
||||
<div class="system-app-item">
|
||||
<span>${app}</span>
|
||||
<button class="remove-system-app-button ripple-element">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="22px" viewBox="0 -960 960 960" width="22px" fill="#FFFFFF"><path d="M154-412v-136h652v136H154Z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
currentSystemAppList.style.display = "none";
|
||||
console.error("Error displaying system app list:", error);
|
||||
}
|
||||
|
||||
const removeSystemAppButtons = document.querySelectorAll(".remove-system-app-button");
|
||||
removeSystemAppButtons.forEach(button => {
|
||||
button.addEventListener("click", async () => {
|
||||
const app = button.closest(".system-app-item").querySelector("span").textContent;
|
||||
try {
|
||||
await execCommand(`
|
||||
sed -i "/${app}/d" "/data/adb/tricky_store/system_app" || true
|
||||
sed -i "/${app}/d" "/data/adb/tricky_store/target.txt" || true
|
||||
`);
|
||||
closeSystemAppOverlay();
|
||||
refreshAppList();
|
||||
} catch (error) {
|
||||
console.error("Error removing system app:", error);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Function to backup previous keybox and set new keybox
|
||||
async function setKeybox(content) {
|
||||
const sanitizedContent = content.replace(/'/g, "'\\''");
|
||||
try {
|
||||
await execCommand(`
|
||||
mv -f /data/adb/tricky_store/keybox.xml /data/adb/tricky_store/keybox.xml.bak 2>/dev/null
|
||||
echo '${sanitizedContent}' > /data/adb/tricky_store/keybox.xml
|
||||
chmod 644 /data/adb/tricky_store/keybox.xml
|
||||
`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Failed to set keybox:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set aosp key
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function aospkb() {
|
||||
const source = await execCommand(`xxd -r -p ${basePath}/common/.default | base64 -d`);
|
||||
const result = await setKeybox(source);
|
||||
if (result) {
|
||||
console.log("AOSP keybox copied successfully.");
|
||||
showPrompt("prompt.aosp_key_set");
|
||||
} else {
|
||||
showPrompt("prompt.key_set_error", false);
|
||||
}
|
||||
}
|
||||
|
||||
// aosp kb eventlistener
|
||||
document.getElementById("aospkb").addEventListener("click", async () => aospkb());
|
||||
|
||||
// valid kb eventlistener
|
||||
document.getElementById("validkb").addEventListener("click", async () => {
|
||||
fetch("https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/.extra")
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
return response.text();
|
||||
})
|
||||
.catch(async () => {
|
||||
return fetch("https://raw.gitmirror.com/KOWX712/Tricky-Addon-Update-Target-List/main/.extra")
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
return response.text();
|
||||
});
|
||||
})
|
||||
.then(async data => {
|
||||
if (!data.trim()) {
|
||||
await aospkb();
|
||||
showPrompt("prompt.no_valid_fallback", false);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const hexBytes = new Uint8Array(data.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
|
||||
const decodedHex = new TextDecoder().decode(hexBytes);
|
||||
const source = atob(decodedHex);
|
||||
const result = await setKeybox(source);
|
||||
if (result) {
|
||||
showPrompt("prompt.valid_key_set");
|
||||
} else {
|
||||
throw new Error("Failed to copy valid keybox");
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error("Failed to decode keybox data");
|
||||
}
|
||||
})
|
||||
.catch(async error => {
|
||||
showPrompt("prompt.no_internet", false);
|
||||
});
|
||||
});
|
||||
|
||||
// File selector
|
||||
const fileSelector = document.querySelector('.file-selector-overlay');
|
||||
const fileSelectorContent = document.querySelector('.file-selector');
|
||||
let currentPath = '/storage/emulated/0/Download';
|
||||
|
||||
// Function to display file in current path
|
||||
function updateCurrentPath() {
|
||||
const currentPathElement = document.querySelector('.current-path');
|
||||
const segments = currentPath.split('/').filter(Boolean);
|
||||
|
||||
// Create spans with data-path attribute for each segment
|
||||
const pathHTML = segments.map((segment, index) => {
|
||||
const fullPath = '/' + segments.slice(0, index + 1).join('/');
|
||||
return `<span class="path-segment" data-path="${fullPath}">${segment}</span>`;
|
||||
}).join('<span class="separator">›</span>');
|
||||
|
||||
currentPathElement.innerHTML = pathHTML;
|
||||
currentPathElement.scrollTo({
|
||||
left: currentPathElement.scrollWidth,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
|
||||
// Function to list files in directory
|
||||
async function listFiles(path, skipAnimation = false) {
|
||||
const fileList = document.querySelector('.file-list');
|
||||
if (!skipAnimation) {
|
||||
fileList.classList.add('switching');
|
||||
await new Promise(resolve => setTimeout(resolve, 150));
|
||||
}
|
||||
try {
|
||||
const result = await execCommand(`find "${path}" -maxdepth 1 -type f -name "*.xml" -o -type d ! -name ".*" | sort`);
|
||||
const items = result.split('\n').filter(Boolean).map(item => ({
|
||||
path: item,
|
||||
name: item.split('/').pop(),
|
||||
isDirectory: !item.endsWith('.xml')
|
||||
}));
|
||||
fileList.innerHTML = '';
|
||||
|
||||
// Add back button item if not in root directory
|
||||
if (currentPath !== '/storage/emulated/0') {
|
||||
const backItem = document.createElement('div');
|
||||
backItem.className = 'file-item ripple-element';
|
||||
backItem.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24">
|
||||
<path d="M141-160q-24 0-42-18.5T81-220v-520q0-23 18-41.5t42-18.5h280l60 60h340q23 0 41.5 18.5T881-680v460q0 23-18.5 41.5T821-160H141Z"/>
|
||||
</svg>
|
||||
<span>..</span>
|
||||
`;
|
||||
backItem.addEventListener('click', async () => {
|
||||
document.querySelector('.back-button').click();
|
||||
});
|
||||
fileList.appendChild(backItem);
|
||||
}
|
||||
items.forEach(item => {
|
||||
if (item.path === path) return;
|
||||
const itemElement = document.createElement('div');
|
||||
itemElement.className = 'file-item ripple-element';
|
||||
itemElement.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24">
|
||||
${item.isDirectory ?
|
||||
'<path d="M141-160q-24 0-42-18.5T81-220v-520q0-23 18-41.5t42-18.5h280l60 60h340q23 0 41.5 18.5T881-680v460q0 23-18.5 41.5T821-160H141Z"/>' :
|
||||
'<path d="M320-240h320v-80H320v80Zm0-160h320v-80H320v80ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520v-200H240v640h480v-440H520ZM240-800v200-200 640-640Z"/>'}
|
||||
</svg>
|
||||
<span>${item.name}</span>
|
||||
`;
|
||||
itemElement.addEventListener('click', async () => {
|
||||
if (item.isDirectory) {
|
||||
currentPath = item.path;
|
||||
const currentPathElement = document.querySelector('.current-path');
|
||||
currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join('<span class="separator">›</span>');
|
||||
currentPathElement.scrollTo({
|
||||
left: currentPathElement.scrollWidth,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
await listFiles(item.path);
|
||||
} else {
|
||||
const source = await execCommand(`cat "${item.path}"`);
|
||||
const result = await setKeybox(source);
|
||||
if (result) {
|
||||
closeCustomKeyboxSelector();
|
||||
showPrompt('prompt.custom_key_set');
|
||||
} else {
|
||||
showPrompt('prompt.custom_key_set_error');
|
||||
}
|
||||
}
|
||||
});
|
||||
fileList.appendChild(itemElement);
|
||||
});
|
||||
|
||||
if (!skipAnimation) {
|
||||
fileList.classList.remove('switching');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error listing files:', error);
|
||||
if (!skipAnimation) {
|
||||
fileList.classList.remove('switching');
|
||||
}
|
||||
}
|
||||
applyRippleEffect();
|
||||
updateCurrentPath();
|
||||
}
|
||||
|
||||
// Update click handler to use data-path attribute
|
||||
document.querySelector('.current-path').addEventListener('click', async (event) => {
|
||||
const segment = event.target.closest('.path-segment');
|
||||
if (!segment) return;
|
||||
|
||||
const targetPath = segment.dataset.path;
|
||||
if (!targetPath || targetPath === currentPath) return;
|
||||
|
||||
// Return if already at /storage/emulated/0
|
||||
const clickedSegment = segment.textContent;
|
||||
if ((clickedSegment === 'storage' || clickedSegment === 'emulated') &&
|
||||
currentPath === '/storage/emulated/0') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Always stay within /storage/emulated/0
|
||||
if (targetPath.split('/').length <= 3) {
|
||||
currentPath = '/storage/emulated/0';
|
||||
} else {
|
||||
currentPath = targetPath;
|
||||
}
|
||||
updateCurrentPath();
|
||||
await listFiles(currentPath);
|
||||
});
|
||||
|
||||
// Back button handler
|
||||
document.querySelector('.back-button').addEventListener('click', async () => {
|
||||
if (currentPath === '/storage/emulated/0') return;
|
||||
currentPath = currentPath.split('/').slice(0, -1).join('/');
|
||||
if (currentPath === '') currentPath = '/storage/emulated/0';
|
||||
const currentPathElement = document.querySelector('.current-path');
|
||||
currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join('<span class="separator">›</span>');
|
||||
currentPathElement.scrollTo({
|
||||
left: currentPathElement.scrollWidth,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
await listFiles(currentPath);
|
||||
});
|
||||
|
||||
// Close custom keybox selector
|
||||
document.querySelector('.close-selector').addEventListener('click', () => closeCustomKeyboxSelector());
|
||||
fileSelector.addEventListener('click', (event) => {
|
||||
if (event.target === fileSelector) closeCustomKeyboxSelector();
|
||||
});
|
||||
|
||||
// close custom keybox selector
|
||||
const closeCustomKeyboxSelector = () => {
|
||||
fileSelector.style.opacity = '0';
|
||||
fileSelectorContent.classList.remove('open');
|
||||
document.body.classList.remove("no-scroll");
|
||||
setTimeout(() => {
|
||||
fileSelector.style.display = 'none';
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// Open custom keybox selector
|
||||
document.getElementById('customkb').addEventListener('click', async () => {
|
||||
await new Promise(resolve => setTimeout(resolve, 80));
|
||||
fileSelector.style.display = 'flex';
|
||||
document.body.classList.add("no-scroll");
|
||||
setTimeout(() => {
|
||||
fileSelector.style.opacity = '1';
|
||||
fileSelectorContent.classList.add('open');
|
||||
}, 10)
|
||||
currentPath = '/storage/emulated/0/Download';
|
||||
const currentPathElement = document.querySelector('.current-path');
|
||||
currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join('<span class="separator">›</span>');
|
||||
currentPathElement.scrollTo({
|
||||
left: currentPathElement.scrollWidth,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
await listFiles(currentPath, true);
|
||||
});
|
||||
68
module/webui/scripts/search_menu.js
Normal file
68
module/webui/scripts/search_menu.js
Normal file
@@ -0,0 +1,68 @@
|
||||
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 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() {
|
||||
const closeMenu = () => {
|
||||
menuOptions.classList.remove('visible');
|
||||
menuIcon.classList.remove('menu-open');
|
||||
menuOverlay.style.display = 'none';
|
||||
}
|
||||
|
||||
menuButton.addEventListener('click', () => {
|
||||
if (menuOptions.classList.contains('visible')) {
|
||||
closeMenu();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
menuOptions.classList.add('visible');
|
||||
menuIcon.classList.add('menu-open');
|
||||
menuOverlay.style.display = 'flex';
|
||||
}, 10);
|
||||
}
|
||||
});
|
||||
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', () => {
|
||||
setTimeout(() => closeMenu(), 80);
|
||||
});
|
||||
});
|
||||
}
|
||||
332
module/webui/scripts/security_patch.js
Normal file
332
module/webui/scripts/security_patch.js
Normal file
@@ -0,0 +1,332 @@
|
||||
import { basePath, execCommand, showPrompt } from './main.js';
|
||||
|
||||
const overlay = document.getElementById('security-patch-overlay');
|
||||
const overlayContent = document.querySelector('.security-patch-card');
|
||||
const advancedToggle = document.getElementById('advanced-mode');
|
||||
const normalInputs = document.getElementById('normal-mode-inputs');
|
||||
const advancedInputs = document.getElementById('advanced-mode-inputs');
|
||||
const allPatchInput = document.getElementById('all-patch');
|
||||
const bootPatchInput = document.getElementById('boot-patch');
|
||||
const systemPatchInput = document.getElementById('system-patch');
|
||||
const vendorPatchInput = document.getElementById('vendor-patch');
|
||||
const getButton = document.getElementById('get-patch');
|
||||
const autoButton = document.getElementById('auto-config');
|
||||
const saveButton = document.getElementById('save-patch');
|
||||
|
||||
// Hide security patch dialog
|
||||
const hideSecurityPatchDialog = () => {
|
||||
document.body.classList.remove("no-scroll");
|
||||
overlay.style.opacity = '0';
|
||||
overlayContent.classList.remove('open');
|
||||
setTimeout(() => {
|
||||
overlay.style.display = 'none';
|
||||
}, 200);
|
||||
}
|
||||
|
||||
// Function to handle security patch operation
|
||||
async function handleSecurityPatch(mode, value = null) {
|
||||
if (mode === 'disable') {
|
||||
try {
|
||||
await execCommand(`
|
||||
rm -f /data/adb/tricky_store/security_patch_auto_config
|
||||
rm -f /data/adb/tricky_store/security_patch.txt
|
||||
`);
|
||||
showPrompt('security_patch.value_empty');
|
||||
return true;
|
||||
} catch (error) {
|
||||
showPrompt('security_patch.save_failed', false);
|
||||
return false;
|
||||
}
|
||||
} else if (mode === 'manual') {
|
||||
try {
|
||||
await execCommand(`
|
||||
rm -f /data/adb/tricky_store/security_patch_auto_config
|
||||
echo "${value}" > /data/adb/tricky_store/security_patch.txt
|
||||
chmod 644 /data/adb/tricky_store/security_patch.txt
|
||||
`);
|
||||
showPrompt('security_patch.save_success');
|
||||
return true;
|
||||
} catch (error) {
|
||||
showPrompt('security_patch.save_failed', false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load current configuration
|
||||
async function loadCurrentConfig() {
|
||||
let allValue, systemValue, bootValue, vendorValue;
|
||||
try {
|
||||
const autoConfig = await execCommand('[ -f /data/adb/tricky_store/security_patch_auto_config ] && echo "true" || echo "false"');
|
||||
if (autoConfig.trim() === 'true') {
|
||||
allValue = null;
|
||||
systemValue = null;
|
||||
bootValue = null;
|
||||
vendorValue = null;
|
||||
} else {
|
||||
// Read values from tricky_store if auto_config is 0
|
||||
const trickyResult = await execCommand('cat /data/adb/tricky_store/security_patch.txt');
|
||||
if (trickyResult) {
|
||||
const trickyLines = trickyResult.split('\n');
|
||||
for (const line of trickyLines) {
|
||||
if (line.startsWith('all=')) {
|
||||
allValue = line.split('=')[1] || null;
|
||||
if (allValue !== null) allPatchInput.value = allValue;
|
||||
} else {
|
||||
allValue = null;
|
||||
}
|
||||
if (line.startsWith('system=')) {
|
||||
systemValue = line.split('=')[1] || null;
|
||||
if (systemValue !== null) systemPatchInput.value = systemValue;
|
||||
} else {
|
||||
systemValue = null;
|
||||
}
|
||||
if (line.startsWith('boot=')) {
|
||||
bootValue = line.split('=')[1] || null;
|
||||
if (bootValue !== null) bootPatchInput.value = bootValue;
|
||||
} else {
|
||||
bootValue = null;
|
||||
}
|
||||
if (line.startsWith('vendor=')) {
|
||||
vendorValue = line.split('=')[1] || null;
|
||||
if (vendorValue !== null) vendorPatchInput.value = vendorValue;
|
||||
} else {
|
||||
vendorValue = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allValue === null && (bootValue || systemValue || vendorValue)) {
|
||||
checkAdvanced(true);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load security patch config:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check advanced mode
|
||||
function checkAdvanced(shouldCheck) {
|
||||
if (shouldCheck) {
|
||||
advancedToggle.checked = true;
|
||||
normalInputs.classList.add('hidden');
|
||||
advancedInputs.classList.remove('hidden');
|
||||
} else {
|
||||
advancedToggle.checked = false;
|
||||
normalInputs.classList.remove('hidden');
|
||||
advancedInputs.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// Unified date formatting function
|
||||
window.formatDate = function(input, type) {
|
||||
let value = input.value.replace(/-/g, '');
|
||||
let formatted = value.slice(0, 4);
|
||||
|
||||
// Allow 'no' input
|
||||
if (value === 'no') {
|
||||
input.value = 'no';
|
||||
input.setSelectionRange(2, 2);
|
||||
return 'no';
|
||||
}
|
||||
|
||||
if (value.startsWith('n')) {
|
||||
// Only allow 'o' after 'n'
|
||||
if (value.length > 1 && value[1] !== 'o') {
|
||||
value = 'n';
|
||||
}
|
||||
formatted = value.slice(0, 2);
|
||||
if (value.length > 2) {
|
||||
input.value = formatted;
|
||||
input.setSelectionRange(2, 2);
|
||||
return formatted;
|
||||
}
|
||||
} else {
|
||||
// Only allow numbers if not starting with 'n'
|
||||
const numbersOnly = value.replace(/\D/g, '');
|
||||
if (numbersOnly !== value) {
|
||||
input.value = numbersOnly;
|
||||
value = numbersOnly;
|
||||
formatted = numbersOnly.slice(0, 4);
|
||||
}
|
||||
|
||||
// Add hyphens on 5th and 7th character
|
||||
if (value.length >= 4) {
|
||||
formatted += '-'+ value.slice(4, 6);
|
||||
}
|
||||
if (value.length >= 6) {
|
||||
formatted += '-'+ value.slice(6, 8);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle backspace/delete
|
||||
const lastChar = value.slice(-1);
|
||||
if (lastChar === '-' || (isNaN(lastChar) && !['n'].includes(lastChar))) {
|
||||
formatted = formatted.slice(0, -1);
|
||||
}
|
||||
|
||||
// Update input value
|
||||
const startPos = input.selectionStart;
|
||||
input.value = formatted;
|
||||
const newLength = formatted.length;
|
||||
const shouldMoveCursor = (value.length === 4 || value.length === 6) && newLength > startPos;
|
||||
input.setSelectionRange(shouldMoveCursor ? newLength : startPos, shouldMoveCursor ? newLength : startPos);
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
// Validate date format YYYY-MM-DD
|
||||
function isValidDateFormat(date) {
|
||||
if (date === 'no') return true;
|
||||
const regex = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/;
|
||||
return regex.test(date);
|
||||
}
|
||||
|
||||
// Validate 6-digit format YYYYMM
|
||||
function isValid6Digit(value) {
|
||||
if (value === 'prop') return true;
|
||||
const regex = /^\d{6}$/;
|
||||
return regex.test(value);
|
||||
}
|
||||
|
||||
// Validate 8-digit format YYYYMMDD
|
||||
function isValid8Digit(value) {
|
||||
const regex = /^\d{8}$/;
|
||||
return regex.test(value);
|
||||
}
|
||||
|
||||
// Initialize event listeners
|
||||
export function securityPatch() {
|
||||
document.getElementById("security-patch").addEventListener("click", () => {
|
||||
setTimeout(() => {
|
||||
document.body.classList.add("no-scroll");
|
||||
overlay.style.display = 'flex';
|
||||
setTimeout(() => {
|
||||
overlay.style.opacity = '1';
|
||||
overlayContent.classList.add('open');
|
||||
loadCurrentConfig();
|
||||
}, 10);
|
||||
}, 80);
|
||||
});
|
||||
|
||||
// Toggle advanced mode
|
||||
advancedToggle.addEventListener('change', () => {
|
||||
normalInputs.classList.toggle('hidden');
|
||||
advancedInputs.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
// Close on overlay click
|
||||
overlay.addEventListener('click', (e) => {
|
||||
if (e.target === overlay) {
|
||||
hideSecurityPatchDialog();
|
||||
}
|
||||
});
|
||||
|
||||
// Auto config button
|
||||
autoButton.addEventListener('click', async () => {
|
||||
try {
|
||||
const output = await execCommand(`sh ${basePath}/common/get_extra.sh --security-patch`);
|
||||
if (output.trim() === "not set") {
|
||||
showPrompt('security_patch.auto_failed', false);
|
||||
} else {
|
||||
await execCommand(`touch /data/adb/tricky_store/security_patch_auto_config`);
|
||||
// Reset inputs
|
||||
allPatchInput.value = '';
|
||||
systemPatchInput.value = '';
|
||||
bootPatchInput.value = '';
|
||||
vendorPatchInput.value = '';
|
||||
|
||||
checkAdvanced(false);
|
||||
showPrompt('security_patch.auto_success');
|
||||
}
|
||||
} catch (error) {
|
||||
showPrompt('security_patch.auto_failed', false);
|
||||
}
|
||||
hideSecurityPatchDialog();
|
||||
loadCurrentConfig();
|
||||
});
|
||||
|
||||
// Save button
|
||||
saveButton.addEventListener('click', async () => {
|
||||
if (!advancedToggle.checked) {
|
||||
// Normal mode validation
|
||||
const allValue = allPatchInput.value.trim();
|
||||
if (!allValue) {
|
||||
// Save empty value to disable auto config
|
||||
await handleSecurityPatch('disable');
|
||||
hideSecurityPatchDialog();
|
||||
return;
|
||||
}
|
||||
if (!isValid8Digit(allValue)) {
|
||||
showPrompt('security_patch.invalid_all', false);
|
||||
return;
|
||||
}
|
||||
const value = `all=${allValue}`;
|
||||
const result = await handleSecurityPatch('manual', value);
|
||||
if (result) {
|
||||
// Reset inputs
|
||||
systemPatchInput.value = '';
|
||||
bootPatchInput.value = '';
|
||||
vendorPatchInput.value = '';
|
||||
}
|
||||
} else {
|
||||
// Advanced mode validation
|
||||
const bootValue = formatDate(bootPatchInput, 'boot');
|
||||
const systemValue = systemPatchInput.value.trim();
|
||||
const vendorValue = vendorPatchInput.value.trim();
|
||||
|
||||
if (!bootValue && !systemValue && !vendorValue) {
|
||||
// Save empty values to disable auto config
|
||||
await handleSecurityPatch('disable');
|
||||
hideSecurityPatchDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
if (systemValue && !isValid6Digit(systemValue)) {
|
||||
showPrompt('security_patch.invalid_system', false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bootValue && !isValidDateFormat(bootValue)) {
|
||||
showPrompt('security_patch.invalid_boot', false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vendorValue && !isValidDateFormat(vendorValue)) {
|
||||
showPrompt('security_patch.invalid_vendor', false);
|
||||
return;
|
||||
}
|
||||
|
||||
const config = [
|
||||
systemValue ? `system=${systemValue}` : '',
|
||||
bootValue ? `boot=${bootValue}` : '',
|
||||
vendorValue ? `vendor=${vendorValue}` : ''
|
||||
].filter(Boolean);
|
||||
const value = config.filter(Boolean).join('\n');
|
||||
const result = await handleSecurityPatch('manual', value);
|
||||
if (result) {
|
||||
// Reset inputs
|
||||
allPatchInput.value = '';
|
||||
}
|
||||
}
|
||||
hideSecurityPatchDialog();
|
||||
loadCurrentConfig();
|
||||
});
|
||||
|
||||
// Get button
|
||||
getButton.addEventListener('click', async () => {
|
||||
try {
|
||||
showPrompt('security_patch.fetching');
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
const output = await execCommand(`sh ${basePath}/common/get_extra.sh --get-security-patch`);
|
||||
showPrompt('security_patch.fetched', true, 1000);
|
||||
checkAdvanced(true);
|
||||
|
||||
allPatchInput.value = output.replace(/-/g, '');
|
||||
systemPatchInput.value = 'prop';
|
||||
bootPatchInput.value = output;
|
||||
vendorPatchInput.value = output;
|
||||
} catch (error) {
|
||||
showPrompt('security_patch.get_failed', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
186
module/webui/scripts/update.js
Normal file
186
module/webui/scripts/update.js
Normal file
@@ -0,0 +1,186 @@
|
||||
import { basePath, execCommand, showPrompt, noConnection, linkRedirect } from './main.js';
|
||||
import { updateCard } from './applist.js';
|
||||
|
||||
const updateMenu = document.querySelector('.update-overlay');
|
||||
const updateMenuContent = document.querySelector('.update-menu');
|
||||
const closeUpdate = document.getElementById('close-update');
|
||||
const releaseNotes = document.querySelector('.changelog');
|
||||
const installButton = document.querySelector('.install');
|
||||
const rebootButton = document.querySelector('.reboot');
|
||||
|
||||
let remoteVersionCode, remoteVersion, zipURL, changelogURL, downloading = false;
|
||||
|
||||
// Function to download file
|
||||
function downloadFile(targetURL, fileName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(targetURL)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.blob();
|
||||
})
|
||||
.then(blob => {
|
||||
const file = new File([blob], fileName, { type: blob.type });
|
||||
const reader = new FileReader();
|
||||
reader.onload = async function() {
|
||||
const base64Data = reader.result.split(',')[1];
|
||||
try {
|
||||
await execCommand(`echo ${base64Data} | base64 -d > ${basePath}/common/tmp/${fileName}`);
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
// Function to check for updates
|
||||
export async function updateCheck() {
|
||||
try {
|
||||
const response = await fetch("https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/update.json")
|
||||
.catch(async () => {
|
||||
return fetch("https://raw.gitmirror.com/KOWX712/Tricky-Addon-Update-Target-List/main/update.json");
|
||||
});
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
noConnection.style.display = "none";
|
||||
const data = await response.json();
|
||||
remoteVersionCode = data.versionCode;
|
||||
remoteVersion = data.version;
|
||||
zipURL = data.zipUrl;
|
||||
changelogURL = data.changelog;
|
||||
|
||||
const updateAvailable = await execCommand(`sh ${basePath}/common/get_extra.sh --check-update ${remoteVersionCode}`);
|
||||
if (updateAvailable.includes("update")) {
|
||||
showPrompt("prompt.new_update", true, 1500);
|
||||
updateCard.style.display = "flex";
|
||||
setupUpdateMenu();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching JSON or executing command:", error);
|
||||
showPrompt("prompt.no_internet", false);
|
||||
noConnection.style.display = "flex";
|
||||
}
|
||||
}
|
||||
|
||||
// Function to render changelog
|
||||
async function renderChangelog() {
|
||||
const changelog = await execCommand(`sh ${basePath}/common/get_extra.sh --release-note ${remoteVersion}`);
|
||||
window.linkRedirect = linkRedirect;
|
||||
marked.setOptions({
|
||||
sanitize: true,
|
||||
walkTokens(token) {
|
||||
if (token.type === 'link') {
|
||||
const href = token.href;
|
||||
token.href = "javascript:void(0);";
|
||||
token.type = "html";
|
||||
token.text = `<a href="javascript:void(0);" onclick="linkRedirect('${href}')">${token.text}</a>`;
|
||||
}
|
||||
}
|
||||
});
|
||||
const cleanedChangelog = changelog
|
||||
.split('\n')
|
||||
.filter(line => line.trim() !== '')
|
||||
.join('\n');
|
||||
const formattedChangelog = marked.parse(cleanedChangelog);
|
||||
releaseNotes.innerHTML = formattedChangelog;
|
||||
}
|
||||
|
||||
// Function to setup update menu
|
||||
function setupUpdateMenu() {
|
||||
function openUpdateMenu() {
|
||||
updateMenu.style.display = "flex";
|
||||
setTimeout(async () => {
|
||||
updateMenu.style.opacity = "1";
|
||||
updateMenuContent.classList.add('open');
|
||||
}, 10);
|
||||
document.body.classList.add("no-scroll");
|
||||
}
|
||||
function closeUpdateMenu() {
|
||||
updateMenu.style.opacity = "0";
|
||||
updateMenuContent.classList.remove('open');
|
||||
document.body.classList.remove("no-scroll");
|
||||
setTimeout(async () => {
|
||||
updateMenu.style.display = "none";
|
||||
}, 200);
|
||||
}
|
||||
|
||||
// Update card
|
||||
updateCard.addEventListener('click', async () => {
|
||||
try {
|
||||
const module = await execCommand(`
|
||||
[ -f ${basePath}/common/tmp/module.zip ] || echo "noModule"
|
||||
[ -f ${basePath}/common/tmp/changelog.md ] || echo "noChangelog"
|
||||
[ ! -f /data/adb/modules/TA_utl/update ] || echo "updated"
|
||||
`);
|
||||
if (module.trim().includes("updated")) {
|
||||
installButton.style.display = "none";
|
||||
rebootButton.style.display = "flex";
|
||||
openUpdateMenu();
|
||||
} else if (module.trim().includes("noChangelog")) {
|
||||
showPrompt("prompt.downloading");
|
||||
await downloadFile(changelogURL, "changelog.md");
|
||||
await renderChangelog();
|
||||
openUpdateMenu();
|
||||
setTimeout(() => {
|
||||
updateCard.click();
|
||||
}, 200);
|
||||
} else if (module.trim().includes("noModule")) {
|
||||
if (downloading) return;
|
||||
downloading = true;
|
||||
try {
|
||||
await execCommand(`sh ${basePath}/common/get_extra.sh --get-update ${zipURL}`);
|
||||
showPrompt("prompt.downloaded");
|
||||
installButton.style.display = "flex";
|
||||
downloading = false;
|
||||
} catch (error) {
|
||||
showPrompt("prompt.download_fail", false);
|
||||
downloading = false;
|
||||
}
|
||||
} else {
|
||||
installButton.style.display = "flex";
|
||||
await renderChangelog();
|
||||
openUpdateMenu();
|
||||
}
|
||||
} catch (error) {
|
||||
showPrompt("prompt.download_fail", false);
|
||||
console.error('Error download module update:', error);
|
||||
}
|
||||
});
|
||||
|
||||
// Close update menu
|
||||
closeUpdate.addEventListener("click", closeUpdateMenu);
|
||||
updateMenu.addEventListener("click", (event) => {
|
||||
if (event.target === updateMenu) closeUpdateMenu();
|
||||
});
|
||||
|
||||
// Install button
|
||||
installButton.addEventListener('click', async () => {
|
||||
try {
|
||||
showPrompt("prompt.installing");
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
await execCommand(`sh ${basePath}/common/get_extra.sh --install-update`);
|
||||
showPrompt("prompt.installed");
|
||||
installButton.style.display = "none";
|
||||
rebootButton.style.display = "flex";
|
||||
} catch (error) {
|
||||
showPrompt("prompt.install_fail", false);
|
||||
console.error('Fail to execute installation script:', error);
|
||||
}
|
||||
});
|
||||
|
||||
// Reboot button
|
||||
rebootButton.addEventListener('click', async () => {
|
||||
try {
|
||||
showPrompt("prompt.rebooting");
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
await execCommand("svc power reboot");
|
||||
} catch (error) {
|
||||
showPrompt("prompt.reboot_fail", false);
|
||||
console.error('Fail to reboot:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
91
module/webui/styles/about.css
Normal file
91
module/webui/styles/about.css
Normal file
@@ -0,0 +1,91 @@
|
||||
.about-overlay {
|
||||
z-index: 1100;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.about-menu {
|
||||
position: relative;
|
||||
width: calc(90vw - 60px);
|
||||
max-width: 800px;
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 15px;
|
||||
padding: 30px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.link,
|
||||
.about-menu p {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#module_name_line1 {
|
||||
font-size: 26px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#module_name_line2 {
|
||||
font-size: 22px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#authored {
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#disclaimer {
|
||||
font-family: serif;
|
||||
width: calc(100% - 20px);
|
||||
padding: 8px 10px;
|
||||
border-radius: 10px;
|
||||
background-color: var(--border-color);
|
||||
}
|
||||
|
||||
#acknowledgment {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.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;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#github {
|
||||
font-size: 18px;
|
||||
padding: 3px 10px;
|
||||
background-color: #606060;
|
||||
color: #fff;
|
||||
fill: #fff;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#link-text {
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
}
|
||||
312
module/webui/styles/applist.css
Normal file
312
module/webui/styles/applist.css
Normal file
@@ -0,0 +1,312 @@
|
||||
.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: var(--border-color);
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
box-sizing: border-box;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 10px;
|
||||
outline: none;
|
||||
padding: 12px;
|
||||
width: calc(100% - 20px);
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
#update-available {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#redirect-to-release {
|
||||
text-align: center;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 15px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.update-overlay {
|
||||
z-index: 1800;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.update-menu {
|
||||
position: relative;
|
||||
width: calc(90% - 60px);
|
||||
max-width: 800px;
|
||||
background-color: var(--bg-secondary);
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
text-align: left;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.update-content h3 {
|
||||
font-size: 22px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.changelog {
|
||||
max-height: 65vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.changelog ul {
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.changelog ul li {
|
||||
margin-left: 15px;
|
||||
margin-bottom: 5px;
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
.changelog a {
|
||||
color: var(--text-secondary);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.changelog a:active {
|
||||
color: var(--btn-primary);
|
||||
}
|
||||
|
||||
.update-button-container {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.install,
|
||||
.reboot {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--border-color);
|
||||
width: 100%;
|
||||
border: none;
|
||||
padding: 12px;
|
||||
border-radius: 12px;
|
||||
font-size: 18px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.reboot {
|
||||
color: var(--btn-primary-text);
|
||||
background-color: var(--btn-primary);
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: var(--bg-secondary);
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
border-radius: 12px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 10px;
|
||||
outline: none;
|
||||
padding: 12px;
|
||||
width: calc(100% - 20px);
|
||||
max-width: 900px;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mode {
|
||||
display: none;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: fit-content;
|
||||
background-color: var(--border-color);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 50px 50px;
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
transition: all 0.2s ease;
|
||||
z-index: 1200;
|
||||
}
|
||||
|
||||
.mode.show {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.mode-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: none;
|
||||
z-index: 1100;
|
||||
}
|
||||
|
||||
.mode-switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.mode-input {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50px 50px;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.2s ease;
|
||||
border: 3px solid transparent;
|
||||
}
|
||||
|
||||
#normal-indicator {
|
||||
background-color: var(--btn-primary);
|
||||
}
|
||||
|
||||
#hack-indicator {
|
||||
background-color: #FF8400;
|
||||
}
|
||||
|
||||
#generate-indicator {
|
||||
background-color: #36DB2B;
|
||||
}
|
||||
|
||||
.mode-input[type="radio"]:checked ~ .mode-icon .status-indicator {
|
||||
transform: scale(1.1);
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
font-size: 15.5px;
|
||||
max-width: calc(100% - 30px);
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-word;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.checkbox-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.custom-checkbox {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 1s ease, transform 0.3s ease, background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.tick-symbol {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 0;
|
||||
transition: transform 0.2s ease-out, opacity 0.3s ease;
|
||||
|
||||
svg {
|
||||
fill: var(--btn-primary-text);
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox:checked + .custom-checkbox {
|
||||
border-color: var(--btn-primary);
|
||||
background-color: var(--btn-primary);
|
||||
transition: border-color 0.1s ease;
|
||||
animation: checked-bounce 0.3s ease-out;
|
||||
}
|
||||
|
||||
.checkbox-checked-generate:checked + .custom-checkbox {
|
||||
border-color: #36DB2B;
|
||||
background-color: #36DB2B;
|
||||
}
|
||||
|
||||
.checkbox-checked-hack:checked + .custom-checkbox {
|
||||
border-color: #FF8400;
|
||||
background-color: #FF8400;
|
||||
}
|
||||
|
||||
.checkbox:not(:checked) + .custom-checkbox {
|
||||
animation: unchecked-bounce 0.3s ease-out;
|
||||
}
|
||||
|
||||
.checkbox:checked + .custom-checkbox .tick-symbol {
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@keyframes checked-bounce {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes unchecked-bounce {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
53
module/webui/styles/boot_hash.css
Normal file
53
module/webui/styles/boot_hash.css
Normal file
@@ -0,0 +1,53 @@
|
||||
.boot-hash-overlay {
|
||||
z-index: 1200;
|
||||
}
|
||||
|
||||
.boot-hash-card {
|
||||
position: fixed;
|
||||
top: 10%;
|
||||
width: calc(90% - 60px);
|
||||
max-width: 300px;
|
||||
height: fit-content;
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
||||
padding: 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.boot-hash-title {
|
||||
width: 100%;
|
||||
font-size: 26px;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.boot-hash-input {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 10px;
|
||||
box-sizing: border-box;
|
||||
outline-color: var(--btn-primary);
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.boot-hash-save-button {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
background-color: var(--btn-primary);
|
||||
color: var(--btn-primary-text);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
88
module/webui/styles/file_selector.css
Normal file
88
module/webui/styles/file_selector.css
Normal file
@@ -0,0 +1,88 @@
|
||||
.file-selector-overlay {
|
||||
z-index: 2000;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.file-selector {
|
||||
width: 90%;
|
||||
max-width: 600px;
|
||||
height: 80vh;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.file-selector-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
}
|
||||
|
||||
.current-path .separator {
|
||||
color: var(--text-secondary);
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
background: none;
|
||||
border: none;
|
||||
fill: var(--border-color);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.current-path {
|
||||
flex-grow: 1;
|
||||
font-size: 16px;
|
||||
overflow: scroll;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.close-selector {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
color: var(--border-color);
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.file-list.switching {
|
||||
transform: scale(0.95);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
background-color: var(--bg-secondary);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.file-item svg {
|
||||
flex-shrink: 0;
|
||||
margin-right: 10px;
|
||||
fill: var(--text-secondary);
|
||||
}
|
||||
|
||||
.file-item span {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
296
module/webui/styles/global.css
Normal file
296
module/webui/styles/global.css
Normal file
@@ -0,0 +1,296 @@
|
||||
@import url('https://mui.kernelsu.org/mmrl/insets.css');
|
||||
@import url('https://mui.kernelsu.org/mmrl/colors.css');
|
||||
|
||||
:root {
|
||||
--top-inset: var(--window-inset-top, 0px);
|
||||
--bottom-inset: var(--window-inset-bottom, 0px);
|
||||
|
||||
/* Background colors */
|
||||
--bg-primary: var(--background, #F5F5F5);
|
||||
--bg-secondary: var(--tonalSurface, #fff);
|
||||
--bg-input: var(--surfaceBright, #F5F5F5);
|
||||
|
||||
/* Text colors */
|
||||
--text-primary: var(--onSurface, #000);
|
||||
--text-secondary: var(--onSurfaceVariant, #757575);
|
||||
|
||||
/* Border colors */
|
||||
--border-color: var(--outlineVariant, #ccc);
|
||||
|
||||
/* Button colors */
|
||||
--btn-primary: var(--primary, #007bff);
|
||||
--btn-primary-text: var(--onPrimary, #fff);
|
||||
--btn-uninstall: var(--error, #FF3636);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
/* Background colors */
|
||||
--bg-primary: var(--background, #151515);
|
||||
--bg-secondary: var(--tonalSurface, #292929);
|
||||
--bg-input: var(--surfaceBright, #1b1b1b);
|
||||
|
||||
/* Text colors */
|
||||
--text-primary: var(--onSurface, #fff);
|
||||
--text-secondary: var(--onSurfaceVariant, #C2C2C2);
|
||||
|
||||
/* Border colors */
|
||||
--border-color: var(--outlineVariant, #636363);
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-primary);
|
||||
padding-top: var(--top-inset);
|
||||
padding-bottom: var(--bottom-inset);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.no-scroll {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.floating-card {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: calc(var(--bottom-inset) + 50px);
|
||||
transition: transform 0.4s ease;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.floating-btn {
|
||||
color: var(--btn-primary-text);
|
||||
background-color: var(--btn-primary);
|
||||
border: none;
|
||||
box-shadow: 0 4px 8px #0003;
|
||||
display: none;
|
||||
bottom: 0;
|
||||
padding: 10px 20px;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
border-radius: 50px 50px;
|
||||
user-select: none;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(5px);
|
||||
display: none;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.overlay-content {
|
||||
transform: scale(0.8);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.overlay-content.open {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 18px;
|
||||
color: var(--border-color);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.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: 2050;
|
||||
width: auto;
|
||||
max-width: calc(100% - 40px);
|
||||
transform: translateY(100%);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.prompt.error {
|
||||
background-color: #f44336;
|
||||
}
|
||||
|
||||
.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: center;
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
|
||||
.uninstall-container {
|
||||
padding: 8px;
|
||||
width: calc(100% - 20px);
|
||||
max-width: 900px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
border: 3px solid var(--btn-uninstall);
|
||||
box-sizing: border-box;
|
||||
background-color: var(--bg-primary);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
|
||||
svg {
|
||||
fill: var(--btn-uninstall);
|
||||
}
|
||||
}
|
||||
|
||||
.uninstall-container i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.uninstall-container span {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: var(--btn-uninstall);
|
||||
}
|
||||
|
||||
.uninstall-container.hidden-uninstall {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.uninstall-confirmation-overlay {
|
||||
align-items: center;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.uninstall-confirmation {
|
||||
width: 90%;
|
||||
max-width: 600px;
|
||||
max-height: 80%;
|
||||
overflow-y: auto;
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 15px;
|
||||
padding: 30px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uninstall-confirmation p {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.uninstall-confirmation-title {
|
||||
font-size: 26px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.uninstall-confirmation-button-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.uninstall-confirmation-button {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--border-color);
|
||||
}
|
||||
|
||||
#confirm-uninstall {
|
||||
color: var(--btn-primary-text);
|
||||
background-color: var(--btn-primary);
|
||||
}
|
||||
|
||||
.permission-popup {
|
||||
opacity: 1;
|
||||
align-items: center;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.permission-content {
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-secondary);
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
width: 80%;
|
||||
max-width: 400px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.permission-content h2 {
|
||||
margin-bottom: 20px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.permission-steps {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.permission-steps ol {
|
||||
padding: 0 25px;
|
||||
}
|
||||
|
||||
.permission-steps li {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.ripple-element {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ripple {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
transform: scale(0);
|
||||
opacity: 1;
|
||||
animation: ripple-animation ease-out forwards;
|
||||
pointer-events: none;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.ripple.end {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@keyframes ripple-animation {
|
||||
to {
|
||||
transform: scale(3);
|
||||
}
|
||||
}
|
||||
165
module/webui/styles/header.css
Normal file
165
module/webui/styles/header.css
Normal file
@@ -0,0 +1,165 @@
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0 5px;
|
||||
padding-top: var(--top-inset);
|
||||
height: 40px;
|
||||
width: calc(100% - 10px);
|
||||
max-width: 1100px;
|
||||
background-color: var(--bg-primary);
|
||||
transition: transform 0.4s ease;
|
||||
z-index: 1100;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#module-version,
|
||||
#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: var(--text-primary);
|
||||
}
|
||||
|
||||
.language-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
background-color: var(--bg-secondary);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1800;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
opacity: 0;
|
||||
max-height: calc(100vh - 50px);
|
||||
overflow-y: auto;
|
||||
transform: translateY(-30px) scale(0);
|
||||
transform-origin: top right;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.language-menu.show {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
|
||||
.language-option {
|
||||
flex-shrink: 0;
|
||||
padding: 8px 10px;
|
||||
text-align: center;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-secondary);
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.language-option::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 10px;
|
||||
width: calc(100% - 20px);
|
||||
height: 1px;
|
||||
background-color: var(--border-color);
|
||||
}
|
||||
|
||||
.language-option:last-child::after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.language-option:first-child {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.language-option:last-child {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.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 {
|
||||
z-index: 2000;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.help-menu {
|
||||
position: relative;
|
||||
width: calc(95vw - 60px);
|
||||
max-width: 800px;
|
||||
background-color: var(--bg-secondary);
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
text-align: left;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.help-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
max-height: calc(85vh - 60px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.help-content-header {
|
||||
font-size: 26px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.instruction strong {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.instruction p {
|
||||
margin: 0;
|
||||
}
|
||||
170
module/webui/styles/search_menu.css
Normal file
170
module/webui/styles/search_menu.css
Normal file
@@ -0,0 +1,170 @@
|
||||
.search-menu-container {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
top: calc(var(--top-inset) + 40px);
|
||||
height: 50px;
|
||||
width: calc(100% - 20px);
|
||||
max-width: 1100px;
|
||||
z-index: 1000;
|
||||
transition: transform 0.4s ease;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.search-card {
|
||||
background-color: var(--bg-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
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;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-secondary);
|
||||
font-size: 17px;
|
||||
outline: none;
|
||||
left: 10px;
|
||||
padding: 0 30px;
|
||||
width: calc(100% - 80px);
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
position: absolute;
|
||||
color: var(--border-color);
|
||||
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: var(--bg-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
width: 48px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
z-index: 200;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
display: inline-block;
|
||||
fill: var(--text-primary);
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.menu-icon.menu-open {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.menu-options {
|
||||
background-color: var(--bg-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 110%;
|
||||
right: 0;
|
||||
z-index: 1200;
|
||||
width: auto;
|
||||
max-height: calc(100vh - 120px);
|
||||
overflow-y: auto;
|
||||
white-space: nowrap;
|
||||
visibility: hidden;
|
||||
transform: translateX(120%);
|
||||
transition: all 0.2s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#select-denylist,
|
||||
#security-patch {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.menu-options.visible {
|
||||
display: block;
|
||||
visibility: visible;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.menu-options ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.menu-options li {
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
background-color: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.menu-options li::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 15px;
|
||||
width: calc(100% - 30px);
|
||||
height: 1px;
|
||||
background-color: var(--border-color);
|
||||
}
|
||||
|
||||
.menu-options li:last-child::after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.menu-options li:first-child {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.menu-options li:last-child {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.menu-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: none;
|
||||
z-index: 100;
|
||||
display: none;
|
||||
}
|
||||
148
module/webui/styles/security_patch.css
Normal file
148
module/webui/styles/security_patch.css
Normal file
@@ -0,0 +1,148 @@
|
||||
.security-patch-overlay {
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.security-patch-card {
|
||||
display: block;
|
||||
position: fixed;
|
||||
top: 10%;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-secondary);
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
||||
width: calc(90% - 60px);
|
||||
max-width: 300px;
|
||||
max-height: calc(80% - 60px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.security-patch-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.security-patch-header {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 26px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.advanced-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.advanced-toggle .checkbox-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.advanced-toggle .checkbox {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.advanced-toggle .custom-checkbox {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 1s ease, transform 0.3s ease, background-color 0.4s ease;
|
||||
}
|
||||
|
||||
.advanced-toggle .tick-symbol {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 0;
|
||||
transition: transform 0.2s ease-out, opacity 0.3s ease;
|
||||
|
||||
svg {
|
||||
fill: var(--btn-primary-text);
|
||||
}
|
||||
}
|
||||
|
||||
.advanced-toggle .checkbox:checked + .custom-checkbox {
|
||||
border-color: var(--btn-primary);
|
||||
background-color: var(--btn-primary);
|
||||
transition: border-color 0.1s ease;
|
||||
animation: checked-bounce 0.3s ease-out;
|
||||
}
|
||||
|
||||
.advanced-toggle .checkbox:checked + .custom-checkbox .tick-symbol {
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.input-group label {
|
||||
padding-top: 10px;
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.input-group input {
|
||||
padding: 15px;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
outline-color: var(--btn-primary);
|
||||
border-radius: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.get-button,
|
||||
.auto-button,
|
||||
.save-button {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.get-button,
|
||||
.auto-button {
|
||||
color: var(--text-primary);
|
||||
background-color: var(--border-color);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
background-color: var(--btn-primary);
|
||||
color: var(--btn-primary-text);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
104
module/webui/styles/system_app.css
Normal file
104
module/webui/styles/system_app.css
Normal file
@@ -0,0 +1,104 @@
|
||||
.add-system-app-overlay {
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.add-system-app-card {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
top: 10%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: calc(90vw - 60px);
|
||||
max-width: 400px;
|
||||
max-height: calc(80vh - 60px);
|
||||
overflow-y: auto;
|
||||
padding: 30px;
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.add-system-app-title {
|
||||
text-align: center;
|
||||
font-size: 26px;
|
||||
user-select: none;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.add-system-app-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.add-system-app-content input {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
outline-color: var(--btn-primary);
|
||||
border-radius: 10px;
|
||||
box-sizing: border-box;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.add-system-app-button {
|
||||
margin-top: 15px;
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
background-color: var(--btn-primary);
|
||||
color: var(--btn-primary-text);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.current-system-app-list {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 10px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.current-system-app-list-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.system-app-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: 10px;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.system-app-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.remove-system-app-button {
|
||||
flex-shrink: 0;
|
||||
margin-left: 10px;
|
||||
background-color: #e84d4d;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"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",
|
||||
"data": [
|
||||
{
|
||||
"info": "Root manager",
|
||||
@@ -22,6 +20,10 @@
|
||||
"name": "KernelSU",
|
||||
"package-name": "me.weishu.kernelsu"
|
||||
},
|
||||
{
|
||||
"name": "KernelSU Next",
|
||||
"package-name": "com.rifsxd.ksunext"
|
||||
},
|
||||
{
|
||||
"name": "Apatch",
|
||||
"package-name": "me.bmax.apatch"
|
||||
@@ -56,22 +58,22 @@
|
||||
"package-name": "xzr.konabess"
|
||||
},
|
||||
{
|
||||
"name": "KsuWebUI",
|
||||
"name": "KSUWebUI",
|
||||
"package-name": "io.github.a13e300.ksuwebui"
|
||||
},
|
||||
{
|
||||
"name": "ShortX",
|
||||
"package-name": "tornaco.apps.shortx"
|
||||
"name": "Shizuku",
|
||||
"package-name": "moe.shizuku.privileged.api"
|
||||
},
|
||||
{
|
||||
"name": "MMRL",
|
||||
"package-name": "com.dergoogler.mmrl"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": "General app that won't detect bootloader",
|
||||
"apps": [
|
||||
{
|
||||
"name": "Scene",
|
||||
"package-name": "com.omarea.vtools"
|
||||
},
|
||||
{
|
||||
"name": "Swift Backup",
|
||||
"package-name": "org.swiftapps.swiftbackup"
|
||||
@@ -88,6 +90,10 @@
|
||||
"name": "Google Slides",
|
||||
"package-name": "com.google.android.apps.docs.editors.slides"
|
||||
},
|
||||
{
|
||||
"name": "Keep Notes",
|
||||
"package-name": "com.google.android.keep"
|
||||
},
|
||||
{
|
||||
"name": "Google Maps",
|
||||
"package-name": "com.google.android.apps.maps"
|
||||
@@ -103,14 +109,20 @@
|
||||
{
|
||||
"name": "Chrome",
|
||||
"package-name": "com.android.chrome"
|
||||
},
|
||||
{
|
||||
"name": "YouTube",
|
||||
"package-name": "com.google.android.youtube"
|
||||
},
|
||||
{
|
||||
"name": "YouTube Music",
|
||||
"package-name": "com.google.android.apps.youtube.music"
|
||||
},
|
||||
{
|
||||
"name": "Speedtest",
|
||||
"package-name": "org.zwanoo.android.speedtest"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Add more app into this list?": [
|
||||
{
|
||||
"issue": "https://github.com/KOWX712/Tricky-Addon-Update-Target-List/issues",
|
||||
"pull-request": "https://github.com/KOWX712/Tricky-Addon-Update-Target-List/pulls"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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": 381,
|
||||
"version": "v3.8.1",
|
||||
"zipUrl": "https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/download/v3.8.1/TrickyAddonModule-v3.8.1.zip",
|
||||
"changelog": "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/changelog.md"
|
||||
}
|
||||
Reference in New Issue
Block a user