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';
|
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
|
// Function to show about overlay
|
||||||
document.getElementById("about").addEventListener("click", () => {
|
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
|
// Show about menu
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.body.classList.add("no-scroll");
|
document.body.classList.add("no-scroll");
|
||||||
@@ -15,20 +15,20 @@ 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");
|
||||||
aboutOverlay.style.opacity = '0';
|
aboutOverlay.style.opacity = '0';
|
||||||
aboutContent.classList.remove('open');
|
aboutContent.classList.remove('open');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
aboutOverlay.style.display = 'none';
|
aboutOverlay.style.display = 'none';
|
||||||
}, 200);
|
}, 200);
|
||||||
};
|
};
|
||||||
|
|
||||||
closeAbout.addEventListener("click", hideMenu);
|
closeAbout.addEventListener("click", hideMenu);
|
||||||
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
|
||||||
|
|||||||
@@ -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);
|
||||||
toast("Failed to read target.txt!");
|
} else {
|
||||||
console.error("Failed to read target.txt file:", error);
|
toast("Failed to read target.txt!");
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 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" || true
|
||||||
[ -z "$SYSTEM_APP" ] || pm list packages -s | awk -F: '{print $2}' | grep -Ex "$SYSTEM_APP" 2>/dev/null || true
|
`);
|
||||||
`)
|
installedPackages = stdout.split("\n").map(line => line.trim()).filter(Boolean);
|
||||||
installedPackages = installedPackages.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 {
|
|
||||||
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"
|
|
||||||
`);
|
|
||||||
return {
|
return {
|
||||||
appName: appName.trim() || packageName,
|
appName: appNameMap[packageName],
|
||||||
packageName
|
packageName
|
||||||
};
|
};
|
||||||
}));
|
}
|
||||||
} catch (error) {
|
const { stdout: appName } = await exec(`
|
||||||
appEntries = appList.map(app => ({
|
base_apk=$(pm path ${packageName} | head -n1 | awk -F: '{print $2}')
|
||||||
appName: app.app_name,
|
aapt dump badging $base_apk 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g"
|
||||||
packageName: app.package_name
|
`, { env: { PATH: `$PATH:${basePath}/common:/data/data/com.termux/files/usr/bin` } });
|
||||||
}));
|
return {
|
||||||
}
|
appName: appName || packageName,
|
||||||
|
packageName
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
// Sort
|
// Sort
|
||||||
const sortedApps = appEntries.sort((a, b) => {
|
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 bootHashOverlay = document.getElementById('boot-hash-overlay');
|
||||||
const bootHash = document.querySelector('.boot-hash-card');
|
const bootHash = document.querySelector('.boot-hash-card');
|
||||||
@@ -20,50 +20,50 @@ document.getElementById("boot-hash").addEventListener("click", async () => {
|
|||||||
bootHash.classList.add('open');
|
bootHash.classList.add('open');
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
const closeBootHashMenu = () => {
|
// read current boot hash
|
||||||
document.body.classList.remove("no-scroll");
|
exec("cat /data/adb/boot_hash")
|
||||||
bootHashOverlay.style.opacity = 0;
|
.then(({ errno, stdout }) => {
|
||||||
bootHash.classList.remove('open');
|
if (errno !== 0) {
|
||||||
setTimeout(() => {
|
inputBox.value = "";
|
||||||
bootHashOverlay.style.display = "none";
|
} else {
|
||||||
}, 200);
|
const validHash = stdout
|
||||||
};
|
.split("\n")
|
||||||
try {
|
.filter(line => !line.startsWith("#") && line.trim())[0];
|
||||||
const bootHashContent = await execCommand("cat /data/adb/boot_hash");
|
inputBox.value = validHash || "";
|
||||||
const validHash = bootHashContent
|
}
|
||||||
.split("\n")
|
});
|
||||||
.filter(line => !line.startsWith("#") && line.trim())[0];
|
});
|
||||||
inputBox.value = validHash || "";
|
|
||||||
} catch (error) {
|
const closeBootHashMenu = () => {
|
||||||
console.warn("Failed to read boot_hash file. Defaulting to empty input.");
|
document.body.classList.remove("no-scroll");
|
||||||
inputBox.value = "";
|
bootHashOverlay.style.opacity = 0;
|
||||||
}
|
bootHash.classList.remove('open');
|
||||||
saveButton.addEventListener("click", async () => {
|
setTimeout(() => {
|
||||||
const inputValue = inputBox.value.trim();
|
bootHashOverlay.style.display = "none";
|
||||||
try {
|
}, 200);
|
||||||
await execCommand(`
|
};
|
||||||
PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH
|
|
||||||
resetprop -n ro.boot.vbmeta.digest ${inputValue}
|
// Save button listener
|
||||||
[ -z "${inputValue}" ] && rm -f /data/adb/boot_hash || {
|
saveButton.addEventListener("click", async () => {
|
||||||
echo "${inputValue}" > /data/adb/boot_hash
|
const inputValue = inputBox.value.trim();
|
||||||
chmod 644 /data/adb/boot_hash
|
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");
|
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) => {
|
|
||||||
if (event.target === bootHashOverlay) closeBootHashMenu();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Enter to save
|
bootHashOverlay.addEventListener("click", (event) => {
|
||||||
inputBox.addEventListener('keydown', (e) => {
|
if (event.target === bootHashOverlay) closeBootHashMenu();
|
||||||
if (e.key === 'Enter') {
|
});
|
||||||
saveButton.click();
|
|
||||||
}
|
// Enter to save
|
||||||
});
|
inputBox.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'Enter') saveButton.click();
|
||||||
});
|
});
|
||||||
@@ -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();
|
exec(`rm -f "${basePath}/common/tmp/exclude-list"`);
|
||||||
await execCommand(`[ -f ${basePath}/common/tmp/exclude-list ] && rm -f "${basePath}/common/tmp/exclude-list"`);
|
|
||||||
} catch (error) {
|
|
||||||
toast("Failed!");
|
|
||||||
console.error("Error occurred:", error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
await fetchAppList();
|
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 ]
|
||||||
[ "$TS_version" -ge 158 ] || echo "NO"
|
`).then(({ errno }) => {
|
||||||
`);
|
if (errno === 0) {
|
||||||
if (version.trim() !== "NO") securityPatchElement.style.display = "flex";
|
securityPatchElement.style.display = "flex";
|
||||||
} catch (error) {
|
} else {
|
||||||
toast("Failed to check Tricky Store version!");
|
console.log("Tricky Store version is lower than 158, or fail to check Tricky store version.");
|
||||||
console.error("Error while checking Tricky Store version:", error);
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,29 +125,30 @@ 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}!`;
|
} else if (appsWithQuestion.includes(app)) {
|
||||||
} else if (appsWithQuestion.includes(app)) {
|
return `${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
|
// 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) {
|
||||||
|
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 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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,25 +16,23 @@ 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)) {
|
app.querySelector(".checkbox").checked = true;
|
||||||
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
|
// 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!");
|
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));
|
||||||
const contentElement = app.querySelector(".content");
|
document.querySelectorAll(".card").forEach(app => {
|
||||||
const packageName = contentElement.getAttribute("data-package");
|
const contentElement = app.querySelector(".content");
|
||||||
const checkbox = app.querySelector(".checkbox");
|
const packageName = contentElement.getAttribute("data-package");
|
||||||
if (UnnecessaryApps.includes(packageName)) {
|
if (unnecessaryApps.includes(packageName)) {
|
||||||
checkbox.checked = false;
|
app.querySelector(".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,67 +111,58 @@ 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 {
|
stdout.split("\n").forEach(app => {
|
||||||
systemAppList.split("\n").forEach(app => {
|
if (app.trim() !== "") {
|
||||||
currentSystemAppListContent.innerHTML += `
|
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">
|
||||||
<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>
|
<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>
|
</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);
|
||||||
|
|||||||
@@ -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 }) => {
|
||||||
`);
|
const result = errno === 0;
|
||||||
showPrompt('security_patch.save_success');
|
showPrompt(result ? 'security_patch.save_success' : 'security_patch.save_failed', result);
|
||||||
return true;
|
return result;
|
||||||
} catch (error) {
|
});
|
||||||
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,27 +216,25 @@ 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 = '';
|
||||||
bootPatchInput.value = '';
|
bootPatchInput.value = '';
|
||||||
vendorPatchInput.value = '';
|
vendorPatchInput.value = '';
|
||||||
|
|
||||||
checkAdvanced(false);
|
checkAdvanced(false);
|
||||||
showPrompt('security_patch.auto_success');
|
showPrompt('security_patch.auto_success');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
hideSecurityPatchDialog();
|
||||||
showPrompt('security_patch.auto_failed', false);
|
loadCurrentConfig();
|
||||||
}
|
});
|
||||||
hideSecurityPatchDialog();
|
|
||||||
loadCurrentConfig();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save button
|
// Save button
|
||||||
@@ -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');
|
setTimeout(() => {
|
||||||
await new Promise(resolve => setTimeout(resolve, 200));
|
exec(`sh ${basePath}/common/get_extra.sh --get-security-patch`)
|
||||||
const output = await execCommand(`sh ${basePath}/common/get_extra.sh --get-security-patch`);
|
.then(({ errno, stdout }) => {
|
||||||
showPrompt('security_patch.fetched', true, 1000);
|
if (errno !== 0) {
|
||||||
checkAdvanced(true);
|
showPrompt('security_patch.get_failed', false);
|
||||||
|
} else {
|
||||||
|
showPrompt('security_patch.fetched', true, 1000);
|
||||||
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,26 +65,28 @@ 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}`)
|
||||||
window.linkRedirect = linkRedirect;
|
.then(({ stdout }) => {
|
||||||
marked.setOptions({
|
window.linkRedirect = linkRedirect;
|
||||||
sanitize: true,
|
marked.setOptions({
|
||||||
walkTokens(token) {
|
sanitize: true,
|
||||||
if (token.type === 'link') {
|
walkTokens(token) {
|
||||||
const href = token.href;
|
if (token.type === 'link') {
|
||||||
token.href = "javascript:void(0);";
|
const href = token.href;
|
||||||
token.type = "html";
|
token.href = "javascript:void(0);";
|
||||||
token.text = `<a href="javascript:void(0);" onclick="linkRedirect('${href}')">${token.text}</a>`;
|
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
|
// 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));
|
const { errno, stderr } = await exec(`sh ${basePath}/common/get_extra.sh --install-update`);
|
||||||
await execCommand(`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);
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user