import custom keybox

This commit is contained in:
KOWX712
2025-02-08 17:21:13 +08:00
parent 2886b7e742
commit 8d67689d76
15 changed files with 377 additions and 23 deletions

View File

@@ -76,7 +76,8 @@
<li id="select-denylist" data-i18n="menu.select_denylist"></li>
<li id="deselect-unnecessary" data-i18n="menu.deselect_unnecessary"></li>
<li id="aospkb" data-i18n="menu.set_aosp_keybox"></li>
<li id="extrakb" data-i18n="menu.set_valid_keybox"></li>
<li id="validkb" data-i18n="menu.set_valid_keybox"></li>
<li id="customkb" data-i18n="menu.set_custom_keybox"></li>
<li id="boot-hash" data-i18n="menu.set_verified_boot_hash"></li>
<li id="about" data-i18n="menu.about"></li>
</ul>
@@ -185,6 +186,13 @@
</ul>
</li>
<br>
<li id="set_custom_keybox">
<strong data-i18n="help.set_custom_keybox"></strong>
<ul>
<li data-i18n="help.set_custom_keybox_description"></li>
</ul>
</li>
<br>
<li id="set_verified_boot_hash">
<strong data-i18n="help.set_verified_boot_hash"></strong>
<ul>

View File

@@ -17,6 +17,8 @@
"deselect_unnecessary_description": "Unnecessary category: Xposed module, root manager, root-related apps, and general apps that never check bootloader status. This option requires Internet connection.",
"set_keybox": "Set AOSP & Valid Keybox",
"set_keybox_description": "Replace tricky store keybox.xml. AOSP keybox will be replaced if there's no more valid keybox. Valid keybox option requires Internet connection.",
"set_custom_keybox": "Set Custom Keybox",
"set_custom_keybox_description": "Import keybox from your device storage. Only support xml file.",
"set_verified_boot_hash": "Set Verified Boot Hash",
"set_verified_boot_hash_description": "Get verifiedBootHash value from Key Attestation Demo. Fix abnormal boot state by resetting ro.boot.vbmeta.digest."
},
@@ -45,6 +47,7 @@
"deselect_unnecessary": "Deselect Unnecessary",
"set_aosp_keybox": "Set AOSP Keybox",
"set_valid_keybox": "Set Valid Keybox",
"set_custom_keybox": "Set Custom Keybox",
"set_verified_boot_hash": "Set Verified Boot Hash",
"about": "About"
},
@@ -81,6 +84,9 @@
"installed": "Installed successfully, reboot now.",
"install_fail": "Fail to install, please update manual",
"rebooting": "Rebooting...",
"reboot_fail": "Fail to reboot, please reboot manually"
"reboot_fail": "Fail to reboot, please reboot manually",
"custom_key_set": "Custom keybox set successfully",
"custom_key_set_error": "Failed to set custom keybox",
"no_file_selected": "No file selected"
}
}

View File

@@ -17,6 +17,8 @@
"deselect_unnecessary_description": "Unnecessary category: Xposed module, root manager, root-related apps, and general apps that never check bootloader status. This option requires Internet connection.",
"set_keybox": "Set AOSP & Valid Keybox",
"set_keybox_description": "Replace tricky store keybox.xml. AOSP keybox will be replaced if there's no more valid keybox. Valid keybox option requires Internet connection.",
"set_custom_keybox": "Set Custom Keybox",
"set_custom_keybox_description": "Import keybox from your device storage. Only support xml file.",
"set_verified_boot_hash": "Set Verified Boot Hash",
"set_verified_boot_hash_description": "Get verifiedBootHash value from Key Attestation Demo. Fix abnormal boot state by resetting ro.boot.vbmeta.digest."
},
@@ -45,6 +47,7 @@
"deselect_unnecessary": "Deselect Unnecessary",
"set_aosp_keybox": "Set AOSP Keybox",
"set_valid_keybox": "Set Valid Keybox",
"set_custom_keybox": "Set Custom Keybox",
"set_verified_boot_hash": "Set Verified Boot Hash",
"about": "About"
},
@@ -81,6 +84,9 @@
"installed": "Installed successfully, reboot now.",
"install_fail": "Fail to install, please update manual",
"rebooting": "Rebooting...",
"reboot_fail": "Fail to reboot, please reboot manually"
"reboot_fail": "Fail to reboot, please reboot manually",
"custom_key_set": "Custom keybox set successfully",
"custom_key_set_error": "Failed to set custom keybox",
"no_file_selected": "No file selected"
}
}

