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
opt: use ksu.spawn for long script
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This file is the backend of JavaScript
|
||||
|
||||
MODPATH=${0%/*}
|
||||
ORG_PATH="$PATH"
|
||||
SKIPLIST="$MODPATH/tmp/skiplist"
|
||||
@@ -17,13 +20,11 @@ aapt() { "$MODPATH/aapt" "$@"; }
|
||||
# wget = low pref, no ssl.
|
||||
# curl, has ssl on android, we use it if found
|
||||
download() {
|
||||
PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:/data/data/com.termux/files/usr/bin:$PATH
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
timeout 10 curl -Ls "$1"
|
||||
else
|
||||
timeout 10 busybox wget --no-check-certificate -qO- "$1"
|
||||
fi
|
||||
PATH="$ORG_PATH"
|
||||
}
|
||||
|
||||
get_xposed() {
|
||||
@@ -39,6 +40,19 @@ get_xposed() {
|
||||
cat "$XPOSED"
|
||||
}
|
||||
|
||||
get_applist() {
|
||||
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
|
||||
}
|
||||
|
||||
get_appname() {
|
||||
base_apk=$(pm path $package_name | head -n1 | awk -F: '{print $2}')
|
||||
app_name=$(aapt dump badging $base_apk 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g")
|
||||
[ -z "$app_name" ] && app_name="$package_name"
|
||||
echo "$app_name"
|
||||
}
|
||||
|
||||
check_update() {
|
||||
[ -f "$MODDIR/disable" ] && rm -f "$MODDIR/disable"
|
||||
LOCAL_VERSION=$(grep '^versionCode=' "$MODPATH/update/module.prop" | awk -F= '{print $2}')
|
||||
@@ -68,7 +82,6 @@ get_update() {
|
||||
}
|
||||
|
||||
install_update() {
|
||||
PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH
|
||||
if command -v magisk >/dev/null 2>&1; then
|
||||
magisk --install-module "$MODPATH/tmp/module.zip" || exit 1
|
||||
elif command -v apd >/dev/null 2>&1; then
|
||||
@@ -133,6 +146,15 @@ case "$1" in
|
||||
get_xposed
|
||||
exit
|
||||
;;
|
||||
--applist)
|
||||
get_applist
|
||||
exit
|
||||
;;
|
||||
--appname)
|
||||
package_name="$2"
|
||||
get_appname
|
||||
exit
|
||||
;;
|
||||
--check-update)
|
||||
REMOTE_VERSION="$2"
|
||||
check_update
|
||||
|
||||
@@ -1,41 +1,42 @@
|
||||
import { exec, toast } from './assets/kernelsu.js';
|
||||
import { basePath, hideFloatingBtn, appsWithExclamation, appsWithQuestion } from './main.js';
|
||||
import { exec, spawn, toast } from './assets/kernelsu.js';
|
||||
import { basePath, loadingIndicator, hideFloatingBtn, appsWithExclamation, appsWithQuestion, applyRippleEffect } from './main.js';
|
||||
|
||||
const appTemplate = document.getElementById('app-template').content;
|
||||
const modeOverlay = document.querySelector('.mode-overlay');
|
||||
export const appListContainer = document.getElementById('apps-list');
|
||||
export const updateCard = document.getElementById('update-card');
|
||||
|
||||
let targetList = [];
|
||||
|
||||
// Fetch and render applist
|
||||
export async function fetchAppList() {
|
||||
try {
|
||||
// fetch target list
|
||||
let targetList = [];
|
||||
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 target list
|
||||
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');
|
||||
const appList = await response.json();
|
||||
const appNameMap = appList.reduce((map, app) => {
|
||||
map[app.package_name] = app.app_name;
|
||||
return map;
|
||||
}, {});
|
||||
// Fetch cached applist
|
||||
const response = await fetch('applist.json');
|
||||
const appList = await response.json();
|
||||
const appNameMap = appList.reduce((map, app) => {
|
||||
map[app.package_name] = app.app_name;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
// Get installed packages first
|
||||
let appEntries = [], installedPackages = [];
|
||||
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);
|
||||
// Get installed packages
|
||||
let appEntries = [], installedPackages = [];
|
||||
const output = spawn('sh', [`${basePath}/common/get_extra.sh`, '--applist']);
|
||||
output.stdout.on('data', (data) => {
|
||||
if (data.trim() === "") return;
|
||||
installedPackages.push(data);
|
||||
});
|
||||
output.on('exit', async () => {
|
||||
// Create appEntries array contain { appName, packageName }
|
||||
appEntries = await Promise.all(installedPackages.map(async (packageName) => {
|
||||
if (appNameMap[packageName]) {
|
||||
return {
|
||||
@@ -43,76 +44,86 @@ export async function fetchAppList() {
|
||||
packageName
|
||||
};
|
||||
}
|
||||
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) => {
|
||||
const aChecked = targetList.includes(a.packageName);
|
||||
const bChecked = targetList.includes(b.packageName);
|
||||
if (aChecked !== bChecked) {
|
||||
return aChecked ? -1 : 1;
|
||||
}
|
||||
return (a.appName || "").localeCompare(b.appName || "");
|
||||
});
|
||||
|
||||
// Render
|
||||
appListContainer.innerHTML = "";
|
||||
sortedApps.forEach(({ appName, packageName }) => {
|
||||
const appElement = document.importNode(appTemplate, true);
|
||||
const contentElement = appElement.querySelector(".content");
|
||||
contentElement.setAttribute("data-package", packageName);
|
||||
|
||||
// Set unique names for radio button groups
|
||||
const radioButtons = appElement.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach((radio) => {
|
||||
radio.name = `mode-radio-${packageName}`;
|
||||
return new Promise((resolve) => {
|
||||
const output = spawn('sh', [`${basePath}/common/get_extra.sh`, '--appname', packageName],
|
||||
{ env: { PATH: `$PATH:${basePath}/common:/data/data/com.termux/files/usr/bin` } });
|
||||
output.stdout.on('data', (data) => {
|
||||
resolve({
|
||||
appName: data,
|
||||
packageName
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
renderAppList(appEntries);
|
||||
});
|
||||
}
|
||||
|
||||
// Preselect the radio button based on the package name
|
||||
const generateRadio = appElement.querySelector('#generate-mode');
|
||||
const hackRadio = appElement.querySelector('#hack-mode');
|
||||
const normalRadio = appElement.querySelector('#normal-mode');
|
||||
/**
|
||||
* Render processed app list to the UI
|
||||
* @param {Array} data - Array of objects containing appName and packageName
|
||||
* @returns {void}
|
||||
*/
|
||||
function renderAppList(data) {
|
||||
// Sort
|
||||
const sortedApps = data.sort((a, b) => {
|
||||
const aChecked = targetList.includes(a.packageName);
|
||||
const bChecked = targetList.includes(b.packageName);
|
||||
if (aChecked !== bChecked) {
|
||||
return aChecked ? -1 : 1;
|
||||
}
|
||||
return (a.appName || "").localeCompare(b.appName || "");
|
||||
});
|
||||
|
||||
if (appsWithExclamation.includes(packageName)) {
|
||||
generateRadio.checked = true;
|
||||
} else if (appsWithQuestion.includes(packageName)) {
|
||||
hackRadio.checked = true;
|
||||
} else {
|
||||
normalRadio.checked = true;
|
||||
}
|
||||
// Render
|
||||
appListContainer.innerHTML = "";
|
||||
sortedApps.forEach(({ appName, packageName }) => {
|
||||
const appElement = document.importNode(appTemplate, true);
|
||||
const contentElement = appElement.querySelector(".content");
|
||||
contentElement.setAttribute("data-package", packageName);
|
||||
|
||||
const nameElement = appElement.querySelector(".name");
|
||||
nameElement.innerHTML = `
|
||||
<div class="app-info">
|
||||
<div class="app-name"><strong>${appName}</strong></div>
|
||||
<div class="package-name">${packageName}</div>
|
||||
</div>
|
||||
`;
|
||||
const checkbox = appElement.querySelector(".checkbox");
|
||||
checkbox.checked = targetList.includes(packageName);
|
||||
appListContainer.appendChild(appElement);
|
||||
// Set unique names for radio button groups
|
||||
const radioButtons = appElement.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach((radio) => {
|
||||
radio.name = `mode-radio-${packageName}`;
|
||||
});
|
||||
} catch (error) {
|
||||
toast("Failed to fetch app list!");
|
||||
console.error("Failed to fetch or render app list with names:", error);
|
||||
}
|
||||
|
||||
// Preselect the radio button based on the package name
|
||||
const generateRadio = appElement.querySelector('#generate-mode');
|
||||
const hackRadio = appElement.querySelector('#hack-mode');
|
||||
const normalRadio = appElement.querySelector('#normal-mode');
|
||||
|
||||
if (appsWithExclamation.includes(packageName)) {
|
||||
generateRadio.checked = true;
|
||||
} else if (appsWithQuestion.includes(packageName)) {
|
||||
hackRadio.checked = true;
|
||||
} else {
|
||||
normalRadio.checked = true;
|
||||
}
|
||||
|
||||
const nameElement = appElement.querySelector(".name");
|
||||
nameElement.innerHTML = `
|
||||
<div class="app-info">
|
||||
<div class="app-name"><strong>${appName}</strong></div>
|
||||
<div class="package-name">${packageName}</div>
|
||||
</div>
|
||||
`;
|
||||
const checkbox = appElement.querySelector(".checkbox");
|
||||
checkbox.checked = targetList.includes(packageName);
|
||||
appListContainer.appendChild(appElement);
|
||||
});
|
||||
|
||||
loadingIndicator.style.display = "none";
|
||||
hideFloatingBtn(false);
|
||||
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
|
||||
toggleableCheckbox();
|
||||
if (appListContainer.firstChild !== updateCard) {
|
||||
appListContainer.insertBefore(updateCard, appListContainer.firstChild);
|
||||
}
|
||||
const checkboxes = appListContainer.querySelectorAll(".checkbox");
|
||||
setupRadioButtonListeners();
|
||||
setupModeMenu();
|
||||
updateCheckboxColor();
|
||||
applyRippleEffect();
|
||||
}
|
||||
|
||||
// Function to save app with ! and ? then process target list
|
||||
|
||||
@@ -41,6 +41,27 @@ export function exec(command, options = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard I/O stream for a child process.
|
||||
* @class
|
||||
*/
|
||||
class Stdio {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
on(event, listener) {
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
this.listeners[event].push(listener);
|
||||
}
|
||||
emit(event, ...args) {
|
||||
if (this.listeners[event]) {
|
||||
this.listeners[event].forEach(listener => listener(...args));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn shell process with ksu.spawn
|
||||
* @param {string} command - The command to execute
|
||||
@@ -71,20 +92,6 @@ export function spawn(command, args = [], options = {}) {
|
||||
}
|
||||
}
|
||||
};
|
||||
function Stdio() {
|
||||
this.listeners = {};
|
||||
}
|
||||
Stdio.prototype.on = function(event, listener) {
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
this.listeners[event].push(listener);
|
||||
};
|
||||
Stdio.prototype.emit = function(event, ...args) {
|
||||
if (this.listeners[event]) {
|
||||
this.listeners[event].forEach(listener => listener(...args));
|
||||
}
|
||||
};
|
||||
const callbackName = getUniqueCallbackName("spawn");
|
||||
window[callbackName] = child;
|
||||
child.on("exit", () => delete window[callbackName]);
|
||||
|
||||
@@ -22,14 +22,12 @@ document.getElementById("boot-hash").addEventListener("click", async () => {
|
||||
}, 10);
|
||||
|
||||
// read current boot hash
|
||||
exec("cat /data/adb/boot_hash")
|
||||
exec(`sed '/^#/d; /^$/d' /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];
|
||||
const validHash = stdout.trim();
|
||||
inputBox.value = validHash || "";
|
||||
}
|
||||
});
|
||||
@@ -48,7 +46,7 @@ const closeBootHashMenu = () => {
|
||||
saveButton.addEventListener("click", async () => {
|
||||
const inputValue = inputBox.value.trim();
|
||||
exec(`
|
||||
resetprop -n ro.boot.vbmeta.digest ${inputValue}
|
||||
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
|
||||
|
||||
@@ -11,7 +11,7 @@ const title = document.querySelector('.header');
|
||||
export const noConnection = document.querySelector('.no-connection');
|
||||
|
||||
// Loading, Save and Prompt Elements
|
||||
const loadingIndicator = document.querySelector('.loading');
|
||||
export const loadingIndicator = document.querySelector('.loading');
|
||||
const prompt = document.getElementById('prompt');
|
||||
const floatingCard = document.querySelector('.floating-card');
|
||||
const floatingBtn = document.querySelector('.floating-btn');
|
||||
@@ -50,16 +50,12 @@ export async function refreshAppList() {
|
||||
appListContainer.innerHTML = '';
|
||||
loadingIndicator.style.display = 'flex';
|
||||
document.querySelector('.uninstall-container').classList.add('hidden-uninstall');
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
window.scrollTo(0, 0);
|
||||
if (noConnection.style.display === "flex") {
|
||||
updateCheck();
|
||||
exec(`rm -f "${basePath}/common/tmp/exclude-list"`);
|
||||
}
|
||||
await fetchAppList();
|
||||
applyRippleEffect();
|
||||
loadingIndicator.style.display = 'none';
|
||||
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
|
||||
fetchAppList();
|
||||
isRefreshing = false;
|
||||
}
|
||||
|
||||
@@ -201,7 +197,10 @@ function checkMMRL() {
|
||||
|
||||
// Funtion to adapt floating button hide in MMRL
|
||||
export function hideFloatingBtn(hide = true) {
|
||||
if (!hide) floatingCard.style.transform = 'translateY(0)';
|
||||
if (!hide) {
|
||||
floatingCard.style.transform = 'translateY(0)';
|
||||
floatingBtn.style.display = 'block';
|
||||
}
|
||||
else floatingCard.style.transform = 'translateY(calc(var(--window-inset-bottom, 0px) + 120px))';
|
||||
}
|
||||
|
||||
@@ -299,15 +298,10 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
setupMenuToggle();
|
||||
setupLanguageMenu();
|
||||
setupSystemAppMenu();
|
||||
await fetchAppList();
|
||||
applyRippleEffect();
|
||||
fetchAppList();
|
||||
checkTrickyStoreVersion();
|
||||
checkMagisk();
|
||||
updateCheck();
|
||||
securityPatch();
|
||||
loadingIndicator.style.display = "none";
|
||||
floatingBtn.style.display = 'block';
|
||||
hideFloatingBtn(false);
|
||||
document.getElementById("refresh").addEventListener("click", refreshAppList);
|
||||
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { exec } from './assets/kernelsu.js';
|
||||
import { exec, spawn } from './assets/kernelsu.js';
|
||||
import { basePath, showPrompt } from './main.js';
|
||||
|
||||
const overlay = document.getElementById('security-patch-overlay');
|
||||
@@ -218,24 +218,29 @@ export function securityPatch() {
|
||||
|
||||
// Auto config button
|
||||
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 = '';
|
||||
const output = spawn('sh', [`${basePath}/common/get_extra.sh`, '--security-patch']);
|
||||
output.stdout.on('data', (data) => {
|
||||
if (data.includes("not set")) {
|
||||
showPrompt('security_patch.auto_failed', false);
|
||||
}
|
||||
});
|
||||
output.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
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');
|
||||
}
|
||||
hideSecurityPatchDialog();
|
||||
loadCurrentConfig();
|
||||
});
|
||||
checkAdvanced(false);
|
||||
showPrompt('security_patch.auto_success');
|
||||
} else {
|
||||
showPrompt('security_patch.auto_failed', false);
|
||||
}
|
||||
hideSecurityPatchDialog();
|
||||
loadCurrentConfig();
|
||||
});
|
||||
});
|
||||
|
||||
// Save button
|
||||
@@ -308,21 +313,18 @@ export function securityPatch() {
|
||||
// Get button
|
||||
getButton.addEventListener('click', async () => {
|
||||
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);
|
||||
const output = spawn('sh', [`${basePath}/common/get_extra.sh`, '--get-security-patch']);
|
||||
output.stdout.on('data', (data) => {
|
||||
showPrompt('security_patch.fetched', true, 1000);
|
||||
checkAdvanced(true);
|
||||
|
||||
allPatchInput.value = stdout.replace(/-/g, '');
|
||||
systemPatchInput.value = 'prop';
|
||||
bootPatchInput.value = stdout;
|
||||
vendorPatchInput.value = stdout;
|
||||
}
|
||||
})
|
||||
}, 200);
|
||||
allPatchInput.value = data.replace(/-/g, '');
|
||||
systemPatchInput.value = 'prop';
|
||||
bootPatchInput.value = data;
|
||||
vendorPatchInput.value = data;
|
||||
});
|
||||
output.on('exit', (code) => {
|
||||
if (code !== 0) showPrompt('security_patch.get_failed', false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { exec } from './assets/kernelsu.js';
|
||||
import { exec, spawn } from './assets/kernelsu.js';
|
||||
import { basePath, showPrompt, noConnection, linkRedirect } from './main.js';
|
||||
import { updateCard } from './applist.js';
|
||||
|
||||
@@ -52,12 +52,14 @@ export async function updateCheck() {
|
||||
zipURL = data.zipUrl;
|
||||
changelogURL = data.changelog;
|
||||
|
||||
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();
|
||||
}
|
||||
const output = spawn('sh', [`${basePath}/common/get_extra.sh`, '--check-update', `${remoteVersionCode}`]);
|
||||
output.stdout.on('data', (data) => {
|
||||
if (data.includes("update")) {
|
||||
showPrompt("prompt.new_update", true, 1500);
|
||||
updateCard.style.display = "flex";
|
||||
setupUpdateMenu();
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching JSON or executing command:", error);
|
||||
showPrompt("prompt.no_internet", false);
|
||||
@@ -111,43 +113,41 @@ function setupUpdateMenu() {
|
||||
|
||||
// Update card
|
||||
updateCard.addEventListener('click', async () => {
|
||||
try {
|
||||
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 (stdout.trim().includes("updated")) {
|
||||
installButton.style.display = "none";
|
||||
rebootButton.style.display = "flex";
|
||||
openUpdateMenu();
|
||||
} else if (stdout.trim().includes("noChangelog")) {
|
||||
showPrompt("prompt.downloading");
|
||||
await downloadFile(changelogURL, "changelog.md");
|
||||
renderChangelog();
|
||||
openUpdateMenu();
|
||||
setTimeout(() => {
|
||||
updateCard.click();
|
||||
}, 200);
|
||||
} else if (stdout.trim().includes("noModule")) {
|
||||
if (downloading) return;
|
||||
downloading = true;
|
||||
const { errno } = await exec(`sh ${basePath}/common/get_extra.sh --get-update ${zipURL}`);
|
||||
if (errno === 0) {
|
||||
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 (stdout.trim().includes("updated")) {
|
||||
installButton.style.display = "none";
|
||||
rebootButton.style.display = "flex";
|
||||
openUpdateMenu();
|
||||
} else if (stdout.trim().includes("noChangelog")) {
|
||||
showPrompt("prompt.downloading");
|
||||
await downloadFile(changelogURL, "changelog.md");
|
||||
renderChangelog();
|
||||
openUpdateMenu();
|
||||
setTimeout(() => {
|
||||
updateCard.click();
|
||||
}, 200);
|
||||
} else if (stdout.trim().includes("noModule")) {
|
||||
if (downloading) return;
|
||||
downloading = true;
|
||||
const download = spawn('sh', [`${basePath}/common/get_extra.sh`, '--get-update', `${zipURL}`],
|
||||
{ env: { PATH: "$PATH:/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:/data/data/com.termux/files/usr/bin" } });
|
||||
download.on('exit', (code) => {
|
||||
downloading = false;
|
||||
if (code === 0) {
|
||||
showPrompt("prompt.downloaded");
|
||||
installButton.style.display = "flex";
|
||||
} else {
|
||||
showPrompt("prompt.download_fail", false);
|
||||
}
|
||||
downloading = false;
|
||||
} else {
|
||||
installButton.style.display = "flex";
|
||||
renderChangelog();
|
||||
openUpdateMenu();
|
||||
}
|
||||
} catch (error) {
|
||||
showPrompt("prompt.download_fail", false);
|
||||
console.error('Error download module update:', error);
|
||||
});
|
||||
} else {
|
||||
installButton.style.display = "flex";
|
||||
renderChangelog();
|
||||
openUpdateMenu();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -160,16 +160,20 @@ function setupUpdateMenu() {
|
||||
// Install button
|
||||
installButton.addEventListener('click', async () => {
|
||||
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";
|
||||
} else {
|
||||
showPrompt("prompt.install_fail", false);
|
||||
console.error('Fail to execute installation script:', stderr);
|
||||
}
|
||||
const output = spawn('sh', [`${basePath}/common/get_extra.sh`, '--install-update'],
|
||||
{ env: { PATH: "$PATH:/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk" } });
|
||||
output.stderr.on('data', (data) => {
|
||||
console.error('Error during installation:', data);
|
||||
})
|
||||
output.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
showPrompt("prompt.installed");
|
||||
installButton.style.display = "none";
|
||||
rebootButton.style.display = "flex";
|
||||
} else {
|
||||
showPrompt("prompt.install_fail", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Reboot button
|
||||
|
||||
@@ -58,12 +58,16 @@
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.update-content h1,
|
||||
.update-content h3 {
|
||||
font-size: 24px;
|
||||
margin: 10px 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.update-content h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.changelog {
|
||||
max-height: 65vh;
|
||||
overflow-y: auto;
|
||||
|
||||
Reference in New Issue
Block a user