diff --git a/AquaNet/src/libs/i18n/en_ref.ts b/AquaNet/src/libs/i18n/en_ref.ts index c2de0d18..732920b8 100644 --- a/AquaNet/src/libs/i18n/en_ref.ts +++ b/AquaNet/src/libs/i18n/en_ref.ts @@ -215,7 +215,7 @@ export const EN_REF_USERBOX = { 'userbox.new.name': 'AquaBox', 'userbox.new.setup': 'Drag and drop your Chuni game folder (Lumi or newer) into the box below to display UserBoxes with their nameplate & avatar. All files are handled in-browser.', - 'userbox.new.setup.notice': 'This tool assumes your files to be in "bin/option" and "data/A000".', + 'userbox.new.setup.notice': 'Select the highest folder containing your game data.', 'userbox.new.setup.processing_file': 'Processing', 'userbox.new.setup.finalizing': 'Saving to internal storage', 'userbox.new.drop': 'Drop game folder here', diff --git a/AquaNet/src/libs/i18n/zh.ts b/AquaNet/src/libs/i18n/zh.ts index 8fe9e851..851de9c9 100644 --- a/AquaNet/src/libs/i18n/zh.ts +++ b/AquaNet/src/libs/i18n/zh.ts @@ -198,6 +198,8 @@ export const zhUserbox: typeof EN_REF_USERBOX = { 'userbox.nameplateId': '名牌', 'userbox.frameId': '边框', 'userbox.trophyId': '称号', + 'userbox.trophyIdSub1': '称号2', + 'userbox.trophyIdSub2': '称号3', 'userbox.mapIconId': '地图图标', 'userbox.voiceId': '系统语音', 'userbox.avatarWear': '企鹅服饰', @@ -220,7 +222,7 @@ export const zhUserbox: typeof EN_REF_USERBOX = { 'userbox.new.name': 'AquaBox', 'userbox.new.setup': '将中二(Lumi 或更高版本)的游戏文件夹拖放到下方区域,以显示带有名牌和头像的 UserBox。所有文件都在浏览器中处理。', - 'userbox.new.setup.notice': '我们支持的目录结构是把 opt 放进 "bin/option" 并且把 "A000" 放在 "data" 里面。', + 'userbox.new.setup.notice': '选择包含游戏数据的最外层文件夹。', 'userbox.new.setup.processing_file': '正在处理文件', 'userbox.new.setup.finalizing': '正在保存到内部存储', 'userbox.new.drop': '将游戏文件夹拖到此处', diff --git a/AquaNet/src/libs/userbox/userbox.ts b/AquaNet/src/libs/userbox/userbox.ts index 2d2a11ad..049aa87f 100644 --- a/AquaNet/src/libs/userbox/userbox.ts +++ b/AquaNet/src/libs/userbox/userbox.ts @@ -5,6 +5,7 @@ const isDirectory = (e: FileSystemEntry): e is FileSystemDirectoryEntry => e.isD const isFile = (e: FileSystemEntry): e is FileSystemFileEntry => e.isFile const getDirectory = (directory: FileSystemDirectoryEntry, path: string): Promise => new Promise((res, rej) => directory.getDirectory(path, {}, d => res(d), e => rej())); +const getParent = (directory: FileSystemDirectoryEntry): Promise => new Promise((res, rej) => directory.getParent(d => res(d), e => rej())); const getFile = (directory: FileSystemDirectoryEntry, path: string): Promise => new Promise((res, rej) => directory.getFile(path, {}, d => res(d), e => rej())); const getFiles = async (directory: FileSystemDirectoryEntry): Promise> => { let reader = directory.createReader(); @@ -44,6 +45,26 @@ const getDirectoryFromPath = async (base: FileSystemDirectoryEntry, path: string return directory; } +const scanRecursive = async (root: FileSystemDirectoryEntry, target: string): Promise => { + let directories: FileSystemEntry[] = [root]; + + while (directories.length > 0) { + const directory = directories[0] as FileSystemDirectoryEntry; + if (directory.isDirectory) { + if (directory.name == target) + return directory; + let children: FileSystemEntry[] = await new Promise(r => directory.createReader().readEntries(d => r(d))); + directories = [ + ...directories, + ...(children.filter(v => v.isDirectory)) + ]; + } + directories.shift(); + } + + return; +} + export let ddsDB: IDBDatabase | undefined ; /* Technically, processName should be in the translation file but I figured it was such a small thing that it didn't REALLY matter... */ @@ -169,12 +190,12 @@ export async function userboxFileProcess(folder: FileSystemEntry, progressUpdate return t("userbox.new.error.invalidFolder"); initializeDb(); - const optionFolder = await getDirectoryFromPath(folder, "bin/option") ?? await getDirectoryFromPath(folder, "option"); + const optionFolder = await scanRecursive(folder, "A001"); if (optionFolder) - await scanOptionFolder(optionFolder, progressUpdate); - const dataFolder = await getDirectoryFromPath(folder, "data"); + await scanOptionFolder((await getParent(optionFolder)) as FileSystemDirectoryEntry, progressUpdate); + const dataFolder = await scanRecursive(folder, "A000"); if (dataFolder) - await scanOptionFolder(dataFolder, progressUpdate); + await scanOptionFolder((await getParent(dataFolder)) as FileSystemDirectoryEntry, progressUpdate); useLocalStorage("userboxURL", "").value = ""; useLocalStorage("userboxNew", false).value = true; useLocalStorage("userboxNewProfile", false).value = true;