View File

@@ -17,6 +17,8 @@
"deselect_unnecessary_description": "Categorías innecesarias: módulos Xposed, gestores de root, aplicaciones relacionadas con root y aplicaciones generales que nunca verifican el estado del bootloader. Esta opción requiere conexión a Internet.",
"set_keybox": "Configurar AOSP y Keybox Válido",
"set_keybox_description": "Reemplazar el archivo keybox.xml de Tricky Store. El AOSP Keybox será reemplazado si no hay un keybox válido. Esta opción requiere conexión a Internet.",
"set_custom_keybox": "Establecer Keybox Personalizado",
"set_custom_keybox_description": "Importar keybox desde el almacenamiento de tu dispositivo. Solo soporta archivos xml.",
"set_verified_boot_hash": "Configurar Boot Hash Verificado",
"set_verified_boot_hash_description": "Obtén el valor de verifiedBootHash del Key Attestation Demo. Corrige un estado de arranque anormal reiniciando ro.boot.vbmeta.digest."
},
@@ -45,6 +47,7 @@
"deselect_unnecessary": "Deseleccionar innecesarios",
"set_aosp_keybox": "Configurar AOSP Keybox",
"set_valid_keybox": "Configurar Keybox Válido",
"set_custom_keybox": "Establecer Keybox Personalizado",
"set_verified_boot_hash": "Configurar Boot Hash Verificado",
"about": "Acerca de"
},
@@ -81,6 +84,9 @@
"installed": "Instalado con éxito, reinicia ahora.",
"install_fail": "Error al instalar, actualiza manualmente",
"rebooting": "Reiniciando...",
"reboot_fail": "Error al reiniciar, reinicia manualmente"
"reboot_fail": "Error al reiniciar, reinicia manualmente",
"custom_key_set": "Keybox personalizado establecido con éxito",
"custom_key_set_error": "Error al establecer el keybox personalizado",
"no_file_selected": "Ningún archivo seleccionado"
}
}

View File

@@ -17,6 +17,8 @@
"deselect_unnecessary_description": "不要なカテゴリー: Xposed モジュール、root マネージャー、root 関連アプリ、Bootloader の状態を確認しない一般的なアプリです。このオプションはインターネット接続が必要です。",
"set_keybox": "AOSP と 有効な Keybox",
"set_keybox_description": "Tricky Store の keybox.xml を置き換えます。有効な Keybox がなくなった場合は、AOSP Keybox に置き換えられます。インターネット接続が必要です。",
"set_custom_keybox": "カスタム Keybox を設定",
"set_custom_keybox_description": "デバイスのストレージからカスタム Keybox ファイルをインポートします。xml ファイルのみ対応。",
"set_verified_boot_hash": "確認付きブートハッシュを設定",
"set_verified_boot_hash_description": "Key Attestation Demo から確認付きブートハッシュの値を取得します。ro.boot.vbmeta.digest をリセットして異常なブート状態を修正します。"
},
@@ -45,6 +47,7 @@
"deselect_unnecessary": "不要な選択を解除",
"set_aosp_keybox": "AOSP Keybox を設定",
"set_valid_keybox": "有効な Keybox を設定",
"set_custom_keybox": "カスタム Keybox を設定",
"set_verified_boot_hash": "確認付きブートハッシュを設定",
"about": "このアドオンについて"
},
@@ -81,6 +84,9 @@
"installed": "正常にインストールされました。再起動してください。",
"install_fail": "インストールに失敗しました。手動で更新してください。",
"rebooting": "再起動中...",
"reboot_fail": "再起動に失敗しました。手動で再起動してください。"
"reboot_fail": "再起動に失敗しました。手動で再起動してください。",
"custom_key_set": "カスタム Keybox の設定に成功しました",
"custom_key_set_error": "カスタム Keybox の設定に失敗しました",
"no_file_selected": "ファイルが選択されていません"
}
}

View File

