🎨 Support configuring the floating window hover trigger delay (#17123)

* 🎨 Support configuring the floating window hover trigger delay

* 🎨 Support configuring the floating window hover trigger delay
This commit is contained in:
Jeffrey Chen 2026-03-02 23:13:02 +08:00 committed by GitHub
parent ec4424265a
commit 2739def842
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 82 additions and 2 deletions

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "تحويم",
"floatWindowMode1": "‫اضغط مع الاستمرار على ${hotkey} + تحويم‬",
"floatWindowMode2": "عدم تشغيل",
"floatWindowDelay": "تأخير تشغيل النافذة العائمة عند التحويم",
"floatWindowDelayTip": "يعمل فقط عندما تكون طريقة تشغيل النافذة العائمة هي التحويم",
"codeSnippet": "أجزاء من الكود",
"codeSnippetTip": "صقل واجهة أو وظيفة من خلال التعليمات البرمجية",
"expandDown": "تمديد للأسفل",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Schweben",
"floatWindowMode1": "Drücken und halten Sie ${hotkey} + Schwellen",
"floatWindowMode2": "Nicht auslösen",
"floatWindowDelay": "Verzögerung beim Auslösen des schwebenden Fensters beim Schweben",
"floatWindowDelayTip": "Wirkt nur, wenn die Auslösermethode des schwebenden Fensters Schweben ist",
"codeSnippet": "Code-Schnipsel",
"codeSnippetTip": "Feinabstimmung der Oberfläche oder Funktionalität durch Code-Schnipsel",
"expandDown": "Nach unten erweitern",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Hover",
"floatWindowMode1": "Press and hold ${hotkey} + Hover",
"floatWindowMode2": "Do not trigger",
"floatWindowDelay": "Floating window hover delay",
"floatWindowDelayTip": "Only takes effect when the floating window trigger method is Hover",
"codeSnippet": "Code Snippet",
"codeSnippetTip": "Fine-tune the interface or functionality through code snippets",
"expandDown": "Expand Down",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Flotar",
"floatWindowMode1": "Presione y mantenga presionado ${hotkey} + Flotar",
"floatWindowMode2": "No activar",
"floatWindowDelay": "Retardo de activación de la ventana flotante al pasar el mouse",
"floatWindowDelayTip": "Solo tiene efecto cuando el método de activación de la ventana flotante es Flotar",
"codeSnippet": "Fragmento de código",
"codeSnippetTip": "Ajusta la interfaz o la funcionalidad mediante fragmentos de código",
"expandDown": "Expandir hacia abajo",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Flotter",
"floatWindowMode1": "Appuyez et maintenez ${hotkey} + Flotter",
"floatWindowMode2": "Ne pas déclencher",
"floatWindowDelay": "Délai d'activation de la fenêtre flottante au survol",
"floatWindowDelayTip": "N'a d'effet que lorsque la méthode de déclenchement de la fenêtre flottante est Flotter",
"codeSnippet": "Extrait de code",
"codeSnippetTip": "Affiner l'interface ou les fonctionnalités grâce à des extraits de code",
"expandDown": "Développer vers le bas",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "מרחף",
"floatWindowMode1": "לחץ והחזק ${hotkey} + מרחף",
"floatWindowMode2": "אל תניע",
"floatWindowDelay": "השהיית הפעלת החלון הצף בעת ריחוף",
"floatWindowDelayTip": "חל רק כאשר שיטת הפעלת החלון הצף היא ריחוף",
"codeSnippet": "קטע קוד",
"codeSnippetTip": "שפר את הממשק או הפונקציה באמצעות קטעי קוד",
"expandDown": "הרחב מטה",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Passa il mouse",
"floatWindowMode1": "Tieni premuto ${hotkey} + Passa il mouse",
"floatWindowMode2": "Non attivare",
"floatWindowDelay": "Ritardo di attivazione della finestra flottante al passaggio del mouse",
"floatWindowDelayTip": "Ha effetto solo quando il metodo di attivazione della finestra flottante è Passa il mouse",
"codeSnippet": "Snippet di codice",
"codeSnippetTip": "Affina l'interfaccia o la funzionalità tramite frammenti di codice",
"expandDown": "Espandi verso il basso",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "ホバー",
"floatWindowMode1": "${hotkey} を押しながらホバー",
"floatWindowMode2": "表示しない",
"floatWindowDelay": "ホバー時のフローティングウィンドウ表示遅延",
"floatWindowDelayTip": "フローティングウィンドウのトリガー方法がホバーのときのみ有効です",
"codeSnippet": "コードスニペット",
"codeSnippetTip": "コードスニペットを使用してインターフェースや機能を微調整します",
"expandDown": "選択範囲を下に拡張",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "호버(Hover)",
"floatWindowMode1": "${hotkey} 누른 채 호버",
"floatWindowMode2": "트리거하지 않음",
"floatWindowDelay": "호버 시 플로팅 창 트리거 지연",
"floatWindowDelayTip": "플로팅 창 트리거 방식이 호버(Hover)일 때만 적용됩니다",
"codeSnippet": "코드 스니펫",
"codeSnippetTip": "코드 스니펫을 통해 인터페이스나 기능을 미세 조정합니다",
"expandDown": "아래로 확장",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Najedź",
"floatWindowMode1": "Naciśnij i przytrzymaj ${hotkey} + Najedź",
"floatWindowMode2": "Nie wywołuj",
"floatWindowDelay": "Opóźnienie wywołania okna pływającego przy najechaniu",
"floatWindowDelayTip": "Działa tylko wtedy, gdy metoda wywoływania okna pływającego to Najedź",
"codeSnippet": "Fragment kodu",
"codeSnippetTip": "Dostosuj interfejs lub funkcjonalność za pomocą fragmentów kodu",
"expandDown": "Rozwiń w dół",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Passar o mouse",
"floatWindowMode1": "Pressionar e segurar ${hotkey} + Passar o mouse",
"floatWindowMode2": "Não acionar",
"floatWindowDelay": "Atraso de acionamento da janela flutuante ao passar o mouse",
"floatWindowDelayTip": "Só tem efeito quando o método de acionamento da janela flutuante é Passar o mouse",
"codeSnippet": "Snippet de Código",
"codeSnippetTip": "Ajuste fino da interface ou funcionalidade através de snippets de código",
"expandDown": "Expandir para Baixo",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Наведение",
"floatWindowMode1": "Нажмите и удерживайте ${hotkey} + Наведение",
"floatWindowMode2": "Не вызывать",
"floatWindowDelay": "Задержка активации плавающего окна при наведении",
"floatWindowDelayTip": "Действует только тогда, когда способ активации плавающего окна — Наведение",
"codeSnippet": "Фрагмент кода",
"codeSnippetTip": "Тонкая настройка интерфейса или функциональности с помощью фрагментов кода",
"expandDown": "Раскрыть вниз",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Prejdenie myšou (Hover)",
"floatWindowMode1": "Podržanie ${hotkey} + Prejdenie myšou",
"floatWindowMode2": "Neaktivovať",
"floatWindowDelay": "Oneskorenie spúšťača plávajúceho okna pri prejdení myšou",
"floatWindowDelayTip": "Platí iba vtedy, keď je spúšťač plávajúceho okna nastavený na Prejdenie myšou",
"codeSnippet": "Útržok kódu (Snippet)",
"codeSnippetTip": "Upravte rozhranie alebo funkcie pomocou vlastného kódu",
"expandDown": "Rozbaliť dole",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "Üzerine gelince",
"floatWindowMode1": "${hotkey} tuşuna basılı tut + üzerine gel",
"floatWindowMode2": "Tetikleme yok",
"floatWindowDelay": "İmleç üzerine gelindiğinde kayan pencere tetikleme gecikmesi",
"floatWindowDelayTip": "Yalnızca kayan pencere tetikleme yöntemi Üzerine gelince olduğunda etkili olur",
"codeSnippet": "Kod Parçası",
"codeSnippetTip": "Arayüzü veya işlevselliği kod parçacıklarıyla ince ayarla",
"expandDown": "Aşağı genişlet",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "懸停",
"floatWindowMode1": "按住 ${hotkey}+懸停",
"floatWindowMode2": "不觸發浮窗",
"floatWindowDelay": "浮窗懸停觸發延遲",
"floatWindowDelayTip": "僅在「浮窗觸發方式」為「懸停」時生效",
"codeSnippet": "代碼片段",
"codeSnippetTip": "透過程式碼片段對介面或功能進行微調",
"expandDown": "向下擴選",

View file

@ -603,6 +603,8 @@
"floatWindowMode0": "悬停",
"floatWindowMode1": "按住 ${hotkey}+悬停",
"floatWindowMode2": "不触发浮窗",
"floatWindowDelay": "浮窗悬停触发延迟",
"floatWindowDelayTip": "仅在“浮窗触发方式”为“悬停”时生效",
"codeSnippet": "代码片段",
"codeSnippetTip": "通过代码片段对界面或功能进行微调",
"expandDown": "向下扩选",

View file

@ -191,7 +191,7 @@ export const initBlockPopover = (app: App) => {
}
clearTimeout(timeoutHide);
showPopover(app);
}, 620);
}, window.siyuan.config.editor.floatWindowDelay);
});
};

