diff --git a/src/aura/init/main/ipcModules/fsIpcHandler.js b/src/aura/init/main/ipcModules/fsIpcHandler.js index 8079399..1995556 100755 --- a/src/aura/init/main/ipcModules/fsIpcHandler.js +++ b/src/aura/init/main/ipcModules/fsIpcHandler.js @@ -42,7 +42,7 @@ const composableFunctions = { const dirName = path.dirname(targetPath); if (!fs.existsSync(dirName)) { - fs.mkdirSync(dirName); + fs.mkdirSync(dirName, { recursive: true }); } const httpModuleIns = url.startsWith("https") ? nodeHttps : nodeHttp; diff --git a/src/aura/init/main/ipcModules/plsIpcHandler.js b/src/aura/init/main/ipcModules/plsIpcHandler.js index df78316..29802d1 100755 --- a/src/aura/init/main/ipcModules/plsIpcHandler.js +++ b/src/aura/init/main/ipcModules/plsIpcHandler.js @@ -283,7 +283,7 @@ const applyPlsIpcHandler = (ipcMain) => { } try { - fs.mkdirSync(PLS_INSTALL_DIR); + fs.mkdirSync(PLS_INSTALL_DIR, { recursive: true }); return { success: true, data: { diff --git a/src/aura/init/shared/default.json b/src/aura/init/shared/default.json index 970b987..9d83fb6 100755 --- a/src/aura/init/shared/default.json +++ b/src/aura/init/shared/default.json @@ -30,7 +30,14 @@ "settingsPasswordEnabled": false, "settingsPasswordWithSalt": "32703D292460CC9A3B867494D6AD9A8E4A3ADF0FAA4D6867BC4D412CC3927D02E47C6D0B1763BB53E57B2241C6193433561CDA09D7C48CA03983072B876F0965", "encryptConfig": false, - "appearance": {} + "appearance": {}, + "uiAccessMethod": { + "showEntryIcon": true, + "fallbackAccessMethods": { + "hotkey": false, + "touch": false + } + } }, "devTools": false } diff --git a/src/aura/ui/composables/settingsRenderer.js b/src/aura/ui/composables/settingsRenderer.js index 86cbb73..eabe406 100755 --- a/src/aura/ui/composables/settingsRenderer.js +++ b/src/aura/ui/composables/settingsRenderer.js @@ -45,6 +45,28 @@ const showToast = (entry) => { */ }; +const setDisableStatus = (el, isDisable, hint = null) => { + if (isDisable) { + el.classList.add("ase-operation-area-disabled"); + if (hint) { + el.setAttribute("data-bs-toggle", "tooltip"); + el.setAttribute("data-bs-placement", "top"); + el.setAttribute("data-bs-title", hint); + const tooltipIns = bootstrap.Tooltip.getOrCreateInstance(el); + tooltipIns.enable(); + } + } else { + el.setAttribute("data-bs-toggle", "tooltip"); + el.setAttribute("data-bs-placement", "top"); + el.setAttribute("data-bs-title", "None"); + el.classList.remove("ase-operation-area-disabled"); + const tooltipIns = bootstrap.Tooltip.getInstance(el); + if (tooltipIns) { + tooltipIns.dispose(); + } + } +}; + const insertOrRemoveEl = (parent, child, isInsert = true) => { if (Array.isArray(child)) { for (const perEl of child) { @@ -71,7 +93,12 @@ const renderInputArea = (entry, operationArea, descriptionArea) => { switchEl.checked = elValue; switchEl.addEventListener("change", async (event) => { showToast(entry); - await entry.callbackFn(event.target.checked); + await entry.callbackFn( + event.target.checked, + switchEl, + operationArea, + descriptionArea + ); }); operationArea.classList.add("form-check", "form-switch"); return switchEl; @@ -92,7 +119,12 @@ const renderInputArea = (entry, operationArea, descriptionArea) => { radioEl.addEventListener("change", async (event) => { if (event.target.checked) { showToast(entry); - await entry.callbackFn(event.target.value); + await entry.callbackFn( + event.target.value, + radioEl, + operationArea, + descriptionArea + ); } }); inlineContainerEl.appendChild(radioEl); @@ -114,7 +146,12 @@ const renderInputArea = (entry, operationArea, descriptionArea) => { inputEl.placeholder = entry.placeHolder; inputEl.id = entry.id; inputEl.addEventListener("change", async (event) => { - const result = await entry.callbackFn(event.target.value); + const result = await entry.callbackFn( + event.target.value, + inputEl, + operationArea, + descriptionArea + ); const success = result.valid; if (success) { showToast(entry); @@ -250,22 +287,6 @@ const renderNormalSettingsItem = (entry, formEl) => { // createOnLeaveEvtListener(channel, evtListener); } - const setDisableStatus = (el, isDisable, hint = null) => { - if (isDisable) { - el.classList.add("ase-operation-area-disabled"); - if (hint) { - el.setAttribute("data-bs-toggle", "tooltip"); - el.setAttribute("data-bs-placement", "top"); - el.setAttribute("data-bs-title", hint); - } - } else { - el.setAttribute("data-bs-toggle", ""); - el.setAttribute("data-bs-placement", ""); - el.setAttribute("data-bs-title", ""); - el.classList.remove("ase-operation-area-disabled"); - } - }; - if (entry.PLSRequired) { if (!global.__HUGO_AURA__.plsStats.connected) { setDisableStatus(entryOperationArea, true, "连接至 PLS 以继续"); @@ -285,6 +306,19 @@ const renderNormalSettingsItem = (entry, formEl) => { const isShow = entry.auraIf(); if (!isShow) entryContainerEl.classList.add("aura-settings-entry-hidden"); + const updateDisableStatus = () => { + const isDisabledRet = entry.auraDisable(); + setDisableStatus( + entryOperationArea, + isDisabledRet.value, + isDisabledRet.tooltip + ); + }; + + if (entry.auraDisable) { + updateDisableStatus(); + } + if (entry.associateVal) { const evtListener = (event) => { if (!entry.associateVal.includes(event.detail.path.join("."))) return; @@ -293,6 +327,10 @@ const renderNormalSettingsItem = (entry, formEl) => { isShow ? cls.remove("aura-settings-entry-hidden") : cls.add("aura-settings-entry-hidden"); + + if (entry.auraDisable) { + updateDisableStatus(); + } }; const channel = entry.PLSRequired ? "onPLSConfigUpdate" @@ -378,7 +416,9 @@ const settingsRenderer = (pendingEl, settingsObj) => { } pendingEl.appendChild(formEl); - global.__HUGO_AURA_GLOBAL__.utils.refreshBsTooltip(); + global.__HUGO_AURA_GLOBAL__.utils.refreshBsTooltip( + ".aura-settings-entry-property-icon" + ); }; module.exports = { settingsRenderer }; diff --git a/src/aura/ui/js/global.js b/src/aura/ui/js/global.js index efd4656..4605597 100755 --- a/src/aura/ui/js/global.js +++ b/src/aura/ui/js/global.js @@ -4,16 +4,14 @@ /* Util: BootStrap Tooltip Ctrl */ let tooltipTriggerCache = null; - const refreshBsTooltip = () => { + const refreshBsTooltip = (selector = '[data-bs-toggle="tooltip"]') => { if (tooltipTriggerCache) { [...tooltipTriggerCache].map((el) => bootstrap.Tooltip.getInstance(el).disable() ); } - const tooltipTriggerList = document.querySelectorAll( - '[data-bs-toggle="tooltip"]' - ); + const tooltipTriggerList = document.querySelectorAll(selector); tooltipTriggerCache = tooltipTriggerList; [...tooltipTriggerList].map( (tooltipTriggerEl) => new bootstrap.Tooltip(tooltipTriggerEl) diff --git a/src/aura/ui/pages/configSubPages/preferences/settings/aura.js b/src/aura/ui/pages/configSubPages/preferences/settings/aura.js index d4757b5..c0add3b 100755 --- a/src/aura/ui/pages/configSubPages/preferences/settings/aura.js +++ b/src/aura/ui/pages/configSubPages/preferences/settings/aura.js @@ -155,6 +155,27 @@ const functions = { return await handleExit(); }, + + getCurAccessMethodCount: () => { + const fallbackMethods = + global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod + .fallbackAccessMethods; + const fallbackMethodsKeys = Object.keys(fallbackMethods); + + let enabledCount = 0; + + for (const method of fallbackMethodsKeys) { + if (fallbackMethods[method]) { + enabledCount += 1; + } + } + + if (global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod.showEntryIcon) { + enabledCount += 1; + } + + return enabledCount; + }, }; const auraSettings = [ @@ -286,8 +307,142 @@ const auraSettings = [ }, { id: 1, - categoryName: "外观", - child: [], + categoryName: "访问方式", + child: [ + { + index: 0, + id: "showEntryIcon", + type: "switch", + name: "显示 HugoAura 设置图标", + description: "控制 HugoAura 设置入口图标在管家首页的显示状态", + restart: false, + reload: true, + tip: true, + tipTitle: "禁用后, HugoAura 图标将不会出现在主页右上角", + associateVal: [ + "auraSettings.uiAccessMethod.fallbackAccessMethods.hotkey", + "auraSettings.uiAccessMethod.fallbackAccessMethods.touch", + ], + auraIf: () => { + return true; + }, + auraDisable: () => { + const fallbackMethods = + global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod + .fallbackAccessMethods; + const fallbackMethodsKeys = Object.keys(fallbackMethods); + let anyEnabled = false; + + for (const method of fallbackMethodsKeys) { + if (fallbackMethods[method]) { + anyEnabled = true; + break; + } + } + + return { + value: !anyEnabled, + tooltip: !anyEnabled ? "至少启用一个备选访问方式" : "", + }; + }, + defaultValue: false, + valueGetter: () => { + return global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod + .showEntryIcon; + }, + callbackFn: async (newVal) => { + if (typeof newVal !== "boolean") return; + global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod.showEntryIcon = + newVal; + }, + }, + { + index: 1, + id: "allowHotkeyAccess", + type: "switch", + name: "使用快捷键打开 HugoAura 设置 UI", + description: + "启用后, 在管家首页按下 Ctrl + Shift + A 以打开 HugoAura 设置", + restart: false, + reload: true, + associateVal: [ + "auraSettings.uiAccessMethod.showEntryIcon", + "auraSettings.uiAccessMethod.fallbackAccessMethods.hotkey", + "auraSettings.uiAccessMethod.fallbackAccessMethods.touch", + ], + auraIf: () => { + return true; + }, + auraDisable: () => { + const enableCount = functions.getCurAccessMethodCount(); + if ( + enableCount < 2 && + !global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod + .showEntryIcon && + global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod + .fallbackAccessMethods.hotkey + ) { + return { value: true, tooltip: "无法禁用所有访问方式" }; + } else { + return { value: false }; + } + }, + defaultValue: false, + valueGetter: () => { + return global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod + .fallbackAccessMethods.hotkey; + }, + callbackFn: async (newVal) => { + if (typeof newVal !== "boolean") return; + global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod.fallbackAccessMethods.hotkey = + newVal; + }, + }, + { + index: 2, + id: "allowTouchAccess", + type: "switch", + name: "使用触摸手势打开 HugoAura 设置 UI", + description: + "启用后, 在管家首页连击 7 次右上角信息栏 ( i ) 中的版本号区域以打开 HugoAura 设置", + restart: false, + reload: true, + tip: true, + tipTitle: "请在 10 秒钟内完成连击操作, 否则计时器将被重置", + associateVal: [ + "auraSettings.uiAccessMethod.showEntryIcon", + "auraSettings.uiAccessMethod.fallbackAccessMethods.hotkey", + "auraSettings.uiAccessMethod.fallbackAccessMethods.touch", + ], + auraIf: () => { + return true; + }, + auraDisable: () => { + const enableCount = functions.getCurAccessMethodCount(); + if ( + enableCount < 2 && + !global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod + .showEntryIcon && + global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod + .fallbackAccessMethods.touch + ) { + return { value: true, tooltip: "无法禁用所有访问方式" }; + } else { + return { value: false }; + } + }, + defaultValue: false, + valueGetter: () => { + return global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod + .fallbackAccessMethods.touch; + }, + callbackFn: async (newVal) => { + if (typeof newVal !== "boolean") return; + global.__HUGO_AURA_CONFIG__.auraSettings.uiAccessMethod.fallbackAccessMethods.touch = + newVal; + }, + }, + ], }, ]; diff --git a/src/aura/ui/pages/headerIcon/headerIcon.css b/src/aura/ui/pages/headerIcon/headerIcon.css index 1e76f92..492a0d8 100755 --- a/src/aura/ui/pages/headerIcon/headerIcon.css +++ b/src/aura/ui/pages/headerIcon/headerIcon.css @@ -7,6 +7,10 @@ transition: opacity 0.25s; } +.aura-header-icon.aura-header-icon-hidden { + display: none; +} + .aura-header-icon:hover { opacity: 0.75; } diff --git a/src/aura/ui/pages/headerIcon/headerIcon.html b/src/aura/ui/pages/headerIcon/headerIcon.html index af02dd2..934e03a 100755 --- a/src/aura/ui/pages/headerIcon/headerIcon.html +++ b/src/aura/ui/pages/headerIcon/headerIcon.html @@ -1,4 +1,4 @@ -