Compare commits

25 Commits
v3.4 ... v3.5

Author SHA1 Message Date
KOWX712
058ac8dfdc v3.5 release 2025-02-23 18:06:34 +08:00
KOWX712
735444d8a3 misc: simplify download function 2025-02-23 16:04:28 +08:00
KOWX712
6a806ac588 fix: deselect unnecessary app 2025-02-23 16:01:18 +08:00
Re*Index. (ot_inc)
3ffe75a1f3 Fixed ja-JP.json (#20) 2025-02-22 22:48:27 +08:00
KOWX712
4fdc057162 misc: update more-exclude.json 2025-02-22 22:03:59 +08:00
KOWX712
b7b5c2c1f0 misc: unify button styling 2025-02-22 22:03:32 +08:00
KOWX712
ddeb13c5e2 misc: function to check advanced mode 2025-02-22 22:03:32 +08:00
KOWX712
410629fad5 opt: move unnecessary list download to JS 2025-02-22 22:03:32 +08:00
KOWX712
7424ed325a opt: move valid kb download operation to JS 2025-02-22 22:03:32 +08:00
KOWX712
f1128cd55b opt: partially move update operation to JS
- move fetch update.json operation to JS
- move changelog download to JS
2025-02-22 22:03:32 +08:00
Bladius2024
e5dcc62fdf feat: add Polish Translation 2025-02-22 02:11:56 +08:00
KOWX712
ee169eb2cd opt: ui border sizing 2025-02-21 17:44:33 +08:00
KOWX712
a9d6833342 opt: uninstall button 2025-02-21 03:34:30 +08:00
KOWX712
a8e388d4cf opt: boot hash window ui 2025-02-21 03:18:57 +08:00
KOWX712
09f6f522de opt: simplify ripple effect class 2025-02-21 02:29:42 +08:00
KOWX712
f2483efc6e deps: update markdown parser
update to marked v15.0.7
2025-02-21 02:06:03 +08:00
KOWX712
6ed4df7d9c misc: rename file 2025-02-21 02:06:03 +08:00
KOWX712
ac4ff62cce opt: ui 2025-02-21 02:06:03 +08:00
KOWX712
b6c81362fe show prompt on fetching security patch date 2025-02-20 18:30:46 +08:00
KOWX712
5f70249003 script opt 2025-02-20 00:17:55 +08:00
KOWX712
16f1cde2d7 fix Failed to fetch app list on vanilla rom
#17
2025-02-20 00:01:05 +08:00
KOWX712
96ea764aa0 Update .extra 2025-02-19 21:23:42 +08:00
KOWX712
c44a101776 option to fetch a security patch date 2025-02-18 19:21:55 +08:00
KOWX712
581d81d5dd reflect recent update 2025-02-17 15:37:15 +08:00
KOWX712
d0882dfa57 use advanced config for security patch 2025-02-16 18:05:02 +08:00
35 changed files with 615 additions and 387 deletions

2
.extra

File diff suppressed because one or more lines are too long

View File

@@ -27,7 +27,9 @@ Configure Tricky Store target.txt with KSU WebUI.
| 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 | ✅ |
| Valid Keybox `not guaranteed` | ❌ |
| Shamiko Whitelist switch. [Why?](https://github.com/rushizgithub/shamiko?tab=readme-ov-file#whitelist) | ❌ |
| Periodically add all app to target.txt | ❌ |

View File

@@ -8,6 +8,14 @@ GitHub release: [Tricky Addon: Update Target List](https://github.com/KOWX712/Tr
Telegram channel: [KOW's Little World](https://t.me/kowchannel)
## Changelog
### 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.

View File

@@ -8,50 +8,41 @@ TMP_DIR="$MODPATH/common/tmp"
SCRIPT_DIR="/data/adb/tricky_store"
APK_PATH="$TMP_DIR/base.apk"
abort() {
manual_download() {
echo "$1"
sleep 3
am start -a android.intent.action.VIEW -d "https://github.com/5ec1cff/KsuWebUIStandalone/releases"
exit 1
}
download() {
download_type=${1#--}
download_url=$2
download_output=$3
PATH=/data/adb/magisk:/data/data/com.termux/files/usr/bin:$PATH
if command -v curl >/dev/null 2>&1; then
if [ "$download_type" = "output" ]; then
timeout 10 curl -Lo "$download_output" "$download_url"
else
timeout 2 curl -s "$download_url"
fi
timeout 10 curl -Ls "$1"
else
if [ "$download_type" = "output" ]; then
timeout 10 busybox wget --no-check-certificate -qO "$download_output" "$download_url"
else
timeout 2 busybox wget --no-check-certificate -qO- "$download_url"
fi
timeout 10 busybox wget --no-check-certificate -qO- "$1"
fi
PATH="$ORG_PATH"
}
get_webui() {
echo "- Downloading KSU WebUI Standalone..."
RESPONSE=$(download --fetch "https://api.github.com/repos/5ec1cff/KsuWebUIStandalone/releases/latest")
URL=$(echo "$RESPONSE" | grep -o '"browser_download_url": "[^"]*"' | cut -d '"' -f 4)
download --output "$URL" "$APK_PATH" || abort "! Error: APK download failed, please check your internet connection."
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"
abort "! Error: APK installation failed."
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" || abort "! Error: WebUI launch failed."
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

View File

@@ -2,8 +2,6 @@
MODPATH=${0%/*}
ORG_PATH="$PATH"
SKIPLIST="$MODPATH/tmp/skiplist"
OUTPUT="$MODPATH/tmp/exclude-list"
KBOUTPUT="$MODPATH/tmp/.extra"
if [ "$MODPATH" = "/data/adb/modules/.TA_utl/common" ]; then
MODDIR="/data/adb/modules/.TA_utl"
@@ -18,56 +16,29 @@ aapt() { "$MODPATH/aapt" "$@"; }
# wget = low pref, no ssl.
# curl, has ssl on android, we use it if found
download() {
download_type=${1#--}
download_url=$2
download_output=$3
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
if [ "$download_type" = "output" ]; then
timeout 10 curl -Lo "$download_output" "$download_url"
else
timeout 3 curl -s "$download_url"
fi
timeout 10 curl -Ls "$1"
else
if [ "$download_type" = "output" ]; then
timeout 10 busybox wget --no-check-certificate -qO "$download_output" "$download_url"
else
timeout 3 busybox wget --no-check-certificate -qO- "$download_url"
fi
timeout 10 busybox wget --no-check-certificate -qO- "$1"
fi
PATH="$ORG_PATH"
}
get_kb() {
download --output "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/.extra" "$KBOUTPUT"
[ -s "$KBOUTPUT" ] || rm -f "$KBOUTPUT"
}
get_xposed() {
pm list packages -3 | cut -d':' -f2 | grep -vxF -f "$SKIPLIST" | grep -vxF -f "$OUTPUT" | while read -r PACKAGE; do
pm list packages -3 | cut -d':' -f2 | grep -vxF -f "$SKIPLIST" | while read -r PACKAGE; do
APK_PATH=$(pm path "$PACKAGE" | grep "base.apk" | cut -d':' -f2 | tr -d '\r')
if [ -n "$APK_PATH" ]; then
if aapt dump xmltree "$APK_PATH" AndroidManifest.xml 2>/dev/null | grep -qE "xposed.category|xposeddescription"; then
echo "$PACKAGE" >>"$OUTPUT"
echo "$PACKAGE"
fi
fi
done
}
get_unnecessary() {
if [ ! -s "$OUTPUT" ] || [ ! -f "$OUTPUT" ]; then
JSON=$(download --fetch "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/more-exclude.json") || exit 1
echo "$JSON" | grep -o '"package-name": *"[^"]*"' | awk -F'"' '{print $4}' >"$OUTPUT"
fi
get_xposed
}
check_update() {
[ -f "$MODDIR/disable" ] && rm -f "$MODDIR/disable"
JSON=$(download --fetch "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/update.json") || exit 1
REMOTE_VERSION=$(echo "$JSON" | grep -o '"versionCode": *[0-9]*' | awk -F: '{print $2}' | tr -d ' ')
LOCAL_VERSION=$(grep -o 'versionCode=[0-9]*' "$MODPATH/update/module.prop" | awk -F= '{print $2}')
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"
@@ -89,12 +60,8 @@ uninstall() {
}
get_update() {
JSON=$(download --fetch "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/update.json") || exit 1
ZIP_URL=$(echo "$JSON" | grep -o '"zipUrl": "[^"]*"' | cut -d '"' -f 4) || exit 1
CHANGELOG_URL=$(echo "$JSON" | grep -o '"changelog": "[^"]*"' | cut -d '"' -f 4) || exit 1
echo "$JSON" | grep '"version"' | sed 's/.*: "//; s/".*//' > "$MODPATH/tmp/version" || exit 1
download --output "$ZIP_URL" "$MODPATH/tmp/module.zip" || exit 1
download --output "$CHANGELOG_URL" "$MODPATH/tmp/changelog.md" || exit 1
download "$ZIP_URL" > "$MODPATH/tmp/module.zip"
[ -s "$MODPATH/tmp/module.zip" ] || exit 1
}
install_update() {
@@ -114,7 +81,6 @@ install_update() {
}
release_note() {
VERSION=$(grep 'v' "$MODPATH/tmp/version")
awk -v header="### $VERSION" '
$0 == header {
print;
@@ -139,32 +105,32 @@ set_security_patch() {
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=" "$TS/module.prop" | cut -d'=' -f2)
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
echo "all=$formatted_security_patch" > "/data/adb/tricky_store/security_patch.txt"
chmod 644 "/data/adb/tricky_store/security_patch.txt"
else
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
--kb)
get_kb
exit
;;
--unnecessary)
get_unnecessary
exit
;;
--xposed)
get_xposed
exit
;;
--update)
--check-update)
REMOTE_VERSION="$2"
check_update
exit
;;
@@ -173,6 +139,7 @@ case "$1" in
exit
;;
--get-update)
ZIP_URL="$2"
get_update
exit
;;
@@ -181,6 +148,7 @@ case "$1" in
exit
;;
--release-note)
VERSION="$2"
release_note
exit
;;
@@ -188,4 +156,8 @@ case "$1" in
set_security_patch
exit
;;
--get-security-patch)
get_latest_security_patch
exit
;;
esac

View File

@@ -1,7 +1,7 @@
id=TA_utl
name=Tricky Addon - Update Target List
version=v3.4
versionCode=340
version=v3.5
versionCode=350
author=KOWX712
description=A WebUI to conifgure tricky store target.txt
updateJson=https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/update.json

View File

@@ -90,7 +90,7 @@ echo "# This file is generated from service.sh to speed up load time" > "$OUTPUT
# Check Xposed module
{
pm list packages -3 2>/dev/null
pm list package -s | grep -E "$SYSTEM_APP"
pm list package -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}' | tr -d '\r')

View File

@@ -9,14 +9,14 @@
<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/boot_hash.css" type="text/css">
<link rel="stylesheet" href="styles/header.css" type="text/css">
<link rel="stylesheet" href="styles/search_menu.css" type="text/css">
<link rel="stylesheet" href="styles/security-patch.css" type="text/css">
<link rel="stylesheet" href="styles/security_patch.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/vbmeta-digest.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>
@@ -51,12 +51,12 @@
<!-- Floating Button Element -->
<div class="floating-card">
<button class="floating-btn" id="save" data-i18n="functional_button.save_and_update_button"></button>
<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">
<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>
@@ -65,24 +65,24 @@
</div>
<div class="menu">
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<label for="menu-toggle" class="menu-button" id="menu-button">
<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 id="refresh" data-i18n="menu.refresh"></li>
<li id="select-all" data-i18n="menu.select_all"></li>
<li id="deselect-all" data-i18n="menu.deselect_all"></li>
<li id="select-denylist" data-i18n="menu.select_denylist"></li>
<li id="deselect-unnecessary" data-i18n="menu.deselect_unnecessary"></li>
<li id="aospkb" data-i18n="menu.set_aosp_keybox"></li>
<li id="validkb" data-i18n="menu.set_valid_keybox"></li>
<li id="customkb" data-i18n="menu.set_custom_keybox"></li>
<li id="boot-hash" data-i18n="menu.set_verified_boot_hash"></li>
<li id="security-patch" data-i18n="menu.set_security_patch"></li>
<li id="about" data-i18n="menu.about"></li>
<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="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>
@@ -91,20 +91,20 @@
<!-- Applist Display -->
<div id="apps-list"></div>
<div class="update-card" id="update-card">
<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" id="card">
<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" id="normal-indicator">
<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>
@@ -112,7 +112,7 @@
<label class="mode-switch" id="generate">
<input type="radio" class="mode-input" id="generate-mode">
<i class="mode-icon">
<div class="status-indicator" id="generate-indicator">
<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>
@@ -120,7 +120,7 @@
<label class="mode-switch" id="hack">
<input type="radio" class="mode-input" id="hack-mode">
<i class="mode-icon">
<div class="status-indicator" id="hack-indicator">
<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>
@@ -218,12 +218,9 @@
<!-- BootHash Input Overlay -->
<div id="boot-hash-overlay" class="boot-hash-overlay"></div>
<div id="boot-hash-card" class="boot-hash-card">
<div class="boot-hash-value">
<textarea id="boot-hash-input" class="input-box" placeholder="Paste your verified Boot Hash here" data-i18n="reset_vbmeta.boot_hash_input_placeholder"></textarea>
</div>
<div class="button-container">
<button id="boot-hash-save-button" class="boot-hash-save-button" data-i18n="reset_vbmeta.boot_hash_save_button"></button>
</div>
<div 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>
<!-- About Overlay -->
@@ -239,11 +236,11 @@
<br>
<p>
<div class="link">
<i class="link-icon" id="telegram" aria-hidden="true">
<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" id="github" aria-hidden="true">
<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>
@@ -265,8 +262,8 @@
<h1 data-i18n="update.changelog"></h1>
<div class="changelog"></div>
<div class="update-button-container">
<button class="install" data-i18n="update.install"></button>
<button class="reboot" data-i18n="update.reboot"></button>
<button class="install ripple-element" data-i18n="update.install"></button>
<button class="reboot ripple-element" data-i18n="update.reboot"></button>
</div>
</div>
</div>
@@ -325,17 +322,20 @@
<label for="advanced-mode" data-i18n="security_patch.advanced_mode"></label>
</div>
<div class="button-container">
<button id="auto-config" class="auto-button" data-i18n="security_patch.auto">Auto</button>
<button id="save-patch" class="save-button" data-i18n="security_patch.save">Save</button>
<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>
<!-- Footer -->
<div class="footer">
<div class="uninstall-container hidden-uninstall">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#FFFFFF"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z" /></svg>
<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" fill="#FF3636"><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>

View File

@@ -54,9 +54,10 @@
"set_security_patch": "Set Security Patch",
"about": "About"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Paste your verified Boot Hash here",
"boot_hash_save_button": "Save"
"boot_hash": {
"title": "Boot Hash",
"input_placeholder": "Paste your verified Boot Hash here",
"save_button": "Save"
},
"about": {
"module_name_line1": "Tricky Addon",
@@ -95,8 +96,12 @@
"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",

View File

@@ -54,9 +54,10 @@
"set_security_patch": "Set Security Patch",
"about": "About"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Paste your verified Boot Hash here",
"boot_hash_save_button": "Save"
"boot_hash": {
"title": "Boot Hash",
"input_placeholder": "Paste your verified Boot Hash here",
"save_button": "Save"
},
"about": {
"module_name_line1": "Tricky Addon",
@@ -95,8 +96,12 @@
"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",

View File

@@ -54,9 +54,10 @@
"set_verified_boot_hash": "Configurar Boot Hash Verificado",
"about": "Acerca de"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Pega aquí tu Boot Hash verificado",
"boot_hash_save_button": "Guardar"
"boot_hash": {
"title": "Boot Hash",
"input_placeholder": "Pega aquí tu Boot Hash verificado",
"save_button": "Guardar"
},
"about": {
"module_name_line1": "Tricky Addon",
@@ -95,8 +96,12 @@
"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",

View File

@@ -54,9 +54,10 @@
"set_security_patch": "セキュリティパッチを設定",
"about": "このアドオンについて"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "確認付きブートハッシュをここに貼り付け",
"boot_hash_save_button": "保存"
"boot_hash": {
"title": "ブートハッシュ",
"input_placeholder": "確認付きブートハッシュをここに貼り付け",
"save_button": "保存"
},
"about": {
"module_name_line1": "Tricky Addon",
@@ -93,12 +94,16 @@
"no_file_selected": "ファイルが選択されていません"
},
"security_patch": {
"title": "セキュリティ补丁",
"title": "セキュリティパッチ",
"advanced_mode": "高度",
"get_date": "セキュリティパッチの日付を取得",
"auto": "自動",
"save": "保存",
"auto_success": "自動配置已成功啟用",
"auto_failed": "自動設定を有効にできませんでした",
"fetching": "取得中...",
"fetched": "完了",
"get_failed": "セキュリティパッチの日付を取得できませんでした",
"auto_success": "自動設定が有効化されました",
"auto_failed": "自動設定が有効化できませんでした",
"save_success": "セキュリティパッチが正常に保存されました",
"save_failed": "セキュリティパッチの保存に失敗しました",
"value_empty": "セキュリティパッチの設定は無効です",
@@ -107,4 +112,4 @@
"invalid_system": "無効な system 形式です",
"invalid_vendor": "無効な vendor 形式です"
}
}
}

View File

@@ -0,0 +1,115 @@
{
"language": "Polski",
"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.",
"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",
"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"
},
"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"
}
}

View File

@@ -54,9 +54,10 @@
"set_verified_boot_hash": "Установить Verified Boot Hash",
"about": "О программе"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Вставьте свой проверенный Boot Hash сюда",
"boot_hash_save_button": "Сохранить"
"boot_hash": {
"title": "Boot Hash",
"input_placeholder": "Вставьте свой проверенный Boot Hash сюда",
"save_button": "Сохранить"
},
"about": {
"module_name_line1": "Tricky Addon",
@@ -95,8 +96,12 @@
"security_patch": {
"title": "Патч безопасности",
"advanced_mode": "Расширенный",
"get_date": "Получить дату патча безопасности",
"auto": "Авто",
"save": "Сохранить",
"fetching": "Получение...",
"fetched": "Готово",
"get_failed": "Не удалось получить дату патча безопасности",
"auto_success": "Автоматическая конфигурация успешно включена",
"auto_failed": "Не удалось включить автоматическую конфигурацию",
"save_success": "Патч безопасности успешно сохранен",

View File

@@ -54,9 +54,10 @@
"set_security_patch": "I-set ang Security Patch",
"about": "Tungkol"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "I-paste ang iyong verified Boot Hash dito",
"boot_hash_save_button": "I-save"
"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",
@@ -95,8 +96,12 @@
"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",

View File

@@ -54,9 +54,10 @@
"set_verified_boot_hash": "Doğrulanmış Boot Hash Ayarla",
"about": "Hakkında"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Doğrulanmış Boot Hash'inizi buraya yapıştırın",
"boot_hash_save_button": "Kaydet"
"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",
@@ -95,8 +96,12 @@
"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",

View File

@@ -54,9 +54,10 @@
"set_verified_boot_hash": "设置哈希值",
"about": "关于"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "在此粘贴您的哈希值",
"boot_hash_save_button": "保存"
"boot_hash": {
"title": "哈希值",
"input_placeholder": "在此粘贴您的哈希值",
"save_button": "保存"
},
"about": {
"module_name_line1": "TS插件",
@@ -95,8 +96,12 @@
"security_patch": {
"title": "安全补丁",
"advanced_mode": "高级",
"get_date": "获取安全补丁日期",
"auto": "自动",
"save": "保存",
"fetching": "获取中...",
"fetched": "完成",
"get_failed": "获取安全补丁日期失败",
"auto_success": "自动配置成功启用",
"auto_failed": "无法启用自动配置",
"save_success": "安全补丁成功保存",

View File

@@ -54,9 +54,10 @@
"set_verified_boot_hash": "設置哈希值",
"about": "關於"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "在此貼上您的哈希值",
"boot_hash_save_button": "保存"
"boot_hash": {
"title": "哈希值",
"input_placeholder": "在此貼上您的哈希值",
"save_button": "保存"
},
"about": {
"module_name_line1": "TS 插件",
@@ -95,8 +96,12 @@
"security_patch": {
"title": "安全補丁",
"advanced_mode": "進階",
"get_date": "獲取安全補丁日期",
"auto": "自動",
"save": "保存",
"fetching": "獲取中...",
"fetched": "完成",
"get_failed": "獲取安全補丁日期失敗",
"auto_success": "自動配置成功啟用",
"auto_failed": "無法啟用自動配置",
"save_success": "安全補丁成功保存",

View File

@@ -38,7 +38,10 @@ export async function fetchAppList() {
console.warn("Applist file not found or could not be loaded. Skipping applist lookup.");
}
const result = await execCommand("pm list packages -3 | awk -F: '{print $2}'; pm list packages -s | awk -F: '{print $2}' | grep -Ex 'com.google.android.gms|com.google.android.gsf|com.android.vending'");
const result = await execCommand(`
pm list packages -3 | awk -F: '{print $2}'
pm list packages -s | awk -F: '{print $2}' | grep -Ex "com.google.android.gms|com.google.android.gsf|com.android.vending" 2>/dev/null || true
`);
const appEntries = result
.split("\n")
.map(line => {

View File

@@ -5,6 +5,11 @@ const card = document.getElementById('boot-hash-card');
const inputBox = document.getElementById('boot-hash-input');
const saveButton = document.getElementById('boot-hash-save-button');
// Remove empty spaces from input
window.trimInput = (input) => {
input.value = input.value.replace(/\s+/g, '');
};
// Function to handle Verified Boot Hash
document.getElementById("boot-hash").addEventListener("click", async () => {
const showCard = () => {
@@ -51,4 +56,11 @@ document.getElementById("boot-hash").addEventListener("click", async () => {
bootHashOverlay.addEventListener("click", (event) => {
if (event.target === bootHashOverlay) closeCard();
});
// Enter to save
inputBox.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
saveButton.click();
}
});
});

View File

@@ -128,7 +128,7 @@ async function generateLanguageMenu() {
const sortedLanguages = languageData.sort((a, b) => a.name.localeCompare(b.name));
sortedLanguages.forEach(({ lang, name }) => {
const button = document.createElement('button');
button.classList.add('language-option');
button.classList.add('language-option', 'ripple-element');
button.setAttribute('data-lang', lang);
button.textContent = name;
languageMenu.appendChild(button);

View File

@@ -21,7 +21,6 @@ export const basePath = "set-path";
export const appsWithExclamation = [];
export const appsWithQuestion = [];
const ADDITIONAL_APPS = [ "android", "com.android.vending", "com.google.android.gms", "io.github.vvb2060.keyattestation", "io.github.vvb2060.mahoshojo", "icu.nullptr.nativetest" ]; // Always keep default apps in target.txt
const rippleClasses = ['.language-option', '.menu-button', '.menu-options li', '.search-card', '.card', '.update-card', '.link-icon', '.floating-btn', '.uninstall-container', '.boot-hash-save-button', '.boot-hash-value', '.reboot', '.install', '.file-item', '.save-button', '.auto-button'];
// Variables
let e = 0;
@@ -232,63 +231,59 @@ function hideFloatingBtn() {
// Function to apply ripple effect
export function applyRippleEffect() {
rippleClasses.forEach(selector => {
document.querySelectorAll(selector).forEach(element => {
if (element.dataset.rippleListener !== "true") {
element.addEventListener("pointerdown", function (event) {
if (isScrolling) return;
if (modeActive) return;
document.querySelectorAll('.ripple-element').forEach(element => {
if (element.dataset.rippleListener !== "true") {
element.addEventListener("pointerdown", function (event) {
if (isScrolling) return;
const ripple = document.createElement("span");
ripple.classList.add("ripple");
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;
// 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));
// Determine animation duration
let duration = 0.3 + (width / 800) * 0.3;
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`;
// 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)" : "";
// 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);
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", handlePointerUp);
element.addEventListener("pointercancel", handlePointerUp);
});
element.dataset.rippleListener = "true";
}
});
// Append ripple and handle cleanup
element.appendChild(ripple);
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", handlePointerUp);
element.addEventListener("pointercancel", handlePointerUp);
});
element.dataset.rippleListener = "true";
}
});
}

File diff suppressed because one or more lines are too long

View File

@@ -40,21 +40,25 @@ document.getElementById("select-denylist").addEventListener("click", async () =>
// Function to read the exclude list and uncheck corresponding apps
document.getElementById("deselect-unnecessary").addEventListener("click", async () => {
try {
const fileCheck = await execCommand(`test -f ${basePath}common/tmp/exclude-list && echo "exists" || echo "not found"`);
if (fileCheck.trim() === "not found") {
setTimeout(async () => {
await execCommand(`sh ${basePath}common/get_extra.sh --unnecessary`);
}, 0);
console.log("Exclude list not found. Running the unnecessary apps script.");
} else {
setTimeout(async () => {
await execCommand(`sh ${basePath}common/get_extra.sh --xposed`);
}, 0);
console.log("Exclude list found. Running xposed script.");
}
await new Promise(resolve => setTimeout(resolve, 100));
const result = await execCommand(`cat ${basePath}common/tmp/exclude-list`);
const UnnecessaryApps = result.split("\n").map(app => app.trim()).filter(Boolean);
const 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();
})
.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");
@@ -66,17 +70,17 @@ document.getElementById("deselect-unnecessary").addEventListener("click", async
});
console.log("Unnecessary apps deselected successfully.");
} catch (error) {
toast("Failed!");
console.error("Failed to deselect unnecessary apps:", error);
toast("Failed to get unnecessary apps!");
console.error("Failed to get unnecessary apps:", error);
}
});
// Function to backup previous keybox and set new keybox
async function setKeybox(path) {
async function setKeybox(content) {
try {
await execCommand(`
mv -f /data/adb/tricky_store/keybox.xml /data/adb/tricky_store/keybox.xml.bak 2>/dev/null
echo '${path}' > /data/adb/tricky_store/keybox.xml
echo '${content}' > /data/adb/tricky_store/keybox.xml
chmod 644 /data/adb/tricky_store/keybox.xml
`);
return true;
@@ -100,27 +104,36 @@ export async function aospkb() {
// Function to replace valid kb
document.getElementById("validkb").addEventListener("click", async () => {
setTimeout(async () => {
await execCommand(`sh ${basePath}common/get_extra.sh --kb`);
}, 100);
const sourcePath = `${basePath}common/tmp/.extra`;
await new Promise(resolve => setTimeout(resolve, 300));
const fileExists = await execCommand(`[ -f ${sourcePath} ] && echo "exists"`);
try {
if (fileExists.trim() !== "exists") {
throw new Error(".extra file not found");
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}`);
}
const source = await execCommand(`xxd -r -p ${sourcePath} | base64 -d`);
const result = await setKeybox(source);
if (result) {
showPrompt("prompt.valid_key_set");
} else {
throw new Error("Failed to copy valid keybox");
return response.text();
})
.then(async data => {
if (!data.trim()) {
await aospkb();
showPrompt("prompt.no_valid_fallback", false);
return;
}
} catch (error) {
await aospkb();
showPrompt("prompt.no_valid_fallback", false);
}
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);
});
});
// Add file selector dialog elements dynamically

View File

@@ -9,6 +9,7 @@ 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');
@@ -121,9 +122,7 @@ async function loadCurrentConfig() {
// Check if in advanced mode
if (autoConfig === '0' && allValue === null && (bootValue || systemValue || vendorValue)) {
advancedToggle.checked = true;
normalInputs.classList.add('hidden');
advancedInputs.classList.remove('hidden');
checkAdvanced(true);
}
}
} catch (error) {
@@ -131,6 +130,19 @@ async function loadCurrentConfig() {
}
}
// 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, '');
@@ -239,11 +251,7 @@ export function securityPatch() {
bootPatchInput.value = '';
vendorPatchInput.value = '';
// Uncheck advanced mode
advancedToggle.checked = false;
normalInputs.classList.remove('hidden');
advancedInputs.classList.add('hidden');
checkAdvanced(false);
showPrompt('security_patch.auto_success');
}
} catch (error) {
@@ -319,4 +327,21 @@ export function securityPatch() {
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);
systemPatchInput.value = 'prop';
bootPatchInput.value = output;
vendorPatchInput.value = output;
} catch (error) {
showPrompt('security_patch.get_failed', false);
}
});
}

View File

@@ -8,27 +8,86 @@ const releaseNotes = document.querySelector('.changelog');
const installButton = document.querySelector('.install');
const rebootButton = document.querySelector('.reboot');
// Function to run the update check
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 output = await execCommand(`sh ${basePath}common/get_extra.sh --update`);
console.log("update script executed successfully.");
const response = await fetch("https://raw.githubusercontent.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";
if (output.includes("update")) {
console.log("Update detected from extra script.");
showPrompt("prompt.new_update", true, 2000);
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();
} else {
console.log("No update detected from extra script.");
}
} catch (error) {
console.error("Failed to execute update script:", 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() {
@@ -45,46 +104,59 @@ function setupUpdateMenu() {
UpdateMenu.style.display = "none";
}, 200);
}
// Update card
updateCard.addEventListener('click', async () => {
try {
const module = await execCommand(`[ -f ${basePath}common/tmp/module.zip ] || echo "false"`);
if (module.trim() === "false") {
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 new Promise(resolve => setTimeout(resolve, 200));
await execCommand(`sh ${basePath}common/get_extra.sh --get-update`);
showPrompt("prompt.downloaded");
}
const changelog = await execCommand(`sh ${basePath}common/get_extra.sh --release-note`);
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>`;
}
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;
}
});
const cleanedChangelog = changelog
.split('\n')
.filter(line => line.trim() !== '')
.join('\n');
const formattedChangelog = marked.parse(cleanedChangelog);
releaseNotes.innerHTML = formattedChangelog;
openUpdateMenu();
} 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");
@@ -99,6 +171,8 @@ function setupUpdateMenu() {
console.error('Fail to execute installation script:', error);
}
});
// Reboot button
rebootButton.addEventListener('click', async () => {
try {
showPrompt("prompt.rebooting");

View File

@@ -91,8 +91,6 @@
box-sizing: border-box;
margin-bottom: 5px;
transition: background-color 0.2s ease;
position: relative;
overflow: hidden;
}
.link-icon svg {

View File

@@ -16,15 +16,14 @@
align-items: center;
background-color: #DCDCDC;
border: none;
border-radius: 10px;
border-radius: 12px;
box-sizing: border-box;
margin: 0 auto;
margin-bottom: 10px;
outline: none;
padding: 12px;
width: calc(100% - 30px);
width: calc(100% - 5px);
max-width: 900px;
position: relative;
overflow: hidden;
}
#update-available {
@@ -60,10 +59,10 @@
.update-menu {
position: relative;
width: 90vw;
width: calc(90% - 60px);
max-width: 800px;
background-color: white;
padding: 10px 0;
padding: 30px;
border-radius: 15px;
text-align: left;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
@@ -80,10 +79,6 @@
color: #ccc;
}
.update-content {
padding: 0 30px;
}
.update-content h3 {
font-size: 22px;
margin: 0;
@@ -116,48 +111,42 @@
.update-button-container {
width: 100%;
padding-top: 10px;
margin-top: 20px;
display: flex;
justify-content: flex-end;
justify-content: center;
}
.install,
.reboot {
margin-top: 10px;
margin-bottom: 15px;
display: none;
justify-content: center;
font-weight: bold;
color: #333;
background-color: #fff;
background-color: #ddd;
width: 100%;
border: none;
padding: 10px 15px;
border: 1px solid #3B3B3B;
border-radius: 50px 50px;
padding: 12px;
border-radius: 12px;
font-size: 18px;
position: relative;
overflow: hidden;
user-select: none;
}
.reboot {
display: none;
color: #fff;
background-color: #007bff;
border: 1px solid #007bff;
}
.card {
background-color: #fff;
border: none;
box-sizing: border-box;
border-radius: 12px;
margin: 0 auto;
margin-bottom: 10px;
outline: none;
padding: 13px;
width: calc(100% - 30px);
padding: 12px;
width: calc(100% - 5px);
max-width: 900px;
transition: background-color 0.2s ease;
position: relative;
overflow: hidden;
}
.content {
@@ -225,8 +214,6 @@
box-sizing: border-box;
transition: all 0.2s ease;
border: 3px solid transparent;
position: relative;
overflow: hidden;
}
#normal-indicator {
@@ -356,9 +343,8 @@
}
.install {
color: #eee;
background-color: #343434;
border: 1px solid #C2C2C2;
background-color: #6E6E6E;
color: white;
}
.update-menu {

View File

@@ -15,16 +15,16 @@
.boot-hash-card {
position: fixed;
top: 30%;
top: 10%;
left: 50%;
transform: translate(-50%, -50%);
width: 80vw;
max-width: 600px;
transform: translateX(-50%);
width: calc(90% - 60px);
max-width: 300px;
background-color: #fff;
border-radius: 18px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
z-index: 1200;
padding: 20px;
padding: 30px;
display: none;
flex-direction: column;
gap: 15px;
@@ -42,46 +42,35 @@
opacity: 1;
}
.boot-hash-value {
.boot-hash-title {
width: 100%;
font-size: 26px;
text-align: center;
user-select: none;
}
.boot-hash-input {
width: 100%;
height: 100px;
font-size: 16px;
background-color: #FFF;
padding: 10px;
background-color: #F5F5F5;
border: 1px solid #ccc;
border-radius: 10px;
box-sizing: border-box;
position: relative;
overflow: hidden;
}
.input-box {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
padding: 10px;
font-size: 16px;
border-radius: 9px;
box-sizing: border-box;
background-color: transparent;
outline-color: #007bff;
}
.button-container {
display: flex;
justify-content: flex-start;
resize: none;
}
.boot-hash-save-button {
padding: 10px 20px;
width: 100%;
padding: 12px;
border: none;
border-radius: 38px;
font-size: 18px;
border-radius: 12px;
font-size: 20px;
font-weight: bold;
background-color: #007bff;
color: white;
margin-left: auto;
position: relative;
overflow: hidden;
user-select: none;
@@ -92,12 +81,9 @@
background-color: #343434;
}
.input-box {
.boot-hash-input {
background-color: #232323;
color: #fff;
}
.boot-hash-value {
background-color: #343434;
border: 1px solid #6E6E6E;
}
}

View File

@@ -29,11 +29,10 @@ body {
align-items: center;
opacity: 0;
padding: 10px 20px;
font-size: 20px;
font-size: 22px;
font-weight: bold;
transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
transition: transform 0.4s ease;
border-radius: 50px 50px;
overflow: hidden;
user-select: none;
}
@@ -74,26 +73,21 @@ body {
.footer {
display: flex;
justify-content: space-between;
align-items: center;
width: calc(100% - 10px);
max-width: 1100px;
padding: 25px 0;
position: relative;
margin-left: auto;
margin-right: auto;
justify-content: center;
margin-bottom: 100px;
}
.uninstall-container {
padding: 10px 10px;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
padding: 8px;
width: calc(100% - 5px);
max-width: 900px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 8px;
background-color: #CE0000;
border-radius: 12px;
border: 3px solid #FF3636;
box-sizing: border-box;
background-color: #F5F5F5;
white-space: nowrap;
overflow: hidden;
user-select: none;
@@ -106,7 +100,7 @@ body {
.uninstall-container span {
font-size: 16px;
font-weight: bold;
color: #fff;
color: #FF3636;
}
.uninstall-container.hidden-uninstall {
@@ -245,6 +239,11 @@ body {
font-size: 16px;
}
.ripple-element {
position: relative;
overflow: hidden;
}
.ripple {
position: absolute;
border-radius: 50%;
@@ -271,6 +270,10 @@ body {
color: #fff;
}
.uninstall-container {
background-color: #121212;
}
.file-selector {
background-color: #343434;
color: #fff;

View File

@@ -8,7 +8,7 @@
width: calc(100% - 10px);
max-width: 1100px;
background-color: #F5F5F5;
transition: transform 0.2s ease;
transition: transform 0.4s ease;
z-index: 1100;
margin-left: auto;
margin-right: auto;
@@ -93,7 +93,6 @@
width: 100%;
white-space: nowrap;
position: relative;
overflow: hidden;
user-select: none;
}

View File

@@ -24,7 +24,6 @@
height: calc(100% - 2px);
width: calc(100% - 60px);
position: absolute;
overflow: hidden;
}
.search-icon {
@@ -41,7 +40,7 @@
outline: none;
left: 10px;
padding: 0 30px;
width: calc(100% - 10);
width: calc(100% - 80px);
}
.clear-btn {
@@ -78,8 +77,6 @@
justify-content: center;
z-index: 200;
align-items: center;
position: relative;
overflow: hidden;
}
.menu-icon {
@@ -135,8 +132,6 @@
padding: 12px 15px;
text-align: left;
background-color: white;
position: relative;
overflow: hidden;
}
.menu-options li::after {

View File

@@ -118,27 +118,28 @@
outline-color: #007bff;
border-radius: 10px;
font-size: 16px;
transition: border-color 0.2s ease;
}
.button-container {
display: flex;
width: 100%;
gap: 10px;
margin-top: 10px;
}
.auto-button, .save-button {
.get-button,
.auto-button,
.save-button {
width: 100%;
padding: 12px;
border: none;
border-radius: 12px;
font-size: 18px;
font-weight: bold;
position: relative;
overflow: hidden;
transition: background-color 0.2s ease;
}
.get-button,
.auto-button {
background-color: #ddd;
user-select: none;
@@ -174,6 +175,7 @@
border: 1px solid #6E6E6E;
}
.get-button,
.auto-button {
background-color: #6E6E6E;
color: white;

View File

@@ -22,6 +22,10 @@
"name": "KernelSU",
"package-name": "me.weishu.kernelsu"
},
{
"name": "KernelSU Next",
"package-name": "com.rifsxd.ksunext"
},
{
"name": "Apatch",
"package-name": "me.bmax.apatch"

View File

@@ -1,6 +1,6 @@
{
"versionCode": 340,
"version": "v3.4",
"zipUrl": "https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/download/v3.4/TrickyAddonModule-v3.4.zip",
"versionCode": 350,
"version": "v3.5",
"zipUrl": "https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/download/v3.5/TrickyAddonModule-v3.5.zip",
"changelog": "https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/changelog.md"
}