misc: move execCommand to exec

This commit is contained in:
KOWX712
2025-05-04 19:04:03 +08:00
parent 5a8097b40c
commit 770f107559
8 changed files with 374 additions and 413 deletions
+3 -3
View File
@@ -1,11 +1,11 @@
import { linkRedirect } from './main.js'; import { linkRedirect } from './main.js';
// Function to show about overlay
document.getElementById("about").addEventListener("click", () => {
const aboutOverlay = document.getElementById('about-overlay'); const aboutOverlay = document.getElementById('about-overlay');
const aboutContent = document.querySelector('.about-menu'); const aboutContent = document.querySelector('.about-menu');
const closeAbout = document.getElementById('close-about'); const closeAbout = document.getElementById('close-about');
// Function to show about overlay
document.getElementById("about").addEventListener("click", () => {
// Show about menu // Show about menu
setTimeout(() => { setTimeout(() => {
document.body.classList.add("no-scroll"); document.body.classList.add("no-scroll");
@@ -15,6 +15,7 @@ document.getElementById("about").addEventListener("click", () => {
aboutContent.classList.add('open'); aboutContent.classList.add('open');
}, 10); }, 10);
}, 80); }, 80);
});
const hideMenu = () => { const hideMenu = () => {
document.body.classList.remove("no-scroll"); document.body.classList.remove("no-scroll");
@@ -29,7 +30,6 @@ document.getElementById("about").addEventListener("click", () => {
aboutOverlay.addEventListener('click', (event) => { aboutOverlay.addEventListener('click', (event) => {
if (event.target === aboutOverlay) hideMenu(); if (event.target === aboutOverlay) hideMenu();
}); });
});
// Event listener for link redirect // Event listener for link redirect
document.getElementById('telegram').addEventListener('click', function() { document.getElementById('telegram').addEventListener('click', function() {
+16 -22
View File
@@ -1,4 +1,4 @@
import { basePath, execCommand, hideFloatingBtn, appsWithExclamation, appsWithQuestion, toast } from './main.js'; import { basePath, exec, hideFloatingBtn, appsWithExclamation, appsWithQuestion, toast } from './main.js';
const appTemplate = document.getElementById('app-template').content; const appTemplate = document.getElementById('app-template').content;
const modeOverlay = document.querySelector('.mode-overlay'); const modeOverlay = document.querySelector('.mode-overlay');
@@ -10,13 +10,14 @@ export async function fetchAppList() {
try { try {
// fetch target list // fetch target list
let targetList = []; let targetList = [];
try { await exec('cat /data/adb/tricky_store/target.txt')
const targetFileContent = await execCommand('cat /data/adb/tricky_store/target.txt'); .then(({ errno, stdout }) => {
targetList = processTargetList(targetFileContent); if (errno === 0) {
} catch (error) { targetList = processTargetList(stdout);
} else {
toast("Failed to read target.txt!"); toast("Failed to read target.txt!");
console.error("Failed to read target.txt file:", error);
} }
});
// fetch applist // fetch applist
const response = await fetch('applist.json'); const response = await fetch('applist.json');
@@ -28,35 +29,28 @@ export async function fetchAppList() {
// Get installed packages first // Get installed packages first
let appEntries = [], installedPackages = []; let appEntries = [], installedPackages = [];
try { const { stdout } = await exec(`
installedPackages = await execCommand(`
pm list packages -3 | awk -F: '{print $2}' 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="" [ -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 [ -z "$SYSTEM_APP" ] || pm list packages -s | awk -F: '{print $2}' | grep -Ex "$SYSTEM_APP" || true
`) `);
installedPackages = installedPackages.split("\n").map(line => line.trim()).filter(Boolean); installedPackages = stdout.split("\n").map(line => line.trim()).filter(Boolean);
appEntries = await Promise.all(installedPackages.map(async packageName => { appEntries = await Promise.all(installedPackages.map(async (packageName) => {
if (appNameMap[packageName]) { if (appNameMap[packageName]) {
return { return {
appName: appNameMap[packageName], appName: appNameMap[packageName],
packageName packageName
}; };
} }
const appName = await execCommand(` const { stdout: appName } = await exec(`
base_apk=$(pm path ${packageName} | head -n1 | awk -F: '{print $2}') base_apk=$(pm path ${packageName} | head -n1 | awk -F: '{print $2}')
${basePath}/common/aapt dump badging $base_apk 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g" aapt dump badging $base_apk 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g"
`); `, { env: { PATH: `$PATH:${basePath}/common:/data/data/com.termux/files/usr/bin` } });
return { return {
appName: appName.trim() || packageName, appName: appName || packageName,
packageName packageName
}; };
})); }));
} catch (error) {
appEntries = appList.map(app => ({
appName: app.app_name,
packageName: app.package_name
}));
}
// Sort // Sort
const sortedApps = appEntries.sort((a, b) => { const sortedApps = appEntries.sort((a, b) => {
+23 -23
View File
@@ -1,4 +1,4 @@
import { execCommand, showPrompt } from './main.js'; import { exec, showPrompt } from './main.js';
const bootHashOverlay = document.getElementById('boot-hash-overlay'); const bootHashOverlay = document.getElementById('boot-hash-overlay');
const bootHash = document.querySelector('.boot-hash-card'); const bootHash = document.querySelector('.boot-hash-card');
@@ -20,6 +20,20 @@ document.getElementById("boot-hash").addEventListener("click", async () => {
bootHash.classList.add('open'); bootHash.classList.add('open');
}, 10); }, 10);
// read current boot hash
exec("cat /data/adb/boot_hash")
.then(({ errno, stdout }) => {
if (errno !== 0) {
inputBox.value = "";
} else {
const validHash = stdout
.split("\n")
.filter(line => !line.startsWith("#") && line.trim())[0];
inputBox.value = validHash || "";
}
});
});
const closeBootHashMenu = () => { const closeBootHashMenu = () => {
document.body.classList.remove("no-scroll"); document.body.classList.remove("no-scroll");
bootHashOverlay.style.opacity = 0; bootHashOverlay.style.opacity = 0;
@@ -28,42 +42,28 @@ document.getElementById("boot-hash").addEventListener("click", async () => {
bootHashOverlay.style.display = "none"; bootHashOverlay.style.display = "none";
}, 200); }, 200);
}; };
try {
const bootHashContent = await execCommand("cat /data/adb/boot_hash"); // Save button listener
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 () => { saveButton.addEventListener("click", async () => {
const inputValue = inputBox.value.trim(); const inputValue = inputBox.value.trim();
try { exec(`
await execCommand(`
PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH
resetprop -n ro.boot.vbmeta.digest ${inputValue} resetprop -n ro.boot.vbmeta.digest ${inputValue}
[ -z "${inputValue}" ] && rm -f /data/adb/boot_hash || { [ -z "${inputValue}" ] && rm -f /data/adb/boot_hash || {
echo "${inputValue}" > /data/adb/boot_hash echo "${inputValue}" > /data/adb/boot_hash
chmod 644 /data/adb/boot_hash chmod 644 /data/adb/boot_hash
} }
`); `, { env: { PATH: "/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH" } })
.then(() => {
showPrompt("prompt.boot_hash_set"); showPrompt("prompt.boot_hash_set");
closeBootHashMenu(); closeBootHashMenu();
} catch (error) {
console.error("Failed to update boot_hash:", error);
showPrompt("prompt.boot_hash_set_error", false);
}
}); });
});
bootHashOverlay.addEventListener("click", (event) => { bootHashOverlay.addEventListener("click", (event) => {
if (event.target === bootHashOverlay) closeBootHashMenu(); if (event.target === bootHashOverlay) closeBootHashMenu();
}); });
// Enter to save // Enter to save
inputBox.addEventListener('keydown', (e) => { inputBox.addEventListener('keydown', (e) => {
if (e.key === 'Enter') { if (e.key === 'Enter') saveButton.click();
saveButton.click();
}
});
}); });
+72 -76
View File
@@ -26,23 +26,16 @@ let isRefreshing = false;
// Function to set basePath // Function to set basePath
async function getBasePath() { async function getBasePath() {
try { const { errno } = await exec('[ -d /data/adb/modules/.TA_utl ]');
await execCommand('[ -d /data/adb/modules/.TA_utl ]'); basePath = errno === 0 ? "/data/adb/modules/.TA_utl" : "/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 // Function to load the version from module.prop
async function getModuleVersion() { function getModuleVersion() {
const moduleVersion = document.getElementById('module-version'); exec(`grep '^version=' ${basePath}/common/update/module.prop | cut -d'=' -f2`)
try { .then(({ stdout }) => {
const version = await execCommand(`grep '^version=' ${basePath}/common/update/module.prop | cut -d'=' -f2`); document.getElementById('module-version').textContent = stdout;
moduleVersion.textContent = version; });
} catch (error) {
console.error("Failed to read version from module.prop:", error);
}
} }
// Function to refresh app list // Function to refresh app list
@@ -59,13 +52,8 @@ export async function refreshAppList() {
await new Promise(resolve => setTimeout(resolve, 500)); await new Promise(resolve => setTimeout(resolve, 500));
window.scrollTo(0, 0); window.scrollTo(0, 0);
if (noConnection.style.display === "flex") { if (noConnection.style.display === "flex") {
try {
updateCheck(); updateCheck();
await execCommand(`[ -f ${basePath}/common/tmp/exclude-list ] && rm -f "${basePath}/common/tmp/exclude-list"`); exec(`rm -f "${basePath}/common/tmp/exclude-list"`);
} catch (error) {
toast("Failed!");
console.error("Error occurred:", error);
}
} }
await fetchAppList(); await fetchAppList();
applyRippleEffect(); applyRippleEffect();
@@ -75,30 +63,27 @@ export async function refreshAppList() {
} }
// Function to check tricky store version // Function to check tricky store version
async function checkTrickyStoreVersion() { function checkTrickyStoreVersion() {
const securityPatchElement = document.getElementById('security-patch'); const securityPatchElement = document.getElementById('security-patch');
try { exec(`
const version = await execCommand(`
TS_version=$(grep "versionCode=" "/data/adb/modules/tricky_store/module.prop" | cut -d'=' -f2) TS_version=$(grep "versionCode=" "/data/adb/modules/tricky_store/module.prop" | cut -d'=' -f2)
[ "$TS_version" -ge 158 ] || echo "NO" [ "$TS_version" -ge 158 ]
`); `).then(({ errno }) => {
if (version.trim() !== "NO") securityPatchElement.style.display = "flex"; if (errno === 0) {
} catch (error) { securityPatchElement.style.display = "flex";
toast("Failed to check Tricky Store version!"); } else {
console.error("Error while checking Tricky Store version:", error); console.log("Tricky Store version is lower than 158, or fail to check Tricky store version.");
} }
});
} }
// Function to check if Magisk // Function to check if Magisk
async function checkMagisk() { function checkMagisk() {
const selectDenylistElement = document.getElementById('select-denylist'); const selectDenylistElement = document.getElementById('select-denylist');
try { exec('command -v magisk')
const magiskEnv = await execCommand(`command -v magisk >/dev/null 2>&1 || echo "NO"`); .then(({ errno }) => {
if (magiskEnv.trim() !== "NO") selectDenylistElement.style.display = "flex"; if (errno === 0) 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 // Function to show the prompt with a success or error message
@@ -117,18 +102,22 @@ export function showPrompt(key, isSuccess = true, duration = 3000) {
}, 100); }, 100);
} }
// Function to redirect link on external browser /**
export async function linkRedirect(link) { * Redirect to a link with am command
try { * @param {string} link - The link to redirect in browser
await execCommand(`am start -a android.intent.action.VIEW -d ${link}`); */
} catch (error) { export function linkRedirect(link) {
toast("Failed!"); toast("Redirecting to " + link);
console.error('Error redirect link:', error); setTimeout(() => {
} exec(`am start -a android.intent.action.VIEW -d ${link}`)
.then(({ errno }) => {
if (errno !== 0) toast("Failed to open link");
});
},100);
} }
// Save configure and preserve ! and ? in target.txt // Save configure and preserve ! and ? in target.txt
document.getElementById("save").addEventListener("click", async () => { document.getElementById("save").addEventListener("click", () => {
const selectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:checked")) const selectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:checked"))
.map(checkbox => checkbox.closest(".card").querySelector(".content").getAttribute("data-package")); .map(checkbox => checkbox.closest(".card").querySelector(".content").getAttribute("data-package"));
let finalAppsList = new Set(selectedApps); let finalAppsList = new Set(selectedApps);
@@ -136,7 +125,6 @@ document.getElementById("save").addEventListener("click", async () => {
finalAppsList.add(app); finalAppsList.add(app);
}); });
finalAppsList = Array.from(finalAppsList); finalAppsList = Array.from(finalAppsList);
try {
const modifiedAppsList = finalAppsList.map(app => { const modifiedAppsList = finalAppsList.map(app => {
if (appsWithExclamation.includes(app)) { if (appsWithExclamation.includes(app)) {
return `${app}!`; return `${app}!`;
@@ -146,19 +134,21 @@ document.getElementById("save").addEventListener("click", async () => {
return app; return app;
}); });
const updatedTargetContent = modifiedAppsList.join("\n"); const updatedTargetContent = modifiedAppsList.join("\n");
await execCommand(`echo "${updatedTargetContent}" | sort -u > /data/adb/tricky_store/target.txt`); exec(`echo "${updatedTargetContent}" | sort -u > /data/adb/tricky_store/target.txt`)
showPrompt("prompt.saved_target"); .then(({ errno }) => {
if (errno === 0) {
for (const app of appsWithExclamation) { for (const app of appsWithExclamation) {
await execCommand(`sed -i 's/^${app}$/${app}!/' /data/adb/tricky_store/target.txt`); exec(`sed -i 's/^${app}$/${app}!/' /data/adb/tricky_store/target.txt`);
} }
for (const app of appsWithQuestion) { for (const app of appsWithQuestion) {
await execCommand(`sed -i 's/^${app}$/${app}?/' /data/adb/tricky_store/target.txt`); exec(`sed -i 's/^${app}$/${app}?/' /data/adb/tricky_store/target.txt`);
} }
} catch (error) { showPrompt("prompt.saved_target");
console.error("Failed to update target.txt:", error); refreshAppList();
} else {
showPrompt("prompt.save_error", false); showPrompt("prompt.save_error", false);
} }
await refreshAppList(); });
}); });
// Uninstall WebUI // Uninstall WebUI
@@ -189,18 +179,16 @@ document.querySelector(".uninstall-container").addEventListener("click", () => {
}) })
confirmButton.addEventListener('click', () => { confirmButton.addEventListener('click', () => {
closeuninstallOverlay(); closeuninstallOverlay();
uninstallWebUI(); exec(`sh ${basePath}/common/get_extra.sh --uninstall`)
}) .then(({ errno }) => {
}); if (errno === 0) {
async function uninstallWebUI() {
try {
await execCommand(`sh ${basePath}/common/get_extra.sh --uninstall`);
showPrompt("prompt.uninstall_prompt"); showPrompt("prompt.uninstall_prompt");
} catch (error) { } else {
console.error("Failed to execute uninstall command:", error);
showPrompt("prompt.uninstall_failed", false); showPrompt("prompt.uninstall_failed", false);
} }
} });
})
});
// Function to check if running in MMRL // Function to check if running in MMRL
function checkMMRL() { function checkMMRL() {
@@ -323,24 +311,32 @@ document.addEventListener('DOMContentLoaded', async () => {
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall'); document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
}); });
// Function to execute shell commands /**
export async function execCommand(command) { * Execute shell command with ksu.exec
* @param {string} command - The command to execute
* @param {Object} [options={}] - Options object containing:
* - cwd <string> - Current working directory of the child process
* - env {Object} - Environment key-value pairs
* @returns {Promise<Object>} Resolves with:
* - errno {number} - Exit code of the command
* - stdout {string} - Standard output from the command
* - stderr {string} - Standard error from the command
*/
export function exec(command, options = {}) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const callbackName = `exec_callback_${Date.now()}_${e++}`; const callbackFuncName = `exec_callback_${Date.now()}_${e++}`;
window[callbackName] = (errno, stdout, stderr) => { window[callbackFuncName] = (errno, stdout, stderr) => {
delete window[callbackName]; resolve({ errno, stdout, stderr });
if (errno === 0) { cleanup(callbackFuncName);
resolve(stdout);
} else {
console.error(`Error executing command: ${stderr}`);
reject(stderr);
}
}; };
function cleanup(successName) {
delete window[successName];
}
try { try {
ksu.exec(command, "{}", callbackName); ksu.exec(command, JSON.stringify(options), callbackFuncName);
} catch (error) { } catch (error) {
console.error(`Execution error: ${error}`);
reject(error); reject(error);
cleanup(callbackFuncName);
} }
}); });
} }
+55 -79
View File
@@ -1,4 +1,4 @@
import { basePath, execCommand, showPrompt, toast, applyRippleEffect, refreshAppList } from './main.js'; import { basePath, exec, showPrompt, toast, applyRippleEffect, refreshAppList } from './main.js';
// Function to check or uncheck all app // Function to check or uncheck all app
function toggleCheckboxes(shouldCheck) { function toggleCheckboxes(shouldCheck) {
@@ -16,26 +16,24 @@ document.getElementById("select-all").addEventListener("click", () => toggleChec
document.getElementById("deselect-all").addEventListener("click", () => toggleCheckboxes(false)); document.getElementById("deselect-all").addEventListener("click", () => toggleCheckboxes(false));
// Function to read the denylist and check corresponding apps // Function to read the denylist and check corresponding apps
document.getElementById("select-denylist").addEventListener("click", async () => { document.getElementById("select-denylist").addEventListener("click", () => {
try { exec(`magisk --denylist ls 2>/dev/null | awk -F'|' '{print $1}' | grep -v "isolated" | sort -u`)
const result = await execCommand(`magisk --denylist ls 2>/dev/null | awk -F'|' '{print $1}' | grep -v "isolated" | sort -u`); .then(({ errno, stdout }) => {
const denylistApps = result.split("\n").map(app => app.trim()).filter(Boolean); if (errno === 0) {
const apps = document.querySelectorAll(".card"); const denylistApps = stdout.split("\n").map(app => app.trim()).filter(Boolean);
apps.forEach(app => { document.querySelectorAll(".card").forEach(app => {
const contentElement = app.querySelector(".content"); const contentElement = app.querySelector(".content");
const packageName = contentElement.getAttribute("data-package"); const packageName = contentElement.getAttribute("data-package");
const checkbox = app.querySelector(".checkbox");
if (denylistApps.includes(packageName)) { if (denylistApps.includes(packageName)) {
checkbox.checked = true; app.querySelector(".checkbox").checked = true;
} }
}); });
await execCommand('touch "/data/adb/tricky_store/target_from_denylist"'); exec('touch "/data/adb/tricky_store/target_from_denylist"');
console.log("Denylist apps selected successfully."); } else {
} catch (error) {
toast("Failed to read DenyList!"); toast("Failed to read DenyList!");
console.error("Failed to select Denylist apps:", error);
} }
}); });
});
// Function to read the exclude list and uncheck corresponding apps // Function to read the exclude list and uncheck corresponding apps
document.getElementById("deselect-unnecessary").addEventListener("click", async () => { document.getElementById("deselect-unnecessary").addEventListener("click", async () => {
@@ -62,18 +60,18 @@ document.getElementById("deselect-unnecessary").addEventListener("click", async
toast("Failed to download unnecessary apps!"); toast("Failed to download unnecessary apps!");
throw error; throw error;
}); });
const xposed = await execCommand(`sh ${basePath}/common/get_extra.sh --xposed`); exec(`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)); .then(({ stdout }) => {
const apps = document.querySelectorAll(".card"); const unnecessaryApps = excludeList.split("\n").map(app => app.trim())
apps.forEach(app => { .filter(Boolean).concat(stdout.split("\n").map(app => app.trim()).filter(Boolean));
document.querySelectorAll(".card").forEach(app => {
const contentElement = app.querySelector(".content"); const contentElement = app.querySelector(".content");
const packageName = contentElement.getAttribute("data-package"); const packageName = contentElement.getAttribute("data-package");
const checkbox = app.querySelector(".checkbox"); if (unnecessaryApps.includes(packageName)) {
if (UnnecessaryApps.includes(packageName)) { app.querySelector(".checkbox").checked = false;
checkbox.checked = false;
} }
}); });
console.log("Unnecessary apps deselected successfully."); });
} catch (error) { } catch (error) {
toast("Failed to get unnecessary apps!"); toast("Failed to get unnecessary apps!");
console.error("Failed to get unnecessary apps:", error); console.error("Failed to get unnecessary apps:", error);
@@ -113,39 +111,36 @@ export async function setupSystemAppMenu() {
const input = document.getElementById("system-app-input"); const input = document.getElementById("system-app-input");
const packageName = input.value.trim(); const packageName = input.value.trim();
if (packageName) { if (packageName) {
try { exec(`pm list packages -s | grep -q ${packageName}`)
const result = await execCommand(`pm list packages -s | grep -q ${packageName} || echo "false"`); .then(({ errno }) => {
if (result.includes("false")) { if (errno !== 0) {
showPrompt("prompt.system_app_not_found", false); showPrompt("prompt.system_app_not_found", false);
} else { } else {
await execCommand(` exec(`
touch "/data/adb/tricky_store/system_app" touch "/data/adb/tricky_store/system_app"
echo "${packageName}" >> "/data/adb/tricky_store/system_app" echo "${packageName}" >> "/data/adb/tricky_store/system_app"
echo "${packageName}" >> "/data/adb/tricky_store/target.txt" echo "${packageName}" >> "/data/adb/tricky_store/target.txt"
`); `)
systemAppInput.value = ""; systemAppInput.value = "";
closeSystemAppOverlay(); closeSystemAppOverlay();
refreshAppList(); 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 // Display current system app list and remove button
async function renderSystemAppList() { async function renderSystemAppList() {
const currentSystemAppList = document.querySelector(".current-system-app-list"); const systemAppList = document.querySelector(".current-system-app-list");
const currentSystemAppListContent = document.querySelector(".current-system-app-list-content"); const systemAppListContent = document.querySelector(".current-system-app-list-content");
currentSystemAppListContent.innerHTML = ""; systemAppListContent.innerHTML = "";
try { const { errno, stdout } = await exec(`[ -f "/data/adb/tricky_store/system_app" ] && cat "/data/adb/tricky_store/system_app" | sed '/^$/d'`);
const systemAppList = await execCommand(`[ -f "/data/adb/tricky_store/system_app" ] && cat "/data/adb/tricky_store/system_app" | sed '/^$/d' || echo "false"`); if (errno !== 0 || stdout.trim() === "") {
if (systemAppList.trim() === 'false' || systemAppList.trim() === '') { systemAppList.style.display = "none";
currentSystemAppList.style.display = "none";
} else { } else {
systemAppList.split("\n").forEach(app => { stdout.split("\n").forEach(app => {
currentSystemAppListContent.innerHTML += ` if (app.trim() !== "") {
systemAppListContent.innerHTML += `
<div class="system-app-item"> <div class="system-app-item">
<span>${app}</span> <span>${app}</span>
<button class="remove-system-app-button ripple-element"> <button class="remove-system-app-button ripple-element">
@@ -153,27 +148,21 @@ export async function setupSystemAppMenu() {
</button> </button>
</div> </div>
`; `;
}
}); });
} }
} catch (error) {
currentSystemAppList.style.display = "none";
console.error("Error displaying system app list:", error);
}
const removeSystemAppButtons = document.querySelectorAll(".remove-system-app-button"); // Remove button listener
removeSystemAppButtons.forEach(button => { document.querySelectorAll(".remove-system-app-button").forEach(button => {
button.addEventListener("click", async () => { button.addEventListener("click", () => {
const app = button.closest(".system-app-item").querySelector("span").textContent; const app = button.closest(".system-app-item").querySelector("span").textContent;
try { exec(`
await execCommand(` sed -i "/${app}/d" "/data/adb/tricky_store/system_app"
sed -i "/${app}/d" "/data/adb/tricky_store/system_app" || true sed -i "/${app}/d" "/data/adb/tricky_store/target.txt"
sed -i "/${app}/d" "/data/adb/tricky_store/target.txt" || true `).then(() => {
`);
closeSystemAppOverlay(); closeSystemAppOverlay();
refreshAppList(); refreshAppList();
} catch (error) { });
console.error("Error removing system app:", error);
}
}); });
}); });
} }
@@ -185,19 +174,15 @@ export async function setupSystemAppMenu() {
* @returns {Boolean} * @returns {Boolean}
*/ */
async function setKeybox(content) { async function setKeybox(content) {
try { await exec(`
await execCommand(`
mv -f /data/adb/tricky_store/keybox.xml /data/adb/tricky_store/keybox.xml.bak 2>/dev/null mv -f /data/adb/tricky_store/keybox.xml /data/adb/tricky_store/keybox.xml.bak 2>/dev/null
cat << 'KB_EOF' > /data/adb/tricky_store/keybox.xml cat << 'KB_EOF' > /data/adb/tricky_store/keybox.xml
${content} ${content}
KB_EOF KB_EOF
chmod 644 /data/adb/tricky_store/keybox.xml chmod 644 /data/adb/tricky_store/keybox.xml
`); `).then(({ errno }) => {
return true; return errno === 0;
} catch (error) { });
console.error("Failed to set keybox:", error);
return false;
}
} }
/** /**
@@ -205,14 +190,9 @@ KB_EOF
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async function aospkb() { async function aospkb() {
const source = await execCommand(`xxd -r -p ${basePath}/common/.default | base64 -d`); const { stdout } = await exec(`xxd -r -p ${basePath}/common/.default | base64 -d`);
const result = await setKeybox(source); const result = setKeybox(stdout);
if (result) { showPrompt(result ? "prompt.aosp_key_set" : "prompt.key_set_error", result);
console.log("AOSP keybox copied successfully.");
showPrompt("prompt.aosp_key_set");
} else {
showPrompt("prompt.key_set_error", false);
}
} }
// aosp kb eventlistener // aosp kb eventlistener
@@ -310,8 +290,8 @@ async function listFiles(path, skipAnimation = false) {
await new Promise(resolve => setTimeout(resolve, 150)); await new Promise(resolve => setTimeout(resolve, 150));
} }
try { try {
const result = await execCommand(`find "${path}" -maxdepth 1 -type f -name "*.xml" -o -type d ! -name ".*" | sort`); const { stdout } = await exec(`find "${path}" -maxdepth 1 -type f -name "*.xml" -o -type d ! -name ".*" | sort`);
const items = result.split('\n').filter(Boolean).map(item => ({ const items = stdout.split('\n').filter(Boolean).map(item => ({
path: item, path: item,
name: item.split('/').pop(), name: item.split('/').pop(),
isDirectory: !item.endsWith('.xml') isDirectory: !item.endsWith('.xml')
@@ -356,14 +336,10 @@ async function listFiles(path, skipAnimation = false) {
}); });
await listFiles(item.path); await listFiles(item.path);
} else { } else {
const source = await execCommand(`cat "${item.path}"`); const { stdout } = await exec(`cat "${item.path}"`);
const result = await setKeybox(source); const result = setKeybox(stdout);
if (result) { showPrompt(result ? "prompt.custom_key_set" : "prompt.custom_key_set_error", result);
closeCustomKeyboxSelector(); closeCustomKeyboxSelector();
showPrompt('prompt.custom_key_set');
} else {
showPrompt('prompt.custom_key_set_error');
}
} }
}); });
fileList.appendChild(itemElement); fileList.appendChild(itemElement);
+44 -49
View File
@@ -1,4 +1,4 @@
import { basePath, execCommand, showPrompt } from './main.js'; import { basePath, exec, showPrompt } from './main.js';
const overlay = document.getElementById('security-patch-overlay'); const overlay = document.getElementById('security-patch-overlay');
const overlayContent = document.querySelector('.security-patch-card'); const overlayContent = document.querySelector('.security-patch-card');
@@ -24,32 +24,26 @@ const hideSecurityPatchDialog = () => {
} }
// Function to handle security patch operation // Function to handle security patch operation
async function handleSecurityPatch(mode, value = null) { function handleSecurityPatch(mode, value = null) {
if (mode === 'disable') { if (mode === 'disable') {
try { exec(`
await execCommand(` rm -f /data/adb/tricky_store/security_patch_auto_config || true
rm -f /data/adb/tricky_store/security_patch_auto_config rm -f /data/adb/tricky_store/security_patch.txt || true
rm -f /data/adb/tricky_store/security_patch.txt `).then(({ errno }) => {
`); const result = errno === 0;
showPrompt('security_patch.value_empty'); showPrompt(result ? 'security_patch.value_empty' : 'security_patch.save_failed', result);
return true; return result;
} catch (error) { });
showPrompt('security_patch.save_failed', false);
return false;
}
} else if (mode === 'manual') { } else if (mode === 'manual') {
try { exec(`
await execCommand(` rm -f /data/adb/tricky_store/security_patch_auto_config || true
rm -f /data/adb/tricky_store/security_patch_auto_config
echo "${value}" > /data/adb/tricky_store/security_patch.txt echo "${value}" > /data/adb/tricky_store/security_patch.txt
chmod 644 /data/adb/tricky_store/security_patch.txt chmod 644 /data/adb/tricky_store/security_patch.txt
`); `).then(({ errno }) => {
showPrompt('security_patch.save_success'); const result = errno === 0;
return true; showPrompt(result ? 'security_patch.save_success' : 'security_patch.save_failed', result);
} catch (error) { return result;
showPrompt('security_patch.save_failed', false); });
return false;
}
} }
} }
@@ -57,17 +51,17 @@ async function handleSecurityPatch(mode, value = null) {
async function loadCurrentConfig() { async function loadCurrentConfig() {
let allValue, systemValue, bootValue, vendorValue; let allValue, systemValue, bootValue, vendorValue;
try { try {
const autoConfig = await execCommand('[ -f /data/adb/tricky_store/security_patch_auto_config ] && echo "true" || echo "false"'); const { errno } = await exec('[ -f /data/adb/tricky_store/security_patch_auto_config ]');
if (autoConfig.trim() === 'true') { if (errno === 0) {
allValue = null; allValue = null;
systemValue = null; systemValue = null;
bootValue = null; bootValue = null;
vendorValue = null; vendorValue = null;
} else { } else {
// Read values from tricky_store if auto_config is 0 // Read values from tricky_store if manual mode
const trickyResult = await execCommand('cat /data/adb/tricky_store/security_patch.txt'); const { stdout } = await exec('cat /data/adb/tricky_store/security_patch.txt');
if (trickyResult) { if (stdout.trim() !== '') {
const trickyLines = trickyResult.split('\n'); const trickyLines = stdout.split('\n');
for (const line of trickyLines) { for (const line of trickyLines) {
if (line.startsWith('all=')) { if (line.startsWith('all=')) {
allValue = line.split('=')[1] || null; allValue = line.split('=')[1] || null;
@@ -222,13 +216,13 @@ export function securityPatch() {
}); });
// Auto config button // Auto config button
autoButton.addEventListener('click', async () => { autoButton.addEventListener('click', () => {
try { exec(`sh ${basePath}/common/get_extra.sh --security-patch`)
const output = await execCommand(`sh ${basePath}/common/get_extra.sh --security-patch`); .then(({ errno, stdout }) => {
if (output.trim() === "not set") { if (errno !== 0 || stdout.trim() === "not set") {
showPrompt('security_patch.auto_failed', false); showPrompt('security_patch.auto_failed', false);
} else { } else {
await execCommand(`touch /data/adb/tricky_store/security_patch_auto_config`); exec(`touch /data/adb/tricky_store/security_patch_auto_config`)
// Reset inputs // Reset inputs
allPatchInput.value = ''; allPatchInput.value = '';
systemPatchInput.value = ''; systemPatchInput.value = '';
@@ -238,12 +232,10 @@ export function securityPatch() {
checkAdvanced(false); checkAdvanced(false);
showPrompt('security_patch.auto_success'); showPrompt('security_patch.auto_success');
} }
} catch (error) {
showPrompt('security_patch.auto_failed', false);
}
hideSecurityPatchDialog(); hideSecurityPatchDialog();
loadCurrentConfig(); loadCurrentConfig();
}); });
});
// Save button // Save button
saveButton.addEventListener('click', async () => { saveButton.addEventListener('click', async () => {
@@ -252,7 +244,7 @@ export function securityPatch() {
const allValue = allPatchInput.value.trim(); const allValue = allPatchInput.value.trim();
if (!allValue) { if (!allValue) {
// Save empty value to disable auto config // Save empty value to disable auto config
await handleSecurityPatch('disable'); handleSecurityPatch('disable');
hideSecurityPatchDialog(); hideSecurityPatchDialog();
return; return;
} }
@@ -261,7 +253,7 @@ export function securityPatch() {
return; return;
} }
const value = `all=${allValue}`; const value = `all=${allValue}`;
const result = await handleSecurityPatch('manual', value); const result = handleSecurityPatch('manual', value);
if (result) { if (result) {
// Reset inputs // Reset inputs
systemPatchInput.value = ''; systemPatchInput.value = '';
@@ -276,7 +268,7 @@ export function securityPatch() {
if (!bootValue && !systemValue && !vendorValue) { if (!bootValue && !systemValue && !vendorValue) {
// Save empty values to disable auto config // Save empty values to disable auto config
await handleSecurityPatch('disable'); handleSecurityPatch('disable');
hideSecurityPatchDialog(); hideSecurityPatchDialog();
return; return;
} }
@@ -302,7 +294,7 @@ export function securityPatch() {
vendorValue ? `vendor=${vendorValue}` : '' vendorValue ? `vendor=${vendorValue}` : ''
].filter(Boolean); ].filter(Boolean);
const value = config.filter(Boolean).join('\n'); const value = config.filter(Boolean).join('\n');
const result = await handleSecurityPatch('manual', value); const result = handleSecurityPatch('manual', value);
if (result) { if (result) {
// Reset inputs // Reset inputs
allPatchInput.value = ''; allPatchInput.value = '';
@@ -314,19 +306,22 @@ export function securityPatch() {
// Get button // Get button
getButton.addEventListener('click', async () => { getButton.addEventListener('click', async () => {
try {
showPrompt('security_patch.fetching'); showPrompt('security_patch.fetching');
await new Promise(resolve => setTimeout(resolve, 200)); setTimeout(() => {
const output = await execCommand(`sh ${basePath}/common/get_extra.sh --get-security-patch`); exec(`sh ${basePath}/common/get_extra.sh --get-security-patch`)
.then(({ errno, stdout }) => {
if (errno !== 0) {
showPrompt('security_patch.get_failed', false);
} else {
showPrompt('security_patch.fetched', true, 1000); showPrompt('security_patch.fetched', true, 1000);
checkAdvanced(true); checkAdvanced(true);
allPatchInput.value = output.replace(/-/g, ''); allPatchInput.value = stdout.replace(/-/g, '');
systemPatchInput.value = 'prop'; systemPatchInput.value = 'prop';
bootPatchInput.value = output; bootPatchInput.value = stdout;
vendorPatchInput.value = output; vendorPatchInput.value = stdout;
} catch (error) {
showPrompt('security_patch.get_failed', false);
} }
})
}, 200);
}); });
} }
+28 -29
View File
@@ -1,4 +1,4 @@
import { basePath, execCommand, showPrompt, noConnection, linkRedirect } from './main.js'; import { basePath, exec, showPrompt, noConnection, linkRedirect } from './main.js';
import { updateCard } from './applist.js'; import { updateCard } from './applist.js';
const updateMenu = document.querySelector('.update-overlay'); const updateMenu = document.querySelector('.update-overlay');
@@ -23,14 +23,12 @@ function downloadFile(targetURL, fileName) {
.then(blob => { .then(blob => {
const file = new File([blob], fileName, { type: blob.type }); const file = new File([blob], fileName, { type: blob.type });
const reader = new FileReader(); const reader = new FileReader();
reader.onload = async function() { reader.onload = () => {
const base64Data = reader.result.split(',')[1]; const base64Data = reader.result.split(',')[1];
try { exec(`echo ${base64Data} | base64 -d > ${basePath}/common/tmp/${fileName}`)
await execCommand(`echo ${base64Data} | base64 -d > ${basePath}/common/tmp/${fileName}`); .then(({ errno, stderr }) => {
resolve(); errno === 0 ? resolve() : reject(stderr);
} catch (error) { });
reject(error);
}
}; };
reader.readAsDataURL(file); reader.readAsDataURL(file);
}) })
@@ -53,8 +51,8 @@ export async function updateCheck() {
zipURL = data.zipUrl; zipURL = data.zipUrl;
changelogURL = data.changelog; changelogURL = data.changelog;
const updateAvailable = await execCommand(`sh ${basePath}/common/get_extra.sh --check-update ${remoteVersionCode}`); const { stdout } = await exec(`sh ${basePath}/common/get_extra.sh --check-update ${remoteVersionCode}`);
if (updateAvailable.includes("update")) { if (stdout.includes("update")) {
showPrompt("prompt.new_update", true, 1500); showPrompt("prompt.new_update", true, 1500);
updateCard.style.display = "flex"; updateCard.style.display = "flex";
setupUpdateMenu(); setupUpdateMenu();
@@ -67,8 +65,9 @@ export async function updateCheck() {
} }
// Function to render changelog // Function to render changelog
async function renderChangelog() { function renderChangelog() {
const changelog = await execCommand(`sh ${basePath}/common/get_extra.sh --release-note ${remoteVersion}`); exec(`sh ${basePath}/common/get_extra.sh --release-note ${remoteVersion}`)
.then(({ stdout }) => {
window.linkRedirect = linkRedirect; window.linkRedirect = linkRedirect;
marked.setOptions({ marked.setOptions({
sanitize: true, sanitize: true,
@@ -81,12 +80,13 @@ async function renderChangelog() {
} }
} }
}); });
const cleanedChangelog = changelog const cleanedChangelog = stdout
.split('\n') .split('\n')
.filter(line => line.trim() !== '') .filter(line => line.trim() !== '')
.join('\n'); .join('\n');
const formattedChangelog = marked.parse(cleanedChangelog); const formattedChangelog = marked.parse(cleanedChangelog);
releaseNotes.innerHTML = formattedChangelog; releaseNotes.innerHTML = formattedChangelog;
});
} }
// Function to setup update menu // Function to setup update menu
@@ -111,38 +111,37 @@ function setupUpdateMenu() {
// Update card // Update card
updateCard.addEventListener('click', async () => { updateCard.addEventListener('click', async () => {
try { try {
const module = await execCommand(` const { stdout } = await exec(`
[ -f ${basePath}/common/tmp/module.zip ] || echo "noModule" [ -f ${basePath}/common/tmp/module.zip ] || echo "noModule"
[ -f ${basePath}/common/tmp/changelog.md ] || echo "noChangelog" [ -f ${basePath}/common/tmp/changelog.md ] || echo "noChangelog"
[ ! -f /data/adb/modules/TA_utl/update ] || echo "updated" [ ! -f /data/adb/modules/TA_utl/update ] || echo "updated"
`); `);
if (module.trim().includes("updated")) { if (stdout.trim().includes("updated")) {
installButton.style.display = "none"; installButton.style.display = "none";
rebootButton.style.display = "flex"; rebootButton.style.display = "flex";
openUpdateMenu(); openUpdateMenu();
} else if (module.trim().includes("noChangelog")) { } else if (stdout.trim().includes("noChangelog")) {
showPrompt("prompt.downloading"); showPrompt("prompt.downloading");
await downloadFile(changelogURL, "changelog.md"); await downloadFile(changelogURL, "changelog.md");
await renderChangelog(); renderChangelog();
openUpdateMenu(); openUpdateMenu();
setTimeout(() => { setTimeout(() => {
updateCard.click(); updateCard.click();
}, 200); }, 200);
} else if (module.trim().includes("noModule")) { } else if (stdout.trim().includes("noModule")) {
if (downloading) return; if (downloading) return;
downloading = true; downloading = true;
try { const { errno } = await exec(`sh ${basePath}/common/get_extra.sh --get-update ${zipURL}`);
await execCommand(`sh ${basePath}/common/get_extra.sh --get-update ${zipURL}`); if (errno === 0) {
showPrompt("prompt.downloaded"); showPrompt("prompt.downloaded");
installButton.style.display = "flex"; installButton.style.display = "flex";
downloading = false; } else {
} catch (error) {
showPrompt("prompt.download_fail", false); showPrompt("prompt.download_fail", false);
downloading = false;
} }
downloading = false;
} else { } else {
installButton.style.display = "flex"; installButton.style.display = "flex";
await renderChangelog(); renderChangelog();
openUpdateMenu(); openUpdateMenu();
} }
} catch (error) { } catch (error) {
@@ -159,16 +158,16 @@ function setupUpdateMenu() {
// Install button // Install button
installButton.addEventListener('click', async () => { installButton.addEventListener('click', async () => {
try {
showPrompt("prompt.installing"); showPrompt("prompt.installing");
await new Promise(resolve => setTimeout(resolve, 300)); await new Promise(resolve => setTimeout(resolve, 300));
await execCommand(`sh ${basePath}/common/get_extra.sh --install-update`); const { errno, stderr } = await exec(`sh ${basePath}/common/get_extra.sh --install-update`);
if (errno === 0) {
showPrompt("prompt.installed"); showPrompt("prompt.installed");
installButton.style.display = "none"; installButton.style.display = "none";
rebootButton.style.display = "flex"; rebootButton.style.display = "flex";
} catch (error) { } else {
showPrompt("prompt.install_fail", false); showPrompt("prompt.install_fail", false);
console.error('Fail to execute installation script:', error); console.error('Fail to execute installation script:', stderr);
} }
}); });
@@ -177,7 +176,7 @@ function setupUpdateMenu() {
try { try {
showPrompt("prompt.rebooting"); showPrompt("prompt.rebooting");
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
await execCommand("svc power reboot"); await exec("svc power reboot");
} catch (error) { } catch (error) {
showPrompt("prompt.reboot_fail", false); showPrompt("prompt.reboot_fail", false);
console.error('Fail to reboot:', error); console.error('Fail to reboot:', error);
+3 -2
View File
@@ -59,8 +59,9 @@
} }
.update-content h3 { .update-content h3 {
font-size: 22px; font-size: 24px;
margin: 0; margin: 10px 0;
margin-top: 0;
} }
.changelog { .changelog {