From 6d8f364d1788483fadce3487bad5a4af11d3b9f3 Mon Sep 17 00:00:00 2001 From: KOWX712 Date: Mon, 4 Nov 2024 21:50:35 +0800 Subject: [PATCH] v2.0 --- README.md | 6 +- changelog.md | 3 + lite-script_only/README.md | 2 +- lite-script_only/UpdateTargetList.sh | 2 +- module/common/UpdateTargetList.sh | 1 - module/customize.sh | 6 +- module/module.prop | 4 +- module/webroot/index.html | 22 ++- module/webroot/index.js | 200 +++++++++++++++++---- module/webroot/styles.css | 253 +++++++++++++++++++-------- 10 files changed, 380 insertions(+), 119 deletions(-) diff --git a/README.md b/README.md index 5947c33..df1e0ba 100755 --- a/README.md +++ b/README.md @@ -8,13 +8,13 @@ An addon module for tricky store - This is **not** a necessary module for root hide but for those who lazy to do it manually ## Requirements -- Tricky store module installed +- [Tricky store](https://github.com/5ec1cff/TrickyStore) module installed ## Custom Configuration - ADDITION and EXCLUDE in `/data/adb/tricky_store/target_list_config` - EXCLUDE for removing unnecessary apps - ADDITION for adding back system app excluded by default -- *Coming soon: Configuration list with **KSU WebUI** (For KernelSU and Apatch users only)* +- Configuration list with **KSU WebUI** (For KernelSU and Apatch, ) ## Instructions ### Automatic update @@ -30,7 +30,7 @@ An addon module for tricky store - MT manager is recommened for this method ## More -**Support to pass Patition Check Fail in Minotaur test** +**Support to pass abnormal boot state** - Put Verfied Boot Hash to `boot_hash` in `/data/adb/modules/TA_utl`, reboot. ## Acknowledgement diff --git a/changelog.md b/changelog.md index 019e531..61022ec 100755 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,9 @@ GitHub release: [Tricky Addon: Update Target List](https://github.com/KOWX712/Tr Telegram channel: [KOW's Little World](https://t.me/kowchannel) ## Changelog +### v2.0 +- Added WebUI for configuration + ### v1.7 - Fixed update issue (Will start to work in next update) diff --git a/lite-script_only/README.md b/lite-script_only/README.md index 7ae25c0..30696f9 100644 --- a/lite-script_only/README.md +++ b/lite-script_only/README.md @@ -4,7 +4,7 @@ - Recommend to run with MT manager ## Changelog -### v1.8 +### v2.0 - More clarify remark in code - Remove useless code diff --git a/lite-script_only/UpdateTargetList.sh b/lite-script_only/UpdateTargetList.sh index 1791403..ac3efc9 100644 --- a/lite-script_only/UpdateTargetList.sh +++ b/lite-script_only/UpdateTargetList.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Tricky Addon Lite: Update Target List Script v1.8 +# Tricky Addon Lite: Update Target List Script v2.0 # GitHub Repository: https://github.com/KOWX712/Tricky-Addon-Update-Target-List/blob/master/lite-script_only/README.md # Telegram channel: https://t.me/kowchannel diff --git a/module/common/UpdateTargetList.sh b/module/common/UpdateTargetList.sh index 01b5cc1..bf40d6f 100644 --- a/module/common/UpdateTargetList.sh +++ b/module/common/UpdateTargetList.sh @@ -26,7 +26,6 @@ ADDITION=$(grep -vE '^[[:space:]]*#|^[[:space:]]*$' "$CONFIG_DIR/ADDITION") echo "- Adding apps into /data/adb/tricky_store/target.txt..." echo " " su -c pm list packages -3 &1 | cat | awk -F: '{print $2}' | grep -Ev "$EXCLUDE" > /data/adb/tricky_store/target.txt -sleep 1 echo "- Adding addition app... " echo " " diff --git a/module/customize.sh b/module/customize.sh index e400859..06e9444 100644 --- a/module/customize.sh +++ b/module/customize.sh @@ -24,7 +24,6 @@ kb="$COMPATH/.default" if [ -d "$TS" ]; then ui_print "- Tricky store module installed" - ui_print " " else ui_print "! Tricky store module is not installed" abort " " @@ -77,8 +76,10 @@ ui_print "- Installing..." if [ -f "$SCRIPT_DIR/UpdateTargetList.sh" ]; then rm -f "$SCRIPT_DIR/UpdateTargetList.sh" fi -mv "$COMPATH/UpdateTargetList.sh" "$SCRIPT_DIR/UpdateTargetList.sh" cp "$MODPATH/module.prop" "$COMPATH/module.prop.orig" +mv "$COMPATH/UpdateTargetList.sh" "$SCRIPT_DIR/UpdateTargetList.sh" + +set_perm $SCRIPT_DIR/UpdateTargetList.sh 0 2000 0755 if [ -d "$CONFIG_DIR" ]; then if [ ! -f "$CONFIG_DIR/EXCLUDE" ] && [ ! -f "$CONFIG_DIR/ADDITION" ]; then @@ -142,6 +143,5 @@ else fi fi -ui_print " " ui_print "- Installation completed successfully! " ui_print " " \ No newline at end of file diff --git a/module/module.prop b/module/module.prop index a694843..5057182 100644 --- a/module/module.prop +++ b/module/module.prop @@ -1,7 +1,7 @@ id=TA_utl name=Tricky Addon - Update Target List -version=v1.7 -versionCode=170 +version=v2.0 +versionCode=200 author=KOWX712 description=Update tricky store target list with action button. Custom config: ADDITION and EXCLUDE in /data/adb/tricky_store/target_list_config updateJson=https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/master/update.json diff --git a/module/webroot/index.html b/module/webroot/index.html index 1bf7b0e..01bc520 100644 --- a/module/webroot/index.html +++ b/module/webroot/index.html @@ -8,15 +8,28 @@ +
Tricky Addon - Update Target List
+
- -
+ +
- Acknowledgment to j-hc/zygisk-detach WebUI + Credit to j-hc/zygisk-detach WebUI
+
\ No newline at end of file diff --git a/module/webroot/index.js b/module/webroot/index.js index 74dd041..9f78482 100644 --- a/module/webroot/index.js +++ b/module/webroot/index.js @@ -51,48 +51,118 @@ async function fetchAppList() { async function renderAppList() { await readExcludeFile(); const apps = await fetchAppList(); - apps.forEach(appName => { + const sortedApps = apps.sort((a, b) => { + const aInExclude = excludeList.includes(a); + const bInExclude = excludeList.includes(b); + return aInExclude === bInExclude ? a.localeCompare(b) : aInExclude ? 1 : -1; + }); + appListContainer.innerHTML = ""; + sortedApps.forEach(appName => { const appElement = document.importNode(appTemplate, true); appElement.querySelector(".name").textContent = appName; const checkbox = appElement.querySelector(".checkbox"); - checkbox.checked = !excludeList.includes(appName); // Deselect if in EXCLUDE + checkbox.checked = !excludeList.includes(appName); appListContainer.appendChild(appElement); }); } -// Add button click event to update EXCLUDE file -document.getElementById("add").addEventListener("click", async () => { - await readExcludeFile(); - const deselectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:not(:checked)")) - .map(checkbox => checkbox.closest(".card").querySelector(".name").textContent); - const selectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:checked")) - .map(checkbox => checkbox.closest(".card").querySelector(".name").textContent); - // Add deselected apps to EXCLUDE if not already present - for (const app of deselectedApps) { - if (!excludeList.includes(app)) { - excludeList.push(app); // Add to the local list - console.log("Added to EXCLUDE list:", app); +// Function to refresh the app list and clear the search input +async function refreshAppList() { + const searchInput = document.getElementById("search"); + searchInput.value = ''; + const apps = appListContainer.querySelectorAll(".card"); + apps.forEach(app => app.style.display = "block"); + await renderAppList(); +} + +// Function to select all apps +function selectAllApps() { + document.querySelectorAll(".checkbox").forEach(checkbox => checkbox.checked = true); +} + +// Function to deselect all apps +function deselectAllApps() { + document.querySelectorAll(".checkbox").forEach(checkbox => checkbox.checked = false); +} + +let promptTimeout; // Variable to store the current timeout + +// 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); // Apply error class if not success + prompt.style.display = 'block'; + + if (promptTimeout) { + clearTimeout(promptTimeout); + } + + promptTimeout = setTimeout(() => { + prompt.style.display = 'none'; + }, 2000); +} + +// Function to update the target list by executing a script +async function updateTargetList() { + try { + await execCommand("/data/adb/tricky_store/UpdateTargetList.sh"); + showPrompt("Successfully updated target.txt"); + } catch (error) { + console.error("Failed to update target list:", error); + showPrompt("Failed to update target.txt !", false); + } +} + +// Menu toggle functionality +function setupMenuToggle() { + const menuButton = document.getElementById('menu-button'); + const menuOptions = document.getElementById('menu-options'); + + menuButton.addEventListener('click', (event) => { + event.stopPropagation(); + if (menuOptions.classList.contains('visible')) { + closeMenu(); } else { - console.log("App already in EXCLUDE file, skipping:", app); + menuOptions.style.display = 'block'; + setTimeout(() => { + menuOptions.classList.remove('hidden'); + menuOptions.classList.add('visible'); + menuButton.classList.add('menu-open'); + menuButton.classList.remove('menu-closed'); + }, 10); + } + }); + + document.addEventListener('click', (event) => { + if (!menuOptions.contains(event.target) && event.target !== menuButton) { + closeMenu(); + } + }); + + const closeMenuItems = ['refresh', 'select-all', 'deselect-all', 'update']; + closeMenuItems.forEach(id => { + const item = document.getElementById(id); + if (item) { + item.addEventListener('click', (event) => { + event.stopPropagation(); + closeMenu(); + }); + } + }); + + function closeMenu() { + if (menuOptions.classList.contains('visible')) { + menuOptions.classList.remove('visible'); + menuOptions.classList.add('hidden'); + menuButton.classList.remove('menu-open'); + menuButton.classList.add('menu-closed'); + setTimeout(() => { + menuOptions.style.display = 'none'; + }, 300); } } - // Remove selected apps from EXCLUDE - if (selectedApps.length > 0) { - selectedApps.forEach(app => { - excludeList = excludeList.filter(excludedApp => excludedApp !== app); // Remove from local list - console.log("Removed from EXCLUDE list:", app); - }); - } - // Overwrite the EXCLUDE file with the updated list - try { - const updatedExcludeContent = excludeList.join("\n"); - await execCommand(`echo "${updatedExcludeContent}" > /data/adb/tricky_store/target_list_config/EXCLUDE`); - console.log("EXCLUDE file updated successfully."); - } catch (error) { - console.error("Failed to update EXCLUDE file:", error); - } - await readExcludeFile(); -}); +} // Search functionality document.getElementById("search").addEventListener("input", (e) => { @@ -104,5 +174,69 @@ document.getElementById("search").addEventListener("input", (e) => { }); }); +// Add button click event to update EXCLUDE file +document.getElementById("save").addEventListener("click", async () => { + await readExcludeFile(); + const deselectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:not(:checked)")) + .map(checkbox => checkbox.closest(".card").querySelector(".name").textContent); + const selectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:checked")) + .map(checkbox => checkbox.closest(".card").querySelector(".name").textContent); + + for (const app of deselectedApps) { + if (!excludeList.includes(app)) { + excludeList.push(app); + console.log("Added to EXCLUDE list:", app); + } else { + console.log("App already in EXCLUDE file, skipping:", app); + } + } + + if (selectedApps.length > 0) { + selectedApps.forEach(app => { + excludeList = excludeList.filter(excludedApp => excludedApp !== app); + console.log("Removed from EXCLUDE list:", app); + }); + } + + try { + const updatedExcludeContent = excludeList.join("\n"); + await execCommand(`echo "${updatedExcludeContent}" > /data/adb/tricky_store/target_list_config/EXCLUDE`); + console.log("EXCLUDE file updated successfully."); + showPrompt("Config saved successfully"); + } catch (error) { + console.error("Failed to update EXCLUDE file:", error); + showPrompt("Failed to save config", false); + } + await readExcludeFile(); +}); + +// Event listener for the "Update Target List" menu option +document.getElementById('update').addEventListener('click', updateTargetList); + // Initial load -renderAppList(); \ No newline at end of file +document.addEventListener('DOMContentLoaded', () => { + setupMenuToggle(); + document.getElementById("refresh").addEventListener("click", refreshAppList); + document.getElementById("select-all").addEventListener("click", selectAllApps); + document.getElementById("deselect-all").addEventListener("click", deselectAllApps); + renderAppList(); +}); + +// Scroll event +let lastScrollY = window.scrollY; +const title = document.getElementById('title'); +const searchCard = document.querySelector('.search-card'); +const menu = document.querySelector('.menu'); + +window.addEventListener('scroll', () => { + if (window.scrollY > lastScrollY) { + title.style.transform = 'translateY(-100%)'; + searchCard.style.transform = 'translateY(-40px)'; + menu.style.transform = 'translateY(-40px)'; + } else { + title.style.transform = 'translateY(0)'; + searchCard.style.transform = 'translateY(0)'; + menu.style.transform = 'translateY(0)'; + } + lastScrollY = window.scrollY; +}); \ No newline at end of file diff --git a/module/webroot/styles.css b/module/webroot/styles.css index 96bf27c..0e5b080 100644 --- a/module/webroot/styles.css +++ b/module/webroot/styles.css @@ -1,107 +1,218 @@ body { background-color: #F5F5F5; } + +#title { + background-color: #F5F5F5; + border: none; + font-size: 18px; + font-weight: bold; + left: 0; + padding: 7px 25px; + position: fixed; + text-align: left; + top: 0; + transition: transform 0.3s ease; + width: 100%; + z-index: 1000; +} + #apps-list { - margin-top: 70px; -} -.card { - border: none; - outline: none; - margin-bottom: 10px; - padding: 20px; - background-color: white; - border-radius: 8px; -} -.content { - justify-content: space-between; - align-items: center; - display: flex; -} -.name { - overflow-wrap: break-word; - word-break: break-word; - max-width: calc(100% - 30px); - margin: 0; - display: inline-block; -} -.checkbox { - margin-left: auto; -} -.floating-card { - display: flex; - justify-content: center; - z-index: 3; - position: fixed; - bottom: 45px; - left: 50%; - transform: translateX(-50%); -} -.floating-btn { - color: #fff; - cursor: pointer; - background-color: #007bff; - border: none; - border-radius: 24px; - justify-content: center; - align-items: center; - width: auto; - height: auto; - padding: 10px 20px; - font-size: 16px; - transition: transform .3s ease-in-out; - display: flex; - box-shadow: 0 4px 8px #0003; + margin-top: 100px; } + .search-card { - position: fixed; - top: 10px; - width: calc(100% - 35px); - left: 50%; - transform: translateX(-50%); - padding: 10px; background-color: white; border: 1px solid #ccc; border-radius: 25px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); display: flex; align-items: center; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + padding: 10px; + position: fixed; + top: 40px; + transition: transform 0.3s ease; + width: calc(100% - 100px); z-index: 1000; } + .search-input { - width: 100%; - border: none; - outline: none; - padding: 5px; - font-size: 14px; background-color: #fff; + border: none; box-sizing: border-box; + font-size: 14px; + outline: none; + padding: 5px 15px; + text-align: left; + width: 100%; +} + +.menu { + display: flex; + position: fixed; + top: 40px; + right: 10px; + z-index: 1000; + transition: transform 0.3s ease; +} + +.menu-toggle { + display: none; +} + +#menu-button { + background-color: white; + border: 1px solid #ccc; + border-radius: 25px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + padding: 13px 17px; + text-align: center; + transition: transform 0.3s ease; +} + +.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; + top: 110%; + right: 0; + transform: translateX(100%); + transition: transform 0.3s ease; + width: 170px; +} + +.menu-options.visible { + display: block; + transform: translateX(0); +} + +.menu-options.hidden { + transform: translateX(110%); +} + +.menu-options ul { + list-style: none; + margin: 0; + padding: 0; +} + +.menu-options li { + cursor: pointer; + padding: 15px 16px; text-align: left; } + +.menu-open { + transform: rotate(90deg); +} + +.menu-closed { + transform: rotate(0deg); +} + +.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 { + background-color: #4CAF50; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + color: white; + display: none; + font-size: 15px; + left: 10px; + padding: 5px 15px; + position: fixed; + bottom: 15px; + z-index: 1000; + transition: opacity 1s ease; +} + +.prompt.error { + background-color: #f44336; +} + +.floating-card { + display: flex; + justify-content: center; + position: fixed; + bottom: 45px; + left: 50%; + transform: translateX(-50%); + z-index: 3; +} + +.floating-btn { + background-color: #007bff; + border: none; + border-radius: 24px; + box-shadow: 0 4px 8px #0003; + color: #fff; + display: flex; + justify-content: center; + align-items: center; + padding: 10px 20px; + font-size: 16px; + transition: transform .3s ease-in-out; +} + .acknowledgment { - width: auto; - background-color: #F5F5F5; color: #6E6E6E; - text-align: center; padding: 20px; + text-align: center; font-size: 14px; } + @media (prefers-color-scheme: dark) { body { + background-color: #121212; color: #eee; + } + + #title { background-color: #121212; } - .card { + + .card, + .search-input, + .search-card { background-color: #343434; } + .search-card { border: 1px solid #6E6E6E; - background-color: #343434; } - .search-input { - color: #eee; + + .menu-options, + #menu-button { background-color: #343434; - } - .acknowledgment { - background-color: #121212; + border: 1px solid #6E6E6E; } } \ No newline at end of file