@@ -17,6 +17,8 @@
"deselect_unnecessary_description": "Ненужные категории: модули Xposed, менеджеры root, приложения, связанные с root, и общие приложения, которые никогда не проверяют статус загрузчика. Этот параметр требует подключения к интернету.",
"set_keybox": "Установить AOSP и действующий Keybox",
"set_keybox_description": "Замените tricky store keybox.xml. AOSP keybox будет заменен, если не будет найден действующий keybox. Опция с действующим keybox требует подключения к интернету.",
"set_custom_keybox": "Установить пользовательский Keybox",
"set_custom_keybox_description": "Импортируйте файл keybox из вашего устройства в хранилище. Поддерживаются только xml файлы.",
"set_verified_boot_hash": "Установить Verified Boot Hash",
"set_verified_boot_hash_description": "Получите значение verifiedBootHash из Key Attestation Demo. Исправьте аномальное состояние загрузки, сбросив ro.boot.vbmeta.digest."
},
@@ -45,6 +47,7 @@
"deselect_unnecessary": "Отменить выбор ненужных",
"set_aosp_keybox": "Установить AOSP Keybox",
"set_valid_keybox": "Установить действующий Keybox",
"set_custom_keybox": "Установить пользовательский Keybox",
"set_verified_boot_hash": "Установить Verified Boot Hash",
"about": "О программе"
},
@@ -81,6 +84,9 @@
"installed": "Успешно установлено, перезагрузите устройство.",
"install_fail": "Не удалось установить, обновите вручную",
"rebooting": "Перезагрузка...",
"reboot_fail": "Не удалось перезагрузить, перезагрузите вручную"
"reboot_fail": "Не удалось перезагрузить, перезагрузите вручную",
"custom_key_set": "Пользовательский keybox успешно установлен",
"custom_key_set_error": "Не удалось установить пользовательский keybox",
"no_file_selected": "Файл не выбран"
}
}

View File

@@ -16,7 +16,9 @@
"deselect_unnecessary": "Huwag Pumili ng Hindi Kinakailangan",
"deselect_unnecessary_description": "Hindi kinakailangang kategorya: Xposed module, root manager, root-related apps, at mga karaniwang apps na hindi kailanman nire-refresh ang bootloader status. Nangangailangan ng koneksyon sa internet.",
"set_keybox": "I-set ang AOSP at Valid Keybox",
"set_keybox_description": "Palitan ang tricky store keybox.xml. Palitan ang AOSP keybox kung walang valid keybox. Nangangailangan ng koneksyon sa internet ang valid keybox option.",
"set_keybox_description": "Palitan ang tricky store keybox. Palitan ang AOSP keybox kung walang valid keybox. Nangangailangan ng koneksyon sa internet ang valid keybox option.",
"set_custom_keybox": "I-set ang Custom Keybox",
"set_custom_keybox_description": "Mag-import ng custom keybox mula sa iyong device storage. Sumusuporta lamang ng xml file.",
"set_verified_boot_hash": "I-set ang Verified Boot Hash",
"set_verified_boot_hash_description": "Kunin ang verifiedBootHash mula sa Key Attestation Demo. Ayusin ang abnormal na boot state sa pamamagitan ng pag-reset ng ro.boot.vbmeta.digest."
},
@@ -45,6 +47,7 @@
"deselect_unnecessary": "Huwag Pumili ng Hindi Kinakailangan",
"set_aosp_keybox": "I-set ang AOSP Keybox",
"set_valid_keybox": "I-set ang Valid Keybox",
"set_custom_keybox": "I-set ang Custom Keybox",
"set_verified_boot_hash": "I-set ang Verified Boot Hash",
"about": "Tungkol"
},
@@ -81,6 +84,9 @@
"installed": "Matagumpay na na-install, mag-reboot na ngayon.",
"install_fail": "Nabigo ang pag-install, pakisubukang mag-update nang manu-mano",
"rebooting": "Nag-re-reboot...",
"reboot_fail": "Nabigo ang pag-reboot, pakisubukang mag-reboot nang manu-mano"
"reboot_fail": "Nabigo ang pag-reboot, pakisubukang mag-reboot nang manu-mano",
"custom_key_set": "Matagumpay na na-set ang Custom Keybox",
"custom_key_set_error": "Nabigong i-set ang Custom Keybox",
"no_file_selected": "Walang napiling file"
}
}

View File

