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
Cleanup, rearrange code
This commit is contained in:
+323
-340
@@ -7,12 +7,10 @@ const languageMenu = document.querySelector('.language-menu');
|
|||||||
const languageOptions = document.querySelectorAll('.language-option');
|
const languageOptions = document.querySelectorAll('.language-option');
|
||||||
const languageOverlay = document.getElementById('language-overlay');
|
const languageOverlay = document.getElementById('language-overlay');
|
||||||
|
|
||||||
// Loading and Prompt Elements
|
// Help Overlay Elements
|
||||||
const loadingIndicator = document.querySelector('.loading');
|
const helpOverlay = document.getElementById('help-overlay');
|
||||||
const prompt = document.getElementById('prompt');
|
const closeHelp = document.getElementById('close-help');
|
||||||
|
const helpList = document.getElementById('help-list');
|
||||||
// Floating Button
|
|
||||||
const floatingBtn = document.querySelector('.floating-btn');
|
|
||||||
|
|
||||||
// Search and Menu Elements
|
// Search and Menu Elements
|
||||||
const searchInput = document.getElementById('search');
|
const searchInput = document.getElementById('search');
|
||||||
@@ -24,15 +22,7 @@ const menuButton = document.getElementById('menu-button');
|
|||||||
const menuOptions = document.getElementById('menu-options');
|
const menuOptions = document.getElementById('menu-options');
|
||||||
const selectDenylistElement = document.getElementById('select-denylist');
|
const selectDenylistElement = document.getElementById('select-denylist');
|
||||||
const menuOverlay = document.getElementById('menu-overlay');
|
const menuOverlay = document.getElementById('menu-overlay');
|
||||||
|
const menuIcon = menuButton.querySelector('.menu-icon');
|
||||||
// Applist Elements
|
|
||||||
const appTemplate = document.getElementById('app-template').content;
|
|
||||||
const appListContainer = document.getElementById('apps-list');
|
|
||||||
|
|
||||||
// Help Overlay Elements
|
|
||||||
const helpOverlay = document.getElementById('help-overlay');
|
|
||||||
const closeHelp = document.getElementById('close-help');
|
|
||||||
const helpList = document.getElementById('help-list');
|
|
||||||
|
|
||||||
// BootHash Overlay Elements
|
// BootHash Overlay Elements
|
||||||
const bootHashOverlay = document.getElementById('boot-hash-overlay');
|
const bootHashOverlay = document.getElementById('boot-hash-overlay');
|
||||||
@@ -40,6 +30,15 @@ const card = document.getElementById('boot-hash-card');
|
|||||||
const inputBox = document.getElementById('boot-hash-input');
|
const inputBox = document.getElementById('boot-hash-input');
|
||||||
const saveButton = document.getElementById('boot-hash-save-button');
|
const saveButton = document.getElementById('boot-hash-save-button');
|
||||||
|
|
||||||
|
// Applist Elements
|
||||||
|
const appTemplate = document.getElementById('app-template').content;
|
||||||
|
const appListContainer = document.getElementById('apps-list');
|
||||||
|
|
||||||
|
// Loading, Save and Prompt Elements
|
||||||
|
const loadingIndicator = document.querySelector('.loading');
|
||||||
|
const floatingBtn = document.querySelector('.floating-btn');
|
||||||
|
const prompt = document.getElementById('prompt');
|
||||||
|
|
||||||
const basePath = "set-path";
|
const basePath = "set-path";
|
||||||
const ADDITIONAL_APPS = [
|
const ADDITIONAL_APPS = [
|
||||||
"com.google.android.gms",
|
"com.google.android.gms",
|
||||||
@@ -109,6 +108,74 @@ document.querySelectorAll(".language-option").forEach((button) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Function to setup the language menu
|
||||||
|
function setupLanguageMenu() {
|
||||||
|
languageButton.addEventListener("click", (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
const isVisible = languageMenu.classList.contains("show");
|
||||||
|
if (isVisible) {
|
||||||
|
closeLanguageMenu();
|
||||||
|
} else {
|
||||||
|
openLanguageMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.addEventListener("click", (event) => {
|
||||||
|
if (!languageButton.contains(event.target) && !languageMenu.contains(event.target)) {
|
||||||
|
closeLanguageMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
languageOptions.forEach(option => {
|
||||||
|
option.addEventListener("click", () => {
|
||||||
|
closeLanguageMenu();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
window.addEventListener('scroll', () => {
|
||||||
|
if (languageMenu.classList.contains("show")) {
|
||||||
|
closeLanguageMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function openLanguageMenu() {
|
||||||
|
languageMenu.classList.add("show");
|
||||||
|
languageOverlay.style.display = 'flex';
|
||||||
|
}
|
||||||
|
function closeLanguageMenu() {
|
||||||
|
languageMenu.classList.remove("show");
|
||||||
|
languageOverlay.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus on search input when search card is clicked
|
||||||
|
searchCard.addEventListener("click", () => {
|
||||||
|
searchInput.focus();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Search functionality
|
||||||
|
searchInput.addEventListener("input", (e) => {
|
||||||
|
const searchQuery = e.target.value.toLowerCase();
|
||||||
|
const apps = appListContainer.querySelectorAll(".card");
|
||||||
|
apps.forEach(app => {
|
||||||
|
const name = app.querySelector(".name").textContent.toLowerCase();
|
||||||
|
app.style.display = name.includes(searchQuery) ? "block" : "none";
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
});
|
||||||
|
if (searchQuery !== "") {
|
||||||
|
clearBtn.style.display = "block";
|
||||||
|
} else {
|
||||||
|
clearBtn.style.display = "none";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear search input
|
||||||
|
clearBtn.addEventListener("click", () => {
|
||||||
|
searchInput.value = "";
|
||||||
|
clearBtn.style.display = "none";
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
const apps = appListContainer.querySelectorAll(".card");
|
||||||
|
apps.forEach(app => {
|
||||||
|
app.style.display = "block";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Function to dynamically update the help menu
|
// Function to dynamically update the help menu
|
||||||
function updateHelpMenu() {
|
function updateHelpMenu() {
|
||||||
helpList.innerHTML = "";
|
helpList.innerHTML = "";
|
||||||
@@ -136,126 +203,90 @@ function updateHelpMenu() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to execute shell commands
|
// Function to setup the help menu
|
||||||
async function execCommand(command) {
|
function setupHelpOverlay() {
|
||||||
return new Promise((resolve, reject) => {
|
helpButton.addEventListener("click", () => {
|
||||||
const callbackName = `exec_callback_${Date.now()}_${e++}`;
|
helpOverlay.classList.remove("hide");
|
||||||
window[callbackName] = (errno, stdout, stderr) => {
|
helpOverlay.style.display = "flex";
|
||||||
delete window[callbackName];
|
requestAnimationFrame(() => {
|
||||||
if (errno === 0) {
|
helpOverlay.classList.add("show");
|
||||||
resolve(stdout);
|
});
|
||||||
} else {
|
document.body.classList.add("no-scroll");
|
||||||
console.error(`Error executing command: ${stderr}`);
|
});
|
||||||
reject(stderr);
|
const hideHelpOverlay = () => {
|
||||||
}
|
helpOverlay.classList.remove("show");
|
||||||
|
helpOverlay.classList.add("hide");
|
||||||
|
document.body.classList.remove("no-scroll");
|
||||||
|
setTimeout(() => {
|
||||||
|
helpOverlay.style.display = "none";
|
||||||
|
}, 200);
|
||||||
};
|
};
|
||||||
try {
|
closeHelp.addEventListener("click", hideHelpOverlay);
|
||||||
ksu.exec(command, "{}", callbackName);
|
helpOverlay.addEventListener("click", (event) => {
|
||||||
} catch (error) {
|
if (event.target === helpOverlay) {
|
||||||
console.error(`Execution error: ${error}`);
|
hideHelpOverlay();
|
||||||
reject(error);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch and render applist
|
// Function to toggle menu option
|
||||||
async function fetchAppList() {
|
function setupMenuToggle() {
|
||||||
try {
|
let menuOpen = false;
|
||||||
let targetList = [];
|
let menuAnimating = false;
|
||||||
try {
|
menuButton.addEventListener('click', (event) => {
|
||||||
const targetFileContent = await execCommand('cat /data/adb/tricky_store/target.txt');
|
if (menuAnimating) return;
|
||||||
targetList = targetFileContent.split("\n").filter(app => app.trim() !== ''); // Filter out empty lines
|
event.stopPropagation();
|
||||||
console.log("Current target list:", targetList);
|
if (menuOptions.classList.contains('visible')) {
|
||||||
} catch (error) {
|
closeMenu();
|
||||||
console.error("Failed to read target.txt file:", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
let applistMap = {};
|
|
||||||
try {
|
|
||||||
const applistResult = await execCommand(`cat ${basePath}applist`);
|
|
||||||
applistMap = applistResult
|
|
||||||
.split("\n")
|
|
||||||
.reduce((map, line) => {
|
|
||||||
const match = line.match(/app-name:\s*(.+),\s*package-name:\s*(.+)/);
|
|
||||||
if (match) {
|
|
||||||
const appName = match[1].trim();
|
|
||||||
const packageName = match[2].trim();
|
|
||||||
map[packageName] = appName;
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}, {});
|
|
||||||
console.log("Applist loaded successfully.");
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Applist file not found or could not be loaded. Skipping applist lookup.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await execCommand("pm list packages -3");
|
|
||||||
const appEntries = result
|
|
||||||
.split("\n")
|
|
||||||
.map(line => {
|
|
||||||
const packageName = line.replace("package:", "").trim();
|
|
||||||
const appName = applistMap[packageName] || null;
|
|
||||||
return { appName, packageName };
|
|
||||||
})
|
|
||||||
.filter(entry => entry.packageName);
|
|
||||||
for (const entry of appEntries) {
|
|
||||||
if (!entry.appName) {
|
|
||||||
try {
|
|
||||||
const apkPath = await execCommand(`pm path ${entry.packageName} | grep "base.apk" | awk -F: '{print $2}' | tr -d '\\r'`);
|
|
||||||
if (apkPath) {
|
|
||||||
const appName = await execCommand(`${basePath}aapt dump badging ${apkPath.trim()} 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g"`);
|
|
||||||
entry.appName = appName.trim() || "Unknown App";
|
|
||||||
} else {
|
} else {
|
||||||
entry.appName = "Unknown App";
|
openMenu();
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
entry.appName = "Unknown App";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
const nameElement = appElement.querySelector(".name");
|
|
||||||
nameElement.innerHTML = `<strong>${appName || "Unknown App"}</strong><br>${packageName}`;
|
|
||||||
const checkbox = appElement.querySelector(".checkbox");
|
|
||||||
checkbox.checked = targetList.includes(packageName);
|
|
||||||
appListContainer.appendChild(appElement);
|
|
||||||
});
|
|
||||||
console.log("App list with names and packages rendered successfully.");
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to fetch or render app list with names:", error);
|
|
||||||
}
|
|
||||||
floatingBtn.style.transform = "translateY(-120px)";
|
|
||||||
toggleableCheckbox();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make checkboxes toggleable
|
|
||||||
function toggleableCheckbox() {
|
|
||||||
const appElements = appListContainer.querySelectorAll(".card");
|
|
||||||
appElements.forEach(card => {
|
|
||||||
const content = card.querySelector(".content");
|
|
||||||
const checkbox = content.querySelector(".checkbox");
|
|
||||||
content.addEventListener("click", (event) => {
|
|
||||||
if (event.target !== checkbox) {
|
|
||||||
checkbox.checked = !checkbox.checked;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
document.addEventListener('click', (event) => {
|
||||||
|
if (!menuOptions.contains(event.target) && event.target !== menuButton) {
|
||||||
|
closeMenu();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
window.addEventListener('scroll', () => {
|
||||||
|
if (menuOptions.classList.contains('visible')) {
|
||||||
|
closeMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const menuOptionsList = document.querySelectorAll('#menu-options li');
|
||||||
|
menuOptionsList.forEach(option => {
|
||||||
|
option.addEventListener('click', (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
closeMenu();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
function openMenu() {
|
||||||
|
menuAnimating = true;
|
||||||
|
menuOptions.style.display = 'block';
|
||||||
|
setTimeout(() => {
|
||||||
|
menuOptions.classList.remove('hidden');
|
||||||
|
menuOptions.classList.add('visible');
|
||||||
|
menuIcon.classList.add('menu-open');
|
||||||
|
menuIcon.classList.remove('menu-closed');
|
||||||
|
menuOverlay.style.display = 'flex';
|
||||||
|
menuOpen = true;
|
||||||
|
menuAnimating = false;
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
function closeMenu() {
|
||||||
|
if (menuOptions.classList.contains('visible')) {
|
||||||
|
menuAnimating = true;
|
||||||
|
menuOptions.classList.remove('visible');
|
||||||
|
menuOptions.classList.add('hidden');
|
||||||
|
menuIcon.classList.remove('menu-open');
|
||||||
|
menuIcon.classList.add('menu-closed');
|
||||||
|
menuOverlay.style.display = 'none';
|
||||||
|
setTimeout(() => {
|
||||||
|
menuOptions.style.display = 'none';
|
||||||
|
menuOpen = false;
|
||||||
|
menuAnimating = false;
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to refresh app list
|
// Function to refresh app list
|
||||||
@@ -422,6 +453,7 @@ async function extrakb() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Function to handle Verified Boot Hash
|
// Function to handle Verified Boot Hash
|
||||||
async function setBootHash() {
|
async function setBootHash() {
|
||||||
const showCard = () => {
|
const showCard = () => {
|
||||||
@@ -473,19 +505,19 @@ async function setBootHash() {
|
|||||||
// Function to show about overlay
|
// Function to show about overlay
|
||||||
function aboutMenu() {
|
function aboutMenu() {
|
||||||
const aboutOverlay = document.getElementById('about-overlay');
|
const aboutOverlay = document.getElementById('about-overlay');
|
||||||
const menu = document.getElementById('about-menu');
|
const aboutMenu = document.getElementById('about-menu');
|
||||||
const closeAbout = document.getElementById('close-about');
|
const closeAbout = document.getElementById('close-about');
|
||||||
const showMenu = () => {
|
const showMenu = () => {
|
||||||
aboutOverlay.style.display = 'flex';
|
aboutOverlay.style.display = 'flex';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
aboutOverlay.style.opacity = '1';
|
aboutOverlay.style.opacity = '1';
|
||||||
menu.style.opacity = '1';
|
aboutMenu.style.opacity = '1';
|
||||||
}, 10);
|
}, 10);
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
};
|
};
|
||||||
const hideMenu = () => {
|
const hideMenu = () => {
|
||||||
aboutOverlay.style.opacity = '0';
|
aboutOverlay.style.opacity = '0';
|
||||||
menu.style.opacity = '0';
|
aboutMenu.style.opacity = '0';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
aboutOverlay.style.display = 'none';
|
aboutOverlay.style.display = 'none';
|
||||||
document.body.style.overflow = 'auto';
|
document.body.style.overflow = 'auto';
|
||||||
@@ -504,6 +536,106 @@ function aboutMenu() {
|
|||||||
menu.addEventListener('click', (event) => event.stopPropagation());
|
menu.addEventListener('click', (event) => event.stopPropagation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch and render applist
|
||||||
|
async function fetchAppList() {
|
||||||
|
try {
|
||||||
|
let targetList = [];
|
||||||
|
try {
|
||||||
|
const targetFileContent = await execCommand('cat /data/adb/tricky_store/target.txt');
|
||||||
|
targetList = targetFileContent.split("\n").filter(app => app.trim() !== ''); // Filter out empty lines
|
||||||
|
console.log("Current target list:", targetList);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to read target.txt file:", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
let applistMap = {};
|
||||||
|
try {
|
||||||
|
const applistResult = await execCommand(`cat ${basePath}applist`);
|
||||||
|
applistMap = applistResult
|
||||||
|
.split("\n")
|
||||||
|
.reduce((map, line) => {
|
||||||
|
const match = line.match(/app-name:\s*(.+),\s*package-name:\s*(.+)/);
|
||||||
|
if (match) {
|
||||||
|
const appName = match[1].trim();
|
||||||
|
const packageName = match[2].trim();
|
||||||
|
map[packageName] = appName;
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}, {});
|
||||||
|
console.log("Applist loaded successfully.");
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Applist file not found or could not be loaded. Skipping applist lookup.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await execCommand("pm list packages -3");
|
||||||
|
const appEntries = result
|
||||||
|
.split("\n")
|
||||||
|
.map(line => {
|
||||||
|
const packageName = line.replace("package:", "").trim();
|
||||||
|
const appName = applistMap[packageName] || null;
|
||||||
|
return { appName, packageName };
|
||||||
|
})
|
||||||
|
.filter(entry => entry.packageName);
|
||||||
|
for (const entry of appEntries) {
|
||||||
|
if (!entry.appName) {
|
||||||
|
try {
|
||||||
|
const apkPath = await execCommand(`pm path ${entry.packageName} | grep "base.apk" | awk -F: '{print $2}' | tr -d '\\r'`);
|
||||||
|
if (apkPath) {
|
||||||
|
const appName = await execCommand(`${basePath}aapt dump badging ${apkPath.trim()} 2>/dev/null | grep "application-label:" | sed "s/application-label://; s/'//g"`);
|
||||||
|
entry.appName = appName.trim() || "Unknown App";
|
||||||
|
} else {
|
||||||
|
entry.appName = "Unknown App";
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
entry.appName = "Unknown App";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
const nameElement = appElement.querySelector(".name");
|
||||||
|
nameElement.innerHTML = `<strong>${appName || "Unknown App"}</strong><br>${packageName}`;
|
||||||
|
const checkbox = appElement.querySelector(".checkbox");
|
||||||
|
checkbox.checked = targetList.includes(packageName);
|
||||||
|
appListContainer.appendChild(appElement);
|
||||||
|
});
|
||||||
|
console.log("App list with names and packages rendered successfully.");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch or render app list with names:", error);
|
||||||
|
}
|
||||||
|
floatingBtn.style.transform = "translateY(-120px)";
|
||||||
|
toggleableCheckbox();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make checkboxes toggleable
|
||||||
|
function toggleableCheckbox() {
|
||||||
|
const appElements = appListContainer.querySelectorAll(".card");
|
||||||
|
appElements.forEach(card => {
|
||||||
|
const content = card.querySelector(".content");
|
||||||
|
const checkbox = content.querySelector(".checkbox");
|
||||||
|
content.addEventListener("click", (event) => {
|
||||||
|
if (event.target !== checkbox) {
|
||||||
|
checkbox.checked = !checkbox.checked;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Function to show the prompt with a success or error message
|
// Function to show the prompt with a success or error message
|
||||||
function showPrompt(key, isSuccess = true) {
|
function showPrompt(key, isSuccess = true) {
|
||||||
const message = translations[key] || key;
|
const message = translations[key] || key;
|
||||||
@@ -522,150 +654,6 @@ function showPrompt(key, isSuccess = true) {
|
|||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to toggle menu option
|
|
||||||
function setupMenuToggle() {
|
|
||||||
const menuIcon = menuButton.querySelector('.menu-icon');
|
|
||||||
const menuOptions = document.getElementById('menu-options');
|
|
||||||
let menuOpen = false;
|
|
||||||
let menuAnimating = false;
|
|
||||||
|
|
||||||
menuButton.addEventListener('click', (event) => {
|
|
||||||
if (menuAnimating) return;
|
|
||||||
event.stopPropagation();
|
|
||||||
if (menuOptions.classList.contains('visible')) {
|
|
||||||
closeMenu();
|
|
||||||
} else {
|
|
||||||
openMenu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener('click', (event) => {
|
|
||||||
if (!menuOptions.contains(event.target) && event.target !== menuButton) {
|
|
||||||
closeMenu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('scroll', () => {
|
|
||||||
if (menuOptions.classList.contains('visible')) {
|
|
||||||
closeMenu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const closeMenuItems = ['refresh', 'select-all', 'deselect-all', 'select-denylist', 'deselect-unnecessary', 'aospkb', 'extrakb', 'boot-hash', 'about'];
|
|
||||||
closeMenuItems.forEach(id => {
|
|
||||||
const item = document.getElementById(id);
|
|
||||||
if (item) {
|
|
||||||
item.addEventListener('click', (event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
closeMenu();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function openMenu() {
|
|
||||||
menuAnimating = true;
|
|
||||||
menuOptions.style.display = 'block';
|
|
||||||
setTimeout(() => {
|
|
||||||
menuOptions.classList.remove('hidden');
|
|
||||||
menuOptions.classList.add('visible');
|
|
||||||
menuIcon.classList.add('menu-open');
|
|
||||||
menuIcon.classList.remove('menu-closed');
|
|
||||||
menuOverlay.style.display = 'flex';
|
|
||||||
menuOpen = true;
|
|
||||||
menuAnimating = false;
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeMenu() {
|
|
||||||
if (menuOptions.classList.contains('visible')) {
|
|
||||||
menuAnimating = true;
|
|
||||||
menuOptions.classList.remove('visible');
|
|
||||||
menuOptions.classList.add('hidden');
|
|
||||||
menuIcon.classList.remove('menu-open');
|
|
||||||
menuIcon.classList.add('menu-closed');
|
|
||||||
menuOverlay.style.display = 'none';
|
|
||||||
setTimeout(() => {
|
|
||||||
menuOptions.style.display = 'none';
|
|
||||||
menuOpen = false;
|
|
||||||
menuAnimating = false;
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to setup the language menu
|
|
||||||
function setupLanguageMenu() {
|
|
||||||
languageButton.addEventListener("click", (event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
const isVisible = languageMenu.classList.contains("show");
|
|
||||||
if (isVisible) {
|
|
||||||
closeLanguageMenu();
|
|
||||||
} else {
|
|
||||||
openLanguageMenu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener("click", (event) => {
|
|
||||||
if (!languageButton.contains(event.target) && !languageMenu.contains(event.target)) {
|
|
||||||
closeLanguageMenu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
languageOptions.forEach(option => {
|
|
||||||
option.addEventListener("click", () => {
|
|
||||||
closeLanguageMenu();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('scroll', () => {
|
|
||||||
if (languageMenu.classList.contains("show")) {
|
|
||||||
closeLanguageMenu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function openLanguageMenu() {
|
|
||||||
languageMenu.classList.add("show");
|
|
||||||
languageOverlay.style.display = 'flex';
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeLanguageMenu() {
|
|
||||||
languageMenu.classList.remove("show");
|
|
||||||
languageOverlay.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Focus on search input when search card is clicked
|
|
||||||
searchCard.addEventListener("click", () => {
|
|
||||||
searchInput.focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Search functionality
|
|
||||||
searchInput.addEventListener("input", (e) => {
|
|
||||||
const searchQuery = e.target.value.toLowerCase();
|
|
||||||
const apps = appListContainer.querySelectorAll(".card");
|
|
||||||
apps.forEach(app => {
|
|
||||||
const name = app.querySelector(".name").textContent.toLowerCase();
|
|
||||||
app.style.display = name.includes(searchQuery) ? "block" : "none";
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
});
|
|
||||||
if (searchQuery !== "") {
|
|
||||||
clearBtn.style.display = "block";
|
|
||||||
} else {
|
|
||||||
clearBtn.style.display = "none";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear search input
|
|
||||||
clearBtn.addEventListener("click", () => {
|
|
||||||
searchInput.value = "";
|
|
||||||
clearBtn.style.display = "none";
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
const apps = appListContainer.querySelectorAll(".card");
|
|
||||||
apps.forEach(app => {
|
|
||||||
app.style.display = "block";
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Save configure
|
// Save configure
|
||||||
document.getElementById("save").addEventListener("click", async () => {
|
document.getElementById("save").addEventListener("click", async () => {
|
||||||
const selectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:checked"))
|
const selectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:checked"))
|
||||||
@@ -687,73 +675,6 @@ document.getElementById("save").addEventListener("click", async () => {
|
|||||||
await refreshAppList();
|
await refreshAppList();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initial load
|
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
|
||||||
const userLang = detectUserLanguage();
|
|
||||||
await loadTranslations(userLang);
|
|
||||||
setupMenuToggle();
|
|
||||||
setupLanguageMenu();
|
|
||||||
document.getElementById("refresh").addEventListener("click", refreshAppList);
|
|
||||||
document.getElementById("select-all").addEventListener("click", selectAllApps);
|
|
||||||
document.getElementById("deselect-all").addEventListener("click", deselectAllApps);
|
|
||||||
document.getElementById("select-denylist").addEventListener("click", selectDenylistApps);
|
|
||||||
document.getElementById("deselect-unnecessary").addEventListener("click", deselectUnnecessaryApps);
|
|
||||||
document.getElementById("aospkb").addEventListener("click", aospkb);
|
|
||||||
document.getElementById("extrakb").addEventListener("click", extrakb);
|
|
||||||
document.getElementById("boot-hash").addEventListener("click", setBootHash);
|
|
||||||
document.getElementById("about").addEventListener("click", aboutMenu);
|
|
||||||
await fetchAppList();
|
|
||||||
checkMagisk();
|
|
||||||
loadingIndicator.style.display = "none";
|
|
||||||
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
|
|
||||||
runExtraScript();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Scroll event
|
|
||||||
let lastScrollY = window.scrollY;
|
|
||||||
const scrollThreshold = 40;
|
|
||||||
window.addEventListener('scroll', () => {
|
|
||||||
if (isRefreshing) return;
|
|
||||||
if (window.scrollY > lastScrollY && window.scrollY > scrollThreshold) {
|
|
||||||
title.style.transform = 'translateY(-100%)';
|
|
||||||
searchMenuContainer.style.transform = 'translateY(-40px)';
|
|
||||||
floatingBtn.style.transform = 'translateY(0)';
|
|
||||||
} else if (window.scrollY < lastScrollY) {
|
|
||||||
title.style.transform = 'translateY(0)';
|
|
||||||
searchMenuContainer.style.transform = 'translateY(0)';
|
|
||||||
floatingBtn.style.transform = 'translateY(-120px)';
|
|
||||||
}
|
|
||||||
lastScrollY = window.scrollY;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Show help overlay
|
|
||||||
helpButton.addEventListener("click", () => {
|
|
||||||
helpOverlay.classList.remove("hide");
|
|
||||||
helpOverlay.style.display = "flex";
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
helpOverlay.classList.add("show");
|
|
||||||
});
|
|
||||||
document.body.classList.add("no-scroll");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Hide help overlay
|
|
||||||
const hideHelpOverlay = () => {
|
|
||||||
helpOverlay.classList.remove("show");
|
|
||||||
helpOverlay.classList.add("hide");
|
|
||||||
document.body.classList.remove("no-scroll");
|
|
||||||
setTimeout(() => {
|
|
||||||
helpOverlay.style.display = "none";
|
|
||||||
}, 200);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Hide when clicking on close button or outside of the overlay content
|
|
||||||
closeHelp.addEventListener("click", hideHelpOverlay);
|
|
||||||
helpOverlay.addEventListener("click", (event) => {
|
|
||||||
if (event.target === helpOverlay) {
|
|
||||||
hideHelpOverlay();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Uninstall WebUI
|
// Uninstall WebUI
|
||||||
document.querySelector(".uninstall-container").addEventListener("click", async () => {
|
document.querySelector(".uninstall-container").addEventListener("click", async () => {
|
||||||
try {
|
try {
|
||||||
@@ -775,3 +696,65 @@ document.querySelector(".uninstall-container").addEventListener("click", async (
|
|||||||
showPrompt("uninstall_failed", false);
|
showPrompt("uninstall_failed", false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Scroll event
|
||||||
|
let lastScrollY = window.scrollY;
|
||||||
|
const scrollThreshold = 40;
|
||||||
|
window.addEventListener('scroll', () => {
|
||||||
|
if (isRefreshing) return;
|
||||||
|
if (window.scrollY > lastScrollY && window.scrollY > scrollThreshold) {
|
||||||
|
title.style.transform = 'translateY(-100%)';
|
||||||
|
searchMenuContainer.style.transform = 'translateY(-40px)';
|
||||||
|
floatingBtn.style.transform = 'translateY(0)';
|
||||||
|
} else if (window.scrollY < lastScrollY) {
|
||||||
|
title.style.transform = 'translateY(0)';
|
||||||
|
searchMenuContainer.style.transform = 'translateY(0)';
|
||||||
|
floatingBtn.style.transform = 'translateY(-120px)';
|
||||||
|
}
|
||||||
|
lastScrollY = window.scrollY;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initial load
|
||||||
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
const userLang = detectUserLanguage();
|
||||||
|
await loadTranslations(userLang);
|
||||||
|
setupMenuToggle();
|
||||||
|
setupLanguageMenu();
|
||||||
|
setupHelpOverlay();
|
||||||
|
document.getElementById("refresh").addEventListener("click", refreshAppList);
|
||||||
|
document.getElementById("select-all").addEventListener("click", selectAllApps);
|
||||||
|
document.getElementById("deselect-all").addEventListener("click", deselectAllApps);
|
||||||
|
document.getElementById("select-denylist").addEventListener("click", selectDenylistApps);
|
||||||
|
document.getElementById("deselect-unnecessary").addEventListener("click", deselectUnnecessaryApps);
|
||||||
|
document.getElementById("aospkb").addEventListener("click", aospkb);
|
||||||
|
document.getElementById("extrakb").addEventListener("click", extrakb);
|
||||||
|
document.getElementById("boot-hash").addEventListener("click", setBootHash);
|
||||||
|
document.getElementById("about").addEventListener("click", aboutMenu);
|
||||||
|
await fetchAppList();
|
||||||
|
checkMagisk();
|
||||||
|
loadingIndicator.style.display = "none";
|
||||||
|
document.querySelector('.uninstall-container').classList.remove('hidden-uninstall');
|
||||||
|
runExtraScript();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Function to execute shell commands
|
||||||
|
async function execCommand(command) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
ksu.exec(command, "{}", callbackName);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Execution error: ${error}`);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user