From 13e172a96c9e80c04eb25175af9b1f7467968c0a Mon Sep 17 00:00:00 2001 From: windingwind <33902321+windingwind@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:49:54 +0200 Subject: [PATCH] add: hover to show note link preview --- .vscode/settings.json | 4 +-- addon/chrome/content/preferences.xhtml | 22 ++++++++++--- addon/chrome/content/templateEditor.xhtml | 18 +++++++++-- addon/locale/en-US/preferences.ftl | 12 +++++-- addon/locale/it-IT/preferences.ftl | 12 +++++-- addon/locale/ru-RU/preferences.ftl | 12 +++++-- addon/locale/tr-TR/preferences.ftl | 12 +++++-- addon/locale/zh-CN/preferences.ftl | 12 +++++-- addon/prefs.js | 2 +- src/api.ts | 2 ++ src/extras/editor/linkPreview.ts | 39 +++++++++++++++++++++-- src/hooks.ts | 6 +++- src/utils/editor.ts | 4 ++- src/utils/hint.ts | 25 ++++++++++++++- 14 files changed, 156 insertions(+), 26 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 55712c1..25fa621 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "typescript.tsdk": "node_modules/typescript/lib" -} \ No newline at end of file + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/addon/chrome/content/preferences.xhtml b/addon/chrome/content/preferences.xhtml index e6e5cb5..de00317 100644 --- a/addon/chrome/content/preferences.xhtml +++ b/addon/chrome/content/preferences.xhtml @@ -38,11 +38,22 @@ native="true" preference="__prefsPrefix__.workspace.outline.keepLinks" /> - + + + + + + + + @@ -59,6 +70,7 @@ placeholder="-1 for disable" id="__addonRef__-sync-period" preference="__prefsPrefix__.syncPeriodSeconds" + onchange="Zotero.__addonInstance__.api.utils.requireRestart();" > diff --git a/addon/chrome/content/templateEditor.xhtml b/addon/chrome/content/templateEditor.xhtml index b7f3d47..b4addfe 100644 --- a/addon/chrome/content/templateEditor.xhtml +++ b/addon/chrome/content/templateEditor.xhtml @@ -153,13 +153,25 @@ color: var(--fill-primary); } .snippet.syntax { - background-color: color-mix(in srgb, var(--accent-yellow) 50%, transparent 50%); + background-color: color-mix( + in srgb, + var(--accent-yellow) 50%, + transparent 50% + ); } .snippet.expression { - background-color: color-mix(in srgb, var(--accent-green) 50%, transparent 50%); + background-color: color-mix( + in srgb, + var(--accent-green) 50%, + transparent 50% + ); } .snippet.variable { - background-color: color-mix(in srgb, var(--accent-azure) 50%, transparent 50%); + background-color: color-mix( + in srgb, + var(--accent-azure) 50%, + transparent 50% + ); } .snippet:hover { background-color: var(--fill-quinary); diff --git a/addon/locale/en-US/preferences.ftl b/addon/locale/en-US/preferences.ftl index e1496d5..f092161 100644 --- a/addon/locale/en-US/preferences.ftl +++ b/addon/locale/en-US/preferences.ftl @@ -8,8 +8,16 @@ editor-title = Note Editor editor-expandLevel-label = Outline expand to heading level editor-keepLinks = .label = Show note links in outline -editor-noteLinkPreview = - .label = Show note link preview on hover +editor-noteLinkPreviewType = Show preview for note link when: +editor-noteLinkPreview-hover = + .label = Hover +editor-noteLinkPreview-ctrl = + .label = Press { PLATFORM() -> + [macos] ⌘ + *[other] Ctrl + } +editor-noteLinkPreview-disable = + .label = Never sync-title = Sync sync-period-label = Auto-sync period (seconds) diff --git a/addon/locale/it-IT/preferences.ftl b/addon/locale/it-IT/preferences.ftl index 16ecaa4..d5a2f2d 100644 --- a/addon/locale/it-IT/preferences.ftl +++ b/addon/locale/it-IT/preferences.ftl @@ -8,8 +8,16 @@ editor-title = Editor delle note editor-expandLevel-label = Espansione dello schema al livello delle intestazioni editor-keepLinks = .label = Mostra i collegamenti delle note nello schema -editor-noteLinkPreview = - .label = Mostra l'anteprima del link alla nota al passaggio del mouse +editor-noteLinkPreviewType = Show preview for note link when: +editor-noteLinkPreview-hover = + .label = Hover +editor-noteLinkPreview-ctrl = + .label = Press { PLATFORM() -> + [macos] ⌘ + *[other] Ctrl + } +editor-noteLinkPreview-disable = + .label = Never sync-title = Sincronizzazione sync-period-label = Intervallo della sincronizzazione automatica (secondi) diff --git a/addon/locale/ru-RU/preferences.ftl b/addon/locale/ru-RU/preferences.ftl index 2cd6567..c590da7 100644 --- a/addon/locale/ru-RU/preferences.ftl +++ b/addon/locale/ru-RU/preferences.ftl @@ -8,8 +8,16 @@ editor-title = Note Editor editor-expandLevel-label = Outline расширить до уровня заголовка editor-keepLinks = .label = Сохранить ссылки -editor-noteLinkPreview = - .label = Show note link preview on hover +editor-noteLinkPreviewType = Show preview for note link when: +editor-noteLinkPreview-hover = + .label = Hover +editor-noteLinkPreview-ctrl = + .label = Press { PLATFORM() -> + [macos] ⌘ + *[other] Ctrl + } +editor-noteLinkPreview-disable = + .label = Never sync-title = Синк sync-period-label = Авто-синк период (сек) diff --git a/addon/locale/tr-TR/preferences.ftl b/addon/locale/tr-TR/preferences.ftl index e69823a..1114d94 100644 --- a/addon/locale/tr-TR/preferences.ftl +++ b/addon/locale/tr-TR/preferences.ftl @@ -8,8 +8,16 @@ editor-title = Not Düzenleyici editor-expandLevel-label = Anahatta gösterilecek başlık düzeyleri editor-keepLinks = .label = Not bağlantılarını anahatta göster -editor-noteLinkPreview = - .label = İmleci bağlantının üzerine getirdiğinde ön izlemeyi göster +editor-noteLinkPreviewType = Show preview for note link when: +editor-noteLinkPreview-hover = + .label = Hover +editor-noteLinkPreview-ctrl = + .label = Press { PLATFORM() -> + [macos] ⌘ + *[other] Ctrl + } +editor-noteLinkPreview-disable = + .label = Never sync-title = Eşitle sync-period-label = Otomatik Eşitleme Sıklığı (saniye) diff --git a/addon/locale/zh-CN/preferences.ftl b/addon/locale/zh-CN/preferences.ftl index 8a4ad1f..2f3b143 100644 --- a/addon/locale/zh-CN/preferences.ftl +++ b/addon/locale/zh-CN/preferences.ftl @@ -8,8 +8,16 @@ editor-title = 笔记编辑器 editor-expandLevel-label = 大纲展开至标题层级 editor-keepLinks = .label = 在大纲中显示笔记链接 -editor-noteLinkPreview = - .label = 鼠标悬停时显示笔记链接预览 +editor-noteLinkPreviewType = 笔记链接预览触发方式: +editor-noteLinkPreview-hover = + .label = 鼠标悬停 +editor-noteLinkPreview-ctrl = + .label = 按下 { PLATFORM() -> + [macos] ⌘ + *[other] Ctrl + } +editor-noteLinkPreview-disable = + .label = 从不 sync-title = 同步 sync-period-label = 自动同步周期 (秒) diff --git a/addon/prefs.js b/addon/prefs.js index 305deae..f9a51bb 100644 --- a/addon/prefs.js +++ b/addon/prefs.js @@ -21,7 +21,7 @@ pref("__prefsPrefix__.exportNote", false); pref("__prefsPrefix__.workspace.outline.expandLevel", 2); pref("__prefsPrefix__.workspace.outline.keepLinks", true); -pref("__prefsPrefix__.editor.noteLinkPreview", true); +pref("__prefsPrefix__.editor.noteLinkPreviewType", "hover"); pref("__prefsPrefix__.openNote.takeover", true); pref("__prefsPrefix__.openNote.defaultAsWindow", false); diff --git a/src/api.ts b/src/api.ts index e7ecdcc..60b0db1 100644 --- a/src/api.ts +++ b/src/api.ts @@ -82,6 +82,7 @@ import { } from "./utils/relation"; import { getWorkspaceByTabID, getWorkspaceByUID } from "./utils/workspace"; import { getString } from "./utils/locale"; +import { showRestartHint } from "./utils/hint"; const workspace = { getWorkspaceByTabID, @@ -181,6 +182,7 @@ const relation = { const utils = { getString, + requireRestart: showRestartHint, }; export default { diff --git a/src/extras/editor/linkPreview.ts b/src/extras/editor/linkPreview.ts index 936becf..b75b78c 100644 --- a/src/extras/editor/linkPreview.ts +++ b/src/extras/editor/linkPreview.ts @@ -14,6 +14,8 @@ interface LinkPreviewOptions { ) => void; openURL: (url: string) => void; + + requireCtrl: boolean; } class LinkPreviewState { @@ -67,7 +69,7 @@ class LinkPreviewState { this.node = target; this.currentLink = href; this.hasHover = true; - this.tryOpenPopup(); + this.tryOpenPopupByHover(); } } } @@ -79,7 +81,24 @@ class LinkPreviewState { } }; - tryOpenPopup() { + handleKeydown = async (event: KeyboardEvent) => { + if (!this.options.requireCtrl) { + return; + } + if (!this.hasHover || !this.currentLink) { + return; + } + const isMac = + typeof navigator != "undefined" ? /Mac/.test(navigator.platform) : false; + if ((isMac && event.metaKey) || (!isMac && event.ctrlKey)) { + this.tryTogglePopupByKey(); + } + }; + + tryOpenPopupByHover() { + if (this.options.requireCtrl) { + return; + } const href = this.currentLink!; setTimeout(() => { if (this.currentLink === href) { @@ -88,6 +107,14 @@ class LinkPreviewState { }, 300); } + tryTogglePopupByKey() { + if (this._hasPopup()) { + this._closePopup(); + } else { + this._openPopup(); + } + } + _openPopup() { console.log("Enter Link Preview", this.currentLink, this.options); document.querySelectorAll(".link-preview").forEach((el) => el.remove()); @@ -158,6 +185,10 @@ class LinkPreviewState { document.querySelectorAll(".link-preview").forEach((el) => el.remove()); this.popup = null; } + + _hasPopup() { + return !!document.querySelector(".link-preview"); + } } function initLinkPreviewPlugin(options: LinkPreviewOptions) { @@ -185,6 +216,10 @@ function initLinkPreviewPlugin(options: LinkPreviewOptions) { pluginState.update(view.state); pluginState.handleMouseMove(event); }, + keydown: (view, event) => { + const pluginState = key.getState(view.state) as LinkPreviewState; + pluginState.handleKeydown(event); + }, wheel: (view, event) => { const pluginState = key.getState(view.state) as LinkPreviewState; pluginState.popup?.layoutPopup(pluginState); diff --git a/src/hooks.ts b/src/hooks.ts index 60b169c..88c6aaf 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -30,7 +30,11 @@ import { showSyncDiff } from "./modules/sync/diffWindow"; import { showSyncInfo } from "./modules/sync/infoWindow"; import { showSyncManager } from "./modules/sync/managerWindow"; import { showTemplateEditor } from "./modules/template/editorWindow"; -import { createNoteFromTemplate, createNoteFromMD, createNote } from "./modules/createNote"; +import { + createNoteFromTemplate, + createNoteFromMD, + createNote, +} from "./modules/createNote"; import { createZToolkit } from "./utils/ztoolkit"; import { waitUtilAsync } from "./utils/wait"; import { initSyncList } from "./modules/sync/api"; diff --git a/src/utils/editor.ts b/src/utils/editor.ts index 0b60c71..8257c18 100644 --- a/src/utils/editor.ts +++ b/src/utils/editor.ts @@ -442,7 +442,8 @@ function getTextBetweenLines( } function initLinkPreview(editor: Zotero.EditorInstance) { - if (!getPref("editor.noteLinkPreview")) { + const previewType = getPref("editor.noteLinkPreviewType") as string; + if (!["hover", "ctrl"].includes(previewType)) { return; } const EditorAPI = getEditorAPI(editor); @@ -469,6 +470,7 @@ function initLinkPreview(editor: Zotero.EditorInstance) { openURL: (url: string) => { Zotero.getActiveZoteroPane().loadURI(url); }, + requireCtrl: previewType === "ctrl", }, editor._iframeWindow, { wrapReflectors: true, cloneFunctions: true }, diff --git a/src/utils/hint.ts b/src/utils/hint.ts index 0ad501f..08ad424 100644 --- a/src/utils/hint.ts +++ b/src/utils/hint.ts @@ -42,4 +42,27 @@ async function showHintWithLink( return progress; } -export { showHint, showHintWithLink }; +function showRestartHint() { + const ps = Services.prompt; + const buttonFlags = + ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING + + ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING; + const index = ps.confirmEx( + // @ts-ignore + null, + Zotero.getString("general.restartRequired"), + Zotero.getString("general.restartRequiredForChange", Zotero.appName), + buttonFlags, + Zotero.getString("general.restartNow"), + Zotero.getString("general.restartLater"), + null, + null, + {}, + ); + + if (index == 0) { + Zotero.Utilities.Internal.quit(true); + } +} + +export { showHint, showHintWithLink, showRestartHint };