@@ -12,13 +12,15 @@
"select_deselect": "Tümünü Seç & Seçimi Kaldır",
"select_description": "Mevcut arayüzdeki tüm uygulamaları seç veya seçimini kaldır.",
"select_denylist": "Reddetme Listesinden Seç",
"select_denylist_description": "Yalnızca Magiskte mevcut, Reddetme Listesindeki uygulamaları seç. Tavsiye edilir.",
"select_denylist_description": "Yalnızca Magisk'te mevcut, Reddetme Listesindeki uygulamaları seç. Tavsiye edilir.",
"deselect_unnecessary": "Gereksizleri Seçme",
"deselect_unnecessary_description": "Gereksiz kategori: Xposed modülü, root yöneticisi, root ile ilgili uygulamalar ve asla bootloader durumunu kontrol etmeyen genel uygulamalar. Bu seçenek internet bağlantısı gerektirir.",
"set_keybox": "AOSP & Geçerli Keybox Ayarla",
"set_keybox_description": "Tricky Store'daki keybox.xml dosyasını değiştirir. Eğer geçerli bir keybox yoksa AOSP keybox ile değiştirilecektir. Geçerli keybox seçeneği internet bağlantısı gerektirir.",
"set_custom_keybox": "Özel Keybox Ayarla",
"set_custom_keybox_description": "Cihaz depolamasından bir keybox dosyasını içe aktarın. Sadece xml dosyaları desteklenir.",
"set_verified_boot_hash": "Doğrulanmış Boot Hash Ayarla",
"set_verified_boot_hash_description": "Key Attestation Demodan verifiedBootHash değerini alın. Abnormal boot durumunu ro.boot.vbmeta.digesti sıfırlayarak düzeltin."
"set_verified_boot_hash_description": "Key Attestation Demo'dan verifiedBootHash değerini alın. Abnormal boot durumunu ro.boot.vbmeta.digest'i sıfırlayarak düzeltin."
},
"update": {
"update_available": "Yeni bir sürüm hazır",
@@ -32,7 +34,7 @@
},
"functional_button": {
"save_and_update_button": "Kaydet",
"uninstall_webui": "WebUIı Kaldır"
"uninstall_webui": "WebUI'ı Kaldır"
},
"loading": {
"loading": "Yükleniyor..."
@@ -45,11 +47,12 @@
"deselect_unnecessary": "Gereksizleri Seçme",
"set_aosp_keybox": "AOSP Keybox Ayarla",
"set_valid_keybox": "Geçerli Keybox Ayarla",
"set_custom_keybox": "Özel Keybox Ayarla",
"set_verified_boot_hash": "Doğrulanmış Boot Hash Ayarla",
"about": "Hakkında"
},
"reset_vbmeta": {
"boot_hash_input_placeholder": "Doğrulanmış Boot Hashinizi buraya yapıştırın",
"boot_hash_input_placeholder": "Doğrulanmış Boot Hash'inizi buraya yapıştırın",
"boot_hash_save_button": "Kaydet"
},
"about": {
@@ -58,7 +61,7 @@
"by": "tarafından",
"telegram_channel": "Telegram Kanalı",
"github": "GitHub",
"disclaimer": "Bu modül, Tricky Store modülünün bir parçası değildir. Herhangi bir sorun yaşarsanız, lütfen bunu Tricky Storea rapor etmeyin.",
"disclaimer": "Bu modül, Tricky Store modülünün bir parçası değildir. Herhangi bir sorun yaşarsanız, lütfen bunu Tricky Store'a rapor etmeyin.",
"acknowledgment": "Teşekkür"
},
"prompt": {
@@ -81,6 +84,9 @@
"installed": "Başarıyla yüklendi, şimdi yeniden başlatın.",
"install_fail": "Yükleme başarısız oldu, lütfen manuel olarak güncelleyin",
"rebooting": "Yeniden başlatılıyor...",
"reboot_fail": "Yeniden başlatma başarısız, lütfen manuel olarak yeniden başlatın"
"reboot_fail": "Yeniden başlatma başarısız, lütfen manuel olarak yeniden başlatın",
"custom_key_set": "Özel keybox başarıyla ayarlandı",
"custom_key_set_error": "Özel keybox ayarlanamadı",
"no_file_selected": "Dosya seçilmedi"
}
}

View File

