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