View file

@ -259,7 +259,19 @@ export const editor = {
<option value="0" ${window.siyuan.config.editor.floatWindowMode === 0 ? "selected" : ""}>${window.siyuan.languages.floatWindowMode0}</option>
<option value="1" ${window.siyuan.config.editor.floatWindowMode === 1 ? "selected" : ""}>${window.siyuan.languages.floatWindowMode1.replace("${hotkey}", updateHotkeyTip("⌘"))}</option>
<option value="2" ${window.siyuan.config.editor.floatWindowMode === 2 ? "selected" : ""}>${window.siyuan.languages.floatWindowMode2}</option>
</select>
</select>
</div>
<div class="fn__flex b3-label config__item${window.siyuan.config.editor.floatWindowMode !== 0 ? " fn__none" : ""}" id="floatWindowDelayWrap">
<div class="fn__flex-1">
${window.siyuan.languages.floatWindowDelay}
<div class="b3-label__text">${window.siyuan.languages.floatWindowDelayTip}</div>
</div>
<span class="fn__space"></span>
<div class="fn__size200 fn__flex-center fn__flex">
<input class="b3-text-field fn__flex-1" id="floatWindowDelay" type="number" min="0" max="10000" value="${window.siyuan.config.editor.floatWindowDelay}"/>
<span class="fn__space"></span>
<span class="ft__on-surface fn__flex-center">ms</span>
</div>
</div>
<div class="fn__flex b3-label config__item">
<div class="fn__flex-1">
@ -466,6 +478,21 @@ export const editor = {
(editor.element.querySelector("#dynamicLoadBlocks") as HTMLInputElement).value = "48";
}
const floatWindowModeElement = editor.element.querySelector("#floatWindowMode") as HTMLSelectElement;
const floatWindowDelayWrapElement = editor.element.querySelector("#floatWindowDelayWrap") as HTMLElement;
if (floatWindowDelayWrapElement && floatWindowModeElement) {
floatWindowDelayWrapElement.classList.toggle("fn__none", parseInt(floatWindowModeElement.value) !== 0);
}
let floatWindowDelay = parseInt((editor.element.querySelector("#floatWindowDelay") as HTMLInputElement).value);
if (floatWindowDelay < 0 || isNaN(floatWindowDelay)) {
floatWindowDelay = 0;
(editor.element.querySelector("#floatWindowDelay") as HTMLInputElement).value = "0";
} else if (floatWindowDelay > 10000) {
floatWindowDelay = 10000;
(editor.element.querySelector("#floatWindowDelay") as HTMLInputElement).value = "10000";
}
fetchPost("/api/setting/setEditor", {
fullWidth: (editor.element.querySelector("#fullWidth") as HTMLInputElement).checked,
markdown: {
@ -499,6 +526,7 @@ export const editor = {
/// #endif
onlySearchForDoc: (editor.element.querySelector("#onlySearchForDoc") as HTMLInputElement).checked,
floatWindowMode: parseInt((editor.element.querySelector("#floatWindowMode") as HTMLSelectElement).value),
floatWindowDelay: floatWindowDelay,
plantUMLServePath: (editor.element.querySelector("#plantUMLServePath") as HTMLInputElement).value,
katexMacros: (editor.element.querySelector("#katexMacros") as HTMLTextAreaElement).value,
codeLineWrap: (editor.element.querySelector("#codeLineWrap") as HTMLInputElement).checked,

View file

@ -441,6 +441,11 @@ declare namespace Config {
* - `2`: Do not trigger the floating window
*/
floatWindowMode: number;
/**
* Hover delay of the floating window in milliseconds.
* Only takes effect when `floatWindowMode` is `0`.
*/
floatWindowDelay: number;
/**
* The font used in the editor
*/

View file

@ -317,6 +317,13 @@ func setEditor(c *gin.Context) {
editor.HistoryRetentionDays = 3650
}
if nil == editor.FloatWindowDelay {
v := 620
editor.FloatWindowDelay = &v
} else {
*editor.FloatWindowDelay = max(0, min(10000, *editor.FloatWindowDelay))
}
oldVirtualBlockRef := model.Conf.Editor.VirtualBlockRef
oldVirtualBlockRefInclude := model.Conf.Editor.VirtualBlockRefInclude
oldVirtualBlockRefExclude := model.Conf.Editor.VirtualBlockRefExclude

View file

@ -45,6 +45,7 @@ type Editor struct {
ListLogicalOutdent bool `json:"listLogicalOutdent"` // 列表逻辑反向缩进
ListItemDotNumberClickFocus bool `json:"listItemDotNumberClickFocus"` // 单击列表项标记聚焦
FloatWindowMode int `json:"floatWindowMode"` // 浮窗触发模式0光标悬停1按住 Ctrl 悬停2不触发浮窗
FloatWindowDelay *int `json:"floatWindowDelay"` // 浮窗悬停触发延迟,单位:毫秒,默认 620nil 表示未设置
DynamicLoadBlocks int `json:"dynamicLoadBlocks"` // 块动态数,可配置区间 [48, 1024]
Justify bool `json:"justify"` // 是否两端对齐
RTL bool `json:"rtl"` // 是否从右到左显示
@ -87,6 +88,7 @@ func NewEditor() *Editor {
ListLogicalOutdent: false,
ListItemDotNumberClickFocus: true,
FloatWindowMode: 0,
FloatWindowDelay: func() *int { v := 620; return &v }(),
DynamicLoadBlocks: 192,
Justify: false,
RTL: false,

View file

@ -292,6 +292,12 @@ func InitConf() {
if 3650 < Conf.Editor.HistoryRetentionDays {
Conf.Editor.HistoryRetentionDays = 3650
}
if nil == Conf.Editor.FloatWindowDelay {
v := 620
Conf.Editor.FloatWindowDelay = &v
} else {
*Conf.Editor.FloatWindowDelay = max(0, min(10000, *Conf.Editor.FloatWindowDelay))
}
if conf.MinDynamicLoadBlocks > Conf.Editor.DynamicLoadBlocks {
Conf.Editor.DynamicLoadBlocks = conf.MinDynamicLoadBlocks
}