@@ -17,6 +17,8 @@
"deselect_unnecessary_description": "非必要分类Xposed 模块、root 管理器、与 root 相关的应用,以及从不检查 bootloader 状态的通用应用。此功能需连网使用。",
"set_keybox": "设置 AOSP & 有效密钥",
"set_keybox_description": "替换 Tricky Store 的密钥keybox.xml。如果没有有效密钥将替换为 AOSP 密钥。有效密钥选项需连网使用。",
"set_custom_keybox": "设置自定义密钥",
"set_custom_keybox_description": "从设备存储导入自定义密钥。仅支持 xml 文件。",
"set_verified_boot_hash": "设置哈希值",
"set_verified_boot_hash_description": "从 Key Attestation Demo 获取 verifiedBootHash哈希值。通过重置 ro.boot.vbmeta.digest 修复异常 boot 状态。"
},
@@ -45,6 +47,7 @@
"deselect_unnecessary": "取消选择非必应用",
"set_aosp_keybox": "设置 AOSP 密钥",
"set_valid_keybox": "设置有效密钥",
"set_custom_keybox": "设置自定义密钥",
"set_verified_boot_hash": "设置哈希值",
"about": "关于"
},
@@ -81,6 +84,9 @@
"installed": "安装完成,重启生效",
"install_fail": "安装失败,请手动更新",
"rebooting": "正在重启...",
"reboot_fail": "重启失败,请手动重启"
"reboot_fail": "重启失败,请手动重启",
"custom_key_set": "成功设置自定义密钥",
"custom_key_set_error": "设置自定义密钥失败",
"no_file_selected": "未选择文件"
}
}

View File

@@ -17,6 +17,8 @@
"deselect_unnecessary_description": "非必要分類Xposed 模組、root 管理器、與 root 相關的應用,以及從不檢查 bootloader 狀態的通用應用。此功能需連網使用。",
"set_keybox": "設置 AOSP & 有效密鑰",
"set_keybox_description": "替換 Tricky Store 的密鑰keybox.xml。如果沒有有效密鑰將替換為 AOSP 密鑰。有效密鑰選項需連網使用。",
"set_custom_keybox": "設置自定義密鑰",
"set_custom_keybox_description": "從設備存儲導入自定義密鑰。僅支持 xml 文件。",
"set_verified_boot_hash": "設置哈希值",
"set_verified_boot_hash_description": "從 Key Attestation Demo 獲取 verifiedBootHash哈希值。通過重置 ro.boot.vbmeta.digest 修復異常 boot 狀態。"
},
@@ -45,6 +47,7 @@
"deselect_unnecessary": "取消選擇非必要應用",
"set_aosp_keybox": "設置 AOSP 密鑰",
"set_valid_keybox": "設置有效密鑰",
"set_custom_keybox": "設置自定義密鑰",
"set_verified_boot_hash": "設置哈希值",
"about": "關於"
},
@@ -81,6 +84,9 @@
"installed": "安裝完成,重啟生效",
"install_fail": "安裝失敗,請手動更新",
"rebooting": "正在重啟...",
"reboot_fail": "重啟失敗,請手動重啟"
"reboot_fail": "重啟失敗,請手動重啟",
"custom_key_set": "成功設置自定義密鑰",
"custom_key_set_error": "設置自定義密鑰失敗",
"no_file_selected": "未選擇文件"
}
}

View File

