diff --git a/manifest.json b/manifest.json index 97a20086..ac7ce223 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "__MSG_extName__", "description": "__MSG_extDescription__", - "version": "0.12.3", + "version": "0.13.0", "default_locale": "en", "icons": { "128": "icon128.png" diff --git a/package.json b/package.json index a0c10b5b..1f72554b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "selection-command", - "version": "0.12.3", + "version": "0.13.0", "author": "ujiro99", "license": "MIT", "private": true, diff --git a/public/_locales/de/messages.json b/public/_locales/de/messages.json index b06b8442..4684254b 100644 --- a/public/_locales/de/messages.json +++ b/public/_locales/de/messages.json @@ -810,7 +810,7 @@ "message": "Wiederherstellen" }, "Option_RestoreFromBackup_legacy": { - "message": "Legacy-Migration" + "message": "Backup aktualisieren" }, "Option_RestoreFromBackup_daily": { "message": "Tägliches Backup" diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index 1fa6d703..40121207 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -822,7 +822,7 @@ "message": "Restore" }, "Option_RestoreFromBackup_legacy": { - "message": "Legacy Migration" + "message": "Update Backup" }, "Option_RestoreFromBackup_daily": { "message": "Daily Backup" diff --git a/public/_locales/es/messages.json b/public/_locales/es/messages.json index f6e51ae6..c27d54d2 100644 --- a/public/_locales/es/messages.json +++ b/public/_locales/es/messages.json @@ -810,7 +810,7 @@ "message": "Restaurar" }, "Option_RestoreFromBackup_legacy": { - "message": "Migración Heredada" + "message": "Actualizar Respaldo" }, "Option_RestoreFromBackup_daily": { "message": "Respaldo Diario" diff --git a/public/_locales/fr/messages.json b/public/_locales/fr/messages.json index e956dbbc..3ca65b87 100644 --- a/public/_locales/fr/messages.json +++ b/public/_locales/fr/messages.json @@ -810,7 +810,7 @@ "message": "Restaurer" }, "Option_RestoreFromBackup_legacy": { - "message": "Migration Héritée" + "message": "Mettre à jour la sauvegarde" }, "Option_RestoreFromBackup_daily": { "message": "Sauvegarde Quotidienne" diff --git a/public/_locales/hi/messages.json b/public/_locales/hi/messages.json index e30f4ac8..2cde6d09 100644 --- a/public/_locales/hi/messages.json +++ b/public/_locales/hi/messages.json @@ -810,7 +810,7 @@ "message": "पुनर्स्थापना" }, "Option_RestoreFromBackup_legacy": { - "message": "लेगेसी माइग्रेशन" + "message": "बैकअप अपडेट करें" }, "Option_RestoreFromBackup_daily": { "message": "दैनिक बैकअप" diff --git a/public/_locales/id/messages.json b/public/_locales/id/messages.json index 3c270188..38176660 100644 --- a/public/_locales/id/messages.json +++ b/public/_locales/id/messages.json @@ -813,7 +813,7 @@ "message": "Pulihkan" }, "Option_RestoreFromBackup_legacy": { - "message": "Migrasi Warisan" + "message": "Perbarui Cadangan" }, "Option_RestoreFromBackup_daily": { "message": "Cadangan Harian" diff --git a/public/_locales/it/messages.json b/public/_locales/it/messages.json index 5d869372..81f7d5d6 100644 --- a/public/_locales/it/messages.json +++ b/public/_locales/it/messages.json @@ -810,7 +810,7 @@ "message": "Ripristina" }, "Option_RestoreFromBackup_legacy": { - "message": "Migrazione Legacy" + "message": "Aggiorna Backup" }, "Option_RestoreFromBackup_daily": { "message": "Backup Giornaliero" diff --git a/public/_locales/ja/messages.json b/public/_locales/ja/messages.json index ac4e67e6..56365043 100644 --- a/public/_locales/ja/messages.json +++ b/public/_locales/ja/messages.json @@ -816,7 +816,7 @@ "message": "復元" }, "Option_RestoreFromBackup_legacy": { - "message": "レガシー移行" + "message": "更新時バックアップ" }, "Option_RestoreFromBackup_daily": { "message": "日次バックアップ" diff --git a/public/_locales/ko/messages.json b/public/_locales/ko/messages.json index a29e72d7..f7f8060a 100644 --- a/public/_locales/ko/messages.json +++ b/public/_locales/ko/messages.json @@ -810,7 +810,7 @@ "message": "복원" }, "Option_RestoreFromBackup_legacy": { - "message": "레거시 마이그레이션" + "message": "백업 업데이트" }, "Option_RestoreFromBackup_daily": { "message": "일간 백업" diff --git a/public/_locales/ms/messages.json b/public/_locales/ms/messages.json index 6dde455f..35c1830e 100644 --- a/public/_locales/ms/messages.json +++ b/public/_locales/ms/messages.json @@ -813,7 +813,7 @@ "message": "Pulihkan" }, "Option_RestoreFromBackup_legacy": { - "message": "Migrasi Legasi" + "message": "Kemas Kini Sandaran" }, "Option_RestoreFromBackup_daily": { "message": "Sandaran Harian" diff --git a/public/_locales/pt_BR/messages.json b/public/_locales/pt_BR/messages.json index d19dd0e3..e9a14ac4 100644 --- a/public/_locales/pt_BR/messages.json +++ b/public/_locales/pt_BR/messages.json @@ -813,7 +813,7 @@ "message": "Restaurar" }, "Option_RestoreFromBackup_legacy": { - "message": "Migração Legada" + "message": "Atualizar Backup" }, "Option_RestoreFromBackup_daily": { "message": "Backup Diário" diff --git a/public/_locales/pt_PT/messages.json b/public/_locales/pt_PT/messages.json index 206ab9ad..550bdc2e 100644 --- a/public/_locales/pt_PT/messages.json +++ b/public/_locales/pt_PT/messages.json @@ -813,7 +813,7 @@ "message": "Restaurar" }, "Option_RestoreFromBackup_legacy": { - "message": "Migração Legada" + "message": "Atualizar Cópia de Segurança" }, "Option_RestoreFromBackup_daily": { "message": "Cópia de Segurança Diária" diff --git a/public/_locales/ru/messages.json b/public/_locales/ru/messages.json index 6bb4ca45..d7b2d03d 100644 --- a/public/_locales/ru/messages.json +++ b/public/_locales/ru/messages.json @@ -810,7 +810,7 @@ "message": "Восстановить" }, "Option_RestoreFromBackup_legacy": { - "message": "Унаследованная миграция" + "message": "Обновить резервную копию" }, "Option_RestoreFromBackup_daily": { "message": "Ежедневная резервная копия" diff --git a/public/_locales/zh_CN/messages.json b/public/_locales/zh_CN/messages.json index 84dfeaa9..ba635ca3 100644 --- a/public/_locales/zh_CN/messages.json +++ b/public/_locales/zh_CN/messages.json @@ -810,7 +810,7 @@ "message": "恢复" }, "Option_RestoreFromBackup_legacy": { - "message": "传统迁移" + "message": "更新备份" }, "Option_RestoreFromBackup_daily": { "message": "每日备份" diff --git a/src/action/addPageRule.ts b/src/action/addPageRule.ts index ef756b1a..58af4aca 100644 --- a/src/action/addPageRule.ts +++ b/src/action/addPageRule.ts @@ -1,4 +1,4 @@ -import { Ipc, BgCommand } from '@/services/ipc' +import { Ipc, BgCommand } from "@/services/ipc" export const AddPageRule = { async execute() { diff --git a/src/action/api.ts b/src/action/api.ts index ad887c5e..df5a4c2f 100644 --- a/src/action/api.ts +++ b/src/action/api.ts @@ -1,7 +1,7 @@ -import { Ipc, BgCommand } from '@/services/ipc' -import { sleep, toUrl, isValidString } from '@/lib/utils' -import type { ExecuteCommandParams, ApiCommand } from '@/types' -import { OPEN_MODE, ExecState, SPACE_ENCODING } from '@/const' +import { Ipc, BgCommand } from "@/services/ipc" +import { sleep, toUrl, isValidString } from "@/lib/utils" +import type { ExecuteCommandParams, ApiCommand } from "@/types" +import { OPEN_MODE, ExecState, SPACE_ENCODING } from "@/const" const isApiCommand = (command: any): command is ApiCommand => { return command.OpenMode === OPEN_MODE.API @@ -16,28 +16,28 @@ export const Api = { changeState(ExecState.EXECUTING) if (!isValidString(command.searchUrl)) { - console.error('searchUrl is not valid.') + console.error("searchUrl is not valid.") return } if (!isApiCommand(command)) { - console.error('command is not for Api.') + console.error("command is not for Api.") return } // Get current URL and title - let pageUrl = '' - let pageTitle = '' + let pageUrl = "" + let pageTitle = "" try { const currentTab = await chrome.tabs.query({ active: true, }) if (currentTab[0]) { - pageUrl = currentTab[0].url ?? '' - pageTitle = currentTab[0].title ?? '' + pageUrl = currentTab[0].url ?? "" + pageTitle = currentTab[0].title ?? "" } } catch (error) { - console.warn('Failed to get current tab info:', error) + console.warn("Failed to get current tab info:", error) } Ipc.send(BgCommand.execApi, { @@ -54,10 +54,10 @@ export const Api = { }) .then(({ ok, res }) => { if (ok) { - changeState(ExecState.SUCCESS, 'Success!') + changeState(ExecState.SUCCESS, "Success!") } else { console.error(res) - changeState(ExecState.FAIL, 'Failed...') + changeState(ExecState.FAIL, "Failed...") } return sleep(1500) }) diff --git a/src/action/background.ts b/src/action/background.ts index 69e4fcd6..51be96bb 100644 --- a/src/action/background.ts +++ b/src/action/background.ts @@ -1,11 +1,11 @@ -import { OPEN_MODE_BG } from '@/const' -import { Popup } from './popup' -import { Window } from './window' -import { Tab } from './tab' -import { Api } from './api' -import { PageAction } from './pageAction' -import { executeAction } from './executor' -import type { ExecuteCommandParams } from '@/types' +import { OPEN_MODE_BG } from "@/const" +import { Popup } from "./popup" +import { Window } from "./window" +import { Tab } from "./tab" +import { Api } from "./api" +import { PageAction } from "./pageAction" +import { executeAction } from "./executor" +import type { ExecuteCommandParams } from "@/types" export const actionsForBackground = { [OPEN_MODE_BG.POPUP]: Popup, diff --git a/src/action/copy.ts b/src/action/copy.ts index d5c33bbd..d00cedd5 100644 --- a/src/action/copy.ts +++ b/src/action/copy.ts @@ -1,14 +1,14 @@ -import { sleep, isEmpty } from '@/lib/utils' -import { getSelectionText } from '@/services/dom' -import type { CopyCommand, ExecuteCommandParams } from '@/types' -import { OPEN_MODE, ExecState } from '@/const' +import { sleep, isEmpty } from "@/lib/utils" +import { getSelectionText } from "@/services/dom" +import type { CopyCommand, ExecuteCommandParams } from "@/types" +import { OPEN_MODE, ExecState } from "@/const" const isCopyCommand = (command: any): command is CopyCommand => { return command.openMode === OPEN_MODE.COPY } async function setClipboard(text: string) { - const type = 'text/plain' + const type = "text/plain" const blob = new Blob([text], { type }) const data = [new ClipboardItem({ [type]: blob })] await navigator.clipboard.write(data) @@ -22,33 +22,33 @@ export const Copy = { changeState = () => {}, }: ExecuteCommandParams) { if (!isCopyCommand(command)) { - console.error('command is not for Copy.') + console.error("command is not for Copy.") return } changeState(ExecState.EXECUTING) const currentText = getSelectionText() - let mode = command.copyOption ?? 'default' + let mode = command.copyOption ?? "default" if (useSecondary) { - if (mode === 'default') { - mode = 'text' + if (mode === "default") { + mode = "text" } else { - mode = 'default' + mode = "default" } } - if (mode === 'default') { + if (mode === "default") { if (isEmpty(currentText)) { await setClipboard(selectionText) } else { - document.execCommand('copy') + document.execCommand("copy") } - } else if (mode === 'text') { + } else if (mode === "text") { await setClipboard(selectionText) } - changeState(ExecState.SUCCESS, 'Copied!') + changeState(ExecState.SUCCESS, "Copied!") await sleep(500) changeState(ExecState.NONE) }, diff --git a/src/action/executor.ts b/src/action/executor.ts index 930eb14e..ef8184cf 100644 --- a/src/action/executor.ts +++ b/src/action/executor.ts @@ -1,6 +1,6 @@ -import type { ExecuteCommandParams } from '@/types' -import { OPEN_MODE } from '@/const' -import { sendEvent, ANALYTICS_EVENTS } from '@/services/analytics' +import type { ExecuteCommandParams } from "@/types" +import { OPEN_MODE } from "@/const" +import { sendEvent, ANALYTICS_EVENTS } from "@/services/analytics" export async function executeAction({ actions, @@ -15,7 +15,7 @@ export async function executeAction({ let mode = command.openMode as OPEN_MODE if ( useSecondary && - 'openModeSecondary' in command && + "openModeSecondary" in command && command.openModeSecondary ) { mode = command.openModeSecondary diff --git a/src/action/getStyles.tsx b/src/action/getStyles.tsx index 304db38e..1b1714a2 100644 --- a/src/action/getStyles.tsx +++ b/src/action/getStyles.tsx @@ -1,5 +1,5 @@ -import type { ExecuteCommandParams } from '@/types' -import { TextStyle } from '@/components/result/TextStyle' +import type { ExecuteCommandParams } from "@/types" +import { TextStyle } from "@/components/result/TextStyle" export const GetStyles = { async execute({ target }: ExecuteCommandParams) { @@ -14,10 +14,10 @@ export const GetStyles = { } const CANVAS_OPTIONS = { - fillStyle: 'rgb(0,0,0)', + fillStyle: "rgb(0,0,0)", height: 50, - size: '40px', - textBaseline: 'top', + size: "40px", + textBaseline: "top", width: 600, } @@ -25,12 +25,12 @@ function getFontOption(css: FontCSS) { return `${css.fontStyle} ${css.fontWeight} ${CANVAS_OPTIONS.size} ${css.fontFamily}` } -function getCanvasData(css: FontCSS, text = 'abcdefghijklmnopqrstuvwxyz') { - const canvas = document.createElement('canvas') +function getCanvasData(css: FontCSS, text = "abcdefghijklmnopqrstuvwxyz") { + const canvas = document.createElement("canvas") canvas.width = CANVAS_OPTIONS.width canvas.height = CANVAS_OPTIONS.height - const ctx = canvas.getContext('2d') + const ctx = canvas.getContext("2d") if (!ctx) return null Object.assign(ctx, CANVAS_OPTIONS) @@ -39,7 +39,7 @@ function getCanvasData(css: FontCSS, text = 'abcdefghijklmnopqrstuvwxyz') { ctx.fillText(text, 0, 0) return canvas - .getContext('2d') + .getContext("2d") ?.getImageData(0, 0, CANVAS_OPTIONS.width, CANVAS_OPTIONS.height).data } @@ -68,11 +68,11 @@ const getActiveFont = (css: FontCSS) => { for (let f = 0; f < stack.length; f++) { const serifStyle = { ...css, - fontFamily: stack[f] + ', serif', + fontFamily: stack[f] + ", serif", } const sansSerifStyle = { ...css, - fontFamily: stack[f] + ', sans-serif', + fontFamily: stack[f] + ", sans-serif", } if ( @@ -90,11 +90,11 @@ function getFontCSS(element: HTMLElement): FontCSS { return { fontFamily: getActiveFont(computed), - fontWeight: computed.getPropertyValue('font-weight') || 'normal', - fontStyle: computed.getPropertyValue('font-style') || 'normal', - fontSize: computed.getPropertyValue('font-size'), - color: computed.getPropertyValue('color'), - lineHeight: computed.getPropertyValue('line-height'), - letterSpacing: computed.getPropertyValue('letter-spacing'), + fontWeight: computed.getPropertyValue("font-weight") || "normal", + fontStyle: computed.getPropertyValue("font-style") || "normal", + fontSize: computed.getPropertyValue("font-size"), + color: computed.getPropertyValue("color"), + lineHeight: computed.getPropertyValue("line-height"), + letterSpacing: computed.getPropertyValue("letter-spacing"), } } diff --git a/src/action/helper.ts b/src/action/helper.ts index de30c5ea..e5a5992f 100644 --- a/src/action/helper.ts +++ b/src/action/helper.ts @@ -1,4 +1,4 @@ -import { escapeJson } from '@/lib/utils' +import { escapeJson } from "@/lib/utils" import { openPopupWindow, openPopupWindowMultiple, @@ -6,10 +6,10 @@ import { OpenPopupsProps, OpenPopupProps, OpenTabProps, -} from '@/services/chrome' -import { incrementCommandExecutionCount } from '@/services/commandMetrics' -import { Ipc, TabCommand } from '@/services/ipc' -import type { CommandVariable } from '@/types' +} from "@/services/chrome" +import { incrementCommandExecutionCount } from "@/services/commandMetrics" +import { Ipc, TabCommand } from "@/services/ipc" +import type { CommandVariable } from "@/types" type Sender = chrome.runtime.MessageSender @@ -36,7 +36,7 @@ export const openPopup = ( await openPopupWindow(param) response(true) } catch (error) { - console.error('Failed to execute openPopups:', error) + console.error("Failed to execute openPopups:", error) response(false) } }) @@ -53,7 +53,7 @@ export const openPopups = ( await openPopupWindowMultiple(param) response(true) } catch (error) { - console.error('Failed to execute openPopups:', error) + console.error("Failed to execute openPopups:", error) response(false) } }) @@ -73,7 +73,7 @@ export const openPopupAndClick = ( }) response(true) } catch (error) { - console.error('Failed to execute openPopupAndClick:', error) + console.error("Failed to execute openPopupAndClick:", error) response(false) } }) @@ -104,7 +104,7 @@ function bindVariables( } let res = str for (const v of arr) { - const re = new RegExp(`\\$\\{${v.name}\\}`, 'g') + const re = new RegExp(`\\$\\{${v.name}\\}`, "g") res = res.replace(re, v.value) } return res diff --git a/src/action/index.ts b/src/action/index.ts index 93837652..514b9bc0 100644 --- a/src/action/index.ts +++ b/src/action/index.ts @@ -1,16 +1,16 @@ -import { OPEN_MODE } from '@/const' -import { Popup } from './popup' -import { Window } from './window' -import { Tab } from './tab' -import { Api } from './api' -import { SelectedLinkPopup } from './selectedLinkPopup' -import { Copy } from './copy' -import { PageAction } from './pageAction' -import { Option } from './option' -import { GetStyles as GetTextStyles } from './getStyles' -import { AddPageRule } from './addPageRule' -import { executeAction } from './executor' -import type { ExecuteCommandParams } from '@/types' +import { OPEN_MODE } from "@/const" +import { Popup } from "./popup" +import { Window } from "./window" +import { Tab } from "./tab" +import { Api } from "./api" +import { SelectedLinkPopup } from "./selectedLinkPopup" +import { Copy } from "./copy" +import { PageAction } from "./pageAction" +import { Option } from "./option" +import { GetStyles as GetTextStyles } from "./getStyles" +import { AddPageRule } from "./addPageRule" +import { executeAction } from "./executor" +import type { ExecuteCommandParams } from "@/types" export const actions = { [OPEN_MODE.POPUP]: Popup, diff --git a/src/action/linkPreview.ts b/src/action/linkPreview.ts index 2b423588..f55f24d1 100644 --- a/src/action/linkPreview.ts +++ b/src/action/linkPreview.ts @@ -1,13 +1,13 @@ -import { Ipc, BgCommand } from '@/services/ipc' +import { Ipc, BgCommand } from "@/services/ipc" import { findAnchorElementFromParent, findClickableElement, getSelectorFromElement, -} from '@/services/dom' -import { getScreenSize } from '@/services/screen' -import { DRAG_OPEN_MODE, POPUP_TYPE } from '@/const' -import { isEmpty } from '@/lib/utils' -import type { ExecuteCommandParams } from '@/types' +} from "@/services/dom" +import { getScreenSize } from "@/services/screen" +import { DRAG_OPEN_MODE, POPUP_TYPE } from "@/const" +import { isEmpty } from "@/lib/utils" +import type { ExecuteCommandParams } from "@/types" export const LinkPreview = { async execute({ command, position, target }: ExecuteCommandParams) { @@ -34,7 +34,7 @@ export const LinkPreview = { return } - console.warn('Href not found, trying to find clickable element') + console.warn("Href not found, trying to find clickable element") const clickElm = findClickableElement(target) if (clickElm) { diff --git a/src/action/option.ts b/src/action/option.ts index fb8c610e..dd509083 100644 --- a/src/action/option.ts +++ b/src/action/option.ts @@ -1,4 +1,4 @@ -import { Ipc, BgCommand } from '@/services/ipc' +import { Ipc, BgCommand } from "@/services/ipc" export const Option = { async execute() { diff --git a/src/action/pageAction.ts b/src/action/pageAction.ts index 105535b6..eca25a92 100644 --- a/src/action/pageAction.ts +++ b/src/action/pageAction.ts @@ -1,10 +1,10 @@ -import { Ipc, BgCommand } from '@/services/ipc' -import { getScreenSize, getWindowPosition } from '@/services/screen' -import { isValidString, isPageActionCommand } from '@/lib/utils' -import { PAGE_ACTION_OPEN_MODE } from '@/const' -import { PopupOption } from '@/services/option/defaultSettings' -import type { ExecuteCommandParams, UrlParam } from '@/types' -import type { OpenAndRunProps } from '@/services/pageAction/background' +import { Ipc, BgCommand } from "@/services/ipc" +import { getScreenSize, getWindowPosition } from "@/services/screen" +import { isValidString, isPageActionCommand } from "@/lib/utils" +import { PAGE_ACTION_OPEN_MODE } from "@/const" +import { PopupOption } from "@/services/option/defaultSettings" +import type { ExecuteCommandParams, UrlParam } from "@/types" +import type { OpenAndRunProps } from "@/services/pageAction/background" export const PageAction = { async execute({ @@ -15,16 +15,16 @@ export const PageAction = { useClipboard, }: ExecuteCommandParams) { if (!isPageActionCommand(command)) { - console.error('command is not for PageAction.') + console.error("command is not for PageAction.") return } if (!isValidString(command.pageActionOption?.startUrl)) { - console.error('searchUrl is not valid.') + console.error("searchUrl is not valid.") return } if (position === null) { - console.error('position is null.') + console.error("position is null.") return } diff --git a/src/action/popup.ts b/src/action/popup.ts index 7de75849..8da9ca58 100644 --- a/src/action/popup.ts +++ b/src/action/popup.ts @@ -1,10 +1,10 @@ -import { Ipc, BgCommand } from '@/services/ipc' -import { isValidString } from '@/lib/utils' -import { getScreenSize, getWindowPosition } from '@/services/screen' -import { POPUP_TYPE, SPACE_ENCODING } from '@/const' -import { PopupOption } from '@/services/option/defaultSettings' -import type { ExecuteCommandParams } from '@/types' -import type { OpenPopupProps } from '@/services/chrome' +import { Ipc, BgCommand } from "@/services/ipc" +import { isValidString } from "@/lib/utils" +import { getScreenSize, getWindowPosition } from "@/services/screen" +import { POPUP_TYPE, SPACE_ENCODING } from "@/const" +import { PopupOption } from "@/services/option/defaultSettings" +import type { ExecuteCommandParams } from "@/types" +import type { OpenPopupProps } from "@/services/chrome" export const Popup = { async execute({ @@ -14,11 +14,11 @@ export const Popup = { useClipboard, }: ExecuteCommandParams) { if (!isValidString(command.searchUrl)) { - console.error('searchUrl is not valid.') + console.error("searchUrl is not valid.") return } if (position === null) { - console.error('position is null.') + console.error("position is null.") return } diff --git a/src/action/selectedLinkPopup.ts b/src/action/selectedLinkPopup.ts index 7cdd7ac0..273b277b 100644 --- a/src/action/selectedLinkPopup.ts +++ b/src/action/selectedLinkPopup.ts @@ -1,7 +1,7 @@ -import { Ipc, BgCommand } from '@/services/ipc' -import { linksInSelection } from '@/services/dom' -import { getScreenSize } from '@/services/screen' -import type { ExecuteCommandParams } from '@/types' +import { Ipc, BgCommand } from "@/services/ipc" +import { linksInSelection } from "@/services/dom" +import { getScreenSize } from "@/services/screen" +import type { ExecuteCommandParams } from "@/types" export const SelectedLinkPopup = { async execute({ command, position }: ExecuteCommandParams) { diff --git a/src/action/tab.ts b/src/action/tab.ts index 618fa539..be90a90e 100644 --- a/src/action/tab.ts +++ b/src/action/tab.ts @@ -1,8 +1,8 @@ -import { Ipc, BgCommand } from '@/services/ipc' -import { isValidString } from '@/lib/utils' -import { SPACE_ENCODING } from '@/const' -import type { ExecuteCommandParams } from '@/types' -import type { OpenTabProps } from '@/services/chrome' +import { Ipc, BgCommand } from "@/services/ipc" +import { isValidString } from "@/lib/utils" +import { SPACE_ENCODING } from "@/const" +import type { ExecuteCommandParams } from "@/types" +import type { OpenTabProps } from "@/services/chrome" export const Tab = { async execute({ @@ -12,7 +12,7 @@ export const Tab = { useClipboard, }: ExecuteCommandParams) { if (!isValidString(command.searchUrl)) { - console.error('searchUrl is not valid.') + console.error("searchUrl is not valid.") return } diff --git a/src/action/window.ts b/src/action/window.ts index d7a56e12..f803f6b1 100644 --- a/src/action/window.ts +++ b/src/action/window.ts @@ -1,10 +1,10 @@ -import { Ipc, BgCommand } from '@/services/ipc' -import { isValidString } from '@/lib/utils' -import { getScreenSize, getWindowPosition } from '@/services/screen' -import { POPUP_TYPE, SPACE_ENCODING } from '@/const' -import { PopupOption } from '@/services/option/defaultSettings' -import type { OpenPopupProps } from '@/services/chrome' -import type { ExecuteCommandParams } from '@/types' +import { Ipc, BgCommand } from "@/services/ipc" +import { isValidString } from "@/lib/utils" +import { getScreenSize, getWindowPosition } from "@/services/screen" +import { POPUP_TYPE, SPACE_ENCODING } from "@/const" +import { PopupOption } from "@/services/option/defaultSettings" +import type { OpenPopupProps } from "@/services/chrome" +import type { ExecuteCommandParams } from "@/types" export const Window = { async execute({ @@ -14,11 +14,11 @@ export const Window = { useClipboard, }: ExecuteCommandParams) { if (!isValidString(command.searchUrl)) { - console.error('searchUrl is not valid.') + console.error("searchUrl is not valid.") return } if (position === null) { - console.error('position is null.') + console.error("position is null.") return } diff --git a/src/background_script.ts b/src/background_script.ts index 54f5bf88..fe95b7bb 100644 --- a/src/background_script.ts +++ b/src/background_script.ts @@ -6,29 +6,29 @@ import { SHORTCUT_NO_SELECTION_BEHAVIOR, HUB_URL, SCREEN, -} from '@/const' -import { executeActionProps } from '@/services/contextMenus' -import { Ipc, BgCommand, TabCommand } from '@/services/ipc' -import { Settings } from '@/services/settings' -import { PopupOption, PopupPlacement } from '@/services/option/defaultSettings' -import * as PageActionBackground from '@/services/pageAction/background' -import { BgData } from '@/services/backgroundData' -import { ContextMenu } from '@/services/contextMenus' -import { closeWindow } from '@/services/chrome' -import { isSearchCommand, isPageActionCommand } from '@/lib/utils' -import { execute } from '@/action/background' -import * as ActionHelper from '@/action/helper' -import type { IpcCallback } from '@/services/ipc' +} from "@/const" +import { executeActionProps } from "@/services/contextMenus" +import { Ipc, BgCommand, TabCommand } from "@/services/ipc" +import { Settings } from "@/services/settings" +import { PopupOption, PopupPlacement } from "@/services/option/defaultSettings" +import * as PageActionBackground from "@/services/pageAction/background" +import { BgData } from "@/services/backgroundData" +import { ContextMenu } from "@/services/contextMenus" +import { closeWindow } from "@/services/chrome" +import { isSearchCommand, isPageActionCommand } from "@/lib/utils" +import { execute } from "@/action/background" +import * as ActionHelper from "@/action/helper" +import type { IpcCallback } from "@/services/ipc" import type { WindowType, WindowLayer, CaptureData, CaptureDataStorage, CaptureScreenShotRes, -} from '@/types' -import { Storage, SESSION_STORAGE_KEY } from '@/services/storage' -import { updateActiveScreenId } from '@/services/screen' -import { ANALYTICS_EVENTS, sendEvent } from './services/analytics' +} from "@/types" +import { Storage, SESSION_STORAGE_KEY } from "@/services/storage" +import { updateActiveScreenId } from "@/services/screen" +import { ANALYTICS_EVENTS, sendEvent } from "./services/analytics" BgData.init() @@ -67,7 +67,7 @@ const commandFuncs = { [BgCommand.openShortcuts]: (): boolean => { chrome.tabs.create({ - url: 'chrome://extensions/shortcuts', + url: "chrome://extensions/shortcuts", }) return false }, @@ -131,7 +131,7 @@ const commandFuncs = { : null if (!cmd) { - console.error('invalid command', param.command) + console.error("invalid command", param.command) response(false) return true } @@ -178,9 +178,9 @@ const commandFuncs = { } } if (!w || w.srcWindowId == null) { - console.warn('window not found', sender.tab?.windowId) + console.warn("window not found", sender.tab?.windowId) chrome.tabs.create({ url: sender.url }) - closeWindow(sender.tab?.windowId as number, 'openInTab').then(() => { + closeWindow(sender.tab?.windowId as number, "openInTab").then(() => { response(true) }) return true @@ -205,7 +205,7 @@ const commandFuncs = { url: sender.url, windowId: targetId, }) - closeWindow(sender.tab?.windowId as number, 'openInTab').then(() => { + closeWindow(sender.tab?.windowId as number, "openInTab").then(() => { response(true) }) } else { @@ -246,7 +246,7 @@ const commandFuncs = { } // Remove the window. - await closeWindow(windowId, 'onHidden') + await closeWindow(windowId, "onHidden") layer.splice( layer.findIndex((w) => w.id === windowId), 1, @@ -293,11 +293,11 @@ const commandFuncs = { const tabId = sender.tab?.id const windowId = sender.tab?.windowId if (!tabId || !windowId) { - response({ success: false, error: 'TabId or WindowId not found.' }) + response({ success: false, error: "TabId or WindowId not found." }) return true } - chrome.tabs.captureVisibleTab(windowId, { format: 'png' }, (dataUrl) => { + chrome.tabs.captureVisibleTab(windowId, { format: "png" }, (dataUrl) => { if (chrome.runtime.lastError) { response({ success: false, error: chrome.runtime.lastError.message }) return @@ -364,7 +364,7 @@ const updateWindowSize = async ( } await Settings.updateCommands([found]) } else { - console.warn('command not found', commandId) + console.warn("command not found", commandId) } } @@ -379,7 +379,7 @@ chrome.windows.onFocusChanged.addListener(async (windowId: number) => { let stack = data.windowStack // Clear selection text - await Storage.set(SESSION_STORAGE_KEY.SELECTION_TEXT, '') + await Storage.set(SESSION_STORAGE_KEY.SELECTION_TEXT, "") if (windowId === chrome.windows.WINDOW_ID_NONE) { return @@ -414,7 +414,7 @@ chrome.windows.onFocusChanged.addListener(async (windowId: number) => { if (closeStack.length > 0) { for (const layer of closeStack) { for (const window of layer) { - await closeWindow(window.id, 'onFocusChanged') + await closeWindow(window.id, "onFocusChanged") } } } @@ -460,7 +460,7 @@ chrome.tabs.onActivated.addListener(async (activeInfo) => { const ret = await Ipc.sendAllTab(TabCommand.closeMenu) ret.filter((v) => v).forEach((v) => console.debug(v)) } catch (error) { - console.error('Failed to close menu:', error) + console.error("Failed to close menu:", error) } // Get the active tab's window and update screen ID @@ -470,14 +470,14 @@ chrome.tabs.onActivated.addListener(async (activeInfo) => { await updateActiveScreenId(tab.windowId) } } catch (error) { - console.error('Failed to get active screen ID:', error) + console.error("Failed to get active screen ID:", error) } }) if (isDebug) { chrome.action.setIcon({ path: { - 128: '/icon128-dev.png', + 128: "/icon128-dev.png", }, }) } @@ -486,7 +486,7 @@ chrome.runtime.onInstalled.addListener((details) => { ContextMenu.init() chrome.storage.session.setAccessLevel({ - accessLevel: 'TRUSTED_AND_UNTRUSTED_CONTEXTS', + accessLevel: "TRUSTED_AND_UNTRUSTED_CONTEXTS", }) if ( @@ -520,7 +520,7 @@ const checkAndPerformDailyBackup = async () => { await dailyBackupManager.performDailyBackup() } } catch (error) { - console.error('Failed to perform daily backup check:', error) + console.error("Failed to perform daily backup check:", error) } } @@ -532,7 +532,7 @@ const checkAndPerformWeeklyBackup = async () => { await weeklyBackupManager.performWeeklyBackup() } } catch (error) { - console.error('Failed to perform weekly backup check:', error) + console.error("Failed to perform weekly backup check:", error) } } @@ -569,8 +569,8 @@ chrome.commands.onCommand.addListener(async (commandName) => { const enableSendTab = tab?.id && - !tab.url?.startsWith('chrome') && - !tab.url?.includes('chromewebstore.google.com') + !tab.url?.startsWith("chrome") && + !tab.url?.includes("chromewebstore.google.com") const selectionText = await Storage.get( SESSION_STORAGE_KEY.SELECTION_TEXT, @@ -623,6 +623,6 @@ chrome.commands.onCommand.addListener(async (commandName) => { SCREEN.SERVICE_WORKER, ) } catch (error) { - console.error('Failed to execute shortcut command:', error) + console.error("Failed to execute shortcut command:", error) } }) diff --git a/src/clipboard.ts b/src/clipboard.ts index 25deba05..de532dab 100644 --- a/src/clipboard.ts +++ b/src/clipboard.ts @@ -1,4 +1,4 @@ -import { ClipboardResult, BgCommand } from '@/services/ipc' +import { ClipboardResult, BgCommand } from "@/services/ipc" /** * Read text from clipboard with retry mechanism @@ -24,12 +24,12 @@ const readClipboardWithRetry = async ( await new Promise((resolve) => setTimeout(resolve, delayMs)) } } - return { data: undefined, err: 'Out of retries.' } + return { data: undefined, err: "Out of retries." } } -const port = chrome.runtime.connect({ name: 'clipboard' }) +const port = chrome.runtime.connect({ name: "clipboard" }) port.onDisconnect.addListener(function (port) { - console.warn('onDisconnect', port.name) + console.warn("onDisconnect", port.name) }) readClipboardWithRetry() diff --git a/src/command_hub.css b/src/command_hub.css index 41132fe6..98dbf883 100644 --- a/src/command_hub.css +++ b/src/command_hub.css @@ -1 +1 @@ -@import url('components/global.css'); +@import url("components/global.css"); diff --git a/src/command_hub.tsx b/src/command_hub.tsx index ce590f4f..cc6d791b 100644 --- a/src/command_hub.tsx +++ b/src/command_hub.tsx @@ -1,17 +1,17 @@ -import { createRoot } from 'react-dom/client' -import { APP_ID, isDebug } from './const' -import './command_hub.css' -import { CommandHub } from '@/components/commandHub/CommandHub' -import { MyCommands } from '@/components/commandHub/MyCommands' +import { createRoot } from "react-dom/client" +import { APP_ID, isDebug } from "./const" +import "./command_hub.css" +import { CommandHub } from "@/components/commandHub/CommandHub" +import { MyCommands } from "@/components/commandHub/MyCommands" -const url = chrome.runtime.getURL('/assets/command_hub.css') -const mode = isDebug ? 'open' : 'closed' // 'open' for debugging +const url = chrome.runtime.getURL("/assets/command_hub.css") +const mode = isDebug ? "open" : "closed" // 'open' for debugging const insertCss = (elm: ShadowRoot) => { fetch(url) .then((res) => res.text()) .then((css) => { - const style = document.createElement('style') + const style = document.createElement("style") style.append(document.createTextNode(css)) elm.insertBefore(style, elm.firstChild) }) @@ -25,9 +25,9 @@ const cloneCss = (from: ShadowRoot, to: ShadowRoot, selector: string) => { } function setupCommandHub() { - const rootDom = document.createElement('div') + const rootDom = document.createElement("div") rootDom.id = `${APP_ID}-command-hub` - document.body.insertAdjacentElement('afterend', rootDom) + document.body.insertAdjacentElement("afterend", rootDom) const shadow = rootDom.attachShadow({ mode }) const root = createRoot(shadow) root.render() @@ -37,18 +37,18 @@ function setupCommandHub() { } function renderMyCommands() { - const container = document.getElementById('MyCommands') + const container = document.getElementById("MyCommands") if (container) { const shadow = container.attachShadow({ mode }) const root = createRoot(shadow) root.render() - container.style.display = 'block' + container.style.display = "block" if (isDebug) { const from = document.getElementById( - 'selection-command-command-hub', + "selection-command-command-hub", )?.shadowRoot - from && cloneCss(from, shadow, 'style') + from && cloneCss(from, shadow, "style") } else { insertCss(shadow) } @@ -62,7 +62,7 @@ function setupMyCommnands() { // Find the CommandShare form. if ( node instanceof HTMLElement && - (node.id === 'CommandShare' || node.id === 'InputForm') + (node.id === "CommandShare" || node.id === "InputForm") ) { renderMyCommands() } diff --git a/src/components/App.css b/src/components/App.css index 01b944d8..1acebd96 100644 --- a/src/components/App.css +++ b/src/components/App.css @@ -1,10 +1,11 @@ -@import url('global.css'); -@import url('Animation.css'); +@import url("global.css"); +@import url("Animation.css"); :host, :root { - --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - 'Helvetica Neue', Arial, sans-serif; - --font-monospace: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + --font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, sans-serif; + --font-monospace: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/src/components/App.tsx b/src/components/App.tsx index db9b13d3..79384f30 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,20 +1,20 @@ -import './App.css' +import "./App.css" -import { useState, useEffect } from 'react' -import { SelectAnchor } from './SelectAnchor' -import { Popup } from './Popup' -import { LinkSelector } from '@/components/LinkSelector' -import { OpenInTab } from '@/components/OpenInTab' -import { PageActionRecorder } from '@/components/pageAction/PageActionRecorder' -import { PageActionRunner } from '@/components/pageAction/PageActionRunner' -import { SelectContextProvider } from '@/hooks/useSelectContext' -import { PageActionContextProvider } from '@/hooks/pageAction/usePageActionContext' -import { Ipc, TabCommand, CONNECTION_PORT, BgCommand } from '@/services/ipc' -import { toast, Toaster } from 'sonner' -import { showReviewRequestToast } from '@/components/ReviewRequestToast' -import { Settings } from '@/services/settings' -import { InvisibleItem } from '@/components/menu/InvisibleItem' -import type { ShowToastParam } from '@/types' +import { useState, useEffect } from "react" +import { SelectAnchor } from "./SelectAnchor" +import { Popup } from "./Popup" +import { LinkSelector } from "@/components/LinkSelector" +import { OpenInTab } from "@/components/OpenInTab" +import { PageActionRecorder } from "@/components/pageAction/PageActionRecorder" +import { PageActionRunner } from "@/components/pageAction/PageActionRunner" +import { SelectContextProvider } from "@/hooks/useSelectContext" +import { PageActionContextProvider } from "@/hooks/pageAction/usePageActionContext" +import { Ipc, TabCommand, CONNECTION_PORT, BgCommand } from "@/services/ipc" +import { toast, Toaster } from "sonner" +import { showReviewRequestToast } from "@/components/ReviewRequestToast" +import { Settings } from "@/services/settings" +import { InvisibleItem } from "@/components/menu/InvisibleItem" +import type { ShowToastParam } from "@/types" type Props = { rootElm: HTMLElement @@ -39,10 +39,10 @@ export function App({ rootElm }: Props) { return } }) - window.removeEventListener('pageshow', connect) + window.removeEventListener("pageshow", connect) } connect() - window.addEventListener('pageshow', connect) + window.addEventListener("pageshow", connect) // from background script // console.log('Listen onConnect') @@ -59,7 +59,7 @@ export function App({ rootElm }: Props) { return () => { chrome.runtime.onConnect.removeListener(onConnect) - window.removeEventListener('pageshow', connect) + window.removeEventListener("pageshow", connect) } }, []) @@ -92,7 +92,7 @@ export function App({ rootElm }: Props) { useEffect(() => { const handleShowReviewRequest = (_: any, __: any, response: any) => { showReviewRequestToast(() => { - Settings.update('hasShownReviewRequest', () => true) + Settings.update("hasShownReviewRequest", () => true) }) response(true) return true diff --git a/src/components/CircularProgress.tsx b/src/components/CircularProgress.tsx index f5fdbae6..a5c8d524 100644 --- a/src/components/CircularProgress.tsx +++ b/src/components/CircularProgress.tsx @@ -1,9 +1,9 @@ -import React, { useEffect, useRef } from 'react' -import clsx from 'clsx' -import lottie from 'lottie-web' +import React, { useEffect, useRef } from "react" +import clsx from "clsx" +import lottie from "lottie-web" -import anim from '@/lottie/rippled-circle.json' -import css from './CircularProgress.module.css' +import anim from "@/lottie/rippled-circle.json" +import css from "./CircularProgress.module.css" interface CircularProgressProps { progress: number @@ -13,11 +13,11 @@ interface CircularProgressProps { export const CircularProgress: React.FC = ({ progress, - progressColor = '#3498db', + progressColor = "#3498db", style, }) => { const completeDiv = useRef(null) - const circleColor = '#e0e0e0' + const circleColor = "#e0e0e0" const strokeWidth = 10 const size = 30 const viewBox = 140 @@ -33,7 +33,7 @@ export const CircularProgress: React.FC = ({ if (!completeDiv.current || !isComplete) return lottie.loadAnimation({ container: completeDiv.current, - renderer: 'svg', + renderer: "svg", loop: true, autoplay: true, animationData: anim, diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index 6b68137a..239538d0 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React from "react" type Props = { name: string @@ -9,7 +9,7 @@ type Props = { export function Icon(props: Props): JSX.Element { const href = `#icon-${props.name}` - const className = props.className ?? 'h-full w-full' + const className = props.className ?? "h-full w-full" return ( diff --git a/src/components/LinkClickGuard.tsx b/src/components/LinkClickGuard.tsx index 58b35d9b..23640e7c 100644 --- a/src/components/LinkClickGuard.tsx +++ b/src/components/LinkClickGuard.tsx @@ -1,5 +1,5 @@ -import React, { useState, useEffect, useRef } from 'react' -import { Point } from '@/types' +import React, { useState, useEffect, useRef } from "react" +import { Point } from "@/types" type LinkClickGuardProps = { show: boolean position: Point @@ -34,14 +34,14 @@ export const LinkClickGuard = (props: LinkClickGuardProps) => { setGuard(false) } } - document.addEventListener('mouseup', mouseUp) + document.addEventListener("mouseup", mouseUp) return () => { - document.removeEventListener('mouseup', mouseUp) + document.removeEventListener("mouseup", mouseUp) } }, []) const styles = { - position: 'absolute', + position: "absolute", top: window.scrollY + position.y - 5, left: window.scrollX + position.x - 5, height: 10, diff --git a/src/components/LinkSelector.tsx b/src/components/LinkSelector.tsx index 6e308fec..a9437614 100644 --- a/src/components/LinkSelector.tsx +++ b/src/components/LinkSelector.tsx @@ -1,7 +1,7 @@ -import React from 'react' -import { useDetectLinkCommand } from '@/hooks/useDetectLinkCommand' -import { LinkClickGuard } from '@/components/LinkClickGuard' -import { CircularProgress } from '@/components/CircularProgress' +import React from "react" +import { useDetectLinkCommand } from "@/hooks/useDetectLinkCommand" +import { LinkClickGuard } from "@/components/LinkClickGuard" +import { CircularProgress } from "@/components/CircularProgress" export function LinkSelector(): JSX.Element { const { @@ -16,20 +16,20 @@ export function LinkSelector(): JSX.Element { if (!mousePosition || !inProgress) return <> const styles = { - position: 'absolute', + position: "absolute", height: 8, width: 8, top: window.scrollY + mousePosition.y - 4, left: window.scrollX + mousePosition.x - 4, zIndex: 2147483647, opacity: preventLinkClick ? 0 : 1, - pointerEvents: 'none', + pointerEvents: "none", // border: '1px solid red', } as React.CSSProperties if (detectDrag) { - styles.cursor = 'grabbing' - styles.pointerEvents = 'auto' + styles.cursor = "grabbing" + styles.pointerEvents = "auto" } const circleStyles = { diff --git a/src/components/OpenInTab.tsx b/src/components/OpenInTab.tsx index 67c8252b..49be78dd 100644 --- a/src/components/OpenInTab.tsx +++ b/src/components/OpenInTab.tsx @@ -1,7 +1,7 @@ -import { useEffect, useState } from 'react' -import { Ipc, BgCommand } from '@/services/ipc' -import { Icon } from '../components/Icon' -import './OpenInTab.css' +import { useEffect, useState } from "react" +import { Ipc, BgCommand } from "@/services/ipc" +import { Icon } from "../components/Icon" +import "./OpenInTab.css" let isPageUnloading = false @@ -32,12 +32,12 @@ export function OpenInTab(): JSX.Element { } if (enableOpenInTab) { - window.addEventListener('pagehide', onPagehide) - document.addEventListener('visibilitychange', onHidden) + window.addEventListener("pagehide", onPagehide) + document.addEventListener("visibilitychange", onHidden) } return () => { - window.removeEventListener('pagehide', onPagehide) - document.removeEventListener('visibilitychange', onHidden) + window.removeEventListener("pagehide", onPagehide) + document.removeEventListener("visibilitychange", onHidden) } }, [enableOpenInTab]) diff --git a/src/components/Popup.module.css b/src/components/Popup.module.css index 3fa37371..7ae66b43 100644 --- a/src/components/Popup.module.css +++ b/src/components/Popup.module.css @@ -19,7 +19,8 @@ --background: var(--sc-bg-color-h) var(--sc-bg-color-s) var(--sc-bg-color-l); --foreground: 222.2 47.4% 11.2%; --border: var(--sc-bd-color-h) var(--sc-bd-color-s) var(--sc-bd-color-l); - --accent: var(--sc-bg-color-h) var(--sc-bg-color-s) calc(var(--sc-bg-color-l) - 6%); + --accent: var(--sc-bg-color-h) var(--sc-bg-color-s) + calc(var(--sc-bg-color-l) - 6%); --accent-foreground: 224 71% 4%; } @@ -34,7 +35,7 @@ .previewContainer { position: relative; - &>div { + & > div { transform: translate(0, 0) !important; } } diff --git a/src/components/ReviewRequestToast.tsx b/src/components/ReviewRequestToast.tsx index 5508df16..22a0ebbb 100644 --- a/src/components/ReviewRequestToast.tsx +++ b/src/components/ReviewRequestToast.tsx @@ -1,19 +1,19 @@ -import { toast } from 'sonner' -import { t } from '@/services/i18n' -import { cn } from '@/lib/utils' -import { PartyPopper } from 'lucide-react' -import { ANALYTICS_EVENTS, sendEvent } from '@/services/analytics' -import { SCREEN } from '@/const' +import { toast } from "sonner" +import { t } from "@/services/i18n" +import { cn } from "@/lib/utils" +import { PartyPopper } from "lucide-react" +import { ANALYTICS_EVENTS, sendEvent } from "@/services/analytics" +import { SCREEN } from "@/const" const REVIEW_URL = - 'https://chromewebstore.google.com/detail/nlnhbibaommoelemmdfnkjkgoppkohje/reviews' -const ICON_URL = chrome.runtime.getURL('icon128.png') + "https://chromewebstore.google.com/detail/nlnhbibaommoelemmdfnkjkgoppkohje/reviews" +const ICON_URL = chrome.runtime.getURL("icon128.png") export function showReviewRequestToast(onAccept: () => void): void { sendEvent( ANALYTICS_EVENTS.OPEN_DIALOG, { - event_label: 'review_request_toast', + event_label: "review_request_toast", }, SCREEN.CONTENT_SCRIPT, ) @@ -24,10 +24,10 @@ export function showReviewRequestToast(onAccept: () => void): void {
- {t('review_request_title')} + {t("review_request_title")}
-
{t('review_request_message')}
+
{t("review_request_message")}
diff --git a/src/components/SelectAnchor.tsx b/src/components/SelectAnchor.tsx index 0cf9c1ea..019b4e7a 100644 --- a/src/components/SelectAnchor.tsx +++ b/src/components/SelectAnchor.tsx @@ -1,11 +1,11 @@ -import React, { useState, useEffect, forwardRef, useCallback } from 'react' -import { LinkClickGuard } from '@/components/LinkClickGuard' -import { useUserSettings } from '@/hooks/useSetting' -import { useSelectContext } from '@/hooks/useSelectContext' -import { useLeftClickHold } from '@/hooks/useLeftClickHold' -import { MOUSE, EXIT_DURATION, STARTUP_METHOD } from '@/const' -import { isEmpty, isPopup } from '@/lib/utils' -import { Point } from '@/types' +import React, { useState, useEffect, forwardRef, useCallback } from "react" +import { LinkClickGuard } from "@/components/LinkClickGuard" +import { useUserSettings } from "@/hooks/useSetting" +import { useSelectContext } from "@/hooks/useSelectContext" +import { useLeftClickHold } from "@/hooks/useLeftClickHold" +import { MOUSE, EXIT_DURATION, STARTUP_METHOD } from "@/const" +import { isEmpty, isPopup } from "@/lib/utils" +import { Point } from "@/types" const SIZE = 40 @@ -118,15 +118,15 @@ export const SelectAnchor = forwardRef((_props, ref) => { setAnchor({ x: e.clientX, y: e.clientY }) } - document.addEventListener('mousedown', onMouseDown) - document.addEventListener('mouseup', onMouseUp) - document.addEventListener('click', onClick) - document.addEventListener('dblclick', onDouble) + document.addEventListener("mousedown", onMouseDown) + document.addEventListener("mouseup", onMouseUp) + document.addEventListener("click", onClick) + document.addEventListener("dblclick", onDouble) return () => { - document.removeEventListener('mousedown', onMouseDown) - document.removeEventListener('mouseup', onMouseUp) - document.removeEventListener('click', onClick) - document.removeEventListener('dblclick', onDouble) + document.removeEventListener("mousedown", onMouseDown) + document.removeEventListener("mouseup", onMouseUp) + document.removeEventListener("click", onClick) + document.removeEventListener("dblclick", onDouble) } }, [isMouseDown, isDragging, detectHold, selected, releaseAnchor, setAnchor]) @@ -139,10 +139,10 @@ export const SelectAnchor = forwardRef((_props, ref) => { } } if (isMouseDown) { - document.addEventListener('mousemove', onMouseMove) + document.addEventListener("mousemove", onMouseMove) } return () => { - document.removeEventListener('mousemove', onMouseMove) + document.removeEventListener("mousemove", onMouseMove) } }, [point, isMouseDown, setIsDragging, releaseAnchor]) @@ -155,12 +155,12 @@ export const SelectAnchor = forwardRef((_props, ref) => { if (point == null) return null const styles = { - position: 'absolute', + position: "absolute", top: window.scrollY + point.y - offset.y - SIZE / 2, left: window.scrollX + point.x - offset.x - SIZE / 2, height: SIZE, width: SIZE, - pointerEvents: 'none', + pointerEvents: "none", zIndex: 2147483647, // backgroundColor: 'rgba(255, 0, 0, 0.3)', // border: '1px solid red', diff --git a/src/components/Tooltip.tsx b/src/components/Tooltip.tsx index 40880d5e..8e715f01 100644 --- a/src/components/Tooltip.tsx +++ b/src/components/Tooltip.tsx @@ -1,13 +1,13 @@ -import { useContext, useEffect, useState } from 'react' -import clsx from 'clsx' +import { useContext, useEffect, useState } from "react" +import clsx from "clsx" import { Popover, PopoverContent, PopoverAnchor, PopoverArrow, -} from '@/components/ui/popover' -import { popupContext } from '@/components/Popup' -import { SIDE } from '@/const' +} from "@/components/ui/popover" +import { popupContext } from "@/components/Popup" +import { SIDE } from "@/const" type PopupProps = { text: string @@ -28,13 +28,13 @@ export function Tooltip(props: PopupProps) { const show = () => setIsOpen(true) const hide = () => setIsOpen(false) if (elm) { - elm.addEventListener('mouseenter', show) - elm.addEventListener('mouseleave', hide) + elm.addEventListener("mouseenter", show) + elm.addEventListener("mouseleave", hide) } return () => { if (elm) { - elm.removeEventListener('mouseenter', show) - elm.removeEventListener('mouseleave', hide) + elm.removeEventListener("mouseenter", show) + elm.removeEventListener("mouseleave", hide) } } }, [elm]) @@ -63,10 +63,10 @@ export function Tooltip(props: PopupProps) { {shouldRender && ( diff --git a/src/components/commandHub/CommandHub.tsx b/src/components/commandHub/CommandHub.tsx index 216e1639..0fcbbd2b 100644 --- a/src/components/commandHub/CommandHub.tsx +++ b/src/components/commandHub/CommandHub.tsx @@ -1,5 +1,5 @@ -import { DownloadButton } from '@/components/commandHub/DownloadButton' -import { StarButton } from '@/components/commandHub/StarButton' +import { DownloadButton } from "@/components/commandHub/DownloadButton" +import { StarButton } from "@/components/commandHub/StarButton" export const CommandHub = (): JSX.Element => { return ( diff --git a/src/components/commandHub/DownloadButton.tsx b/src/components/commandHub/DownloadButton.tsx index d2e6135e..edb19676 100644 --- a/src/components/commandHub/DownloadButton.tsx +++ b/src/components/commandHub/DownloadButton.tsx @@ -1,17 +1,17 @@ -import { useState, useEffect } from 'react' -import clsx from 'clsx' -import { Ipc, BgCommand } from '@/services/ipc' -import { useSection } from '@/hooks/useSetting' -import { useDetectUrlChanged } from '@/hooks/useDetectUrlChanged' -import { CACHE_SECTIONS } from '@/services/settingsCache' -import { sendEvent, ANALYTICS_EVENTS } from '@/services/analytics' +import { useState, useEffect } from "react" +import clsx from "clsx" +import { Ipc, BgCommand } from "@/services/ipc" +import { useSection } from "@/hooks/useSetting" +import { useDetectUrlChanged } from "@/hooks/useDetectUrlChanged" +import { CACHE_SECTIONS } from "@/services/settingsCache" +import { sendEvent, ANALYTICS_EVENTS } from "@/services/analytics" import { Popover, PopoverContent, PopoverAnchor, PopoverArrow, -} from '@/components/ui/popover' -import { SCREEN } from '@/const' +} from "@/components/ui/popover" +import { SCREEN } from "@/const" const TooltipDuration = 2000 @@ -24,13 +24,13 @@ export const DownloadButton = (): JSX.Element => { const open = position != null const setButtonClickListener = () => { - document.querySelectorAll('button[data-command]').forEach((button) => { + document.querySelectorAll("button[data-command]").forEach((button) => { if (!(button instanceof HTMLButtonElement)) return const command = button.dataset.command const id = button.dataset.id if (command == null) return - button.dataset.clickable = 'true' - button.addEventListener('click', () => { + button.dataset.clickable = "true" + button.addEventListener("click", () => { Ipc.send(BgCommand.addCommand, { command }).then((res) => { if (res) { sendEvent( @@ -52,15 +52,15 @@ export const DownloadButton = (): JSX.Element => { const installed = document.querySelector( `button[data-id="${id}"]`, ) as HTMLElement - if (installed) installed.style.display = 'none' + if (installed) installed.style.display = "none" // show installed label const p = document.querySelector(`p[data-id="${id}"]`) as HTMLElement - if (p) p.style.display = 'block' + if (p) p.style.display = "block" }) } const updateCount = () => { - document.querySelectorAll('span[data-id]').forEach((span) => { + document.querySelectorAll("span[data-id]").forEach((span) => { if (!(span instanceof HTMLElement)) return const count = Number(span.dataset.downloadCount) if (count == null || isNaN(count)) return @@ -121,7 +121,7 @@ export const DownloadButton = (): JSX.Element => { {shouldRender && ( { const [urls, setUrls] = useState([]) @@ -73,18 +73,18 @@ export const MyCommands = (): JSX.Element => { return (
-

{t('commnadHub_youcanshare')}

+

{t("commnadHub_youcanshare")}

{!enableMarquee ? (
@@ -92,16 +92,16 @@ export const MyCommands = (): JSX.Element => { ) : (
@@ -322,7 +322,7 @@ const HelpDialog = ({ open, onOpenChange }: HelpDialogProps) => { diff --git a/src/components/help/help.module.css b/src/components/help/help.module.css index 90985479..c425b206 100644 --- a/src/components/help/help.module.css +++ b/src/components/help/help.module.css @@ -20,7 +20,7 @@ } :global .pageActionHelp b:before { - content: ''; + content: ""; z-index: -1; @apply absolute w-full h-3 -left-1 -bottom-0.5; @apply bg-blue-100 rounded; diff --git a/src/components/menu/InvisibleItem.tsx b/src/components/menu/InvisibleItem.tsx index 002ad2f9..ba3b74ca 100644 --- a/src/components/menu/InvisibleItem.tsx +++ b/src/components/menu/InvisibleItem.tsx @@ -1,15 +1,15 @@ -import React, { useRef, useEffect, useMemo } from 'react' -import { cn } from '@/lib/utils' +import React, { useRef, useEffect, useMemo } from "react" +import { cn } from "@/lib/utils" -import { ResultPopup } from '@/components/result/ResultPopup' -import { Icon } from '@/components/Icon' -import { useContextMenu } from '@/hooks/useContextMenu' -import { useSelectContext } from '@/hooks/useSelectContext' -import { useCommandExecutor } from '@/hooks/useCommandExecutor' -import type { SelectionCommand } from '@/types' -import { POPUP_OFFSET, ExecState } from '@/const' +import { ResultPopup } from "@/components/result/ResultPopup" +import { Icon } from "@/components/Icon" +import { useContextMenu } from "@/hooks/useContextMenu" +import { useSelectContext } from "@/hooks/useSelectContext" +import { useCommandExecutor } from "@/hooks/useCommandExecutor" +import type { SelectionCommand } from "@/types" +import { POPUP_OFFSET, ExecState } from "@/const" -import css from './Menu.module.css' +import css from "./Menu.module.css" type InvisibleItemProps = { positionElm?: Element | null @@ -30,9 +30,9 @@ export function InvisibleItem(props: InvisibleItemProps): React.ReactNode { const onSelectionchange = () => { clearResult() } - document.addEventListener('selectionchange', onSelectionchange) + document.addEventListener("selectionchange", onSelectionchange) return () => { - document.removeEventListener('selectionchange', onSelectionchange) + document.removeEventListener("selectionchange", onSelectionchange) } }, []) @@ -53,12 +53,12 @@ export function InvisibleItem(props: InvisibleItemProps): React.ReactNode { const style = useMemo(() => { return { - position: 'absolute' as const, + position: "absolute" as const, top: window.scrollY + position.y, left: window.scrollX + position.x, height: 0, width: 0, - pointerEvents: 'none' as const, + pointerEvents: "none" as const, } }, [position]) @@ -82,7 +82,7 @@ export function InvisibleItem(props: InvisibleItemProps): React.ReactNode { visible={visible} positionRef={elmRef} onClose={clearResult} - className={'pointer-events-auto'} + className={"pointer-events-auto"} > {result} @@ -104,7 +104,7 @@ function IconWithState(props: ImageProps): JSX.Element {
{status === ExecState.EXECUTING && ( diff --git a/src/components/menu/MenuImage.tsx b/src/components/menu/MenuImage.tsx index 141461f7..1b44f664 100644 --- a/src/components/menu/MenuImage.tsx +++ b/src/components/menu/MenuImage.tsx @@ -1,6 +1,6 @@ -import { useState } from 'react' -import { isEmpty, cn } from '@/lib/utils' -import css from './Menu.module.css' +import { useState } from "react" +import { isEmpty, cn } from "@/lib/utils" +import css from "./Menu.module.css" type MenuImageProps = { src?: string diff --git a/src/components/option/CopyButton.tsx b/src/components/option/CopyButton.tsx index 9553ee46..f6e703e1 100644 --- a/src/components/option/CopyButton.tsx +++ b/src/components/option/CopyButton.tsx @@ -1,5 +1,5 @@ -import { useState, useRef } from 'react' -import { Copy } from 'lucide-react' +import { useState, useRef } from "react" +import { Copy } from "lucide-react" import { Dialog, DialogClose, @@ -8,12 +8,12 @@ import { DialogHeader, DialogTitle, DialogFooter, -} from '@/components/ui/dialog' -import { Button } from '@/components/ui/button' -import { Input } from '@/components/ui/input' -import { Tooltip } from '@/components/Tooltip' -import { t } from '@/services/i18n' -import { cn } from '@/lib/utils' +} from "@/components/ui/dialog" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Tooltip } from "@/components/Tooltip" +import { t } from "@/services/i18n" +import { cn } from "@/lib/utils" type CopyButtonProps = { srcTitle: string @@ -40,7 +40,7 @@ export const CopyButton = ({ type="button" ref={buttonRef} className={cn( - 'outline-gray-200 p-2 rounded-md transition hover:bg-gray-100 hover:scale-125 group/edit-button', + "outline-gray-200 p-2 rounded-md transition hover:bg-gray-100 hover:scale-125 group/edit-button", className, )} onClick={() => setOpen(true)} @@ -58,7 +58,7 @@ export const CopyButton = ({ /> ) @@ -71,7 +71,7 @@ function incrementLastNumber(str: string): string { const incrementedNumber = (parseInt(number, 10) + 1).toString() return str.slice(0, -number.length) + incrementedNumber } else { - return str + ' 1' + return str + " 1" } } @@ -98,9 +98,9 @@ export const CopyDialog = ({ - {t('Option_copy_title')} + {t("Option_copy_title")} - {t('Option_copy_desc')} + {t("Option_copy_desc")} diff --git a/src/components/option/Dialog.module.css b/src/components/option/Dialog.module.css index f507bba6..8e89f5fc 100644 --- a/src/components/option/Dialog.module.css +++ b/src/components/option/Dialog.module.css @@ -24,7 +24,7 @@ .button, .buttonCancel { - composes: button from '../Common.module.css'; + composes: button from "../Common.module.css"; padding: 6px 8px 6px; line-height: 1.2; border-radius: 6px; diff --git a/src/components/option/EditButton.tsx b/src/components/option/EditButton.tsx index 9ffd7458..652b5582 100644 --- a/src/components/option/EditButton.tsx +++ b/src/components/option/EditButton.tsx @@ -1,8 +1,8 @@ -import React, { useRef } from 'react' -import { Pencil } from 'lucide-react' -import { Tooltip } from '@/components/Tooltip' -import { t } from '@/services/i18n' -import { cn } from '@/lib/utils' +import React, { useRef } from "react" +import { Pencil } from "lucide-react" +import { Tooltip } from "@/components/Tooltip" +import { t } from "@/services/i18n" +import { cn } from "@/lib/utils" type EditButtonProps = { onClick: () => void @@ -27,14 +27,14 @@ export const EditButton = ({
) diff --git a/src/components/option/ImportExport.tsx b/src/components/option/ImportExport.tsx index 1899327d..706565d0 100644 --- a/src/components/option/ImportExport.tsx +++ b/src/components/option/ImportExport.tsx @@ -473,43 +473,50 @@ export function ImportExport() { setSelectedBackupType(value as typeof selectedBackupType) } > - {availableBackups.map(([type, backup]) => ( -
- -
- - {backup.info && ( -
-
- {t("Option_RestoreFromBackup_created")}{" "} - {new Date(backup.info.timestamp).toLocaleString()} -
-
- {t("Option_RestoreFromBackup_commands")}{" "} - {backup.info.commandCount}{" "} - {t("Option_RestoreFromBackup_items")} -
- {backup.info.folderCount !== undefined && ( + {availableBackups + .sort(([typeA], [typeB]) => { + // Put legacy at the bottom + if (typeA === BACKUP_TYPES.LEGACY) return 1 + if (typeB === BACKUP_TYPES.LEGACY) return -1 + return 0 + }) + .map(([type, backup]) => ( +
+ +
+ + {backup.info && ( +
- {t("Option_RestoreFromBackup_folders")}{" "} - {backup.info.folderCount}{" "} + {t("Option_RestoreFromBackup_created")}{" "} + {new Date(backup.info.timestamp).toLocaleString()} +
+
+ {t("Option_RestoreFromBackup_commands")}{" "} + {backup.info.commandCount}{" "} {t("Option_RestoreFromBackup_items")}
- )} -
- )} + {backup.info.folderCount !== undefined && ( +
+ {t("Option_RestoreFromBackup_folders")}{" "} + {backup.info.folderCount}{" "} + {t("Option_RestoreFromBackup_items")} +
+ )} +
+ )} +
-
- ))} + ))}

{t("Option_RestoreFromBackup_warning")}{" "} diff --git a/src/components/option/LoadingIcon.module.css b/src/components/option/LoadingIcon.module.css index 510f38bb..b57603fd 100644 --- a/src/components/option/LoadingIcon.module.css +++ b/src/components/option/LoadingIcon.module.css @@ -27,7 +27,7 @@ animation: spin 1s linear infinite; &::before { - content: ''; + content: ""; box-sizing: content-box; position: absolute; display: block; diff --git a/src/components/option/LoadingIcon.tsx b/src/components/option/LoadingIcon.tsx index d58c738d..f868b907 100644 --- a/src/components/option/LoadingIcon.tsx +++ b/src/components/option/LoadingIcon.tsx @@ -1,5 +1,5 @@ -import React, { forwardRef } from 'react' -import styles from './LoadingIcon.module.css' +import React, { forwardRef } from "react" +import styles from "./LoadingIcon.module.css" type LoadingIconProp = { children?: React.ReactNode diff --git a/src/components/option/Option.module.css b/src/components/option/Option.module.css index 1bd60ac8..224cf916 100644 --- a/src/components/option/Option.module.css +++ b/src/components/option/Option.module.css @@ -22,7 +22,7 @@ margin: 0; } -.titleSpan+.titleSpan { +.titleSpan + .titleSpan { margin-left: 4px; } @@ -92,9 +92,11 @@ .bgHatching { background-color: #fff; - background-image: repeating-linear-gradient(45deg, - #6b7280, - #6b7280 1px, - transparent 1px, - transparent 4px); + background-image: repeating-linear-gradient( + 45deg, + #6b7280, + #6b7280 1px, + transparent 1px, + transparent 4px + ); } diff --git a/src/components/option/RemoveButton.tsx b/src/components/option/RemoveButton.tsx index 29e55d26..fcabcd6d 100644 --- a/src/components/option/RemoveButton.tsx +++ b/src/components/option/RemoveButton.tsx @@ -1,10 +1,10 @@ -import { useState, useRef } from 'react' -import { Trash2 } from 'lucide-react' -import { Tooltip } from '@/components/Tooltip' -import { MenuImage } from '@/components/menu/MenuImage' -import { RemoveDialog } from '@/components/option/RemoveDialog' -import { cn } from '@/lib/utils' -import { t } from '@/services/i18n' +import { useState, useRef } from "react" +import { Trash2 } from "lucide-react" +import { Tooltip } from "@/components/Tooltip" +import { MenuImage } from "@/components/menu/MenuImage" +import { RemoveDialog } from "@/components/option/RemoveDialog" +import { cn } from "@/lib/utils" +import { t } from "@/services/i18n" type RemoveButtonProps = { onRemove: () => void @@ -31,7 +31,7 @@ export const RemoveButton = ({ ) diff --git a/src/components/option/RemoveDialog.tsx b/src/components/option/RemoveDialog.tsx index c6ad3b7a..73f7ded5 100644 --- a/src/components/option/RemoveDialog.tsx +++ b/src/components/option/RemoveDialog.tsx @@ -1,6 +1,6 @@ -import { useRef } from 'react' -import { Trash2 } from 'lucide-react' -import { t } from '@/services/i18n' +import { useRef } from "react" +import { Trash2 } from "lucide-react" +import { t } from "@/services/i18n" import { Dialog, @@ -11,8 +11,8 @@ import { DialogHeader, DialogTitle, DialogFooter, -} from '@/components/ui/dialog' -import { Button } from '@/components/ui/button' +} from "@/components/ui/dialog" +import { Button } from "@/components/ui/button" type RemoveDialogProps = { open: boolean @@ -34,7 +34,7 @@ export const RemoveDialog = (props: RemoveDialogProps) => { - {t('Option_remove_title')} + {t("Option_remove_title")} {props.description}

@@ -43,7 +43,7 @@ export const RemoveDialog = (props: RemoveDialogProps) => { @@ -55,7 +55,7 @@ export const RemoveDialog = (props: RemoveDialogProps) => { ref={closeRef} > - {t('Option_remove_ok')} + {t("Option_remove_ok")} diff --git a/src/components/option/SettingForm.tsx b/src/components/option/SettingForm.tsx index c2013555..ee8ee540 100644 --- a/src/components/option/SettingForm.tsx +++ b/src/components/option/SettingForm.tsx @@ -1,51 +1,50 @@ -import { useState, useEffect, useRef } from 'react' -import { CSSTransition } from 'react-transition-group' -import { z } from 'zod' -import { zodResolver } from '@hookform/resolvers/zod' -import { useForm, useWatch } from 'react-hook-form' +import { useState, useEffect, useRef } from "react" +import { CSSTransition } from "react-transition-group" +import { z } from "zod" +import { zodResolver } from "@hookform/resolvers/zod" +import { useForm, useWatch } from "react-hook-form" import { MessageSquareMore, SquareTerminal, Eye, BookOpen, Paintbrush, -} from 'lucide-react' +} from "lucide-react" -import { Form } from '@/components/ui/form' -import { LoadingIcon } from '@/components/option/LoadingIcon' -import { InputField } from '@/components/option/field/InputField' -import { SelectField } from '@/components/option/field/SelectField' -import { SwitchField } from '@/components/option/field/SwitchField' -import { PopupPlacementField } from '@/components/option/field/PopupPlacementField' -import { commandSchema, folderSchema } from '@/types/schema' -import { CommandList } from '@/components/option/editor/CommandList' -import { toCommandTree, toFlatten } from '@/services/option/commandTree' -import { isCommand, removeUnstoredParam } from '@/services/option/commandUtils' +import { Form } from "@/components/ui/form" +import { LoadingIcon } from "@/components/option/LoadingIcon" +import { InputField } from "@/components/option/field/InputField" +import { SelectField } from "@/components/option/field/SelectField" +import { SwitchField } from "@/components/option/field/SwitchField" +import { PopupPlacementField } from "@/components/option/field/PopupPlacementField" +import { commandSchema, folderSchema } from "@/types/schema" +import { CommandList } from "@/components/option/editor/CommandList" +import { toCommandTree, toFlatten } from "@/services/option/commandTree" +import { isCommand, removeUnstoredParam } from "@/services/option/commandUtils" import { PageRuleList, pageRuleSchema, -} from '@/components/option/editor/PageRuleList' +} from "@/components/option/editor/PageRuleList" import { UserStyleList, userStyleSchema, -} from '@/components/option/editor/UserStyleList' -import { ShortcutList } from '@/components/option/editor/ShortcutList' -import { ShortcutSettingsSchema } from '@/types/schema' +} from "@/components/option/editor/UserStyleList" +import { ShortcutList } from "@/components/option/editor/ShortcutList" +import { ShortcutSettingsSchema } from "@/types/schema" -import { t as _t } from '@/services/i18n' +import { t as _t } from "@/services/i18n" const t = (key: string, p?: string[]) => _t(`Option_${key}`, p) import { STYLE, STARTUP_METHOD, KEYBOARD, - COMMAND_MAX, DRAG_OPEN_MODE, LINK_COMMAND_ENABLED, LINK_COMMAND_STARTUP_METHOD, STYLE_VARIABLE, -} from '@/const' -import type { UserSettings } from '@/types' -import { PopupPlacementSchema } from '@/types/schema' +} from "@/const" +import type { UserSettings } from "@/types" +import { PopupPlacementSchema } from "@/types/schema" import { isMenuCommand, isLinkCommand, @@ -54,9 +53,9 @@ import { sleep, e2a, cn, -} from '@/lib/utils' -import { Settings } from '@/services/settings' -import DefaultSettings from '@/services/option/defaultSettings' +} from "@/lib/utils" +import { Settings } from "@/services/settings" +import DefaultSettings from "@/services/option/defaultSettings" const formSchema = z .object({ @@ -65,15 +64,15 @@ const formSchema = z method: z.nativeEnum(STARTUP_METHOD), keyboardParam: z.nativeEnum(KEYBOARD).optional(), leftClickHoldParam: z - .number({ message: t('zod_number') }) - .min(50, { message: t('zod_number_min', ['50']) }) - .max(500, { message: t('zod_number_max', ['500']) }) + .number({ message: t("zod_number") }) + .min(50, { message: t("zod_number_min", ["50"]) }) + .max(500, { message: t("zod_number_max", ["500"]) }) .optional(), }) .strict(), popupPlacement: PopupPlacementSchema, style: z.nativeEnum(STYLE), - commands: z.array(commandSchema).min(1).max(COMMAND_MAX), + commands: z.array(commandSchema).min(1), folders: z.array(folderSchema), linkCommand: z .object({ @@ -87,14 +86,14 @@ const formSchema = z method: z.nativeEnum(LINK_COMMAND_STARTUP_METHOD), keyboardParam: z.nativeEnum(KEYBOARD).optional(), threshold: z - .number({ message: t('zod_number') }) - .min(50, { message: t('zod_number_min', ['50']) }) - .max(400, { message: t('zod_number_max', ['400']) }) + .number({ message: t("zod_number") }) + .min(50, { message: t("zod_number_min", ["50"]) }) + .max(400, { message: t("zod_number_max", ["400"]) }) .optional(), leftClickHoldParam: z - .number({ message: t('zod_number') }) - .min(50, { message: t('zod_number_min', ['50']) }) - .max(500, { message: t('zod_number_max', ['500']) }) + .number({ message: t("zod_number") }) + .min(50, { message: t("zod_number_min", ["50"]) }) + .max(500, { message: t("zod_number_max", ["500"]) }) .optional(), }) .strict(), @@ -107,30 +106,30 @@ const formSchema = z .strict() type FormValues = z.infer -export type SettingsFormType = Omit +export type SettingsFormType = Omit export function SettingForm({ className }: { className?: string }) { const [isSaving, setIsSaving] = useState(false) const saveToRef = useRef() const isLoadingRef = useRef() const loadingRef = useRef(null) - const os = isMac() ? 'mac' : 'windows' + const os = isMac() ? "mac" : "windows" const form = useForm({ resolver: zodResolver(formSchema), - mode: 'onChange', + mode: "onChange", }) const { reset, getValues, setValue, register, subscribe } = form const startupMethod = useWatch({ control: form.control, - name: 'startupMethod.method', + name: "startupMethod.method", defaultValue: STARTUP_METHOD.TEXT_SELECTION, }) const linkCommandMethod = useWatch({ control: form.control, - name: 'linkCommand.startupMethod.method', + name: "linkCommand.startupMethod.method", defaultValue: LINK_COMMAND_STARTUP_METHOD.KEYBOARD, }) @@ -170,7 +169,7 @@ export function SettingForm({ className }: { className?: string }) { // Handle settings synchronization across tabs and windows useEffect(() => { const handleVisibilityChange = async () => { - if (document.visibilityState === 'visible') { + if (document.visibilityState === "visible") { await updateFormSettings() } } @@ -179,11 +178,11 @@ export function SettingForm({ className }: { className?: string }) { await updateFormSettings() } - document.addEventListener('visibilitychange', handleVisibilityChange) + document.addEventListener("visibilitychange", handleVisibilityChange) Settings.addChangedListener(handleSettingsChange) return () => { - document.removeEventListener('visibilitychange', handleVisibilityChange) + document.removeEventListener("visibilitychange", handleVisibilityChange) Settings.removeChangedListener(handleSettingsChange) } }, []) @@ -211,7 +210,7 @@ export function SettingForm({ className }: { className?: string }) { }) await sleep(1000) } catch (e) { - console.error('Failed to update settings!', settings) + console.error("Failed to update settings!", settings) console.error(e) } finally { setIsSaving(false) @@ -226,29 +225,29 @@ export function SettingForm({ className }: { className?: string }) { sideOffset, alignOffset, } - setValue('popupPlacement', popupPlacement) + setValue("popupPlacement", popupPlacement) } // Set default value for startupMethod. useEffect(() => { if (startupMethod === STARTUP_METHOD.KEYBOARD) { - const val = getValues('startupMethod.keyboardParam') + const val = getValues("startupMethod.keyboardParam") if (isEmpty(val)) { - setValue('startupMethod.keyboardParam', KEYBOARD.SHIFT) + setValue("startupMethod.keyboardParam", KEYBOARD.SHIFT) } } else if (startupMethod === STARTUP_METHOD.LEFT_CLICK_HOLD) { - const val = getValues('startupMethod.leftClickHoldParam') + const val = getValues("startupMethod.leftClickHoldParam") if (val == null || isNaN(val)) { - setValue('startupMethod.leftClickHoldParam', 200) + setValue("startupMethod.leftClickHoldParam", 200) } } if ( startupMethod === STARTUP_METHOD.KEYBOARD || startupMethod === STARTUP_METHOD.LEFT_CLICK_HOLD ) { - const userStyles = getValues('userStyles') + const userStyles = getValues("userStyles") if (userStyles.every((s) => s.name !== STYLE_VARIABLE.POPUP_DELAY)) { - setValue('userStyles', [ + setValue("userStyles", [ ...userStyles, { name: STYLE_VARIABLE.POPUP_DELAY, value: 0 }, ]) @@ -259,28 +258,28 @@ export function SettingForm({ className }: { className?: string }) { // Set default value for linkCommand.startupMethod. useEffect(() => { if (linkCommandMethod === LINK_COMMAND_STARTUP_METHOD.KEYBOARD) { - const val = getValues('linkCommand.startupMethod.keyboardParam') + const val = getValues("linkCommand.startupMethod.keyboardParam") if (isEmpty(val)) { setValue( - 'linkCommand.startupMethod.keyboardParam', + "linkCommand.startupMethod.keyboardParam", DefaultSettings.linkCommand.startupMethod.keyboardParam, ) } } else if (linkCommandMethod === LINK_COMMAND_STARTUP_METHOD.DRAG) { - const val = getValues('linkCommand.startupMethod.threshold') + const val = getValues("linkCommand.startupMethod.threshold") if (val == null || isNaN(val)) { setValue( - 'linkCommand.startupMethod.threshold', + "linkCommand.startupMethod.threshold", DefaultSettings.linkCommand.startupMethod.threshold, ) } } else if ( linkCommandMethod === LINK_COMMAND_STARTUP_METHOD.LEFT_CLICK_HOLD ) { - const val = getValues('linkCommand.startupMethod.leftClickHoldParam') + const val = getValues("linkCommand.startupMethod.leftClickHoldParam") if (val == null || isNaN(val)) { setValue( - 'linkCommand.startupMethod.leftClickHoldParam', + "linkCommand.startupMethod.leftClickHoldParam", DefaultSettings.linkCommand.startupMethod.leftClickHoldParam, ) } @@ -318,27 +317,27 @@ export function SettingForm({ className }: { className?: string }) { nodeRef={loadingRef} > - {_t('saving')} + {_t("saving")}

- {t('startupMethod')} + {t("startupMethod")}

-

{t('startupMethod_desc')}

+

{t("startupMethod_desc")}

({ name: t(`startupMethod_${method}`), value: method, @@ -348,7 +347,7 @@ export function SettingForm({ className }: { className?: string }) { ({ name: t(`style_${style}`), value: style, @@ -359,8 +358,8 @@ export function SettingForm({ className }: { className?: string }) { k != KEYBOARD.META) .map((key) => ({ @@ -373,24 +372,24 @@ export function SettingForm({ className }: { className?: string }) { )} - {getValues('popupPlacement') != null && + {getValues("popupPlacement") != null && startupMethod !== STARTUP_METHOD.CONTEXT_MENU && ( )}
@@ -398,9 +397,9 @@ export function SettingForm({ className }: { className?: string }) {

- {t('commands')} + {t("commands")}

-

{t('commands_desc')}

+

{t("commands_desc")}


@@ -413,13 +412,13 @@ export function SettingForm({ className }: { className?: string }) {

- {t('linkCommand')} + {t("linkCommand")}

-

{t('linkCommand_desc')}

+

{t("linkCommand_desc")}

opt !== LINK_COMMAND_ENABLED.INHERIT) .map((opt) => ({ @@ -430,7 +429,7 @@ export function SettingForm({ className }: { className?: string }) { ({ name: t(`openMode_${opt}`), value: opt, @@ -439,7 +438,7 @@ export function SettingForm({ className }: { className?: string }) { ({ name: t(`linkCommandStartupMethod_${opt}`), value: opt, @@ -449,7 +448,7 @@ export function SettingForm({ className }: { className?: string }) { k != KEYBOARD.META) .map((key) => ({ @@ -462,15 +461,15 @@ export function SettingForm({ className }: { className?: string }) {

@@ -509,21 +508,21 @@ export function SettingForm({ className }: { className?: string }) {

- {t('pageRules')} + {t("pageRules")}

-

{t('pageRules_desc')}

+

{t("pageRules_desc")}


- {t('userStyles')} + {t("userStyles")}

-

{t('userStyles_desc')}

+

{t("userStyles_desc")}

diff --git a/src/components/option/SortableItem.tsx b/src/components/option/SortableItem.tsx index b8da2cc5..3e4f42e4 100644 --- a/src/components/option/SortableItem.tsx +++ b/src/components/option/SortableItem.tsx @@ -1,8 +1,8 @@ -import { useSortable } from '@dnd-kit/sortable' -import { CSS } from '@dnd-kit/utilities' -import { GripVertical } from 'lucide-react' -import { cn } from '@/lib/utils' -import type { Command, CommandFolder } from '@/types' +import { useSortable } from "@dnd-kit/sortable" +import { CSS } from "@dnd-kit/utilities" +import { GripVertical } from "lucide-react" +import { cn } from "@/lib/utils" +import type { Command, CommandFolder } from "@/types" type SrotabelItemProps = { id: string @@ -34,7 +34,7 @@ export function SortableItem(props: SrotabelItemProps) { }, transition: { duration: 150, - easing: 'cubic-bezier(0.25, 1, 0.5, 1)', + easing: "cubic-bezier(0.25, 1, 0.5, 1)", }, }) @@ -49,19 +49,19 @@ export function SortableItem(props: SrotabelItemProps) { ref={isDroppable ? setNodeRef : null} style={style} className={cn( - 'pl-1 flex items-center cursor-auto', - props.index === 0 ? '' : 'border-t', + "pl-1 flex items-center cursor-auto", + props.index === 0 ? "" : "border-t", props.index === activeIndex - ? 'border-y bg-gray-100/80 shadow-lg relative z-10' - : '', + ? "border-y bg-gray-100/80 shadow-lg relative z-10" + : "", props.className, )} {...attributes} >
void @@ -17,12 +17,12 @@ type Props = { export const TableOfContents = (props: Props) => { const properties = [ - 'startupMethod', - 'commands', - 'shortcuts', - 'linkCommand', - 'pageRules', - 'userStyles', + "startupMethod", + "commands", + "shortcuts", + "linkCommand", + "pageRules", + "userStyles", ] const labels = properties.reduce( @@ -65,17 +65,17 @@ const Icon = ({ className: string }) => { switch (name) { - case 'startupMethod': + case "startupMethod": return - case 'commands': + case "commands": return - case 'linkCommand': + case "linkCommand": return - case 'shortcuts': + case "shortcuts": return - case 'pageRules': + case "pageRules": return - case 'userStyles': + case "userStyles": return default: return null diff --git a/src/components/option/editor/CommandEditDialog.module.css b/src/components/option/editor/CommandEditDialog.module.css index 99844857..a97547af 100644 --- a/src/components/option/editor/CommandEditDialog.module.css +++ b/src/components/option/editor/CommandEditDialog.module.css @@ -1,8 +1,8 @@ -.CollapsibleContent[data-state='open'] { +.CollapsibleContent[data-state="open"] { animation: slideDown 150ms ease-out; } -.CollapsibleContent[data-state='closed'] { +.CollapsibleContent[data-state="closed"] { animation: slideUp 100ms ease-out; } @@ -34,21 +34,21 @@ @apply stroke-gray-600; } -.pageActionStart>div, -.pageActionEnd>div { +.pageActionStart > div, +.pageActionEnd > div { @apply w-14 h-14 rounded-full bg-red-200 text-center; } -.pageActionStart>div>p+p, -.pageActionEnd>div>p+p { +.pageActionStart > div > p + p, +.pageActionEnd > div > p + p { @apply hidden; } -.collapse[data-state='open'] .iconUpDown { +.collapse[data-state="open"] .iconUpDown { display: none; } -.collapse[data-state='closed'] .iconDownUp { +.collapse[data-state="closed"] .iconDownUp { display: none; } @@ -57,7 +57,7 @@ } .triangle:not(.pageActionEnd):after { - content: ''; + content: ""; position: absolute; height: 24px; top: 14px; diff --git a/src/components/option/editor/CommandEditDialog.tsx b/src/components/option/editor/CommandEditDialog.tsx index 3e5e0cbb..24641af6 100644 --- a/src/components/option/editor/CommandEditDialog.tsx +++ b/src/components/option/editor/CommandEditDialog.tsx @@ -1,7 +1,7 @@ -import { useState, useEffect, useRef } from 'react' -import { useForm, useFieldArray, useWatch } from 'react-hook-form' -import { zodResolver } from '@hookform/resolvers/zod' -import { z } from 'zod' +import { useState, useEffect, useRef } from "react" +import { useForm, useFieldArray, useWatch } from "react-hook-form" +import { zodResolver } from "@hookform/resolvers/zod" +import { z } from "zod" import { Plus, Trash2, @@ -9,7 +9,7 @@ import { SquareTerminal, ChevronsUpDown, ChevronsDownUp, -} from 'lucide-react' +} from "lucide-react" import { Dialog, @@ -20,7 +20,7 @@ import { DialogTitle, DialogFooter, DialogPortal, -} from '@/components/ui/dialog' +} from "@/components/ui/dialog" import { FormControl, @@ -28,24 +28,24 @@ import { FormField, FormItem, FormLabel, -} from '@/components/ui/form' +} from "@/components/ui/form" import { Collapsible, CollapsibleContent, CollapsibleTrigger, -} from '@/components/ui/collapsible' - -import { Input } from '@/components/ui/input' -import { Form } from '@/components/ui/form' -import { Button } from '@/components/ui/button' -import { InputField } from '@/components/option/field/InputField' -import { IconField } from '@/components/option/field/IconField' -import { SelectField } from '@/components/option/field/SelectField' -import { TextareaField } from '@/components/option/field/TextareaField' -import { PageActionSection } from '@/components/option/editor/PageActionSection' -import { PaeActionHelp } from '@/components/help/PageActionHelp' -import { PageActionStep } from '@/types/schema' +} from "@/components/ui/collapsible" + +import { Input } from "@/components/ui/input" +import { Form } from "@/components/ui/form" +import { Button } from "@/components/ui/button" +import { InputField } from "@/components/option/field/InputField" +import { IconField } from "@/components/option/field/IconField" +import { SelectField } from "@/components/option/field/SelectField" +import { TextareaField } from "@/components/option/field/TextareaField" +import { PageActionSection } from "@/components/option/editor/PageActionSection" +import { PaeActionHelp } from "@/components/help/PageActionHelp" +import { PageActionStep } from "@/types/schema" import { OPEN_MODE, @@ -56,44 +56,44 @@ import { PAGE_ACTION_OPEN_MODE, ICON_NOT_FOUND, SCREEN, -} from '@/const' +} from "@/const" import { FaviconContextProvider, useFavicon, FaviconEvent, -} from '@/hooks/option/useFavicon' +} from "@/hooks/option/useFavicon" -import { Ipc, BgCommand } from '@/services/ipc' -import { getScreenSize } from '@/services/screen' -import { Storage, SESSION_STORAGE_KEY } from '@/services/storage' -import { ANALYTICS_EVENTS, sendEvent } from '@/services/analytics' +import { Ipc, BgCommand } from "@/services/ipc" +import { getScreenSize } from "@/services/screen" +import { Storage, SESSION_STORAGE_KEY } from "@/services/storage" +import { ANALYTICS_EVENTS, sendEvent } from "@/services/analytics" -import { isEmpty, e2a, cn } from '@/lib/utils' -import { t as _t } from '@/services/i18n' +import { isEmpty, e2a, cn } from "@/lib/utils" +import { t as _t } from "@/services/i18n" const t = (key: string, p?: string[]) => _t(`Option_${key}`, p) -import { SEARCH_OPEN_MODE, isSearchType, commandSchema } from '@/types/schema' +import { SEARCH_OPEN_MODE, isSearchType, commandSchema } from "@/types/schema" import type { SelectionCommand, CommandFolder, PageActionRecordingData, -} from '@/types' +} from "@/types" -import css from './CommandEditDialog.module.css' -import { calcLevel } from '@/services/option/commandTree' +import css from "./CommandEditDialog.module.css" +import { calcLevel } from "@/services/option/commandTree" const EmptyFolder = { id: ROOT_FOLDER, - title: t('Command_rootFolder'), + title: t("Command_rootFolder"), } as CommandFolder const defaultValue = (openMode: OPEN_MODE) => { if (SEARCH_OPEN_MODE.includes(openMode as any)) { return { - id: '', - searchUrl: '', - iconUrl: '', + id: "", + searchUrl: "", + iconUrl: "", openMode: OPEN_MODE.POPUP as const, openModeSecondary: OPEN_MODE.TAB as const, spaceEncoding: SPACE_ENCODING.PLUS, @@ -106,19 +106,19 @@ const defaultValue = (openMode: OPEN_MODE) => { } if (openMode === OPEN_MODE.API) { return { - id: '', - searchUrl: '', - iconUrl: '', + id: "", + searchUrl: "", + iconUrl: "", openMode: OPEN_MODE.API as const, - fetchOptions: '', + fetchOptions: "", variables: [], parentFolderId: ROOT_FOLDER, } } if (openMode === OPEN_MODE.PAGE_ACTION) { return { - id: '', - iconUrl: '', + id: "", + iconUrl: "", openMode: OPEN_MODE.PAGE_ACTION as const, parentFolderId: ROOT_FOLDER, popupOption: { @@ -126,7 +126,7 @@ const defaultValue = (openMode: OPEN_MODE) => { height: POPUP_OPTION.height + 50, }, pageActionOption: { - startUrl: '', + startUrl: "", openMode: PAGE_ACTION_OPEN_MODE.POPUP, steps: [], }, @@ -134,10 +134,10 @@ const defaultValue = (openMode: OPEN_MODE) => { } if (openMode === OPEN_MODE.LINK_POPUP) { return { - id: '', - title: 'Link Popup', + id: "", + title: "Link Popup", iconUrl: - 'https://cdn3.iconfinder.com/data/icons/fluent-regular-24px-vol-5/24/ic_fluent_open_24_regular-1024.png', + "https://cdn3.iconfinder.com/data/icons/fluent-regular-24px-vol-5/24/ic_fluent_open_24_regular-1024.png", openMode: OPEN_MODE.LINK_POPUP as const, parentFolderId: ROOT_FOLDER, popupOption: { @@ -148,10 +148,10 @@ const defaultValue = (openMode: OPEN_MODE) => { } if (openMode === OPEN_MODE.COPY) { return { - id: '', - title: 'Copy text', + id: "", + title: "Copy text", iconUrl: - 'https://cdn0.iconfinder.com/data/icons/phosphor-light-vol-2/256/copy-light-1024.png', + "https://cdn0.iconfinder.com/data/icons/phosphor-light-vol-2/256/copy-light-1024.png", openMode: OPEN_MODE.COPY as const, copyOption: COPY_OPTION.DEFAULT, parentFolderId: ROOT_FOLDER, @@ -159,10 +159,10 @@ const defaultValue = (openMode: OPEN_MODE) => { } if (openMode === OPEN_MODE.GET_TEXT_STYLES) { return { - id: '', - title: 'Get Text Styles', + id: "", + title: "Get Text Styles", iconUrl: - 'https://cdn0.iconfinder.com/data/icons/phosphor-light-vol-3/256/paint-brush-light-1024.png', + "https://cdn0.iconfinder.com/data/icons/phosphor-light-vol-3/256/paint-brush-light-1024.png", openMode: OPEN_MODE.GET_TEXT_STYLES as const, parentFolderId: ROOT_FOLDER, } @@ -211,7 +211,7 @@ const CommandEditDialogInner = ({ const form = useForm>({ resolver: zodResolver(commandSchema), - mode: 'onChange', + mode: "onChange", defaultValues: defaultValue(DEFAULT_MODE), }) const { register, reset, getValues, setValue, clearErrors } = form @@ -220,27 +220,27 @@ const CommandEditDialogInner = ({ const isUpdate = command != null const variableArray = useFieldArray({ - name: 'variables', + name: "variables", control: form.control, - keyName: '_id', + keyName: "_id", }) const openMode = useWatch({ control: form.control, - name: 'openMode', + name: "openMode", defaultValue: DEFAULT_MODE, }) const searchUrl = useWatch({ control: form.control, - name: 'searchUrl', - defaultValue: '', + name: "searchUrl", + defaultValue: "", }) const startUrl = useWatch({ control: form.control, - name: 'pageActionOption.startUrl', - defaultValue: '', + name: "pageActionOption.startUrl", + defaultValue: "", }) const iconUrlSrc = searchUrl || startUrl @@ -250,21 +250,21 @@ const CommandEditDialogInner = ({ SESSION_STORAGE_KEY.PA_RECORDING, { startUrl, - openMode: getValues('pageActionOption.openMode'), - size: getValues('popupOption') ?? POPUP_OPTION, - steps: getValues('pageActionOption.steps'), + openMode: getValues("pageActionOption.openMode"), + size: getValues("popupOption") ?? POPUP_OPTION, + steps: getValues("pageActionOption.steps"), }, ) await Ipc.send(BgCommand.startPageActionRecorder, { startUrl, - openMode: getValues('pageActionOption.openMode'), - size: getValues('popupOption') ?? POPUP_OPTION, + openMode: getValues("pageActionOption.openMode"), + size: getValues("popupOption") ?? POPUP_OPTION, screen: await getScreenSize(), }) sendEvent( ANALYTICS_EVENTS.OPEN_DIALOG, { - event_label: 'pageAction_recorder', + event_label: "pageAction_recorder", }, SCREEN.OPTION, ) @@ -301,7 +301,7 @@ const CommandEditDialogInner = ({ }, [iconUrlSrc, setIconUrlSrc]) useEffect(() => { - if (!open) setIconUrlSrc('') + if (!open) setIconUrlSrc("") setTimeout(() => { setInitialized(open) }, 100) @@ -312,8 +312,8 @@ const CommandEditDialogInner = ({ SESSION_STORAGE_KEY.PA_RECORDING, ({ size, steps }) => { if (steps == null) return - setValue('popupOption', size) - setValue('pageActionOption.steps', steps as PageActionStep[]) + setValue("popupOption", size) + setValue("pageActionOption.steps", steps as PageActionStep[]) }, ) }, []) @@ -321,11 +321,11 @@ const CommandEditDialogInner = ({ useEffect(() => { const sub = (e: any) => { if (e.type === FaviconEvent.FAIL) { - setValue('iconUrl', ICON_NOT_FOUND) + setValue("iconUrl", ICON_NOT_FOUND) } else { - setValue('iconUrl', e.detail.faviconUrl) + setValue("iconUrl", e.detail.faviconUrl) } - clearErrors('iconUrl') + clearErrors("iconUrl") } subscribe(FaviconEvent.START, sub) @@ -345,13 +345,13 @@ const CommandEditDialogInner = ({ - {t('Command_edit')} + {t("Command_edit")} {openMode === OPEN_MODE.PAGE_ACTION && ( )} - {t('Command_input')} + {t("Command_input")}
@@ -372,10 +372,10 @@ const CommandEditDialogInner = ({ @@ -399,7 +399,7 @@ const CommandEditDialogInner = ({ ({ name: t(`openMode_${mode}`), value: mode, @@ -412,19 +412,19 @@ const CommandEditDialogInner = ({ @@ -442,7 +442,7 @@ const CommandEditDialogInner = ({ (
- {t('variables')} + {t("variables")}
@@ -467,7 +467,7 @@ const CommandEditDialogInner = ({ render={({ field }) => ( - {t('variableName')} + {t("variableName")} @@ -482,7 +482,7 @@ const CommandEditDialogInner = ({ render={({ field }) => ( - {t('variableValue')} + {t("variableValue")} @@ -511,8 +511,8 @@ const CommandEditDialogInner = ({ className="relative mt-1 rounded-lg h-7 left-[50%] translate-x-[-50%]" onClick={() => variableArray.append({ - name: '', - value: '', + name: "", + value: "", }) } > @@ -529,7 +529,7 @@ const CommandEditDialogInner = ({ ({ name: t(`copyOption_${opt}`), value: opt, @@ -540,7 +540,7 @@ const CommandEditDialogInner = ({ {/* details */} - {t('labelDetail')} + {t("labelDetail")} @@ -578,19 +578,19 @@ const CommandEditDialogInner = ({ ({ name: t(`spaceEncoding_${enc}`), value: enc, }))} - description={t('spaceEncoding_desc')} + description={t("spaceEncoding_desc")} /> )} ({ name: folder.title, value: folder.id, @@ -606,7 +606,7 @@ const CommandEditDialogInner = ({ diff --git a/src/components/option/editor/CommandList.tsx b/src/components/option/editor/CommandList.tsx index 31dddd30..2ad0773b 100644 --- a/src/components/option/editor/CommandList.tsx +++ b/src/components/option/editor/CommandList.tsx @@ -1,5 +1,5 @@ -import { useState, useRef, useEffect } from 'react' -import { useFieldArray } from 'react-hook-form' +import { useState, useRef, useEffect } from "react" +import { useFieldArray } from "react-hook-form" import { DndContext, @@ -9,42 +9,42 @@ import { useSensor, useSensors, DragStartEvent, -} from '@dnd-kit/core' +} from "@dnd-kit/core" import { SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, -} from '@dnd-kit/sortable' +} from "@dnd-kit/sortable" -import { CommandEditDialog } from '@/components/option/editor/CommandEditDialog' -import { FolderEditDialog } from '@/components/option/editor/FolderEditDialog' +import { CommandEditDialog } from "@/components/option/editor/CommandEditDialog" +import { FolderEditDialog } from "@/components/option/editor/FolderEditDialog" import { CommandSchemaType, CommandsSchemaType, FoldersSchemaType, -} from '@/types/schema' +} from "@/types/schema" -import { ANALYTICS_EVENTS, sendEvent } from '@/services/analytics' -import { SCREEN } from '@/const' -import type { Command, CommandFolder, SelectionCommand } from '@/types' +import { ANALYTICS_EVENTS, sendEvent } from "@/services/analytics" +import { SCREEN } from "@/const" +import type { Command, CommandFolder, SelectionCommand } from "@/types" // Imported services and hooks import { toCommandTree, toFlatten, type FlattenNode, -} from '@/services/option/commandTree' +} from "@/services/option/commandTree" import { isCommand, isFolder, getDescendantFolderIds, -} from '@/services/option/commandUtils' -import { isValidDrop } from '@/services/option/dragAndDrop' -import { useCommandActions } from '@/hooks/option/useCommandActions' -import { useCommandDragDrop } from '@/hooks/option/useCommandDragDrop' -import { CommandListMenu } from './CommandListMenu' -import { CommandTreeRenderer } from './CommandTreeRenderer' +} from "@/services/option/commandUtils" +import { isValidDrop } from "@/services/option/dragAndDrop" +import { useCommandActions } from "@/hooks/option/useCommandActions" +import { useCommandDragDrop } from "@/hooks/option/useCommandDragDrop" +import { CommandListMenu } from "./CommandListMenu" +import { CommandTreeRenderer } from "./CommandTreeRenderer" // Drag filtering utilities @@ -109,16 +109,16 @@ export const CommandList = ({ control }: CommandListProps) => { const commandsRef = useRef(null) const editDataRef = useRef(null) - const commandArray = useFieldArray({ - name: 'commands', + const commandArray = useFieldArray({ + name: "commands", control: control, - keyName: '_id', + keyName: "_id", }) - const folderArray = useFieldArray({ - name: 'folders', + const folderArray = useFieldArray({ + name: "folders", control: control, - keyName: '_id', + keyName: "_id", }) const sensors = useSensors( @@ -140,7 +140,7 @@ export const CommandList = ({ control }: CommandListProps) => { sendEvent( ANALYTICS_EVENTS.OPEN_DIALOG, { - event_label: 'command_edit', + event_label: "command_edit", }, SCREEN.OPTION, ) @@ -253,8 +253,8 @@ export const CommandList = ({ control }: CommandListProps) => { useEffect(() => { commandsRef.current?.style.setProperty( - 'height', - commandsRef.current.scrollHeight + 'px', + "height", + commandsRef.current.scrollHeight + "px", ) }, [commandArray.fields, folderArray.fields]) diff --git a/src/components/option/editor/CommandListMenu.tsx b/src/components/option/editor/CommandListMenu.tsx index 23e59ed1..5ca84967 100644 --- a/src/components/option/editor/CommandListMenu.tsx +++ b/src/components/option/editor/CommandListMenu.tsx @@ -61,7 +61,7 @@ export const CommandListMenu: React.FC = ({ asChild > diff --git a/src/components/option/editor/CommandTreeRenderer.tsx b/src/components/option/editor/CommandTreeRenderer.tsx index c24ebfa0..a15931ac 100644 --- a/src/components/option/editor/CommandTreeRenderer.tsx +++ b/src/components/option/editor/CommandTreeRenderer.tsx @@ -1,17 +1,17 @@ -import React from 'react' -import { SortableItem } from '@/components/option/SortableItem' -import { EditButton } from '@/components/option/EditButton' -import { CopyButton } from '@/components/option/CopyButton' -import { RemoveButton } from '@/components/option/RemoveButton' -import { MenuImage } from '@/components/menu/MenuImage' -import type { FlattenNode } from '@/services/option/commandTree' -import type { CommandFolder } from '@/types' +import React from "react" +import { SortableItem } from "@/components/option/SortableItem" +import { EditButton } from "@/components/option/EditButton" +import { CopyButton } from "@/components/option/CopyButton" +import { RemoveButton } from "@/components/option/RemoveButton" +import { MenuImage } from "@/components/menu/MenuImage" +import type { FlattenNode } from "@/services/option/commandTree" +import type { CommandFolder } from "@/types" import { isCommand, isFolder, isPageActionCommand, -} from '@/services/option/commandUtils' -import { calcLevel } from '@/services/option/commandTree' +} from "@/services/option/commandUtils" +import { calcLevel } from "@/services/option/commandTree" interface Props { nodes: FlattenNode[] diff --git a/src/components/option/editor/FolderEditDialog.tsx b/src/components/option/editor/FolderEditDialog.tsx index 61c1f838..15a9acf8 100644 --- a/src/components/option/editor/FolderEditDialog.tsx +++ b/src/components/option/editor/FolderEditDialog.tsx @@ -1,8 +1,8 @@ -import { useEffect } from 'react' -import { useForm } from 'react-hook-form' -import { zodResolver } from '@hookform/resolvers/zod' -import { z } from 'zod' -import { FolderPlus, Save } from 'lucide-react' +import { useEffect } from "react" +import { useForm } from "react-hook-form" +import { zodResolver } from "@hookform/resolvers/zod" +import { z } from "zod" +import { FolderPlus, Save } from "lucide-react" import { Dialog, DialogClose, @@ -12,21 +12,21 @@ import { DialogTitle, DialogFooter, DialogPortal, -} from '@/components/ui/dialog' -import { Form } from '@/components/ui/form' -import { Button } from '@/components/ui/button' -import { InputField } from '@/components/option/field/InputField' -import { IconField } from '@/components/option/field/IconField' -import { SwitchField } from '@/components/option/field/SwitchField' -import { SelectField } from '@/components/option/field/SelectField' -import { isEmpty } from '@/lib/utils' -import { t as _t } from '@/services/i18n' -import { ROOT_FOLDER } from '@/const' -import { folderSchema } from '@/types/schema' -import { getDescendantFolderIds } from '@/services/option/commandUtils' +} from "@/components/ui/dialog" +import { Form } from "@/components/ui/form" +import { Button } from "@/components/ui/button" +import { InputField } from "@/components/option/field/InputField" +import { IconField } from "@/components/option/field/IconField" +import { SwitchField } from "@/components/option/field/SwitchField" +import { SelectField } from "@/components/option/field/SelectField" +import { isEmpty } from "@/lib/utils" +import { t as _t } from "@/services/i18n" +import { ROOT_FOLDER } from "@/const" +import { folderSchema } from "@/types/schema" +import { getDescendantFolderIds } from "@/services/option/commandUtils" const t = (key: string, p?: string[]) => _t(`Option_${key}`, p) -import type { CommandFolder } from '@/types' -import { calcLevel } from '@/services/option/commandTree' +import type { CommandFolder } from "@/types" +import { calcLevel } from "@/services/option/commandTree" type FolderEditDialog = { open: boolean @@ -44,17 +44,17 @@ export const FolderEditDialog = ({ folders, }: FolderEditDialog) => { const DefaultValue = { - id: '', - title: '', + id: "", + title: "", iconUrl: - 'https://cdn4.iconfinder.com/data/icons/basic-ui-2-line/32/folder-archive-document-archives-fold-1024.png', + "https://cdn4.iconfinder.com/data/icons/basic-ui-2-line/32/folder-archive-document-archives-fold-1024.png", onlyIcon: true, parentFolderId: ROOT_FOLDER, } const form = useForm>({ resolver: zodResolver(folderSchema), - mode: 'onChange', + mode: "onChange", defaultValues: DefaultValue, }) @@ -72,38 +72,38 @@ export const FolderEditDialog = ({ - {t('folders_edit')} + {t("folders_edit")} - {t('folders_input')} + {t("folders_input")}
{ @@ -126,15 +126,15 @@ export const FolderEditDialog = ({
diff --git a/src/components/option/editor/PageActionSection.tsx b/src/components/option/editor/PageActionSection.tsx index 9925618f..ac29c311 100644 --- a/src/components/option/editor/PageActionSection.tsx +++ b/src/components/option/editor/PageActionSection.tsx @@ -1,21 +1,21 @@ -import { useState } from 'react' -import { useFieldArray } from 'react-hook-form' -import { Disc3 } from 'lucide-react' -import { PAGE_ACTION_OPEN_MODE } from '@/const' -import { FormLabel, FormDescription } from '@/components/ui/form' -import type { PageAction } from '@/services/pageAction' -import { t as _t } from '@/services/i18n' +import { useState } from "react" +import { useFieldArray } from "react-hook-form" +import { Disc3 } from "lucide-react" +import { PAGE_ACTION_OPEN_MODE } from "@/const" +import { FormLabel, FormDescription } from "@/components/ui/form" +import type { PageAction } from "@/services/pageAction" +import { t as _t } from "@/services/i18n" const t = (key: string, p?: string[]) => _t(`Option_${key}`, p) -import { cn, e2a, isEmpty, capitalize } from '@/lib/utils' -import { PageActionStep } from '@/types/schema' -import { DeepPartial } from '@/types' +import { cn, e2a, isEmpty, capitalize } from "@/lib/utils" +import { PageActionStep } from "@/types/schema" +import { DeepPartial } from "@/types" -import { InputField } from '@/components/option/field/InputField' -import { SelectField } from '@/components/option/field/SelectField' -import { StepList } from '@/components/pageAction/StepList' -import { InputEditor } from '@/components/pageAction/InputEditor' -import { RemoveDialog } from '@/components/option/RemoveDialog' -import { TypeIcon } from '@/components/pageAction/TypeIcon' +import { InputField } from "@/components/option/field/InputField" +import { SelectField } from "@/components/option/field/SelectField" +import { StepList } from "@/components/pageAction/StepList" +import { InputEditor } from "@/components/pageAction/InputEditor" +import { RemoveDialog } from "@/components/option/RemoveDialog" +import { TypeIcon } from "@/components/pageAction/TypeIcon" type PageActionSectionProps = { form: any @@ -29,12 +29,12 @@ export const PageActionSection = ({ const { register, getValues } = form const pageActionArray = useFieldArray({ - name: 'pageActionOption.steps', + name: "pageActionOption.steps", control: form.control, - keyName: '_id', + keyName: "_id", }) const steps = pageActionArray.fields as unknown as PageActionStep[] - const recDisabled = !getValues('pageActionOption.startUrl') + const recDisabled = !getValues("pageActionOption.startUrl") // for Editor const [editId, setEditId] = useState(null) @@ -90,19 +90,19 @@ export const PageActionSection = ({ mode !== PAGE_ACTION_OPEN_MODE.NONE) .map((mode) => ({ @@ -113,8 +113,8 @@ export const PageActionSection = ({
- {t('pageAction_title')} - {t('pageAction_desc')} + {t("pageAction_title")} + {t("pageAction_desc")}
_t(`Option_${key}`, p) -import { POPUP_ENABLED, LINK_COMMAND_ENABLED, INHERIT } from '@/const' -import { e2a, cn } from '@/lib/utils' -import type { PageRule, PopupPlacementOrInherit } from '@/types' -import { PopupPlacementSchema } from '@/types/schema' +import { POPUP_ENABLED, LINK_COMMAND_ENABLED, INHERIT } from "@/const" +import { e2a, cn } from "@/lib/utils" +import type { PageRule, PopupPlacementOrInherit } from "@/types" +import { PopupPlacementSchema } from "@/types/schema" -import css from './CommandEditDialog.module.css' +import css from "./CommandEditDialog.module.css" export const pageRuleSchema = z.object({ - urlPattern: z.string().url({ message: t('zod_url') }), + urlPattern: z.string().url({ message: t("zod_url") }), popupEnabled: z.nativeEnum(POPUP_ENABLED), - popupPlacement: z.union([ - z.literal('inherit'), - PopupPlacementSchema, - ]), + popupPlacement: z.union([z.literal("inherit"), PopupPlacementSchema]), linkCommandEnabled: z.nativeEnum(LINK_COMMAND_ENABLED), }) @@ -52,7 +46,7 @@ const pageRulesSchema = z.object({ type pageRulesType = z.infer const DefaultRule = { - urlPattern: '', + urlPattern: "", popupEnabled: POPUP_ENABLED.ENABLE, popupPlacement: INHERIT as PopupPlacementOrInherit, linkCommandEnabled: LINK_COMMAND_ENABLED.INHERIT, @@ -78,10 +72,10 @@ export const PageRuleList = ({ } } - const pageRuleArray = useFieldArray({ + const pageRuleArray = useFieldArray({ control: control, - name: 'pageRules', - keyName: '_id', + name: "pageRules", + keyName: "_id", }) const upsert = (rule: PageRule) => { @@ -110,15 +104,15 @@ export const PageRuleList = ({ ref={addButtonRef} > - {t('pageRules') - .split(' ') + {t("pageRules") + .split(" ") .map((w) => ( {w} ))}
@@ -127,8 +121,8 @@ export const PageRuleList = ({
  • @@ -144,16 +138,16 @@ export const PageRuleList = ({

    • - {t('popupEnabled')}: {t(`${field.popupEnabled}`)} + {t("popupEnabled")}: {t(`${field.popupEnabled}`)}
    • - {t('popupPlacement')}:{' '} + {t("popupPlacement")}:{" "} {field.popupPlacement === INHERIT - ? t('inherit') + ? t("inherit") : `${field.popupPlacement.side} ${field.popupPlacement.align}`}
    • - {t('linkCommandEnabled')}:{' '} + {t("linkCommandEnabled")}:{" "} {t(`linkCommand_enabled${field.linkCommandEnabled}`, [ t(`linkCommand_enabled${linkCommandEnabled}`), ])} @@ -207,20 +201,20 @@ export const PageRuleDialog = ({ }: PageRuleDialogProps) => { const form = useForm>({ resolver: zodResolver(pageRuleSchema), - mode: 'onChange', + mode: "onChange", }) const { register, reset, setValue, watch } = form - const popupPlacement = watch('popupPlacement') + const popupPlacement = watch("popupPlacement") const [isCollapsibleOpen, setIsCollapsibleOpen] = useState(false) const handlePopupPlacementSubmit = ( data: z.infer, ) => { - setValue('popupPlacement', data) + setValue("popupPlacement", data) } const handleInheritChange = (inherit: boolean) => { - setValue('popupPlacement', inherit ? INHERIT : PopupPlacement) + setValue("popupPlacement", inherit ? INHERIT : PopupPlacement) setIsCollapsibleOpen(!inherit) } @@ -245,25 +239,25 @@ export const PageRuleDialog = ({ - {t('pageRules_add')} + {t("pageRules_add")} - {t('pageRules_add_desc')} + {t("pageRules_add_desc")}
      ({ name: t(`${mode}`), value: mode, @@ -272,7 +266,7 @@ export const PageRuleDialog = ({ ({ name: t(`linkCommand_enabled${opt}`, [ t(`linkCommand_enabled${linkCommandEnabled}`), @@ -289,24 +283,31 @@ export const PageRuleDialog = ({ onChange={(e) => handleInheritChange(e.target.checked)} className="rounded border-gray-300 cursor-pointer" /> -
      @@ -316,7 +317,7 @@ export const PageRuleDialog = ({ diff --git a/src/components/option/editor/ShortcutList.tsx b/src/components/option/editor/ShortcutList.tsx index 38912926..52117e8c 100644 --- a/src/components/option/editor/ShortcutList.tsx +++ b/src/components/option/editor/ShortcutList.tsx @@ -1,21 +1,23 @@ -import { useEffect, useState, useMemo } from 'react' -import { Control, useFieldArray, useWatch } from 'react-hook-form' -import { Keyboard, SquareArrowOutUpRight } from 'lucide-react' -import { SelectField } from '@/components/option/field/SelectField' -import type { - SelectOptionType, - SelectGroupType, -} from '@/components/option/field/SelectField' -import { t as _t } from '@/services/i18n' -import { Ipc, BgCommand } from '@/services/ipc' -import type { Command, CommandFolder, ShortcutCommand } from '@/types' +import { useEffect, useState, useMemo } from "react" +import { Control, useFieldArray, useWatch } from "react-hook-form" +import { Keyboard, SquareArrowOutUpRight } from "lucide-react" +import { SelectField } from "@/components/option/field/SelectField" +import type { SelectOptionType } from "@/components/option/field/SelectField" +import { t as _t } from "@/services/i18n" +import { Ipc, BgCommand } from "@/services/ipc" +import type { Command, CommandFolder, ShortcutCommand } from "@/types" import { OPEN_MODE_BG, SHORTCUT_PLACEHOLDER, SHORTCUT_NO_SELECTION_BEHAVIOR, -} from '@/const' -import { cn } from '@/lib/utils' -import css from './ShortcutList.module.css' +} from "@/const" +import { + toCommandTree, + toFlatten, + calcLevel, +} from "@/services/option/commandTree" +import { cn } from "@/lib/utils" +import css from "./ShortcutList.module.css" const t = (key: string, p?: string[]) => _t(`Option_${key}`, p) @@ -33,75 +35,53 @@ const createNameRender = (openMode: string) => { {name} - {t('shortcut_text_selection_only')} + {t("shortcut_text_selection_only")} ) : undefined } -// Group commands by folder while maintaining order -const groupCommandsByFolder = ( +// Create flat list of commands and folders with proper hierarchy levels using toFlatten +const flattenCommandsAndFolders = ( commands: Command[], folders: CommandFolder[], -): (SelectOptionType | SelectGroupType)[] => { - const folderMap = new Map(folders.map((folder) => [folder.id, folder])) - - // Create a map to store commands by folder - const commandsByFolder = new Map() - commandsByFolder.set('root', []) - - // First, group commands by folder - commands.forEach((command) => { - if (!command) return - const folderId = command.parentFolderId || 'root' - if (!commandsByFolder.has(folderId)) { - commandsByFolder.set(folderId, []) - } - commandsByFolder.get(folderId)?.push(command) - }) +): SelectOptionType[] => { + const tree = toCommandTree(commands, folders) + const flattenedNodes = toFlatten(tree) - // Then, create the final array maintaining the original order - const result: (SelectOptionType | SelectGroupType)[] = [] + const result: SelectOptionType[] = [] - commands.forEach((command) => { - if (!command) return - const folderId = command.parentFolderId || 'root' - const folderCommands = commandsByFolder.get(folderId) + flattenedNodes.forEach((node) => { + if ("openMode" in node.content) { + // This is a command + const command = node.content as Command + const level = calcLevel(command, folders) - if (!folderCommands) return - - if (folderId === 'root') { - // For root commands, add them individually result.push({ name: command.title, value: command.id, iconUrl: command.iconUrl, nameRender: createNameRender(command.openMode), + level: level, }) } else { - // For folder commands, add them as a group if not already added - const folder = folderMap.get(folderId) - if ( - folder && - !result.some((item) => 'label' in item && item.label === folder.title) - ) { - result.push({ - label: folder.title, - iconUrl: folder.iconUrl, - iconSvg: folder.iconSvg, - options: folderCommands.map((cmd: Command) => ({ - name: cmd.title, - value: cmd.id, - iconUrl: cmd.iconUrl, - nameRender: createNameRender(cmd.openMode), - })), - }) - } + // This is a folder + const folder = node.content as CommandFolder + const level = calcLevel(folder, folders) + + result.push({ + name: folder.title, + value: folder.id, + iconUrl: folder.iconUrl, + iconSvg: folder.iconSvg, + level: level, + isGroup: true, // Folders are not selectable + }) } }) @@ -114,26 +94,26 @@ export function ShortcutList({ control }: ShortcutListProps) { shortcuts: { shortcuts: ShortcutCommand[] } }>({ control, - name: 'shortcuts.shortcuts', + name: "shortcuts.shortcuts", }) const userCommands = useWatch({ control, - name: 'commands', + name: "commands", defaultValue: [], }) const folders = useWatch({ control, - name: 'folders', + name: "folders", defaultValue: [], }) const shortcutValues = useWatch({ control, - name: 'shortcuts.shortcuts', + name: "shortcuts.shortcuts", }) const updateCommands = () => { chrome.commands.getAll((cmds) => { - const filteredCommands = cmds.filter((cmd) => cmd.description !== '') + const filteredCommands = cmds.filter((cmd) => cmd.description !== "") setCommands(filteredCommands) }) } @@ -144,7 +124,7 @@ export function ShortcutList({ control }: ShortcutListProps) { // Update commands when the page becomes visible or focused const handleVisibilityChange = () => { - if (document.visibilityState === 'visible') { + if (document.visibilityState === "visible") { updateCommands() } } @@ -153,12 +133,12 @@ export function ShortcutList({ control }: ShortcutListProps) { updateCommands() } - document.addEventListener('visibilitychange', handleVisibilityChange) - window.addEventListener('focus', handleFocus) + document.addEventListener("visibilitychange", handleVisibilityChange) + window.addEventListener("focus", handleFocus) return () => { - document.removeEventListener('visibilitychange', handleVisibilityChange) - window.removeEventListener('focus', handleFocus) + document.removeEventListener("visibilitychange", handleVisibilityChange) + window.removeEventListener("focus", handleFocus) } }, []) @@ -166,7 +146,7 @@ export function ShortcutList({ control }: ShortcutListProps) { // Initialize the shortcuts if (fields.length !== 0) return const initialData = commands.map((cmd) => ({ - id: cmd.name || '', + id: cmd.name || "", commandId: SHORTCUT_PLACEHOLDER, noSelectionBehavior: SHORTCUT_NO_SELECTION_BEHAVIOR.USE_CLIPBOARD, })) @@ -174,17 +154,17 @@ export function ShortcutList({ control }: ShortcutListProps) { }, [replace, commands, userCommands]) const options = useMemo( - () => groupCommandsByFolder(userCommands, folders), + () => flattenCommandsAndFolders(userCommands, folders), [userCommands, folders], ) const noSelectionOptions = [ { - name: t('shortcut_no_selection_do_nothing'), + name: t("shortcut_no_selection_do_nothing"), value: SHORTCUT_NO_SELECTION_BEHAVIOR.DO_NOTHING, }, { - name: t('shortcut_no_selection_use_clipboard'), + name: t("shortcut_no_selection_use_clipboard"), value: SHORTCUT_NO_SELECTION_BEHAVIOR.USE_CLIPBOARD, }, ] @@ -193,13 +173,13 @@ export function ShortcutList({ control }: ShortcutListProps) {
      -

      {t('shortcuts')}

      +

      {t("shortcuts")}

      - {t('shortcuts_desc')} + {t("shortcuts_desc")}
      - {t('shortcuts_settings_desc')}{' '} + {t("shortcuts_settings_desc")}{" "}

      @@ -220,7 +200,7 @@ export function ShortcutList({ control }: ShortcutListProps) { const opts = [ { - name: t('shortcut_select_placeholder'), + name: t("shortcut_select_placeholder"), value: SHORTCUT_PLACEHOLDER, }, ...options, @@ -238,14 +218,14 @@ export function ShortcutList({ control }: ShortcutListProps) { {showNoSel && ( diff --git a/src/components/option/editor/UserStyleList.tsx b/src/components/option/editor/UserStyleList.tsx index 2430250e..d51f4177 100644 --- a/src/components/option/editor/UserStyleList.tsx +++ b/src/components/option/editor/UserStyleList.tsx @@ -1,8 +1,8 @@ -import { useEffect, useState, useRef } from 'react' -import { useForm, useFieldArray } from 'react-hook-form' -import { z } from 'zod' -import { zodResolver } from '@hookform/resolvers/zod' -import { Paintbrush, Save } from 'lucide-react' +import { useEffect, useState, useRef } from "react" +import { useForm, useFieldArray } from "react-hook-form" +import { z } from "zod" +import { zodResolver } from "@hookform/resolvers/zod" +import { Paintbrush, Save } from "lucide-react" import { Form, FormControl, @@ -11,7 +11,7 @@ import { FormItem, FormLabel, FormMessage, -} from '@/components/ui/form' +} from "@/components/ui/form" import { Dialog, DialogClose, @@ -21,23 +21,23 @@ import { DialogTitle, DialogFooter, DialogPortal, -} from '@/components/ui/dialog' +} from "@/components/ui/dialog" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, -} from '@/components/ui/select' -import { Tooltip } from '@/components/Tooltip' -import { Input } from '@/components/ui/input' -import { Button } from '@/components/ui/button' -import { EditButton } from '@/components/option/EditButton' -import { RemoveButton } from '@/components/option/RemoveButton' +} from "@/components/ui/select" +import { Tooltip } from "@/components/Tooltip" +import { Input } from "@/components/ui/input" +import { Button } from "@/components/ui/button" +import { EditButton } from "@/components/option/EditButton" +import { RemoveButton } from "@/components/option/RemoveButton" -import { STYLE_VARIABLE } from '@/const' -import { cn, hyphen2Underscore } from '@/lib/utils' -import { t as _t } from '@/services/i18n' +import { STYLE_VARIABLE } from "@/const" +import { cn, hyphen2Underscore } from "@/lib/utils" +import { t as _t } from "@/services/i18n" const t = (key: string, p?: string[]) => _t(`Option_${key}`, p) export const userStyleSchema = z.object({ @@ -53,7 +53,7 @@ type UserStyleType = z.infer type UserStylesType = z.infer type AttributesType = { - type: 'string' | 'number' | 'color' + type: "string" | "number" | "color" default: string | number max?: number min?: number @@ -64,43 +64,43 @@ type AttributeMap = Record const Attributes: AttributeMap = { [STYLE_VARIABLE.BACKGROUND_COLOR]: { - type: 'color', - default: '#FFFFFF', + type: "color", + default: "#FFFFFF", }, [STYLE_VARIABLE.BORDER_COLOR]: { - type: 'color', - default: '#F3F4F6', + type: "color", + default: "#F3F4F6", }, [STYLE_VARIABLE.FONT_SCALE]: { - type: 'number', + type: "number", default: 1, max: 3, min: 0.5, step: 0.1, }, [STYLE_VARIABLE.IMAGE_SCALE]: { - type: 'number', + type: "number", default: 1, max: 3, min: 0.5, step: 0.1, }, [STYLE_VARIABLE.PADDING_SCALE]: { - type: 'number', + type: "number", default: 1, max: 3, min: 0.5, step: 0.1, }, [STYLE_VARIABLE.POPUP_DELAY]: { - type: 'number', + type: "number", default: 250, max: 1000, min: 0, step: 10, }, [STYLE_VARIABLE.POPUP_DURATION]: { - type: 'number', + type: "number", default: 150, max: 1000, min: 0, @@ -115,13 +115,13 @@ const Units: UnitMap = { [STYLE_VARIABLE.FONT_SCALE]: undefined, [STYLE_VARIABLE.IMAGE_SCALE]: undefined, [STYLE_VARIABLE.PADDING_SCALE]: undefined, - [STYLE_VARIABLE.POPUP_DELAY]: 'ms', - [STYLE_VARIABLE.POPUP_DURATION]: 'ms', + [STYLE_VARIABLE.POPUP_DELAY]: "ms", + [STYLE_VARIABLE.POPUP_DURATION]: "ms", } const DefaultValue = { name: STYLE_VARIABLE.FONT_SCALE, - value: '', + value: "", } as const type UserStyleListProps = { @@ -133,10 +133,10 @@ export const UserStyleList = ({ control }: UserStyleListProps) => { const editorRef = useRef(DefaultValue) const addButtonRef = useRef(null) - const array = useFieldArray({ - name: 'userStyles', + const array = useFieldArray({ + name: "userStyles", control: control, - keyName: '_id', + keyName: "_id", }) const selectedList = array.fields.map((field) => field.name) @@ -149,7 +149,7 @@ export const UserStyleList = ({ control }: UserStyleListProps) => { if (!open) { editorRef.current = { name: defaultName, - value: '', + value: "", } } _setDialogOpen(open) @@ -188,15 +188,15 @@ export const UserStyleList = ({ control }: UserStyleListProps) => { disabled={selectedAll} > - {t('userStyles') - .split(' ') + {t("userStyles") + .split(" ") .map((w) => ( {w} ))}
      @@ -205,8 +205,8 @@ export const UserStyleList = ({ control }: UserStyleListProps) => {
    • @@ -264,11 +264,11 @@ export const UserStyleDialog = ({ const isUpdate = (variable as any)._id != null const form = useForm>({ resolver: zodResolver(userStyleSchema), - mode: 'onChange', + mode: "onChange", defaultValues: variable, }) const { reset, watch, setValue } = form - const variableName = watch('name') + const variableName = watch("name") const attr = Attributes[variableName] useEffect(() => { @@ -277,7 +277,7 @@ export const UserStyleDialog = ({ useEffect(() => { if (!isUpdate) { - setValue('value', Attributes[variableName]?.default) + setValue("value", Attributes[variableName]?.default) } }, [variableName]) @@ -288,10 +288,10 @@ export const UserStyleDialog = ({ - {t('userStyles_add')} + {t("userStyles_add")} - {t('userStyles_add_desc')} + {t("userStyles_add_desc")} {isUpdate ? (

      - {t('userStyles_name')} + {t("userStyles_name")}

      {t( `userStyles_option_${hyphen2Underscore(field.value)}`, @@ -313,10 +313,10 @@ export const UserStyleDialog = ({ onValueChange={field.onChange} value={field.value} > - {t('userStyles_name')} + {t("userStyles_name")} - + @@ -347,7 +347,7 @@ export const UserStyleDialog = ({ name="value" render={({ field }) => ( - {t('userStyles_value')} + {t("userStyles_value")} diff --git a/src/components/option/field/IconField.tsx b/src/components/option/field/IconField.tsx index 80f63b51..9da01f42 100644 --- a/src/components/option/field/IconField.tsx +++ b/src/components/option/field/IconField.tsx @@ -1,10 +1,10 @@ -import React, { useState, useRef } from 'react' -import { useController } from 'react-hook-form' -import { FormLabel, FormMessage, FormDescription } from '@/components/ui/form' -import { Input } from '@/components/ui/input' -import { MenuImage } from '@/components/menu/MenuImage' -import { isEmpty, isValidSVG } from '@/lib/utils' -import { t as _t } from '@/services/i18n' +import React, { useState, useRef } from "react" +import { useController } from "react-hook-form" +import { FormLabel, FormMessage, FormDescription } from "@/components/ui/form" +import { Input } from "@/components/ui/input" +import { MenuImage } from "@/components/menu/MenuImage" +import { isEmpty, isValidSVG } from "@/lib/utils" +import { t as _t } from "@/services/i18n" const t = (key: string, p?: string[]) => _t(`Option_${key}`, p) type IconField = { @@ -16,7 +16,7 @@ type IconField = { description?: string } -import { useFavicon } from '@/hooks/option/useFavicon' +import { useFavicon } from "@/hooks/option/useFavicon" export const IconField = ({ control, @@ -138,13 +138,13 @@ const UrlOrSvgInput = ({ const handleInputChange = (event: React.ChangeEvent) => { const inputText = event.target.value if (isValidUrl(inputText)) { - onChange({ url: inputText, svg: '' }) + onChange({ url: inputText, svg: "" }) } else if (isValidSVG(inputText)) { - onChange({ url: '', svg: inputText }) + onChange({ url: "", svg: inputText }) } else { - onChange({ url: inputText, svg: '' }) + onChange({ url: inputText, svg: "" }) if (inputText.length > 0) { - setError(t('icon_error')) + setError(t("icon_error")) } return } @@ -155,7 +155,7 @@ const UrlOrSvgInput = ({ <> _t(`Option_${key}`, p) type PopupPlacementType = z.infer @@ -34,7 +34,7 @@ export const PopupPlacementField = ({ }: PopupPlacementFieldType) => { const form = useForm({ resolver: zodResolver(PopupPlacementSchema), - mode: 'onChange', + mode: "onChange", defaultValues: defaultValues, }) const { register } = form @@ -47,19 +47,19 @@ export const PopupPlacementField = ({ const side = useWatch({ control: form.control, - name: 'side', + name: "side", }) const align = useWatch({ control: form.control, - name: 'align', + name: "align", }) const isAlignOffsetDisabled = align === ALIGN.center return (

      -

      {t('popupPlacement')}

      +

      {t("popupPlacement")}

      (
      - {t('popupPlacement_side')} + {t("popupPlacement_side")} - {t('popupPlacement_side_desc')} + {t("popupPlacement_side_desc")}
      @@ -90,7 +90,7 @@ export const PopupPlacementField = ({
      - {t('mouse_pointer')} + {t("mouse_pointer")}
      @@ -107,15 +107,15 @@ export const PopupPlacementField = ({ (
      - {t('popupPlacement_align')} + {t("popupPlacement_align")} - {t('popupPlacement_align_desc')} + {t("popupPlacement_align_desc")}
      @@ -167,19 +167,23 @@ export const PopupPlacementField = ({ { value={side} aria-label={t(`popupPlacement_${side}`)} className={cn( - 'relative w-full h-9 shadow-sm text-xs font-mono text-gray-600', + "relative w-full h-9 shadow-sm text-xs font-mono text-gray-600", )} > {checked && } @@ -219,7 +223,7 @@ const AlignItem = ({ current: ALIGN }) => { const _side = - side === SIDE.left || side === SIDE.right ? 'vertical' : 'horizontal' + side === SIDE.left || side === SIDE.right ? "vertical" : "horizontal" const checked = align === current return ( @@ -228,8 +232,8 @@ const AlignItem = ({ value={align} aria-label={t(`popupPlacement_${align}`)} className={cn( - 'relative', - 'flex-col gap-0 h-auto w-full py-1 shadow-sm text-xs font-mono text-gray-600', + "relative", + "flex-col gap-0 h-auto w-full py-1 shadow-sm text-xs font-mono text-gray-600", )} > {checked && } diff --git a/src/components/option/field/SelectField.tsx b/src/components/option/field/SelectField.tsx index 0e9e0efe..945036b2 100644 --- a/src/components/option/field/SelectField.tsx +++ b/src/components/option/field/SelectField.tsx @@ -5,17 +5,15 @@ import { FormLabel, FormMessage, FormDescription, -} from '@/components/ui/form' +} from "@/components/ui/form" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, - SelectGroup, - SelectLabel, -} from '@/components/ui/select' -import { MenuImage } from '@/components/menu/MenuImage' +} from "@/components/ui/select" +import { MenuImage } from "@/components/menu/MenuImage" export type SelectOptionType = { name: string @@ -24,20 +22,14 @@ export type SelectOptionType = { iconUrl?: string iconSvg?: string level?: number -} - -export type SelectGroupType = { - label: string - options: SelectOptionType[] - iconUrl?: string - iconSvg?: string + isGroup?: boolean } export type SelectFieldType = { control: any name: string formLabel: string - options: (SelectOptionType | SelectGroupType)[] + options: SelectOptionType[] placeholder?: string description?: string labelClass?: string @@ -70,7 +62,7 @@ const renderOption = (opt: SelectOptionType) => { {renderOptionContent(opt)} @@ -78,20 +70,6 @@ const renderOption = (opt: SelectOptionType) => { ) } -const renderGroupLabel = (group: SelectGroupType) => ( - - {(group.iconUrl != null || group.iconSvg != null) && ( - - )} - {group.label} - -) - export const SelectField = ({ control, name, @@ -119,24 +97,7 @@ export const SelectField = ({ - {options.map((item, index) => { - if ('options' in item) { - // Grouped options - return ( - - {item.label && renderGroupLabel(item)} - {item.options.map((opt) => ( -
      - {renderOption(opt)} -
      - ))} -
      - ) - } else { - // Regular options - return renderOption(item) - } - })} + {options.map((o) => renderOption(o))}
      diff --git a/src/components/option/field/SwitchField.tsx b/src/components/option/field/SwitchField.tsx index 99617629..e906d12f 100644 --- a/src/components/option/field/SwitchField.tsx +++ b/src/components/option/field/SwitchField.tsx @@ -1,4 +1,4 @@ -import { Switch } from '@/components/ui/switch' +import { Switch } from "@/components/ui/switch" import { FormControl, @@ -7,7 +7,7 @@ import { FormItem, FormLabel, FormMessage, -} from '@/components/ui/form' +} from "@/components/ui/form" type SwitchFieldType = { control: any diff --git a/src/components/option/field/TextareaField.tsx b/src/components/option/field/TextareaField.tsx index b1481152..57653ec1 100644 --- a/src/components/option/field/TextareaField.tsx +++ b/src/components/option/field/TextareaField.tsx @@ -1,13 +1,13 @@ -import React, { useEffect } from 'react' -import { Textarea } from '@/components/ui/textarea' +import React, { useEffect } from "react" +import { Textarea } from "@/components/ui/textarea" import { FormControl, FormField, FormItem, FormLabel, FormMessage, -} from '@/components/ui/form' -import { cn } from '@/lib/utils' +} from "@/components/ui/form" +import { cn } from "@/lib/utils" type TextareaFieldType = { control: any @@ -25,8 +25,8 @@ export const TextareaField = ({ className, }: TextareaFieldType) => { const updateHeight = (elm: HTMLTextAreaElement) => { - elm.style.height = '5px' - elm.style.height = elm.scrollHeight + 'px' + elm.style.height = "5px" + elm.style.height = elm.scrollHeight + "px" } const handleInput = (e: React.FormEvent) => { @@ -55,7 +55,7 @@ export const TextareaField = ({ id={`textarea-${name}`} {...field} placeholder={placeholder} - className={cn('resize-none max-h-80', className)} + className={cn("resize-none max-h-80", className)} onInput={handleInput} /> diff --git a/src/components/pageAction/Controller.tsx b/src/components/pageAction/Controller.tsx index 41b0b621..d0a18f38 100644 --- a/src/components/pageAction/Controller.tsx +++ b/src/components/pageAction/Controller.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState, forwardRef } from 'react' +import { useEffect, useState, forwardRef } from "react" import { Disc3, Circle, @@ -7,23 +7,28 @@ import { RotateCcw, Check, LoaderCircle, -} from 'lucide-react' -import { StepList } from '@/components/pageAction/StepList' -import { usePageActionContext } from '@/hooks/pageAction/usePageActionContext' +} from "lucide-react" +import { StepList } from "@/components/pageAction/StepList" +import { usePageActionContext } from "@/hooks/pageAction/usePageActionContext" import { PageActionListener as Listener, RunningStatus, -} from '@/services/pageAction' -import { Ipc, BgCommand, RunPageAction } from '@/services/ipc' -import { t } from '@/services/i18n' -import type { PageActiontStatus, PageActionStep, DeepPartial } from '@/types' -import { cn } from '@/lib/utils' +} from "@/services/pageAction" +import { Ipc, BgCommand, RunPageAction } from "@/services/ipc" +import { t } from "@/services/i18n" +import type { + PageActiontStatus, + PageActionStep, + PageActiontResult, + DeepPartial, +} from "@/types" +import { cn } from "@/lib/utils" import { PAGE_ACTION_OPEN_MODE, PAGE_ACTION_EXEC_STATE as EXEC_STATE, -} from '@/const' +} from "@/const" -import css from './PageActionRecorder.module.css' +import css from "./PageActionRecorder.module.css" type Props = { steps: PageActionStep[] @@ -43,9 +48,9 @@ export const Controller = forwardRef( const [hover, setHover] = useState(false) const clearState = () => { - setCurrentId('') - setFailedId('') - setFailedMesage('') + setCurrentId("") + setFailedId("") + setFailedMesage("") } const preview = () => { @@ -54,9 +59,9 @@ export const Controller = forwardRef( Ipc.send(BgCommand.previewPageAction, { steps: props.steps, openMode: PAGE_ACTION_OPEN_MODE.NONE, - srcUrl: `{{${t('PageAction_InputMenu_url')}}}`, - selectedText: `{{${t('PageAction_InputMenu_selectedText')}}}`, - clipboardText: `{{${t('PageAction_InputMenu_clipboard')}}}`, + srcUrl: `{{${t("PageAction_InputMenu_url")}}}`, + selectedText: `{{${t("PageAction_InputMenu_selectedText")}}}`, + clipboardText: `{{${t("PageAction_InputMenu_clipboard")}}}`, }) }, 100) clearState() @@ -85,11 +90,15 @@ export const Controller = forwardRef( } const onStatusChange = ({ results }: PageActiontStatus) => { - const r = results.find((r) => r.status === EXEC_STATE.Start) + const r = results.find( + (r: PageActiontResult) => r.status === EXEC_STATE.Start, + ) if (r != null) { setCurrentId(r.stepId) } - const f = results.find((r) => r.status === EXEC_STATE.Failed) + const f = results.find( + (r: PageActiontResult) => r.status === EXEC_STATE.Failed, + ) if (f != null) { setFailedId(f?.stepId) setFailedMesage(f.message) @@ -100,8 +109,8 @@ export const Controller = forwardRef( RunningStatus.subscribe(onStatusChange) RunningStatus.get().then((status) => { setCurrentId(status.stepId) - setFailedId('') - setFailedMesage('') + setFailedId("") + setFailedMesage("") }) return () => { RunningStatus.unsubscribe(onStatusChange) @@ -124,8 +133,8 @@ export const Controller = forwardRef( return (
      ( className={css.recordButtonIcon} /> - {t('PageAction_Controller_recording')}... + {t("PageAction_Controller_recording")}... ) : isRunning ? ( @@ -154,7 +163,7 @@ export const Controller = forwardRef( className="stroke-sky-500 animate-spin" /> - {t('PageAction_Controller_previewing')} + {t("PageAction_Controller_previewing")}
      ) : ( @@ -169,7 +178,7 @@ export const Controller = forwardRef( className="stroke-gray-500 fill-gray-100" /> - {t('PageAction_Controller_not_recording')} + {t("PageAction_Controller_not_recording")} )} @@ -178,7 +187,7 @@ export const Controller = forwardRef( @@ -189,21 +198,21 @@ export const Controller = forwardRef( > - {t('PageAction_Controller_stop')} + {t("PageAction_Controller_stop")} ) : ( )}
      diff --git a/src/components/pageAction/Draggable.tsx b/src/components/pageAction/Draggable.tsx index aad23af5..749c6390 100644 --- a/src/components/pageAction/Draggable.tsx +++ b/src/components/pageAction/Draggable.tsx @@ -1,9 +1,9 @@ -import { useDraggable } from '@dnd-kit/core' -import { cn } from '@/lib/utils' -import { GripVertical } from 'lucide-react' -import { Point } from '@/types' +import { useDraggable } from "@dnd-kit/core" +import { cn } from "@/lib/utils" +import { GripVertical } from "lucide-react" +import { Point } from "@/types" -import css from './PageActionRecorder.module.css' +import css from "./PageActionRecorder.module.css" type Props = { id: string @@ -35,9 +35,9 @@ export function Draggable(props: Props) { diffY = transform?.y ?? 0 const style = { - position: 'absolute', + position: "absolute", transform: `translate3d(${diffX}px, ${diffY}px, 0)`, - transition: 'box-shadow 0.1s ease', + transition: "box-shadow 0.1s ease", ...pos, } as React.CSSProperties @@ -45,14 +45,14 @@ export function Draggable(props: Props) {
      {props.children}