@@ -19,7 +19,7 @@ export const basePath = "set-path";
export const appsWithExclamation = [];
export const appsWithQuestion = [];
const ADDITIONAL_APPS = [ "android", "com.android.vending", "com.google.android.gms", "io.github.vvb2060.keyattestation", "io.github.vvb2060.mahoshojo", "icu.nullptr.nativetest" ]; // Always keep default apps in target.txt
const rippleClasses = ['.language-option', '.menu-button', '.menu-options li', '.search-card', '.card', '.update-card', '.link-icon', '.floating-btn', '.uninstall-container', '.boot-hash-save-button', '.boot-hash-value', '.reboot', '.install'];
const rippleClasses = ['.language-option', '.menu-button', '.menu-options li', '.search-card', '.card', '.update-card', '.link-icon', '.floating-btn', '.uninstall-container', '.boot-hash-save-button', '.boot-hash-value', '.reboot', '.install', '.file-item'];
// Variables
let e = 0;
@@ -184,7 +184,7 @@ function hideFloatingBtn() {
}
// Function to apply ripple effect
function applyRippleEffect() {
export function applyRippleEffect() {
rippleClasses.forEach(selector => {
document.querySelectorAll(selector).forEach(element => {
if (element.dataset.rippleListener !== "true") {

View File

@@ -1,4 +1,4 @@
import { basePath, execCommand, showPrompt, toast } from './main.js';
import { basePath, execCommand, showPrompt, toast, applyRippleEffect } from './main.js';
// Function to check or uncheck all app
function toggleCheckboxes(shouldCheck) {
@@ -86,7 +86,7 @@ export async function aospkb() {
}
// Function to replace valid kb
document.getElementById("extrakb").addEventListener("click", async () => {
document.getElementById("validkb").addEventListener("click", async () => {
setTimeout(async () => {
await execCommand(`sh ${basePath}common/get_extra.sh --kb`);
}, 100);
@@ -107,3 +107,179 @@ document.getElementById("extrakb").addEventListener("click", async () => {
showPrompt("prompt.no_valid_fallback", false);
}
});
// Add file selector dialog elements dynamically
const fileSelector = document.createElement('div');
fileSelector.className = 'file-selector-overlay';
fileSelector.innerHTML = `
<div class="file-selector">
<div class="file-selector-header">
<button class="back-button">
<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 -960 960 960" width="20"><path d="M400-80 0-480l400-400 56 57-343 343 343 343-56 57Z"/></svg>
</button>
<div class="current-path">/storage/emulated/0/Download</div>
<button class="close-selector">&#x2715;</button>
</div>
<div class="file-list"></div>
</div>
`;
document.body.appendChild(fileSelector);
// Add styles for animations
const style = document.createElement('style');
style.textContent = `
.file-selector-overlay {
transition: opacity 0.3s ease;
opacity: 0;
}
.file-selector-overlay.visible {
opacity: 1;
}
.file-list {
transition: transform 0.3s ease, opacity 0.3s ease;
}
.file-list.switching {
transform: scale(0.95);
opacity: 0;
}
`;
document.head.appendChild(style);
let currentPath = '/storage/emulated/0/Download';
// Function to list files in directory
async function listFiles(path, skipAnimation = false) {
const fileList = document.querySelector('.file-list');
if (!skipAnimation) {
fileList.classList.add('switching');
await new Promise(resolve => setTimeout(resolve, 150));
}
try {
const result = await execCommand(`find "${path}" -maxdepth 1 -type f -name "*.xml" -o -type d ! -name ".*" | sort`);
const items = result.split('\n').filter(Boolean).map(item => ({
path: item,
name: item.split('/').pop(),
isDirectory: !item.endsWith('.xml')
}));
fileList.innerHTML = '';
// Add back button item if not in root directory
if (currentPath !== '/storage/emulated/0') {
const backItem = document.createElement('div');
backItem.className = 'file-item';
backItem.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24">
<path d="M141-160q-24 0-42-18.5T81-220v-520q0-23 18-41.5t42-18.5h280l60 60h340q23 0 41.5 18.5T881-680v460q0 23-18.5 41.5T821-160H141Z"/>
</svg>
<span>..</span>
`;
backItem.addEventListener('click', async () => {
currentPath = currentPath.split('/').slice(0, -1).join('/');
if (currentPath === '') currentPath = '/storage/emulated/0';
const currentPathElement = document.querySelector('.current-path');
currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join('<span class="separator"></span>');
currentPathElement.scrollTo({
left: currentPathElement.scrollWidth,
behavior: 'smooth'
});
await listFiles(currentPath);
});
fileList.appendChild(backItem);
}
items.forEach(item => {
if (item.path === path) return;
const itemElement = document.createElement('div');
itemElement.className = 'file-item';
itemElement.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24">
${item.isDirectory ?
'<path d="M141-160q-24 0-42-18.5T81-220v-520q0-23 18-41.5t42-18.5h280l60 60h340q23 0 41.5 18.5T881-680v460q0 23-18.5 41.5T821-160H141Z"/>' :
'<path d="M320-240h320v-80H320v80Zm0-160h320v-80H320v80ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520v-200H240v640h480v-440H520ZM240-800v200-200 640-640Z"/>'}
</svg>
<span>${item.name}</span>
`;
itemElement.addEventListener('click', async () => {
if (item.isDirectory) {
currentPath = item.path;
const currentPathElement = document.querySelector('.current-path');
currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join('<span class="separator"></span>');
currentPathElement.scrollTo({
left: currentPathElement.scrollWidth,
behavior: 'smooth'
});
await listFiles(item.path);
} else {
try {
const content = await execCommand(`cat "${item.path}"`);
await execCommand(`mv -f /data/adb/tricky_store/keybox.xml /data/adb/tricky_store/keybox.xml.bak 2>/dev/null && echo '${content}' > /data/adb/tricky_store/keybox.xml`);
fileSelector.style.display = 'none';
showPrompt('prompt.custom_key_set');
} catch (error) {
console.error('Error processing file:', error);
showPrompt('prompt.custom_key_set_error');
}
}
});
fileList.appendChild(itemElement);
});
if (!skipAnimation) {
fileList.classList.remove('switching');
}
} catch (error) {
console.error('Error listing files:', error);
if (!skipAnimation) {
fileList.classList.remove('switching');
}
}
applyRippleEffect();
}
// Back button handler
document.querySelector('.back-button').addEventListener('click', async () => {
if (currentPath === '/storage/emulated/0') return;
currentPath = currentPath.split('/').slice(0, -1).join('/');
if (currentPath === '') currentPath = '/storage/emulated/0';
const currentPathElement = document.querySelector('.current-path');
currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join('<span class="separator"></span>');
currentPathElement.scrollTo({
left: currentPathElement.scrollWidth,
behavior: 'smooth'
});
await listFiles(currentPath);
});
// Close custom keybox selector
document.querySelector('.close-selector').addEventListener('click', () => {
fileSelector.classList.remove('visible');
document.body.classList.remove("no-scroll");
setTimeout(() => {
fileSelector.style.display = 'none';
}, 300);
});
fileSelector.addEventListener('click', (event) => {
if (event.target === fileSelector) {
fileSelector.classList.remove('visible');
document.body.classList.remove("no-scroll");
setTimeout(() => {
fileSelector.style.display = 'none';
}, 300);
}
});
// Open custom keybox selector
document.getElementById('customkb').addEventListener('click', async () => {
fileSelector.style.display = 'flex';
document.body.classList.add("no-scroll");
fileSelector.offsetHeight;
fileSelector.classList.add('visible');
currentPath = '/storage/emulated/0/Download';
const currentPathElement = document.querySelector('.current-path');
currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join('<span class="separator"></span>');
currentPathElement.scrollTo({
left: currentPathElement.scrollWidth,
behavior: 'smooth'
});
await listFiles(currentPath, true);
});

View File

@@ -41,6 +41,7 @@
border: none;
font-size: 18px;
color: #ccc;
user-select: none;
}
.link,

View File

@@ -113,6 +113,95 @@ body {
display: none;
}
.file-selector-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index: 2000;
justify-content: center;
align-items: center;
}
.file-selector {
width: 90%;
max-width: 600px;
height: 80vh;
background-color: #fff;
border-radius: 15px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.file-selector-header {
display: flex;
align-items: center;
padding: 10px;
border-bottom: 1px solid #ccc;
}
.current-path .separator {
color: #6E6E6E;
padding: 0 4px;
}
.back-button {
background: none;
border: none;
padding: 5px;
margin-right: 10px;
fill: #6E6E6E;
user-select: none;
}
.current-path {
flex-grow: 1;
font-size: 16px;
overflow: scroll;
white-space: nowrap;
}
.close-selector {
background: none;
border: none;
font-size: 20px;
color: #ccc;
padding: 5px;
}
.file-list {
flex-grow: 1;
overflow-y: auto;
padding: 10px;
}
.file-item {
display: flex;
align-items: center;
padding: 10px;
border-radius: 8px;
background-color: #fff;
position: relative;
overflow: hidden;
user-select: none;
}
.file-item svg {
margin-right: 10px;
fill: #6E6E6E;
}
.file-item span {
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.ripple {
position: absolute;
border-radius: 50%;
@@ -138,4 +227,29 @@ body {
background-color: #121212;
color: #fff;
}
.file-selector {
background-color: #343434;
color: #fff;
}
.file-selector-header {
border-bottom: 1px solid #6E6E6E;
}
.file-item {
background-color: #343434;
}
.current-path .separator {
color: #C2C2C2;
}
.back-button {
fill: #C2C2C2;
}
.file-item svg {
fill: #C2C2C2;
}
}

View File

@@ -63,7 +63,7 @@
display: flex;
flex-direction: column;
position: absolute;
right: 0;
right: 5px;
background-color: white;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
z-index: 1800;
@@ -180,6 +180,7 @@
border: none;
font-size: 20px;
color: #ccc;
user-select: none;
}
.help-content {