joplin-plugin-explorer 1.5.7 → 1.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "joplin-plugin-explorer",
3
- "version": "1.5.7",
3
+ "version": "1.5.9",
4
4
  "description": "A unified sidebar that displays notebooks and notes together in a single tree view",
5
5
  "author": "lim0513",
6
6
  "homepage": "https://github.com/lim0513/joplin-explorer",
package/publish/index.js CHANGED
@@ -1 +1 @@
1
- (()=>{"use strict";var e={982(e){e.exports=require("crypto")},896(e){e.exports=require("fs")},928(e){e.exports=require("path")}},t={};function o(a){var i=t[a];if(void 0!==i)return i.exports;var n=t[a]={exports:{}};return e[a](n,n.exports,o),n.exports}const a={zh_CN:{newNotebook:"新建笔记本",newNote:"新建笔记",newTodo:"新建待办",sort:"排序",collapseAll:"全部折叠",expandAll:"全部展开",search:"搜索笔记内容...",searchResultCount:"找到 {count} 条结果",searchNoResult:"没有找到匹配的笔记",searching:"搜索中...",sync:"同步",syncing:"同步中...",syncDone:"✔ 同步完成",syncFailed:"⚠ 同步失败",loading:"加载中...",sortUpdatedDesc:"↓ 修改时间",sortUpdatedAsc:"↑ 修改时间",sortTitleAsc:"↑ 标题",sortTitleDesc:"↓ 标题",sortManual:"⇅ 手动排序",ctxNewNoteHere:"在此新建笔记",ctxNewTodoHere:"在此新建待办",ctxNewSubNotebook:"新建子笔记本",ctxRenameFolder:"编辑",ctxExportFolder:"导出笔记本",ctxDeleteFolder:"删除笔记本",ctxOpenNote:"打开笔记",ctxOpenInNewWindow:"在新窗口中打开",ctxCopyLink:"复制 Markdown 链接",ctxDuplicateNote:"复制副本",ctxSwitchNoteType:"笔记/待办 切换",ctxToggleTodo:"切换完成状态",ctxRenameNote:"重命名",ctxMoveNote:"移动到笔记本...",ctxNoteInfo:"笔记属性",ctxDeleteNote:"删除笔记",confirmDeleteFolder:"确定删除此笔记本及其所有内容吗?",confirmDeleteNote:"确定删除此笔记吗?",promptRename:"请输入新名称:",promptMoveNote:"请输入目标笔记本名称:",promptNewNotebookName:"请输入新笔记本名称:",dropCreateNotebook:"释放以创建新笔记本",searchSectionNotes:"笔记",searchSectionTags:"标签",searchSectionFolders:"笔记本",searchTagNoteCount:"{count} 条笔记",pinned:"收藏夹",tags:"标签",ctxRenameTag:"重命名标签",ctxDeleteTag:"删除标签",ctxUntagNote:"从标签移除",confirmDeleteTag:"删除该标签?(只删除标签本身,不会删除笔记)",ctxPublishNote:"发布笔记",ctxExport:"导出",sharedBadge:"已发布 · 点击打开发布对话框",refresh:"刷新",newItem:"新建",trash:"回收站",ctxRestoreNote:"恢复",ctxPermanentDelete:"彻底删除",ctxEmptyTrash:"清空回收站",confirmEmptyTrash:"清空回收站?所有已删除的笔记本和笔记将被永久删除,无法恢复。",smartFolders:"智能文件夹",smartRecent:"最近更新",smartTodos:"未完成待办",pvType:"类型",pvSize:"大小",pvCreated:"创建",pvUpdated:"更新",pvNote:"笔记",pvTodo:"待办",pvChars:"字符",ctxSetTags:"设置标签",ctxMoveToFolder:"移动到笔记本",ctxCopyExternalLink:"复制外部链接",ctxPin:"📌 收藏",ctxUnpin:"取消收藏",cancel:"取消"},zh_TW:{newNotebook:"新建筆記本",newNote:"新建筆記",newTodo:"新建待辦",sort:"排序",collapseAll:"全部摺疊",expandAll:"全部展開",search:"搜尋筆記內容...",searchResultCount:"找到 {count} 條結果",searchNoResult:"沒有找到匹配的筆記",searching:"搜尋中...",sync:"同步",syncing:"同步中...",syncDone:"✔ 同步完成",syncFailed:"⚠ 同步失敗",loading:"載入中...",sortUpdatedDesc:"↓ 修改時間",sortUpdatedAsc:"↑ 修改時間",sortTitleAsc:"↑ 標題",sortTitleDesc:"↓ 標題",sortManual:"⇅ 手動排序",ctxNewNoteHere:"在此新建筆記",ctxNewTodoHere:"在此新建待辦",ctxNewSubNotebook:"新建子筆記本",ctxRenameFolder:"編輯",ctxExportFolder:"匯出筆記本",ctxDeleteFolder:"刪除筆記本",ctxOpenNote:"開啟筆記",ctxOpenInNewWindow:"在新視窗中開啟",ctxCopyLink:"複製 Markdown 連結",ctxDuplicateNote:"複製副本",ctxSwitchNoteType:"筆記/待辦 切換",ctxToggleTodo:"切換完成狀態",ctxRenameNote:"重新命名",ctxMoveNote:"移動到筆記本...",ctxNoteInfo:"筆記屬性",ctxDeleteNote:"刪除筆記",confirmDeleteFolder:"確定刪除此筆記本及其所有內容嗎?",confirmDeleteNote:"確定刪除此筆記嗎?",promptRename:"請輸入新名稱:",promptMoveNote:"請輸入目標筆記本名稱:",promptNewNotebookName:"請輸入新筆記本名稱:",dropCreateNotebook:"釋放以建立新筆記本",searchSectionNotes:"筆記",searchSectionTags:"標籤",searchSectionFolders:"筆記本",searchTagNoteCount:"{count} 條筆記",pinned:"收藏夾",tags:"標籤",ctxRenameTag:"重新命名標籤",ctxDeleteTag:"刪除標籤",ctxUntagNote:"自標籤移除",confirmDeleteTag:"刪除該標籤?(僅刪除標籤本身,不會刪除筆記)",ctxPublishNote:"發佈筆記",ctxExport:"匯出",sharedBadge:"已發佈 · 點擊開啟發佈對話框",refresh:"重新整理",newItem:"新增",trash:"垃圾桶",ctxRestoreNote:"還原",ctxPermanentDelete:"永久刪除",ctxEmptyTrash:"清空垃圾桶",confirmEmptyTrash:"清空垃圾桶?所有已刪除的筆記本和筆記將被永久刪除,無法還原。",smartFolders:"智慧資料夾",smartRecent:"最近更新",smartTodos:"未完成待辦",pvType:"類型",pvSize:"大小",pvCreated:"建立",pvUpdated:"更新",pvNote:"筆記",pvTodo:"待辦",pvChars:"字元",ctxSetTags:"設定標籤",ctxMoveToFolder:"移動到筆記本",ctxCopyExternalLink:"複製外部連結",ctxPin:"📌 收藏",ctxUnpin:"取消收藏",cancel:"取消"},en_US:{newNotebook:"New Notebook",newNote:"New Note",newTodo:"New To-do",sort:"Sort",collapseAll:"Collapse All",expandAll:"Expand All",search:"Search note contents...",searchResultCount:"{count} results found",searchNoResult:"No matching notes found",searching:"Searching...",sync:"Synchronise",syncing:"Syncing...",syncDone:"✔ Sync Done",syncFailed:"⚠ Sync Failed",loading:"Loading...",sortUpdatedDesc:"↓ Updated",sortUpdatedAsc:"↑ Updated",sortTitleAsc:"↑ Title",sortTitleDesc:"↓ Title",sortManual:"⇅ Manual",ctxNewNoteHere:"New Note Here",ctxNewTodoHere:"New To-do Here",ctxNewSubNotebook:"New Sub-notebook",ctxRenameFolder:"Edit",ctxExportFolder:"Export Notebook",ctxDeleteFolder:"Delete Notebook",ctxOpenNote:"Open Note",ctxOpenInNewWindow:"Open in New Window",ctxCopyLink:"Copy Markdown Link",ctxDuplicateNote:"Duplicate",ctxSwitchNoteType:"Switch Note/To-do",ctxToggleTodo:"Toggle Completed",ctxRenameNote:"Rename",ctxMoveNote:"Move to Notebook...",ctxNoteInfo:"Note Properties",ctxDeleteNote:"Delete Note",confirmDeleteFolder:"Delete this notebook and all its contents?",confirmDeleteNote:"Delete this note?",promptRename:"Enter new name:",promptMoveNote:"Enter target notebook name:",promptNewNotebookName:"Enter new notebook name:",dropCreateNotebook:"Release to create a new notebook",searchSectionNotes:"Notes",searchSectionTags:"Tags",searchSectionFolders:"Notebooks",searchTagNoteCount:"{count} notes",pinned:"Pinned",tags:"Tags",ctxRenameTag:"Rename tag",ctxDeleteTag:"Delete tag",ctxUntagNote:"Remove from tag",confirmDeleteTag:"Delete this tag? (Only the tag is removed - notes are kept.)",ctxPublishNote:"Publish note",ctxExport:"Export",sharedBadge:"Published · click to open the publish dialog",refresh:"Refresh",newItem:"New",trash:"Trash",ctxRestoreNote:"Restore",ctxPermanentDelete:"Delete permanently",ctxEmptyTrash:"Empty trash",confirmEmptyTrash:"Empty the trash? All deleted notebooks and notes will be permanently removed. This cannot be undone.",smartFolders:"Smart folders",smartRecent:"Recently updated",smartTodos:"Open to-dos",pvType:"Type",pvSize:"Size",pvCreated:"Created",pvUpdated:"Updated",pvNote:"Note",pvTodo:"To-do",pvChars:"chars",ctxSetTags:"Set tags",ctxMoveToFolder:"Move to notebook",ctxCopyExternalLink:"Copy external link",ctxPin:"📌 Pin",ctxUnpin:"Unpin",cancel:"Cancel"},ru:{newNotebook:"Новый блокнот",newNote:"Новая заметка",newTodo:"Новая задача",sort:"Сортировка",collapseAll:"Свернуть все",expandAll:"Развернуть все",search:"Искать в содержимом заметок...",searchResultCount:"Найдено результатов: {count}",searchNoResult:"Заметки не найдены",searching:"Поиск...",sync:"Синхронизировать",syncing:"Синхронизация...",syncDone:"✔ Синхронизация завершена",syncFailed:"⚠ Ошибка синхронизации",loading:"Загрузка...",sortUpdatedDesc:"↓ Обновлено",sortUpdatedAsc:"↑ Обновлено",sortTitleAsc:"↑ Название",sortTitleDesc:"↓ Название",sortManual:"⇅ Вручную",ctxNewNoteHere:"Создать заметку здесь",ctxNewTodoHere:"Создать задачу здесь",ctxNewSubNotebook:"Новый вложенный блокнот",ctxRenameFolder:"Редактировать",ctxExportFolder:"Экспортировать блокнот",ctxDeleteFolder:"Удалить блокнот",ctxOpenNote:"Открыть заметку",ctxOpenInNewWindow:"Открыть в новом окне",ctxCopyLink:"Скопировать Markdown-ссылку",ctxDuplicateNote:"Создать копию",ctxSwitchNoteType:"Переключить между заметкой и задачей",ctxToggleTodo:"Переключить статус выполнения",ctxRenameNote:"Переименовать",ctxMoveNote:"Переместить в блокнот...",ctxNoteInfo:"Свойства заметки",ctxDeleteNote:"Удалить заметку",confirmDeleteFolder:"Удалить блокнот и все его содержимое?",confirmDeleteNote:"Удалить заметку?",promptRename:"Введите новое название:",promptMoveNote:"Переместить в блокнот:",promptNewNotebookName:"Введите название нового блокнота:",dropCreateNotebook:"Отпустите, чтобы создать новый блокнот",searchSectionNotes:"Заметки",searchSectionTags:"Метки",searchSectionFolders:"Блокноты",searchTagNoteCount:"Заметок: {count}",pinned:"Закрепленные",tags:"Теги",ctxRenameTag:"Переименовать тег",ctxDeleteTag:"Удалить тег",ctxUntagNote:"Убрать из тега",confirmDeleteTag:"Удалить этот тег? (Удаляется только тег, заметки сохраняются.)",ctxPublishNote:"Опубликовать заметку",ctxExport:"Экспорт",sharedBadge:"Опубликовано · нажмите, чтобы открыть диалог публикации",refresh:"Обновить",newItem:"Создать",trash:"Корзина",ctxRestoreNote:"Восстановить",ctxPermanentDelete:"Удалить навсегда",ctxEmptyTrash:"Очистить корзину",confirmEmptyTrash:"Очистить корзину? Все удалённые блокноты и заметки будут удалены безвозвратно.",smartFolders:"Умные папки",smartRecent:"Недавно обновлённые",smartTodos:"Незавершённые задачи",pvType:"Тип",pvSize:"Размер",pvCreated:"Создано",pvUpdated:"Обновлено",pvNote:"Заметка",pvTodo:"Задача",pvChars:"симв.",ctxSetTags:"Назначить теги",ctxMoveToFolder:"Переместить в блокнот",ctxCopyExternalLink:"Копировать внешнюю ссылку",ctxPin:"📌 Закрепить",ctxUnpin:"Открепить",cancel:"Отмена"},ja_JP:{newNotebook:"新規ノートブック",newNote:"新規ノート",newTodo:"新規タスク",sort:"並べ替え",collapseAll:"すべて折りたたむ",expandAll:"すべて展開",search:"ノート内容を検索...",searchResultCount:"{count} 件の結果",searchNoResult:"一致するノートが見つかりません",searching:"検索中...",sync:"同期",syncing:"同期中...",syncDone:"✔ 同期完了",syncFailed:"⚠ 同期に失敗しました",loading:"読み込み中...",sortUpdatedDesc:"↓ 更新日時",sortUpdatedAsc:"↑ 更新日時",sortTitleAsc:"↑ タイトル",sortTitleDesc:"↓ タイトル",sortManual:"⇅ 手動",ctxNewNoteHere:"ここに新規ノート",ctxNewTodoHere:"ここに新規タスク",ctxNewSubNotebook:"新規サブノートブック",ctxRenameFolder:"編集",ctxExportFolder:"ノートブックをエクスポート",ctxDeleteFolder:"ノートブックを削除",ctxOpenNote:"ノートを開く",ctxOpenInNewWindow:"新しいウィンドウで開く",ctxCopyLink:"Markdownリンクをコピー",ctxDuplicateNote:"複製",ctxSwitchNoteType:"ノート/タスク切り替え",ctxToggleTodo:"完了状態を切り替え",ctxRenameNote:"名前を変更",ctxMoveNote:"ノートブックに移動...",ctxNoteInfo:"ノートプロパティ",ctxDeleteNote:"ノートを削除",confirmDeleteFolder:"このノートブックとその内容をすべて削除しますか?",confirmDeleteNote:"このノートを削除しますか?",promptRename:"新しい名前を入力:",promptMoveNote:"移動先のノートブック名:",promptNewNotebookName:"新しいノートブック名を入力:",dropCreateNotebook:"ドロップして新規ノートブックを作成",searchSectionNotes:"ノート",searchSectionTags:"タグ",searchSectionFolders:"ノートブック",searchTagNoteCount:"{count} 件のノート",pinned:"ピン留め",tags:"タグ",ctxRenameTag:"タグ名を変更",ctxDeleteTag:"タグを削除",ctxUntagNote:"タグから外す",confirmDeleteTag:"このタグを削除しますか?(タグのみ削除され、ノートは残ります)",ctxPublishNote:"ノートを公開",ctxExport:"エクスポート",sharedBadge:"公開済み · クリックで公開ダイアログを開く",refresh:"更新",newItem:"新規",trash:"ゴミ箱",ctxRestoreNote:"復元",ctxPermanentDelete:"完全に削除",ctxEmptyTrash:"ゴミ箱を空にする",confirmEmptyTrash:"ゴミ箱を空にしますか?削除済みのノートブックとノートは完全に削除され、元に戻せません。",smartFolders:"スマートフォルダ",smartRecent:"最近更新",smartTodos:"未完了の ToDo",pvType:"種類",pvSize:"サイズ",pvCreated:"作成",pvUpdated:"更新",pvNote:"ノート",pvTodo:"ToDo",pvChars:"文字",ctxSetTags:"タグを設定",ctxMoveToFolder:"ノートブックへ移動",ctxCopyExternalLink:"外部リンクをコピー",ctxPin:"📌 ピン留め",ctxUnpin:"ピン解除",cancel:"キャンセル"}},i=o(896),n=o(928),s=o(982);function l(e){let t=0,o=0;const a=/^[ \t]*(?:[-*+]|\d+[.)])\s+\[([ xX])\]/gm;let i;for(;i=a.exec(e);)t++," "!==i[1]&&o++;return{total:t,done:o}}let r="Published";function d(e){let t="";return e.is_shared&&(t+='<span class="shared-badge" title="'+r+'"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></span>'),e.cb_total&&(t+=function(e,t){if(!t)return"";const o=Math.max(0,Math.min(1,e/t));let a="";if(o>=1)a='<circle cx="8" cy="8" r="7" class="pie-fill"/><path d="M4.8 8.3 L7.1 10.6 L11.3 5.9" fill="none" stroke="var(--joplin-background-color, #fff)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>';else if(o>0){const e=2*o*Math.PI-Math.PI/2,t=8+7*Math.cos(e),i=8+7*Math.sin(e);a='<path class="pie-fill" d="M8 8 L8 1 A7 7 0 '+(o>.5?1:0)+" 1 "+t.toFixed(2)+" "+i.toFixed(2)+' Z"/>'}return'<span class="todo-pie" title="'+e+"/"+t+'"><svg width="12" height="12" viewBox="0 0 16 16"><circle cx="8" cy="8" r="7" class="pie-ring"/>'+a+"</svg></span>"}(e.cb_done||0,e.cb_total)),t}function c(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}const p={".gif":"image/gif",".ico":"image/x-icon",".jpeg":"image/jpeg",".jpg":"image/jpeg",".png":"image/png",".svg":"image/svg+xml",".webp":"image/webp"};function m(e,t){const o="icon"+(t?" "+t:"");return"image"===e.type?'<span class="'+o+'"><img class="custom-icon" src="'+c(e.value)+'" /></span>':'<span class="'+o+'">'+c(e.value)+"</span>"}const u={};async function f(e,t,o,a){const l=o+":"+String(e);if(u[l])return u[l];const r=await async function(e,t,o,a){const l="string"==typeof e?e.trim():"";if(!l)return{type:"text",value:t};if(/^data:image\//i.test(l)||/^https?:\/\//i.test(l))return{type:"image",value:l};const r=function(e){const t=e.trim();return/^file:\/\//i.test(t)?decodeURIComponent(t.replace(/^file:\/\//i,"")):0===t.indexOf("~/")&&process&&process.env&&process.env.HOME?n.join(process.env.HOME,t.substring(2)):n.isAbsolute(t)?t:null}(l);if(!r)return{type:"text",value:l};const d=n.extname(r).toLowerCase(),c=p[d];if(!c)return console.warn("Joplin Explorer: unsupported icon file type",r),{type:"text",value:t};const m=n.join(a,"custom-icons"),u=s.createHash("sha1").update(r).digest("hex"),f=n.join(m,o+"-"+u+d);try{await i.promises.mkdir(m,{recursive:!0}),(await i.promises.stat(r)).isFile()&&await i.promises.copyFile(r,f)}catch(e){console.warn("Joplin Explorer: failed to copy icon file",r,e)}try{return{type:"image",value:"data:"+c+";base64,"+(await i.promises.readFile(f)).toString("base64")}}catch(e){return console.warn("Joplin Explorer: failed to load icon file",f,e),{type:"text",value:t}}}(e,t,o,a);return u[l]=r,r}function w(e,t){const o=e.order||0,a=t.order||0;return o!==a?a-o:(e.title||"").localeCompare(t.title||"")}function g(e,t=!0,o={type:"text",value:"📂"},a={type:"text",value:"📁"}){let i=e.icon;if(i&&"string"==typeof i)try{i=JSON.parse(i)}catch(e){i=null}return i&&i.emoji?{type:"text",value:String(i.emoji)}:t?a:o}function h(e){return e.is_todo?e.todo_completed?"☑":"☐":"📝"}function y(e,t,o,a=0,i=!0,n={type:"text",value:"📂"},s={type:"text",value:"📁"}){let l="";for(const r of e){const e=8+18*a;if("folder"===r.type){const d=r.total_count||r.note_count||0,p=!0===o[r.id],u=p?"▶":"▼",f=p?"toggle":"toggle expanded";l+='<div class="tree-item folder'+(p?" collapsed":"")+'" style="padding-left:'+e+'px" data-id="'+r.id+'" data-type="folder">',i&&(l+='<span class="'+f+'">'+u+"</span>"),l+=m(g(r,!1,n,s),"folder-icon icon-when-open"),l+=m(g(r,!0,n,s),"folder-icon icon-when-collapsed"),l+='<span class="label">'+c(r.title)+"</span>",l+='<span class="count">'+d+"</span>",l+="</div>",l+='<div class="children'+(p?" collapsed":"")+'" data-folder-id="'+r.id+'">',r.children&&(l+=y(r.children,t,o,a+1,i,n,s)),l+="</div>"}else{const o=r.id===t?" selected":"",a=h(r);l+='<div class="tree-item note'+o+'" style="padding-left:'+e+'px" data-id="'+r.id+'" data-type="note" data-todo="'+(r.is_todo?1:0)+'">',l+='<span class="icon note-icon">'+a+"</span>",l+='<span class="label">'+c(r.title)+"</span>",l+=d(r),l+="</div>"}}return l}function x(e,t){const o=e.slice();switch(t){case"title_asc":o.sort((e,t)=>(e.title||"").localeCompare(t.title||""));break;case"title_desc":o.sort((e,t)=>(t.title||"").localeCompare(e.title||""));break;case"updated_asc":o.sort((e,t)=>(e.user_updated_time||0)-(t.user_updated_time||0));break;case"manual":o.sort((e,t)=>{const o=e.order||0,a=t.order||0;return o!==a?a-o:(t.user_updated_time||0)-(e.user_updated_time||0)});break;default:o.sort((e,t)=>(t.user_updated_time||0)-(e.user_updated_time||0))}return o}joplin.plugins.register({onStart:async function(){const e=(t=await joplin.settings.globalValue("locale")||"en_US",a[t]||a[t.split("_")[0]]||a.en_US);var t;r=e.sharedBadge||r;const o=await joplin.views.panels.create("notesInListPanel");await joplin.views.panels.addScript(o,"webview/panel.css"),await joplin.views.panels.addScript(o,"webview/panel.js"),await joplin.views.panels.setHtml(o,'<div id="notes-in-list-root"><p style="padding:12px;">'+e.loading+"</p></div>"),await joplin.views.panels.show(o,!0);try{await joplin.settings.registerSection("joplinExplorer",{label:"Joplin Explorer",iconName:"fas fa-columns"}),await joplin.settings.registerSettings({pinnedItems:{section:"joplinExplorer",type:2,value:'{"notes":[],"folders":[]}',public:!1,label:"Pinned Items (JSON)"},folderOrder:{section:"joplinExplorer",type:2,value:"{}",public:!1,label:"Folder Manual Order (JSON)"},noteSortMode:{section:"joplinExplorer",type:2,value:"updated_desc",public:!1,label:"Note Sort Mode"},uiState:{section:"joplinExplorer",type:2,value:"{}",public:!1,label:"UI State (JSON)"},showTagsSection:{section:"joplinExplorer",type:3,value:!0,public:!0,label:"Show tags section",description:"Show Joplin tags as folders below the notebook tree."},autoRefresh:{section:"joplinExplorer",type:3,value:!0,public:!0,label:"Auto refresh on external changes",description:"Poll Joplin's change feed every 5 seconds and refresh the panel when notes are created, moved or deleted by other plugins or sync. Edits to the currently open note are ignored (they already update live)."},restoreUiState:{section:"joplinExplorer",type:3,value:!0,public:!0,label:"Restore last view state on startup",description:"Remember collapsed/expanded folders and sections between sessions. When off, the tree starts fully collapsed."},showSmartFolders:{section:"joplinExplorer",type:3,value:!0,public:!0,label:"Show smart folders",description:"Saved searches rendered as folders: Recently updated, Open to-dos, and your own rules."},smartFolderRules:{section:"joplinExplorer",type:2,value:"",public:!0,label:"Custom smart folders",description:'Name:query pairs separated by ";", using Joplin search syntax. Example: Work:notebook:Work updated:day-30;Starred:tag:star'},smartFolderLimit:{section:"joplinExplorer",type:1,value:5,minimum:1,maximum:50,public:!0,label:"Smart folder result limit",description:"Maximum notes shown per smart folder (newest first). Default: 5."},hoverPreview:{section:"joplinExplorer",type:3,value:!0,public:!0,label:"Note preview on hover",description:"Show title, updated time and a body snippet when hovering a note."},hoverPreviewLength:{section:"joplinExplorer",type:1,value:200,minimum:50,maximum:1e3,public:!0,label:"Hover preview length (characters)"},toggleArrowPosition:{section:"joplinExplorer",type:2,value:"right",isEnum:!0,options:{right:"After the text",left:"Left of the text (classic tree)"},public:!0,label:"Expand arrow position",description:"Applies to notebooks, section headers and section rows alike, so everything matches."},expandAllMode:{section:"joplinExplorer",type:2,value:"restore",isEnum:!0,options:{restore:"Restore the state before Collapse All",skeleton:"Folders only (leaf notebooks stay collapsed)",all:"Everything"},public:!0,label:"Expand All behavior",description:"What the Expand All button restores. Default: the tree as it was before the last Collapse All."},showFolderToggles:{section:"joplinExplorer",type:3,value:!0,public:!0,label:"Show toggle arrows",description:"Show expand/collapse arrows before folders and the pinned section."},openFolderIcon:{section:"joplinExplorer",type:2,value:"📂",public:!0,label:"Open folder icon",description:"Emoji, image URL, data URI, or local image path for expanded folders without a custom notebook icon."},closedFolderIcon:{section:"joplinExplorer",type:2,value:"📁",public:!0,label:"Closed folder icon",description:"Emoji, image URL, data URI, or local image path for collapsed folders without a custom notebook icon."},openPinnedIcon:{section:"joplinExplorer",type:2,value:"📌",public:!0,label:"Open pinned icon",description:"Emoji, image URL, data URI, or local image path for the expanded pinned section."},closedPinnedIcon:{section:"joplinExplorer",type:2,value:"📌",public:!0,label:"Closed pinned icon",description:"Emoji, image URL, data URI, or local image path for the collapsed pinned section."}})}catch(e){console.error("Joplin Explorer: failed to register settings",e)}const i=await joplin.views.dialogs.create("explorerInputDialog"),n=await joplin.views.dialogs.create("explorerConfirmDialog"),s=await joplin.views.dialogs.create("explorerInfoDialog");async function p(t){return await joplin.views.dialogs.setHtml(n,'<div style="padding:10px;min-width:280px;"><div style="font-size:13px;">'+c(t)+"</div></div>"),await joplin.views.dialogs.setButtons(n,[{id:"ok",title:"OK"},{id:"cancel",title:e.cancel||"Cancel"}]),"ok"===(await joplin.views.dialogs.open(n)).id}async function _(e,t){await joplin.views.dialogs.setHtml(s,'<div style="padding:10px;min-width:320px;"><div style="font-size:14px;font-weight:bold;margin-bottom:10px;">'+c(e)+'</div><div style="font-size:12px;line-height:1.8;white-space:pre-wrap;">'+c(t)+"</div></div>"),await joplin.views.dialogs.setButtons(s,[{id:"ok",title:"OK"}]),await joplin.views.dialogs.open(s)}async function v(t,o){await joplin.views.dialogs.setHtml(i,'<div style="padding:10px;min-width:300px;"><div style="margin-bottom:8px;font-size:13px;">'+c(t)+'</div><form name="inputForm"><input name="value" type="text" value="'+c(o||"")+'" style="width:100%;box-sizing:border-box;padding:6px 8px;font-size:13px;" /></form></div>'),await joplin.views.dialogs.setButtons(i,[{id:"ok",title:"OK"},{id:"cancel",title:e.cancel||"Cancel"}]);const a=await joplin.views.dialogs.open(i);return"ok"===a.id&&a.formData&&a.formData.inputForm&&a.formData.inputForm.value||null}let N="",b={},j="updated_desc";try{const e=String(await joplin.settings.value("noteSortMode")||"");["updated_desc","updated_asc","title_asc","title_desc","manual"].indexOf(e)>=0&&(j=e)}catch(e){}let T=[],k={},S=[],F=[],I=!1,D=!1,E=!0,C=!1,M={},R=!0,O=null,A=[],P={},U=!0,J=!1;if(D=!0,!1!==await joplin.settings.value("restoreUiState"))try{const e=String(await joplin.settings.value("uiState")||"{}"),t=JSON.parse(e);t&&"object"==typeof t&&(t.collapsedFolders&&"object"==typeof t.collapsedFolders&&!Array.isArray(t.collapsedFolders)&&(b=t.collapsedFolders,J=!0),"boolean"==typeof t.tagsCollapsed&&(D=t.tagsCollapsed),"boolean"==typeof t.pinnedCollapsed&&(I=t.pinnedCollapsed),"boolean"==typeof t.trashCollapsed&&(E=t.trashCollapsed),"boolean"==typeof t.smartCollapsed&&(C=t.smartCollapsed),t.seenFolders&&"object"==typeof t.seenFolders&&!Array.isArray(t.seenFolders)&&(M=t.seenFolders,R=!1))}catch(e){}let L=null;function H(){L&&clearTimeout(L),L=setTimeout(async()=>{L=null;try{await joplin.settings.setValue("uiState",JSON.stringify({collapsedFolders:b,tagsCollapsed:D,pinnedCollapsed:I,trashCollapsed:E,smartCollapsed:C,seenFolders:M}))}catch(e){console.error("Joplin Explorer: failed to save UI state",e)}},500)}const q=await joplin.plugins.dataDir();let z=null;function W(e=600){z&&clearTimeout(z),z=setTimeout(async()=>{z=null,await $()},e)}let B=null,V={};async function K(){try{await joplin.settings.setValue("pinnedItems",JSON.stringify(F))}catch(e){console.error("Joplin Explorer: failed to save pinned items",e)}}async function X(){try{await joplin.settings.setValue("folderOrder",JSON.stringify(P))}catch(e){console.error("Joplin Explorer: failed to save folder order",e)}}function Z(e){let t=e;for(;t;){delete b[t];const e=k[t];t=e?e.parent_id:null}}async function $(){try{const t=await async function(){let e=[],t=1,o=!0;for(;o;){const a=await joplin.data.get(["folders"],{fields:["id","title","parent_id","icon"],page:t,limit:100});e=e.concat(a.items),o=a.has_more,t++}return e}();await async function(){try{const e=await joplin.settings.value("folderOrder"),t=e?JSON.parse(e):{};P=t&&"object"==typeof t&&!Array.isArray(t)?t:{}}catch(e){P={}}}();let a=!1;const i=new Set(t.map(e=>e.id));for(const e of Object.keys(P))i.has(e)||(delete P[e],a=!0);a&&await X();for(const e of t)e.order=P[e.id]||0;T=t,k={};for(const e of t)k[e.id]=e;let n=!1;for(const e of t)M[e.id]||(M[e.id]=!0,R||(b[e.id]=!0),n=!0);if(R&&(R=!1,n=!0),n&&H(),U){if(!J)for(const e of t)b[e.id]=!0;const e=await joplin.workspace.selectedNote();e&&(N=e.id,Z(e.parent_id)),U=!1}const s=await async function(){let e=[],t=1,o=!0;for(;o;){const a=await joplin.data.get(["notes"],{fields:["id","title","parent_id","is_todo","todo_completed","updated_time","user_updated_time","order","is_shared","body"],page:t,limit:100});for(const e of a.items){const t=l(e.body||"");e.cb_total=t.total,e.cb_done=t.done,delete e.body}e=e.concat(a.items),o=a.has_more,t++}return e}(),r={};for(const e of t)r[e.id]=[];for(const e of s)r[e.parent_id]&&r[e.parent_id].push(e);for(const e of Object.keys(r))r[e]=x(r[e],j);const p=[];for(const e of Object.keys(r))for(const t of r[e])p.push(t);S=p;const u=await joplin.settings.value("showFolderToggles"),_=await joplin.settings.value("openFolderIcon"),v=await joplin.settings.value("closedFolderIcon"),L=await joplin.settings.value("openPinnedIcon"),z=await joplin.settings.value("closedPinnedIcon"),W=await f(_,"📂","openFolderIcon",q),B=await f(v,"📁","closedFolderIcon",q),V=await f(L,"📌","openPinnedIcon",q),$=await f(z,"📌","closedPinnedIcon",q),G=!1!==u,Q=function(e,t){const o={},a={},i={};for(const t of e)o[t.id]={type:"folder",id:t.id,title:t.title,parent_id:t.parent_id,icon:t.icon,order:t.order||0,note_count:0,children:[]},a[t.id]=[],i[t.id]=[];for(const e of Object.keys(t))if(i[e])for(const o of t[e])i[e].push({type:"note",id:o.id,title:o.title||"(untitled)",is_todo:o.is_todo,todo_completed:o.todo_completed,is_shared:o.is_shared,cb_total:o.cb_total,cb_done:o.cb_done});const n=[];for(const t of e){const e=o[t.id];t.parent_id&&o[t.parent_id]?a[t.parent_id].push(e):n.push(e)}function s(e){const t=a[e.id].sort(w);for(const e of t)s(e);e.note_count=i[e.id].length,e.children=t.concat(i[e.id])}n.sort(w);for(const e of n)s(e);const l=n;function r(e){let t=0;if(!e.children)return 0;for(const o of e.children)"note"===o.type?t++:"folder"===o.type&&(r(o),t+=o.total_count||0);return e.total_count=t,t}for(const e of l)r(e);return l}(t,r),ee=y(Q,N,b,0,G,W,B);if(!1!==await joplin.settings.value("showTagsSection"))try{let e=[],t=1,o=!0;for(;o;){const a=await joplin.data.get(["tags"],{fields:["id","title"],page:t,limit:100});e=e.concat(a.items),o=a.has_more,t++}e.sort((e,t)=>(e.title||"").localeCompare(t.title||""));let a=e.map(()=>"");e.length<=200&&(a=await Promise.all(e.map(e=>joplin.data.get(["tags",e.id,"notes"],{fields:["id"],limit:100}).then(e=>0===e.items.length?"0":e.has_more?"100+":String(e.items.length)).catch(()=>""))),e=e.filter((e,t)=>"0"!==a[t]),a=a.filter(e=>"0"!==e)),A=e.map((e,t)=>({id:e.id,title:e.title||"",count:a[t]||""}))}catch(e){A=[]}else A=[];await async function(){try{const e=await joplin.settings.value("pinnedItems");if(!e)return;const t=JSON.parse(e);if(t&&!Array.isArray(t)&&t.notes&&t.folders){F=[];for(const e of t.folders)F.push({id:e,type:"folder"});for(const e of t.notes)F.push({id:e,type:"note"});await K()}else Array.isArray(t)&&(F=t)}catch(e){F=[]}}();const ae=new Set(t.map(e=>e.id)),ie=new Set(p.map(e=>e.id)),ne=F.length;F=F.filter(e=>"folder"===e.type?ae.has(e.id):ie.has(e.id)),F.length!==ne&&await K();let se="";const le=F.length;if(le>0){se+='<div class="pinned-section-header'+(I?" collapsed":"")+'" id="pinned-header">',G&&(se+='<span class="toggle">'+(I?"▶":"▼")+"</span>"),se+=m(V,"icon-when-open")+m($,"icon-when-collapsed")+'<span class="label">'+e.pinned+'</span><span class="count">'+le+"</span></div>",se+='<div class="pinned-section-body'+(I?" collapsed":"")+'" id="pinned-body">';for(const e of F)if("folder"===e.type){const t=k[e.id]||null;if(t){const e=g(t,!0,W,B);se+='<div class="tree-item folder pinned-item" data-id="'+t.id+'" data-type="folder">',se+=m(e,"folder-icon"),se+='<span class="label">'+c(t.title)+"</span>",se+="</div>"}}else{let t=null;for(const o of p)if(o.id===e.id){t=o;break}if(t){const e=t.id===N?" selected":"",o=h(t);se+='<div class="tree-item note pinned-item'+e+'" data-id="'+t.id+'" data-type="note" data-todo="'+(t.is_todo?1:0)+'">',se+='<span class="icon note-icon">'+o+"</span>",se+='<span class="label">'+c(t.title)+"</span>",se+=d(t),se+="</div>"}}se+="</div>"}let re="";if(A.length>0){re+='<div class="tags-section-header'+(D?" collapsed":"")+'" id="tags-header">',G&&(re+='<span class="toggle">'+(D?"▶":"▼")+"</span>"),re+='<span class="icon">🏷️</span><span class="label">'+e.tags+'</span><span class="count">'+A.length+"</span></div>",re+='<div class="tags-section-body'+(D?" collapsed":"")+'" id="tags-body">';for(const e of A)re+='<div class="tree-item folder tag-folder collapsed" data-tag-id="'+e.id+'" data-type="tag">',G&&(re+='<span class="toggle">▶</span>'),re+='<span class="icon">🏷️</span>',re+='<span class="label">'+c(e.title)+"</span>",e.count&&(re+='<span class="count">'+e.count+"</span>"),re+="</div>",re+='<div class="tag-children collapsed" data-tag-id="'+e.id+'"></div>';re+="</div>"}let de="";try{const t={};let o=0,a=!1,i=1,n=!0;for(;n;){const e=await joplin.data.get(["folders"],{fields:["id","deleted_time"],include_deleted:"1",page:i,limit:100});for(const a of e.items||[])a.deleted_time>0&&(t[a.id]=!0,o++);n=e.has_more,i++}const s=(await joplin.data.get(["notes"],{fields:["id","parent_id","deleted_time"],include_deleted:"1",order_by:"deleted_time",order_dir:"DESC",limit:100})).items||[];for(const e of s){if(!e.deleted_time)break;t[e.parent_id]||o++}100===s.length&&s[99].deleted_time>0&&(a=!0),(o>0||a)&&(de+='<div class="trash-section-header'+(E?" collapsed":"")+'" id="trash-header">',G&&(de+='<span class="toggle">'+(E?"▶":"▼")+"</span>"),de+='<span class="icon">🗑️</span><span class="label">'+e.trash+'</span><span class="count">'+o+(a?"+":"")+"</span></div>",de+='<div class="trash-children'+(E?" collapsed":"")+'" id="trash-children"></div>')}catch(e){}let ce="";if(!1!==await joplin.settings.value("showSmartFolders")){const t=[{id:"recent",title:e.smartRecent,query:"updated:day-7"},{id:"todos",title:e.smartTodos,query:"type:todo iscompleted:0"}],o=String(await joplin.settings.value("smartFolderRules")||"").trim();if(o){const e=o.split(";");for(let o=0;o<e.length;o++){const a=e[o].trim();if(!a)continue;const i=a.indexOf(":");i<=0||t.push({id:"rule"+o,title:a.slice(0,i).trim(),query:a.slice(i+1).trim()})}}ce+='<div class="smart-section-header'+(C?" collapsed":"")+'" id="smart-header">',G&&(ce+='<span class="toggle">'+(C?"▶":"▼")+"</span>"),ce+='<span class="icon">🔍</span><span class="label">'+e.smartFolders+"</span></div>",ce+='<div class="smart-section-body'+(C?" collapsed":"")+'" id="smart-body">';for(const e of t){if(!e.title||!e.query)continue;let t=0,o=!1;try{if("recent"===e.id)t=(await te(1)).length;else if("todos"===e.id){const e=await oe(101);t=Math.min(e.length,100),o=e.length>100}else{let a=1,i=!0;for(;i&&t<=100;){const o=await joplin.data.get(["search"],{query:e.query,fields:["id"],page:a,limit:100});t+=(o.items||[]).length,i=o.has_more,a++}t>100&&(t=100,o=!0)}}catch(e){}const a=t>0;ce+='<div class="tree-item folder smart-folder collapsed'+(a?"":" smart-empty")+'" style="padding-left:26px" data-smart-id="'+e.id+'" data-query="'+c(e.query)+'" data-type="smart"><span class="toggle">▶</span><span class="icon">🔍</span><span class="label">'+c(e.title)+"</span>"+(a&&"recent"!==e.id?'<span class="count">'+t+(o?"+":"")+"</span>":"")+"</div>",a&&(ce+='<div class="smart-children collapsed" data-smart-id="'+e.id+'"></div>')}ce+="</div>"}const pe=c(JSON.stringify(F)),me=t.length>0&&t.every(e=>!0===b[e.id]),ue={updated_desc:e.sortUpdatedDesc,updated_asc:e.sortUpdatedAsc,title_asc:e.sortTitleAsc,title_desc:e.sortTitleDesc,manual:e.sortManual},fe=c(JSON.stringify(e)),we=String(await joplin.settings.value("expandAllMode")||"restore"),ge=!1!==await joplin.settings.value("hoverPreview")?"1":"0",he="left"===String(await joplin.settings.value("toggleArrowPosition")||"right")?"left":"right",ye='<div id="notes-in-list-root" data-i18n="'+fe+'" data-pinned="'+pe+'" data-sort="'+c(j)+'" data-expand-mode="'+c(we)+'" data-hover-preview="'+ge+'" data-arrow-pos="'+he+'" data-collapse-snapshot="'+c(JSON.stringify(O))+'"> <div class="toolbar"> <button id="btn-new" title="'+e.newItem+'">+</button> <button id="btn-sort" title="'+e.sort+'">'+ue[j]+'</button> <button id="btn-collapse-all" data-mode="'+(me?"expand":"collapse")+'" title="'+(me?e.expandAll:e.collapseAll)+'">'+(me?"▼":"▲")+'</button> <button id="btn-refresh" title="'+e.refresh+'">↻</button> </div> <div class="search-bar"> <input id="search-input" type="text" placeholder="🔍 '+e.search+'" /> </div> <div id="tree-container">'+se+ce+'<div id="main-tree">'+ee+"</div>"+re+de+' <div id="drop-zone-empty" class="drop-zone-empty">+ '+e.dropCreateNotebook+'</div> </div> <div id="search-results" style="display:none;"></div> <div class="bottom-bar"> <button id="btn-sync" title="'+e.sync+'">🔄 '+e.sync+"</button> </div></div>";if(await joplin.views.panels.setHtml(o,ye),de&&!E)try{const e=await Y();await joplin.views.panels.postMessage(o,{name:"trashNotes",folders:e.folders,notes:e.notes})}catch(e){}}catch(e){console.error("Notes In List: refresh error",e),await joplin.views.panels.setHtml(o,'<div style="padding:12px;color:red;">Error: '+c(String(e))+"</div>")}}async function G(e){try{const t=S.findIndex(t=>t.id===e),a=await joplin.data.get(["notes",e],{fields:["id","title","parent_id","is_todo","todo_completed","updated_time","user_updated_time","order","is_shared","body"]}),i=l(a.body||"");if(a.cb_total=i.total,a.cb_done=i.done,delete a.body,t<0||S[t].parent_id!==a.parent_id)return void await $();const n=S[t],s=0===j.indexOf("title_")&&(n.title||"")!==(a.title||""),r=0===j.indexOf("updated_")&&n.user_updated_time!==a.user_updated_time;if(S[t]=a,s||r)return void await $();await joplin.views.panels.postMessage(o,{name:"updateNote",id:a.id,title:a.title||"(untitled)",icon:h(a),badges:d(a)})}catch(e){await $()}}async function Q(e){let t=[],o=1,a=!0;for(;a&&t.length<200;){const i=await joplin.data.get(["tags",e,"notes"],{fields:["id","title","is_todo","todo_completed"],page:o,limit:50});t=t.concat(i.items),a=i.has_more,o++}return t.map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed}))}async function Y(){const e=[],t={},o={};try{let a=1,i=!0;for(;i;){const n=await joplin.data.get(["folders"],{fields:["id","title","parent_id","deleted_time"],include_deleted:"1",page:a,limit:100});for(const a of n.items||[])o[a.id]=a.parent_id||"",a.deleted_time>0&&(e.push({id:a.id,title:a.title||"(untitled)",parent_id:a.parent_id}),t[a.id]=!0);i=n.has_more,a++}}catch(e){}const a=[],i={},n=[];for(const o of e)o.parent_id&&t[o.parent_id]?(i[o.parent_id]=i[o.parent_id]||[]).push(o):n.push(o);const s=(e,t)=>{a.push({id:e.id,title:e.title,depth:t});for(const o of i[e.id]||[])s(o,t+1)};for(const e of n)s(e,0);await Promise.all(a.map(async e=>{try{const t=await joplin.data.get(["folders",e.id,"notes"],{fields:["id"],include_deleted:"1",limit:1});e.hasNotes=!(!t.items||!t.items.length)}catch(t){e.hasNotes=!0}}));const l=[];let r=1,d=!0;for(;d&&l.length<200;){const e=await joplin.data.get(["notes"],{fields:["id","title","parent_id","is_todo","todo_completed","deleted_time"],include_deleted:"1",order_by:"deleted_time",order_dir:"DESC",page:r,limit:50});let a=!1;for(const i of e.items||[]){if(!i.deleted_time){a=!0;break}let e=!1,n=i.parent_id,s=0;for(;n&&s++<50;){if(t[n]){e=!0;break}n=o[n]||""}e||l.push({id:i.id,title:i.title||"(untitled)",is_todo:i.is_todo,todo_completed:i.todo_completed})}if(a)break;d=e.has_more,r++}return{folders:a,notes:l}}async function ee(e){const t={};try{let e=1,o=!0;for(;o;){const a=await joplin.data.get(["folders"],{fields:["id","parent_id"],include_deleted:"1",page:e,limit:100});for(const e of a.items||[])e.parent_id&&(t[e.parent_id]=t[e.parent_id]||[]).push(e.id);o=a.has_more,e++}}catch(e){}const o=async e=>{for(const a of t[e]||[])await o(a);try{let t=1,o=!0;for(;o;){const a=await joplin.data.get(["folders",e,"notes"],{fields:["id"],include_deleted:"1",page:t,limit:100});for(const e of a.items||[])try{await joplin.data.delete(["notes",e.id],{permanent:"1"})}catch(e){}o=(a.items||[]).length>0&&a.has_more}}catch(e){}try{await joplin.data.delete(["folders",e],{permanent:"1"})}catch(e){}};await o(e)}async function te(e){return((await joplin.data.get(["notes"],{fields:["id","title","is_todo","todo_completed","user_updated_time"],order_by:"user_updated_time",order_dir:"DESC",limit:Math.min(e,100)})).items||[]).map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed}))}async function oe(e){const t=[];let o=1,a=!0;for(;a&&t.length<e&&o<=10;){const e=await joplin.data.get(["notes"],{fields:["id","title","is_todo","todo_completed","user_updated_time"],order_by:"is_todo",order_dir:"DESC",page:o,limit:100});let i=!1;for(const o of e.items||[]){if(!o.is_todo){i=!0;break}o.todo_completed||t.push({id:o.id,title:o.title||"(untitled)",is_todo:o.is_todo,todo_completed:o.todo_completed,user_updated_time:o.user_updated_time||0})}if(i)break;a=e.has_more,o++}return t.sort((e,t)=>(t.user_updated_time||0)-(e.user_updated_time||0)),t.slice(0,e)}await joplin.settings.onChange(async e=>{e.keys&&e.keys.indexOf("autoRefresh")>=0&&await re(),e.keys&&(e.keys.indexOf("toggleArrowPosition")>=0||e.keys.indexOf("showSmartFolders")>=0||e.keys.indexOf("smartFolderRules")>=0||e.keys.indexOf("hoverPreview")>=0||e.keys.indexOf("expandAllMode")>=0||e.keys.indexOf("showTagsSection")>=0||e.keys.indexOf("showFolderToggles")>=0||e.keys.indexOf("openFolderIcon")>=0||e.keys.indexOf("closedFolderIcon")>=0||e.keys.indexOf("openPinnedIcon")>=0||e.keys.indexOf("closedPinnedIcon")>=0)&&(function(){for(const e of Object.keys(u))delete u[e]}(),await $())}),await joplin.views.panels.onMessage(o,async t=>{if("openNote"===t.name)N=t.id,await joplin.commands.execute("openNote",t.id);else if("refresh"===t.name)await $();else if("toggleFolder"===t.name)b[t.id]?delete b[t.id]:b[t.id]=!0,H();else if("collapseAll"===t.name){for(const e of T)b[e.id]=!0;Array.isArray(t.prevCollapsed)&&(O=t.prevCollapsed.map(String)),H()}else if("expandAll"===t.name){if(b={},Array.isArray(t.collapsedIds))for(const e of t.collapsedIds)b[String(e)]=!0;H()}else if("panelReady"===t.name)await $();else if("notePreview"===t.name)try{if(!1===await joplin.settings.value("hoverPreview"))return;const e=Number(await joplin.settings.value("hoverPreviewLength"))||200,a=await joplin.data.get(["notes",t.id],{fields:["id","title","body","is_todo","user_created_time","user_updated_time"],include_deleted:"1"});if(!a)return;const i=String(a.body||"").replace(/```[\s\S]*?```/g," ").replace(/!\[[^\]]*\]\([^)]*\)/g," ").replace(/\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/^#{1,6}\s+/gm,"").replace(/[`*_>~]/g,"").replace(/\s+/g," ").trim().slice(0,e);await joplin.views.panels.postMessage(o,{name:"notePreview",id:t.id,title:a.title||"(untitled)",created:a.user_created_time||0,updated:a.user_updated_time||0,isTodo:!!a.is_todo,size:String(a.body||"").length,snippet:i})}catch(e){}else if("refreshView"===t.name)await $();else if("newNotebook"===t.name){const t=await v(e.promptNewNotebookName,"");if(!t||!t.trim())return;const a=await joplin.data.post(["folders"],null,{title:t.trim()});M[a.id]=!0,delete b[a.id],await $(),await joplin.views.panels.postMessage(o,{name:"scrollToFolder",folderId:a.id})}else if("newNote"===t.name){await joplin.commands.execute("newNote");const e=await joplin.workspace.selectedNote();e&&(N=e.id,Z(e.parent_id)),await $()}else if("newTodo"===t.name){await joplin.commands.execute("newTodo");const e=await joplin.workspace.selectedNote();e&&(N=e.id,Z(e.parent_id)),await $()}else if("search"===t.name)await async function(e){const t=e.query;if(t&&t.trim())try{const a=t.toLowerCase(),i={};for(const e of T)i[e.id]=e.title;let n=[],s=1,l=!0;for(;l&&n.length<100;){const e=await joplin.data.get(["search"],{query:t,fields:["id","title","body","parent_id","is_todo","todo_completed"],page:s,limit:20});n=n.concat(e.items),l=e.has_more,s++}const r=new Set(n.map(e=>e.id)),d=[];for(const e of S)!r.has(e.id)&&(e.title||"").toLowerCase().indexOf(a)>=0&&d.push(e);for(let e=0;e<d.length&&e<50;e++)try{const t=await joplin.data.get(["notes",d[e].id],{fields:["id","title","body","parent_id","is_todo","todo_completed"]});n.push(t)}catch(e){}const c=[];for(const e of n){let t="";const o=e.body||"",n=o.toLowerCase().indexOf(a);if(n>=0){const e=Math.max(0,n-40),i=Math.min(o.length,n+a.length+80);t=(e>0?"...":"")+o.substring(e,i).replace(/\n/g," ")+(i<o.length?"...":"")}else t=o.substring(0,120).replace(/\n/g," ")+(o.length>120?"...":"");c.push({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed,snippet:t,folderName:i[e.parent_id]||""})}let p=[],m=1,u=!0;for(;u;){const e=await joplin.data.get(["tags"],{fields:["id","title"],page:m,limit:100});p=p.concat(e.items),u=e.has_more,m++}const f=[];for(const e of p)if((e.title||"").toLowerCase().indexOf(a)>=0){let t=0;try{const o=await joplin.data.get(["tags",e.id,"notes"],{fields:["id"],limit:100});t=o.has_more?o.items.length+"+":o.items.length}catch(e){}f.push({id:e.id,title:e.title,noteCount:t})}const w=[];for(const e of T)if((e.title||"").toLowerCase().indexOf(a)>=0){let t="";if(e.icon&&"string"==typeof e.icon)try{const o=JSON.parse(e.icon);o&&o.emoji&&(t=String(o.emoji))}catch(e){}w.push({id:e.id,title:e.title,parent_id:e.parent_id,iconEmoji:t})}await joplin.views.panels.postMessage(o,{name:"searchResults",notes:c,tags:f,folders:w,query:t,searchId:e.searchId})}catch(e){console.error("Joplin Explorer: search error",e)}else await joplin.views.panels.postMessage(o,{name:"searchResults",results:null,query:"",searchId:e.searchId})}(t);else if("loadTagNotes"===t.name)try{const e=t.tagId;let a=[],i=1,n=!0;for(;n&&a.length<100;){const t=await joplin.data.get(["tags",e,"notes"],{fields:["id","title","parent_id","is_todo","todo_completed"],page:i,limit:50});a=a.concat(t.items),n=t.has_more,i++}const s={};for(const e of T)s[e.id]=e.title;const l=a.map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed,snippet:"",folderName:s[e.parent_id]||""}));await joplin.views.panels.postMessage(o,{name:"tagNotes",tagId:e,notes:l})}catch(e){console.error("Joplin Explorer: loadTagNotes error",e)}else if("toggleTagsSection"===t.name)D=!D,H();else if("tagFolderNotes"===t.name)try{const e=await Q(t.tagId);await joplin.views.panels.postMessage(o,{name:"tagFolderNotes",tagId:t.tagId,notes:e})}catch(e){console.error("Joplin Explorer: tagFolderNotes error",e)}else if("tagNoteAdd"===t.name)try{await joplin.data.post(["tags",t.tagId,"notes"],null,{id:t.noteId});const e=await Q(t.tagId);await joplin.views.panels.postMessage(o,{name:"tagFolderNotes",tagId:t.tagId,notes:e})}catch(e){console.error("Joplin Explorer: tagNoteAdd error",e)}else if("toggleSmartSection"===t.name)C=!C,H();else if("smartFolderNotes"===t.name)try{const e=Math.max(1,Number(await joplin.settings.value("smartFolderLimit"))||5);if("recent"===t.smartId||"todos"===t.smartId){const a="recent"===t.smartId?await te(e):await oe(e);return void await joplin.views.panels.postMessage(o,{name:"smartFolderNotes",smartId:t.smartId,notes:a})}let a=[],i=1,n=!0;for(;n&&a.length<100;){const e=await joplin.data.get(["search"],{query:String(t.query||""),fields:["id","title","is_todo","todo_completed","user_updated_time"],page:i,limit:50});a=a.concat((e.items||[]).map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed,user_updated_time:e.user_updated_time||0}))),n=e.has_more,i++}a.sort((e,t)=>(t.user_updated_time||0)-(e.user_updated_time||0)),await joplin.views.panels.postMessage(o,{name:"smartFolderNotes",smartId:t.smartId,notes:a.slice(0,e)})}catch(e){console.error("Joplin Explorer: smartFolderNotes error",e)}else if("toggleTrashSection"===t.name)E=!E,H();else if("trashFolderNotes"===t.name)try{let e=[],a=1,i=!0;for(;i&&e.length<200;){const o=await joplin.data.get(["folders",t.folderId,"notes"],{fields:["id","title","is_todo","todo_completed"],include_deleted:"1",page:a,limit:50});e=e.concat((o.items||[]).map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed}))),i=o.has_more,a++}await joplin.views.panels.postMessage(o,{name:"trashFolderNotes",folderId:t.folderId,notes:e})}catch(e){console.error("Joplin Explorer: trashFolderNotes error",e)}else if("trashNotes"===t.name)try{const e=await Y();await joplin.views.panels.postMessage(o,{name:"trashNotes",folders:e.folders,notes:e.notes})}catch(e){console.error("Joplin Explorer: trashNotes error",e)}else if("locateFolder"===t.name)try{Z(t.folderId),await $(),await joplin.views.panels.postMessage(o,{name:"exitSearchAndLocate",folderId:t.folderId})}catch(e){console.error("Joplin Explorer: locateFolder error",e)}else if("locatePinnedFolder"===t.name)try{Z(t.folderId),await $(),await joplin.views.panels.postMessage(o,{name:"scrollToFolder",folderId:t.folderId})}catch(e){console.error("Joplin Explorer: locatePinnedFolder error",e)}else if("reorderPinned"===t.name)try{const e=t.dragId,o=t.targetId,a=t.position,i=F.findIndex(t=>t.id===e);if(i<0)return;const n=F[i];F.splice(i,1);let s=F.findIndex(e=>e.id===o);s<0?F.push(n):("after"===a&&s++,F.splice(s,0,n)),await K(),await $()}catch(e){console.error("Joplin Explorer: reorderPinned error",e)}else if("togglePinnedCollapse"===t.name)I=!I,H();else if("cycleSort"===t.name){const e=["updated_desc","updated_asc","title_asc","title_desc","manual"],t=e.indexOf(j);j=e[(t+1)%e.length];try{await joplin.settings.setValue("noteSortMode",j)}catch(e){}await $()}else if("sync"===t.name)try{await joplin.commands.execute("synchronize")}catch(t){console.error("Joplin Explorer: sync command failed",t),await joplin.views.panels.postMessage(o,{name:"syncState",state:"error"});const a=t&&t.message?String(t.message):String(t);await _(e.syncFailed,a)}else if("contextMenu"===t.name)await async function(t){const a=t.action,i=t.id,n=t.itemType;try{if("folder"===n)switch(a){case"newNote":{const t=await joplin.data.post(["notes"],null,{title:e.newNote,parent_id:i});await joplin.commands.execute("openNote",t.id),N=t.id,Z(i);break}case"newTodo":{const t=await joplin.data.post(["notes"],null,{title:e.newTodo,parent_id:i,is_todo:1});await joplin.commands.execute("openNote",t.id),N=t.id,Z(i);break}case"newSubNotebook":{const t=await v(e.newNotebook,"");if(t&&t.trim()){const e=await joplin.data.post(["folders"],null,{title:t.trim(),parent_id:i});M[e.id]=!0,delete b[i],delete b[e.id]}break}case"deleteFolder":{const t=await joplin.data.get(["folders",i],{fields:["title"]});await p(e.confirmDeleteFolder+"\n\n"+t.title)&&await joplin.data.delete(["folders",i]);break}case"renameFolder":try{const e=(await joplin.data.get(["folders",i],{fields:["updated_time"]})).updated_time,t=N;await joplin.commands.execute("openFolderDialog",{folderId:i}),(async()=>{for(let o=0;o<240;o++){await new Promise(e=>setTimeout(e,500));try{if((await joplin.data.get(["folders",i],{fields:["updated_time"]})).updated_time!==e){if(W(100),t){await new Promise(e=>setTimeout(e,400));try{const e=await joplin.workspace.selectedNote();e&&e.id===t||await joplin.commands.execute("openNote",t)}catch(e){}}return}}catch(e){return void W(100)}}})()}catch(t){const o=await joplin.data.get(["folders",i],{fields:["title"]}),a=await v(e.promptRename,o.title);a&&a.trim()&&await joplin.data.put(["folders",i],null,{title:a.trim()})}break;case"exportFolder":try{await joplin.commands.execute("exportFolders",[i])}catch(e){}break;case"pinFolder":F.some(e=>e.id===i)||(F.push({id:i,type:"folder"}),await K());break;case"unpinFolder":F=F.filter(e=>e.id!==i),await K()}else if("note"===n)switch(a){case"openNote":await joplin.commands.execute("openNote",i),N=i;break;case"openInNewWindow":try{await joplin.commands.execute("openNoteInNewWindow",i)}catch(e){await joplin.commands.execute("openNote",i)}break;case"copyLink":{const e=await joplin.data.get(["notes",i],{fields:["id","title"]}),t="["+e.title+"](:/"+e.id+")";try{await joplin.clipboard.writeText(t)}catch(e){await joplin.views.panels.postMessage(o,{name:"copyText",text:t})}break}case"duplicateNote":{const e=await joplin.data.get(["notes",i],{fields:["title","body","parent_id","is_todo"]}),t=await joplin.data.post(["notes"],null,{title:e.title+" (copy)",body:e.body,parent_id:e.parent_id,is_todo:e.is_todo});await joplin.commands.execute("openNote",t.id),N=t.id;break}case"switchNoteType":{const e=await joplin.data.get(["notes",i],{fields:["is_todo"]});await joplin.data.put(["notes",i],null,{is_todo:e.is_todo?0:1});break}case"toggleTodo":{const e=await joplin.data.get(["notes",i],{fields:["is_todo","todo_completed"]});e.is_todo&&await joplin.data.put(["notes",i],null,{todo_completed:e.todo_completed?0:Date.now()});break}case"publishNote":try{await joplin.commands.execute("showShareNoteDialog",[i])}catch(e){}break;case"exportPdf":try{await joplin.commands.execute("exportPdf",[i])}catch(e){}break;case"exportNote":try{const e=await joplin.views.dialogs.showOpenDialog({properties:["openDirectory"]}),o=Array.isArray(e)?e[0]:e;o&&await joplin.commands.execute("exportNotes",[i],t.format||"md",o)}catch(e){console.error("Joplin Explorer: exportNote error",e)}break;case"setTags":try{await joplin.commands.execute("setTags",[i])}catch(e){}break;case"moveToFolderDialog":try{await joplin.commands.execute("moveToFolder",[i])}catch(e){}break;case"copyExternalLink":{const e="joplin://x-callback-url/openNote?id="+i;try{await joplin.clipboard.writeText(e)}catch(t){await joplin.views.panels.postMessage(o,{name:"copyText",text:e})}break}case"renameNote":{const t=await joplin.data.get(["notes",i],{fields:["title"]}),o=await v(e.promptRename,t.title);o&&o.trim()&&await joplin.data.put(["notes",i],null,{title:o.trim()});break}case"moveNote":if(t.targetFolderName){let e=null;for(const o of T)if(o.title===t.targetFolderName){e=o;break}e&&await joplin.data.put(["notes",i],null,{parent_id:e.id})}break;case"noteInfo":{const t=await joplin.data.get(["notes",i],{fields:["id","title","created_time","updated_time","is_todo","parent_id","body"]}),o=k[t.parent_id]?k[t.parent_id].title:"",a=(t.body||"").length,n="ID: "+t.id+"\n"+(e.ctxRenameNote||"Title")+": "+t.title+"\n"+(e.newNotebook||"Notebook")+": "+o+"\n"+(e.sortUpdatedDesc?e.sortUpdatedDesc.replace(/[↓↑\u2193\u2191]\s*/,""):"Created")+": "+new Date(t.created_time).toLocaleString()+"\n"+(e.sortUpdatedAsc?e.sortUpdatedAsc.replace(/[↓↑\u2193\u2191]\s*/,""):"Updated")+": "+new Date(t.updated_time).toLocaleString()+"\nType: "+(t.is_todo?"To-do":"Note")+"\nSize: "+a+" chars";await _(t.title,n);break}case"deleteNote":{const t=await joplin.data.get(["notes",i],{fields:["title"]});await p(e.confirmDeleteNote+"\n\n"+t.title)&&await joplin.data.delete(["notes",i]);break}case"untagNote":if(t.tagId){await joplin.data.delete(["tags",t.tagId,"notes",i]);try{const e=await Q(t.tagId);await joplin.views.panels.postMessage(o,{name:"tagFolderNotes",tagId:t.tagId,notes:e})}catch(e){}}break;case"pinNote":F.some(e=>e.id===i)||(F.push({id:i,type:"note"}),await K());break;case"unpinNote":F=F.filter(e=>e.id!==i),await K()}else if("tag"===n)switch(a){case"renameTag":{const t=await joplin.data.get(["tags",i],{fields:["title"]}),o=await v(e.ctxRenameTag,t.title);o&&o.trim()&&await joplin.data.put(["tags",i],null,{title:o.trim()});break}case"deleteTag":{const t=await joplin.data.get(["tags",i],{fields:["title"]});await p(e.confirmDeleteTag+"\n\n"+t.title)&&await joplin.data.delete(["tags",i]);break}}else if("trashSection"===n){if("emptyTrash"===a&&await p(e.confirmEmptyTrash)){try{await joplin.commands.execute("emptyTrash")}catch(e){const t=await Y();for(const e of t.folders)0===e.depth&&await ee(e.id);for(const e of t.notes)try{await joplin.data.delete(["notes",e.id],{permanent:"1"})}catch(e){}}try{const e=await Y();await joplin.views.panels.postMessage(o,{name:"trashNotes",folders:e.folders,notes:e.notes})}catch(e){}}}else if("trashNote"===n||"trashFolder"===n){const t="trashFolder"===n;switch(a){case"restoreItem":try{await joplin.commands.execute(t?"restoreFolder":"restoreNote",[i])}catch(e){console.error("Joplin Explorer: restore error",e)}break;case"permanentDeleteItem":{const o=t?"folders":"notes";let a="";try{const e=await joplin.data.get([o,i],{fields:["title"],include_deleted:"1"});a=e?e.title:""}catch(e){}if(await p(e.confirmDeleteNote+"\n\n"+a))if(t)await ee(i);else try{await joplin.data.delete(["notes",i],{permanent:"1"})}catch(e){try{await joplin.commands.execute("permanentlyDeleteNote",[i])}catch(e){}}break}}try{const e=await Y();await joplin.views.panels.postMessage(o,{name:"trashNotes",folders:e.folders,notes:e.notes})}catch(e){}}await $()}catch(e){console.error("Notes In List: context menu error",e)}}(t);else if("dragDrop"===t.name)await async function(e){try{const t=e.dragId,o=e.dragType,a=e.targetId,i=e.position;if("note"===o)if(k[a])await joplin.data.put(["notes",t],null,{parent_id:a});else{const e=await joplin.data.get(["notes",a],{fields:["parent_id"]});"manual"!==j||"above"!==i&&"below"!==i?await joplin.data.put(["notes",t],null,{parent_id:e.parent_id}):await async function(e,t,o){const a=(await joplin.data.get(["notes",t],{fields:["parent_id"]})).parent_id,i=S.filter(t=>t.parent_id===a&&t.id!==e).sort((e,t)=>{const o=e.order||0,a=t.order||0;return o!==a?a-o:(t.user_updated_time||0)-(e.user_updated_time||0)}),n=i.findIndex(e=>e.id===t),s=n<0?i.length:"above"===o?n:n+1,l=s>0?i[s-1]:null,r=s<i.length?i[s]:null,d=l?l.order||0:null,c=r?r.order||0:null,p=1e6;if(i.every(e=>0===(e.order||0))||null!==d&&null!==c&&d-c<2){const t=Date.now(),o=i.slice();o.splice(s,0,null);let n=t;const l=[];for(let e=0;e<o.length;e++){const a=t-e*p,i=o[e];null===i?n=a:l.push(joplin.data.put(["notes",i.id],null,{order:a}))}return await Promise.all(l),void await joplin.data.put(["notes",e],null,{parent_id:a,order:n})}let m;m=null!==d&&null!==c?(d+c)/2:null!==d?d-p:null!==c?c+p:Date.now(),await joplin.data.put(["notes",e],null,{parent_id:a,order:m})}(t,a,i)}else if("folder"===o){const e=!!k[a];"into"===i?e&&t!==a&&await joplin.data.put(["folders",t],null,{parent_id:a}):!e||"above"!==i&&"below"!==i||await async function(e,t,o){const a=k[t],i=k[e];if(!a||!i||e===t)return;const n=a.parent_id||"";let s=n;for(;s;){if(s===e)return;s=k[s]&&k[s].parent_id||""}const l=T.filter(t=>(t.parent_id||"")===n&&t.id!==e).sort((e,t)=>{const o=e.order||0,a=t.order||0;return o!==a?a-o:(e.title||"").localeCompare(t.title||"")}),r=l.findIndex(e=>e.id===t),d=r<0?l.length:"above"===o?r:r+1,c=d>0?l[d-1]:null,p=d<l.length?l[d]:null,m=c?c.order||0:null,u=p?p.order||0:null,f=l.every(e=>0===(e.order||0)),w=null!==m&&null!==u&&m-u<2,g=1e6;if((i.parent_id||"")!==n&&await joplin.data.put(["folders",e],null,{parent_id:n}),f||w){const t=Date.now(),o=l.slice();o.splice(d,0,null);for(let a=0;a<o.length;a++){const i=t-a*g,n=o[a];null===n?P[e]=i:P[n.id]=i}return void await X()}let h;h=null!==m&&null!==u?(m+u)/2:null!==m?m-g:null!==u?u+g:Date.now(),P[e]=h,await X()}(t,a,i)}await $()}catch(e){console.error("Notes In List: drag drop error",e)}}(t);else if("dragToEmpty"===t.name)try{const o=t.dragId,a=t.dragType,i=await v(e.promptNewNotebookName,"");if(!i||!i.trim())return;const n=await joplin.data.post(["folders"],null,{title:i.trim()});M[n.id]=!0,delete b[n.id],"note"===a?await joplin.data.put(["notes",o],null,{parent_id:n.id}):"folder"===a&&o!==n.id&&await joplin.data.put(["folders",o],null,{parent_id:n.id}),await $()}catch(e){console.error("Notes In List: drag to empty error",e)}});let ae="",ie=null,ne="";async function se(){const e=[];let t=1,o=!0;for(;o;){const a=await joplin.data.get(["folders"],{fields:["id","title","parent_id","icon"],page:t,limit:100});for(const t of a.items||[])e.push(t.id+""+(t.title||"")+""+(t.parent_id||"")+""+(t.icon||""));o=a.has_more,t++}const a=e.sort().join("\n"),i=""!==ne&&a!==ne;return ne=a,i}async function le(){try{if(!ae){const e=await joplin.data.get(["events"]);return ae=String(e.cursor||""),void await se()}let e=!1,t=0;for(;t++<20;){const t=await joplin.data.get(["events"],{cursor:ae});for(const o of t.items||[])2===Number(o.type)&&o.item_id===N||(e=!0);if(t.cursor&&(ae=String(t.cursor)),!t.has_more)break}!e&&await se()&&(e=!0),e&&W(300)}catch(e){ie&&(clearInterval(ie),ie=null),console.warn("Joplin Explorer: change-events polling disabled",e)}}async function re(){const e=!1!==await joplin.settings.value("autoRefresh");ie&&(clearInterval(ie),ie=null),e&&(ae="",await le(),ie=setInterval(le,5e3))}await re(),await joplin.workspace.onNoteSelectionChange(async()=>{const e=await joplin.workspace.selectedNote();e&&e.id!==N&&(N=e.id,await joplin.views.panels.postMessage(o,{name:"selectNote",id:e.id}))}),await joplin.workspace.onNoteChange(async e=>{var t;e&&e.id?(t=e.id,V[t]=!0,B&&clearTimeout(B),B=setTimeout(async()=>{B=null;const e=Object.keys(V);V={};for(const t of e)await G(t)},600)):W()});try{await joplin.workspace.onSyncStart(async()=>{await joplin.views.panels.postMessage(o,{name:"syncState",state:"syncing"})})}catch(e){console.warn("Joplin Explorer: onSyncStart not available",e)}try{await joplin.workspace.onSyncComplete(async t=>{const a=!(!t||!t.withErrors);await $(),await joplin.views.panels.postMessage(o,{name:"syncState",state:a?"error":"done"}),a&&await _(e.syncFailed,"Joplin reported errors during synchronisation. Open the Synchronisation Status screen (Tools → Synchronisation Status) to see the details.")})}catch(e){console.warn("Joplin Explorer: onSyncComplete not available",e)}await $()}})})();
1
+ (()=>{"use strict";var e={982(e){e.exports=require("crypto")},896(e){e.exports=require("fs")},928(e){e.exports=require("path")}},t={};function o(a){var s=t[a];if(void 0!==s)return s.exports;var n=t[a]={exports:{}};return e[a](n,n.exports,o),n.exports}const a={zh_CN:{newNotebook:"新建笔记本",newNote:"新建笔记",newTodo:"新建待办",sort:"排序",collapseAll:"全部折叠",expandAll:"全部展开",search:"搜索笔记内容...",searchResultCount:"找到 {count} 条结果",searchNoResult:"没有找到匹配的笔记",searching:"搜索中...",sync:"同步",syncing:"同步中...",syncDone:"✔ 同步完成",syncFailed:"⚠ 同步失败",loading:"加载中...",sortUpdatedDesc:"↓ 修改时间",sortUpdatedAsc:"↑ 修改时间",sortTitleAsc:"↑ 标题",sortTitleDesc:"↓ 标题",sortManual:"⇅ 手动排序",ctxNewNoteHere:"在此新建笔记",ctxNewTodoHere:"在此新建待办",ctxNewSubNotebook:"新建子笔记本",ctxRenameFolder:"编辑",ctxExportFolder:"导出笔记本",ctxDeleteFolder:"删除笔记本",ctxOpenNote:"打开笔记",ctxOpenInNewWindow:"在新窗口中打开",ctxCopyLink:"复制 Markdown 链接",ctxDuplicateNote:"复制副本",ctxSwitchNoteType:"笔记/待办 切换",ctxToggleTodo:"切换完成状态",ctxRenameNote:"重命名",ctxMoveNote:"移动到笔记本...",ctxNoteInfo:"笔记属性",ctxDeleteNote:"删除笔记",confirmDeleteFolder:"确定删除此笔记本及其所有内容吗?",confirmDeleteNote:"确定删除此笔记吗?",promptRename:"请输入新名称:",promptMoveNote:"请输入目标笔记本名称:",promptNewNotebookName:"请输入新笔记本名称:",dropCreateNotebook:"释放以创建新笔记本",searchSectionNotes:"笔记",searchSectionTags:"标签",searchSectionFolders:"笔记本",searchTagNoteCount:"{count} 条笔记",pinned:"收藏夹",tags:"标签",ctxRenameTag:"重命名标签",ctxDeleteTag:"删除标签",ctxUntagNote:"从标签移除",confirmDeleteTag:"删除该标签?(只删除标签本身,不会删除笔记)",ctxPublishNote:"发布笔记",ctxExport:"导出",sharedBadge:"已发布 · 点击打开发布对话框",sShowTags:"显示标签分区",sShowTagsDesc:"在笔记本树下方将 Joplin 标签显示为文件夹。",sAutoRefresh:"外部变更自动刷新",sAutoRefreshDesc:"每 5 秒轮询 Joplin 的变更事件,其他插件或同步创建、移动、删除笔记时自动刷新面板。当前打开笔记的编辑不受影响(本就实时更新)。",sRestoreUi:"启动时恢复上次视图状态",sRestoreUiDesc:"跨会话记住文件夹/分区的折叠状态。关闭后启动时全部收缩。",sShowSmart:"显示智能文件夹",sShowSmartDesc:"将保存的搜索显示为文件夹:最近更新、未完成待办,以及自定义规则。",sSmartRules:"自定义智能文件夹",sSmartRulesDesc:'"名称:查询" 用 ";" 分隔,使用 Joplin 搜索语法。示例:工作:notebook:Work updated:day-30;星标:tag:star',sSmartLimit:"智能文件夹结果条数",sSmartLimitDesc:"每个智能文件夹最多显示的笔记数(最新优先)。默认 5。",sHoverPreview:"悬停预览笔记",sHoverPreviewDesc:"悬停笔记时显示标题、更新时间和正文摘要。",sHoverPreviewLen:"悬停预览长度(字符)",sArrowPos:"展开箭头位置",sArrowPosDesc:"同时作用于笔记本、分区标题和分区行,保持风格统一。",sArrowRight:"文字后面",sArrowLeft:"文字左侧(经典树形)",sExpandMode:"全部展开行为",sExpandModeDesc:"展开按钮恢复的内容。默认:恢复上次全部收缩前的状态。",sExpandRestore:"恢复收缩前的状态",sExpandSkeleton:"仅文件夹(叶子笔记本保持收缩)",sExpandAllOpt:"全部展开",sSectionOrder:"分区顺序",sSectionOrderDesc:"逗号分隔的分区顺序。可用键:pinned(收藏夹)、smart(智能文件夹)、tree(笔记本树)、tags(标签)、trash(回收站)。遗漏的分区按默认顺序排在末尾。",sSectionGap:"分区间距(px)",sSectionGapDesc:"每个分区分割线上方的留白。默认 5。",sShowToggles:"显示展开箭头",sShowTogglesDesc:"在文件夹和收藏夹分区前显示展开/收缩箭头。",sOpenFolderIcon:"展开文件夹图标",sOpenFolderIconDesc:"无自定义笔记本图标时,展开的文件夹使用的 Emoji、图片 URL、data URI 或本地图片路径。",sClosedFolderIcon:"收起文件夹图标",sClosedFolderIconDesc:"无自定义笔记本图标时,收起的文件夹使用的 Emoji、图片 URL、data URI 或本地图片路径。",sOpenPinnedIcon:"收藏夹展开图标",sOpenPinnedIconDesc:"收藏夹分区展开时使用的 Emoji、图片 URL、data URI 或本地图片路径。",sClosedPinnedIcon:"收藏夹收起图标",sClosedPinnedIconDesc:"收藏夹分区收起时使用的 Emoji、图片 URL、data URI 或本地图片路径。",refresh:"刷新",newItem:"新建",trash:"回收站",ctxRestoreNote:"恢复",ctxPermanentDelete:"彻底删除",ctxEmptyTrash:"清空回收站",confirmEmptyTrash:"清空回收站?所有已删除的笔记本和笔记将被永久删除,无法恢复。",smartFolders:"智能文件夹",smartRecent:"最近更新",smartTodos:"未完成待办",pvType:"类型",pvSize:"大小",pvCreated:"创建",pvUpdated:"更新",pvNote:"笔记",pvTodo:"待办",pvChars:"字符",ctxSetTags:"设置标签",ctxMoveToFolder:"移动到笔记本",ctxCopyExternalLink:"复制外部链接",ctxPin:"📌 收藏",ctxUnpin:"取消收藏",cancel:"取消"},zh_TW:{newNotebook:"新建筆記本",newNote:"新建筆記",newTodo:"新建待辦",sort:"排序",collapseAll:"全部摺疊",expandAll:"全部展開",search:"搜尋筆記內容...",searchResultCount:"找到 {count} 條結果",searchNoResult:"沒有找到匹配的筆記",searching:"搜尋中...",sync:"同步",syncing:"同步中...",syncDone:"✔ 同步完成",syncFailed:"⚠ 同步失敗",loading:"載入中...",sortUpdatedDesc:"↓ 修改時間",sortUpdatedAsc:"↑ 修改時間",sortTitleAsc:"↑ 標題",sortTitleDesc:"↓ 標題",sortManual:"⇅ 手動排序",ctxNewNoteHere:"在此新建筆記",ctxNewTodoHere:"在此新建待辦",ctxNewSubNotebook:"新建子筆記本",ctxRenameFolder:"編輯",ctxExportFolder:"匯出筆記本",ctxDeleteFolder:"刪除筆記本",ctxOpenNote:"開啟筆記",ctxOpenInNewWindow:"在新視窗中開啟",ctxCopyLink:"複製 Markdown 連結",ctxDuplicateNote:"複製副本",ctxSwitchNoteType:"筆記/待辦 切換",ctxToggleTodo:"切換完成狀態",ctxRenameNote:"重新命名",ctxMoveNote:"移動到筆記本...",ctxNoteInfo:"筆記屬性",ctxDeleteNote:"刪除筆記",confirmDeleteFolder:"確定刪除此筆記本及其所有內容嗎?",confirmDeleteNote:"確定刪除此筆記嗎?",promptRename:"請輸入新名稱:",promptMoveNote:"請輸入目標筆記本名稱:",promptNewNotebookName:"請輸入新筆記本名稱:",dropCreateNotebook:"釋放以建立新筆記本",searchSectionNotes:"筆記",searchSectionTags:"標籤",searchSectionFolders:"筆記本",searchTagNoteCount:"{count} 條筆記",pinned:"收藏夾",tags:"標籤",ctxRenameTag:"重新命名標籤",ctxDeleteTag:"刪除標籤",ctxUntagNote:"自標籤移除",confirmDeleteTag:"刪除該標籤?(僅刪除標籤本身,不會刪除筆記)",ctxPublishNote:"發佈筆記",ctxExport:"匯出",sharedBadge:"已發佈 · 點擊開啟發佈對話框",sShowTags:"顯示標籤分區",sShowTagsDesc:"在筆記本樹下方將 Joplin 標籤顯示為資料夾。",sAutoRefresh:"外部變更自動重新整理",sAutoRefreshDesc:"每 5 秒輪詢 Joplin 的變更事件,其他外掛或同步建立、移動、刪除筆記時自動重新整理面板。目前開啟筆記的編輯不受影響(本就即時更新)。",sRestoreUi:"啟動時還原上次檢視狀態",sRestoreUiDesc:"跨工作階段記住資料夾/分區的摺疊狀態。關閉後啟動時全部收合。",sShowSmart:"顯示智慧資料夾",sShowSmartDesc:"將儲存的搜尋顯示為資料夾:最近更新、未完成待辦,以及自訂規則。",sSmartRules:"自訂智慧資料夾",sSmartRulesDesc:'「名稱:查詢」用 ";" 分隔,使用 Joplin 搜尋語法。範例:工作:notebook:Work updated:day-30;星標:tag:star',sSmartLimit:"智慧資料夾結果筆數",sSmartLimitDesc:"每個智慧資料夾最多顯示的筆記數(最新優先)。預設 5。",sHoverPreview:"懸停預覽筆記",sHoverPreviewDesc:"懸停筆記時顯示標題、更新時間和內文摘要。",sHoverPreviewLen:"懸停預覽長度(字元)",sArrowPos:"展開箭頭位置",sArrowPosDesc:"同時作用於筆記本、分區標題和分區列,保持風格統一。",sArrowRight:"文字後面",sArrowLeft:"文字左側(經典樹狀)",sExpandMode:"全部展開行為",sExpandModeDesc:"展開按鈕還原的內容。預設:還原上次全部收合前的狀態。",sExpandRestore:"還原收合前的狀態",sExpandSkeleton:"僅資料夾(葉子筆記本保持收合)",sExpandAllOpt:"全部展開",sSectionOrder:"分區順序",sSectionOrderDesc:"逗號分隔的分區順序。可用鍵:pinned(最愛)、smart(智慧資料夾)、tree(筆記本樹)、tags(標籤)、trash(回收站)。遺漏的分區按預設順序排在末尾。",sSectionGap:"分區間距(px)",sSectionGapDesc:"每個分區分隔線上方的留白。預設 5。",sShowToggles:"顯示展開箭頭",sShowTogglesDesc:"在資料夾和最愛分區前顯示展開/收合箭頭。",sOpenFolderIcon:"展開資料夾圖示",sOpenFolderIconDesc:"無自訂筆記本圖示時,展開的資料夾使用的 Emoji、圖片 URL、data URI 或本機圖片路徑。",sClosedFolderIcon:"收合資料夾圖示",sClosedFolderIconDesc:"無自訂筆記本圖示時,收合的資料夾使用的 Emoji、圖片 URL、data URI 或本機圖片路徑。",sOpenPinnedIcon:"最愛展開圖示",sOpenPinnedIconDesc:"最愛分區展開時使用的 Emoji、圖片 URL、data URI 或本機圖片路徑。",sClosedPinnedIcon:"最愛收合圖示",sClosedPinnedIconDesc:"最愛分區收合時使用的 Emoji、圖片 URL、data URI 或本機圖片路徑。",refresh:"重新整理",newItem:"新增",trash:"垃圾桶",ctxRestoreNote:"還原",ctxPermanentDelete:"永久刪除",ctxEmptyTrash:"清空垃圾桶",confirmEmptyTrash:"清空垃圾桶?所有已刪除的筆記本和筆記將被永久刪除,無法還原。",smartFolders:"智慧資料夾",smartRecent:"最近更新",smartTodos:"未完成待辦",pvType:"類型",pvSize:"大小",pvCreated:"建立",pvUpdated:"更新",pvNote:"筆記",pvTodo:"待辦",pvChars:"字元",ctxSetTags:"設定標籤",ctxMoveToFolder:"移動到筆記本",ctxCopyExternalLink:"複製外部連結",ctxPin:"📌 收藏",ctxUnpin:"取消收藏",cancel:"取消"},en_US:{newNotebook:"New Notebook",newNote:"New Note",newTodo:"New To-do",sort:"Sort",collapseAll:"Collapse All",expandAll:"Expand All",search:"Search note contents...",searchResultCount:"{count} results found",searchNoResult:"No matching notes found",searching:"Searching...",sync:"Synchronise",syncing:"Syncing...",syncDone:"✔ Sync Done",syncFailed:"⚠ Sync Failed",loading:"Loading...",sortUpdatedDesc:"↓ Updated",sortUpdatedAsc:"↑ Updated",sortTitleAsc:"↑ Title",sortTitleDesc:"↓ Title",sortManual:"⇅ Manual",ctxNewNoteHere:"New Note Here",ctxNewTodoHere:"New To-do Here",ctxNewSubNotebook:"New Sub-notebook",ctxRenameFolder:"Edit",ctxExportFolder:"Export Notebook",ctxDeleteFolder:"Delete Notebook",ctxOpenNote:"Open Note",ctxOpenInNewWindow:"Open in New Window",ctxCopyLink:"Copy Markdown Link",ctxDuplicateNote:"Duplicate",ctxSwitchNoteType:"Switch Note/To-do",ctxToggleTodo:"Toggle Completed",ctxRenameNote:"Rename",ctxMoveNote:"Move to Notebook...",ctxNoteInfo:"Note Properties",ctxDeleteNote:"Delete Note",confirmDeleteFolder:"Delete this notebook and all its contents?",confirmDeleteNote:"Delete this note?",promptRename:"Enter new name:",promptMoveNote:"Enter target notebook name:",promptNewNotebookName:"Enter new notebook name:",dropCreateNotebook:"Release to create a new notebook",searchSectionNotes:"Notes",searchSectionTags:"Tags",searchSectionFolders:"Notebooks",searchTagNoteCount:"{count} notes",pinned:"Pinned",tags:"Tags",ctxRenameTag:"Rename tag",ctxDeleteTag:"Delete tag",ctxUntagNote:"Remove from tag",confirmDeleteTag:"Delete this tag? (Only the tag is removed - notes are kept.)",ctxPublishNote:"Publish note",ctxExport:"Export",sharedBadge:"Published · click to open the publish dialog",sShowTags:"Show tags section",sShowTagsDesc:"Show Joplin tags as folders below the notebook tree.",sAutoRefresh:"Auto refresh on external changes",sAutoRefreshDesc:"Poll Joplin's change feed every 5 seconds and refresh the panel when notes are created, moved or deleted by other plugins or sync. Edits to the currently open note are ignored (they already update live).",sRestoreUi:"Restore last view state on startup",sRestoreUiDesc:"Remember collapsed/expanded folders and sections between sessions. When off, the tree starts fully collapsed.",sShowSmart:"Show smart folders",sShowSmartDesc:"Saved searches rendered as folders: Recently updated, Open to-dos, and your own rules.",sSmartRules:"Custom smart folders",sSmartRulesDesc:'Name:query pairs separated by ";", using Joplin search syntax. Example: Work:notebook:Work updated:day-30;Starred:tag:star',sSmartLimit:"Smart folder result limit",sSmartLimitDesc:"Maximum notes shown per smart folder (newest first). Default: 5.",sHoverPreview:"Note preview on hover",sHoverPreviewDesc:"Show title, updated time and a body snippet when hovering a note.",sHoverPreviewLen:"Hover preview length (characters)",sArrowPos:"Expand arrow position",sArrowPosDesc:"Applies to notebooks, section headers and section rows alike, so everything matches.",sArrowRight:"After the text",sArrowLeft:"Left of the text (classic tree)",sExpandMode:"Expand All behavior",sExpandModeDesc:"What the Expand All button restores. Default: the tree as it was before the last Collapse All.",sExpandRestore:"Restore the state before Collapse All",sExpandSkeleton:"Folders only (leaf notebooks stay collapsed)",sExpandAllOpt:"Everything",sSectionOrder:"Section order",sSectionOrderDesc:"Comma-separated section order. Keys: pinned, smart (smart folders), tree (notebook tree), tags, trash. Omitted sections keep the default order at the end.",sSectionGap:"Section spacing (px)",sSectionGapDesc:"Blank space above each section divider. Default: 5.",sShowToggles:"Show toggle arrows",sShowTogglesDesc:"Show expand/collapse arrows before folders and the pinned section.",sOpenFolderIcon:"Open folder icon",sOpenFolderIconDesc:"Emoji, image URL, data URI, or local image path for expanded folders without a custom notebook icon.",sClosedFolderIcon:"Closed folder icon",sClosedFolderIconDesc:"Emoji, image URL, data URI, or local image path for collapsed folders without a custom notebook icon.",sOpenPinnedIcon:"Open pinned icon",sOpenPinnedIconDesc:"Emoji, image URL, data URI, or local image path for the expanded pinned section.",sClosedPinnedIcon:"Closed pinned icon",sClosedPinnedIconDesc:"Emoji, image URL, data URI, or local image path for the collapsed pinned section.",refresh:"Refresh",newItem:"New",trash:"Trash",ctxRestoreNote:"Restore",ctxPermanentDelete:"Delete permanently",ctxEmptyTrash:"Empty trash",confirmEmptyTrash:"Empty the trash? All deleted notebooks and notes will be permanently removed. This cannot be undone.",smartFolders:"Smart folders",smartRecent:"Recently updated",smartTodos:"Open to-dos",pvType:"Type",pvSize:"Size",pvCreated:"Created",pvUpdated:"Updated",pvNote:"Note",pvTodo:"To-do",pvChars:"chars",ctxSetTags:"Set tags",ctxMoveToFolder:"Move to notebook",ctxCopyExternalLink:"Copy external link",ctxPin:"📌 Pin",ctxUnpin:"Unpin",cancel:"Cancel"},ru:{newNotebook:"Новый блокнот",newNote:"Новая заметка",newTodo:"Новая задача",sort:"Сортировка",collapseAll:"Свернуть все",expandAll:"Развернуть все",search:"Искать в содержимом заметок...",searchResultCount:"Найдено результатов: {count}",searchNoResult:"Заметки не найдены",searching:"Поиск...",sync:"Синхронизировать",syncing:"Синхронизация...",syncDone:"✔ Синхронизация завершена",syncFailed:"⚠ Ошибка синхронизации",loading:"Загрузка...",sortUpdatedDesc:"↓ Обновлено",sortUpdatedAsc:"↑ Обновлено",sortTitleAsc:"↑ Название",sortTitleDesc:"↓ Название",sortManual:"⇅ Вручную",ctxNewNoteHere:"Создать заметку здесь",ctxNewTodoHere:"Создать задачу здесь",ctxNewSubNotebook:"Новый вложенный блокнот",ctxRenameFolder:"Редактировать",ctxExportFolder:"Экспортировать блокнот",ctxDeleteFolder:"Удалить блокнот",ctxOpenNote:"Открыть заметку",ctxOpenInNewWindow:"Открыть в новом окне",ctxCopyLink:"Скопировать Markdown-ссылку",ctxDuplicateNote:"Создать копию",ctxSwitchNoteType:"Переключить между заметкой и задачей",ctxToggleTodo:"Переключить статус выполнения",ctxRenameNote:"Переименовать",ctxMoveNote:"Переместить в блокнот...",ctxNoteInfo:"Свойства заметки",ctxDeleteNote:"Удалить заметку",confirmDeleteFolder:"Удалить блокнот и все его содержимое?",confirmDeleteNote:"Удалить заметку?",promptRename:"Введите новое название:",promptMoveNote:"Переместить в блокнот:",promptNewNotebookName:"Введите название нового блокнота:",dropCreateNotebook:"Отпустите, чтобы создать новый блокнот",searchSectionNotes:"Заметки",searchSectionTags:"Метки",searchSectionFolders:"Блокноты",searchTagNoteCount:"Заметок: {count}",pinned:"Закрепленные",tags:"Теги",ctxRenameTag:"Переименовать тег",ctxDeleteTag:"Удалить тег",ctxUntagNote:"Убрать из тега",confirmDeleteTag:"Удалить этот тег? (Удаляется только тег, заметки сохраняются.)",ctxPublishNote:"Опубликовать заметку",ctxExport:"Экспорт",sharedBadge:"Опубликовано · нажмите, чтобы открыть диалог публикации",sShowTags:"Показывать раздел тегов",sShowTagsDesc:"Показывать теги Joplin как папки под деревом блокнотов.",sAutoRefresh:"Автообновление при внешних изменениях",sAutoRefreshDesc:"Опрашивать ленту изменений Joplin каждые 5 секунд и обновлять панель, когда заметки создаются, перемещаются или удаляются другими плагинами или синхронизацией. Правки открытой заметки игнорируются (они и так обновляются сразу).",sRestoreUi:"Восстанавливать состояние вида при запуске",sRestoreUiDesc:"Запоминать свёрнутые/развёрнутые папки и разделы между сеансами. Если выключено, дерево запускается полностью свёрнутым.",sShowSmart:"Показывать умные папки",sShowSmartDesc:"Сохранённые поиски в виде папок: Недавно обновлённые, Открытые задачи и ваши собственные правила.",sSmartRules:"Свои умные папки",sSmartRulesDesc:"Пары «Имя:запрос» через «;», синтаксис поиска Joplin. Пример: Работа:notebook:Work updated:day-30;Избранное:tag:star",sSmartLimit:"Лимит результатов умной папки",sSmartLimitDesc:"Максимум заметок в умной папке (сначала новые). По умолчанию: 5.",sHoverPreview:"Предпросмотр заметки при наведении",sHoverPreviewDesc:"Показывать заголовок, время обновления и фрагмент текста при наведении на заметку.",sHoverPreviewLen:"Длина предпросмотра (символов)",sArrowPos:"Положение стрелки раскрытия",sArrowPosDesc:"Действует одинаково на блокноты, заголовки и строки разделов.",sArrowRight:"После текста",sArrowLeft:"Слева от текста (классическое дерево)",sExpandMode:"Поведение «Развернуть всё»",sExpandModeDesc:"Что восстанавливает кнопка разворачивания. По умолчанию: состояние до последнего «Свернуть всё».",sExpandRestore:"Восстановить состояние до сворачивания",sExpandSkeleton:"Только папки (листовые блокноты остаются свёрнутыми)",sExpandAllOpt:"Всё",sSectionOrder:"Порядок разделов",sSectionOrderDesc:"Порядок разделов через запятую. Ключи: pinned (закладки), smart (умные папки), tree (дерево блокнотов), tags (теги), trash (корзина). Пропущенные разделы идут в конце в порядке по умолчанию.",sSectionGap:"Отступ между разделами (px)",sSectionGapDesc:"Пустое место над разделителем каждого раздела. По умолчанию: 5.",sShowToggles:"Показывать стрелки раскрытия",sShowTogglesDesc:"Показывать стрелки перед папками и разделом закладок.",sOpenFolderIcon:"Значок открытой папки",sOpenFolderIconDesc:"Emoji, URL изображения, data URI или локальный путь для развёрнутых папок без своего значка блокнота.",sClosedFolderIcon:"Значок закрытой папки",sClosedFolderIconDesc:"Emoji, URL изображения, data URI или локальный путь для свёрнутых папок без своего значка блокнота.",sOpenPinnedIcon:"Значок раскрытых закладок",sOpenPinnedIconDesc:"Emoji, URL изображения, data URI или локальный путь для развёрнутого раздела закладок.",sClosedPinnedIcon:"Значок свёрнутых закладок",sClosedPinnedIconDesc:"Emoji, URL изображения, data URI или локальный путь для свёрнутого раздела закладок.",refresh:"Обновить",newItem:"Создать",trash:"Корзина",ctxRestoreNote:"Восстановить",ctxPermanentDelete:"Удалить навсегда",ctxEmptyTrash:"Очистить корзину",confirmEmptyTrash:"Очистить корзину? Все удалённые блокноты и заметки будут удалены безвозвратно.",smartFolders:"Умные папки",smartRecent:"Недавно обновлённые",smartTodos:"Незавершённые задачи",pvType:"Тип",pvSize:"Размер",pvCreated:"Создано",pvUpdated:"Обновлено",pvNote:"Заметка",pvTodo:"Задача",pvChars:"симв.",ctxSetTags:"Назначить теги",ctxMoveToFolder:"Переместить в блокнот",ctxCopyExternalLink:"Копировать внешнюю ссылку",ctxPin:"📌 Закрепить",ctxUnpin:"Открепить",cancel:"Отмена"},ja_JP:{newNotebook:"新規ノートブック",newNote:"新規ノート",newTodo:"新規タスク",sort:"並べ替え",collapseAll:"すべて折りたたむ",expandAll:"すべて展開",search:"ノート内容を検索...",searchResultCount:"{count} 件の結果",searchNoResult:"一致するノートが見つかりません",searching:"検索中...",sync:"同期",syncing:"同期中...",syncDone:"✔ 同期完了",syncFailed:"⚠ 同期に失敗しました",loading:"読み込み中...",sortUpdatedDesc:"↓ 更新日時",sortUpdatedAsc:"↑ 更新日時",sortTitleAsc:"↑ タイトル",sortTitleDesc:"↓ タイトル",sortManual:"⇅ 手動",ctxNewNoteHere:"ここに新規ノート",ctxNewTodoHere:"ここに新規タスク",ctxNewSubNotebook:"新規サブノートブック",ctxRenameFolder:"編集",ctxExportFolder:"ノートブックをエクスポート",ctxDeleteFolder:"ノートブックを削除",ctxOpenNote:"ノートを開く",ctxOpenInNewWindow:"新しいウィンドウで開く",ctxCopyLink:"Markdownリンクをコピー",ctxDuplicateNote:"複製",ctxSwitchNoteType:"ノート/タスク切り替え",ctxToggleTodo:"完了状態を切り替え",ctxRenameNote:"名前を変更",ctxMoveNote:"ノートブックに移動...",ctxNoteInfo:"ノートプロパティ",ctxDeleteNote:"ノートを削除",confirmDeleteFolder:"このノートブックとその内容をすべて削除しますか?",confirmDeleteNote:"このノートを削除しますか?",promptRename:"新しい名前を入力:",promptMoveNote:"移動先のノートブック名:",promptNewNotebookName:"新しいノートブック名を入力:",dropCreateNotebook:"ドロップして新規ノートブックを作成",searchSectionNotes:"ノート",searchSectionTags:"タグ",searchSectionFolders:"ノートブック",searchTagNoteCount:"{count} 件のノート",pinned:"ピン留め",tags:"タグ",ctxRenameTag:"タグ名を変更",ctxDeleteTag:"タグを削除",ctxUntagNote:"タグから外す",confirmDeleteTag:"このタグを削除しますか?(タグのみ削除され、ノートは残ります)",ctxPublishNote:"ノートを公開",ctxExport:"エクスポート",sharedBadge:"公開済み · クリックで公開ダイアログを開く",sShowTags:"タグセクションを表示",sShowTagsDesc:"ノートブックツリーの下に Joplin のタグをフォルダーとして表示します。",sAutoRefresh:"外部変更時に自動更新",sAutoRefreshDesc:"Joplin の変更フィードを 5 秒ごとに確認し、他のプラグインや同期によるノートの作成・移動・削除時にパネルを更新します。開いているノートの編集は対象外(もともと即時反映)。",sRestoreUi:"起動時に前回の表示状態を復元",sRestoreUiDesc:"フォルダー/セクションの折りたたみ状態をセッションをまたいで記憶します。オフの場合は全て折りたたんだ状態で起動します。",sShowSmart:"スマートフォルダーを表示",sShowSmartDesc:"保存済み検索をフォルダーとして表示:最近の更新、未完了タスク、独自ルール。",sSmartRules:"カスタムスマートフォルダー",sSmartRulesDesc:'「名前:クエリ」を ";" 区切りで。Joplin 検索構文を使用。例:仕事:notebook:Work updated:day-30;スター:tag:star',sSmartLimit:"スマートフォルダー表示件数",sSmartLimitDesc:"各スマートフォルダーに表示する最大ノート数(新しい順)。既定値:5。",sHoverPreview:"ホバーでノートをプレビュー",sHoverPreviewDesc:"ノートにカーソルを合わせるとタイトル・更新日時・本文の抜粋を表示します。",sHoverPreviewLen:"ホバープレビューの長さ(文字数)",sArrowPos:"展開矢印の位置",sArrowPosDesc:"ノートブック・セクション見出し・セクション行すべてに適用され、統一されます。",sArrowRight:"テキストの後ろ",sArrowLeft:"テキストの左(クラシックツリー)",sExpandMode:"「すべて展開」の動作",sExpandModeDesc:"展開ボタンが復元する内容。既定:前回「すべて折りたたむ」前の状態。",sExpandRestore:"折りたたみ前の状態を復元",sExpandSkeleton:"フォルダーのみ(末端ノートブックは折りたたんだまま)",sExpandAllOpt:"すべて",sSectionOrder:"セクションの順序",sSectionOrderDesc:"カンマ区切りのセクション順。キー:pinned(お気に入り)、smart(スマートフォルダー)、tree(ノートブックツリー)、tags(タグ)、trash(ゴミ箱)。省略したセクションは既定順で末尾に並びます。",sSectionGap:"セクション間隔(px)",sSectionGapDesc:"各セクション区切り線の上の余白。既定値:5。",sShowToggles:"展開矢印を表示",sShowTogglesDesc:"フォルダーとお気に入りセクションの前に展開/折りたたみ矢印を表示します。",sOpenFolderIcon:"展開フォルダーのアイコン",sOpenFolderIconDesc:"カスタムアイコンのないノートブックが展開時に使う Emoji、画像 URL、data URI、ローカル画像パス。",sClosedFolderIcon:"折りたたみフォルダーのアイコン",sClosedFolderIconDesc:"カスタムアイコンのないノートブックが折りたたみ時に使う Emoji、画像 URL、data URI、ローカル画像パス。",sOpenPinnedIcon:"お気に入り展開アイコン",sOpenPinnedIconDesc:"お気に入りセクション展開時に使う Emoji、画像 URL、data URI、ローカル画像パス。",sClosedPinnedIcon:"お気に入り折りたたみアイコン",sClosedPinnedIconDesc:"お気に入りセクション折りたたみ時に使う Emoji、画像 URL、data URI、ローカル画像パス。",refresh:"更新",newItem:"新規",trash:"ゴミ箱",ctxRestoreNote:"復元",ctxPermanentDelete:"完全に削除",ctxEmptyTrash:"ゴミ箱を空にする",confirmEmptyTrash:"ゴミ箱を空にしますか?削除済みのノートブックとノートは完全に削除され、元に戻せません。",smartFolders:"スマートフォルダ",smartRecent:"最近更新",smartTodos:"未完了の ToDo",pvType:"種類",pvSize:"サイズ",pvCreated:"作成",pvUpdated:"更新",pvNote:"ノート",pvTodo:"ToDo",pvChars:"文字",ctxSetTags:"タグを設定",ctxMoveToFolder:"ノートブックへ移動",ctxCopyExternalLink:"外部リンクをコピー",ctxPin:"📌 ピン留め",ctxUnpin:"ピン解除",cancel:"キャンセル"}},s=o(896),n=o(928),i=o(982);function r(e){let t=0,o=0;const a=/^[ \t]*(?:[-*+]|\d+[.)])\s+\[([ xX])\]/gm;let s;for(;s=a.exec(e);)t++," "!==s[1]&&o++;return{total:t,done:o}}let l="Published";function d(e){let t="";return e.is_shared&&(t+='<span class="shared-badge" title="'+l+'"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></span>'),e.cb_total&&(t+=function(e,t){if(!t)return"";const o=Math.max(0,Math.min(1,e/t));let a="";if(o>=1)a='<circle cx="8" cy="8" r="7" class="pie-fill"/><path d="M4.8 8.3 L7.1 10.6 L11.3 5.9" fill="none" stroke="var(--joplin-background-color, #fff)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>';else if(o>0){const e=2*o*Math.PI-Math.PI/2,t=8+7*Math.cos(e),s=8+7*Math.sin(e);a='<path class="pie-fill" d="M8 8 L8 1 A7 7 0 '+(o>.5?1:0)+" 1 "+t.toFixed(2)+" "+s.toFixed(2)+' Z"/>'}return'<span class="todo-pie" title="'+e+"/"+t+'"><svg width="12" height="12" viewBox="0 0 16 16"><circle cx="8" cy="8" r="7" class="pie-ring"/>'+a+"</svg></span>"}(e.cb_done||0,e.cb_total)),t}function c(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}const p={".gif":"image/gif",".ico":"image/x-icon",".jpeg":"image/jpeg",".jpg":"image/jpeg",".png":"image/png",".svg":"image/svg+xml",".webp":"image/webp"};function m(e,t){const o="icon"+(t?" "+t:"");return"image"===e.type?'<span class="'+o+'"><img class="custom-icon" src="'+c(e.value)+'" /></span>':'<span class="'+o+'">'+c(e.value)+"</span>"}const u={};async function f(e,t,o,a){const r=o+":"+String(e);if(u[r])return u[r];const l=await async function(e,t,o,a){const r="string"==typeof e?e.trim():"";if(!r)return{type:"text",value:t};if(/^data:image\//i.test(r)||/^https?:\/\//i.test(r))return{type:"image",value:r};const l=function(e){const t=e.trim();return/^file:\/\//i.test(t)?decodeURIComponent(t.replace(/^file:\/\//i,"")):0===t.indexOf("~/")&&process&&process.env&&process.env.HOME?n.join(process.env.HOME,t.substring(2)):n.isAbsolute(t)?t:null}(r);if(!l)return{type:"text",value:r};const d=n.extname(l).toLowerCase(),c=p[d];if(!c)return console.warn("Joplin Explorer: unsupported icon file type",l),{type:"text",value:t};const m=n.join(a,"custom-icons"),u=i.createHash("sha1").update(l).digest("hex"),f=n.join(m,o+"-"+u+d);try{await s.promises.mkdir(m,{recursive:!0}),(await s.promises.stat(l)).isFile()&&await s.promises.copyFile(l,f)}catch(e){console.warn("Joplin Explorer: failed to copy icon file",l,e)}try{return{type:"image",value:"data:"+c+";base64,"+(await s.promises.readFile(f)).toString("base64")}}catch(e){return console.warn("Joplin Explorer: failed to load icon file",f,e),{type:"text",value:t}}}(e,t,o,a);return u[r]=l,l}function w(e,t){const o=e.order||0,a=t.order||0;return o!==a?a-o:(e.title||"").localeCompare(t.title||"")}function g(e,t=!0,o={type:"text",value:"📂"},a={type:"text",value:"📁"}){let s=e.icon;if(s&&"string"==typeof s)try{s=JSON.parse(s)}catch(e){s=null}return s&&s.emoji?{type:"text",value:String(s.emoji)}:t?a:o}function h(e){return e.is_todo?e.todo_completed?"☑":"☐":"📝"}function y(e,t,o,a=0,s=!0,n={type:"text",value:"📂"},i={type:"text",value:"📁"}){let r="";for(const l of e){const e=8+18*a;if("folder"===l.type){const d=l.total_count||l.note_count||0,p=!0===o[l.id],u=p?"▶":"▼",f=p?"toggle":"toggle expanded";r+='<div class="tree-item folder'+(p?" collapsed":"")+'" style="padding-left:'+e+'px" data-id="'+l.id+'" data-type="folder">',s&&(r+='<span class="'+f+'">'+u+"</span>"),r+=m(g(l,!1,n,i),"folder-icon icon-when-open"),r+=m(g(l,!0,n,i),"folder-icon icon-when-collapsed"),r+='<span class="label">'+c(l.title)+"</span>",r+='<span class="count">'+d+"</span>",r+="</div>",r+='<div class="children'+(p?" collapsed":"")+'" data-folder-id="'+l.id+'">',l.children&&(r+=y(l.children,t,o,a+1,s,n,i)),r+="</div>"}else{const o=l.id===t?" selected":"",a=h(l);r+='<div class="tree-item note'+o+'" style="padding-left:'+e+'px" data-id="'+l.id+'" data-type="note" data-todo="'+(l.is_todo?1:0)+'">',r+='<span class="icon note-icon">'+a+"</span>",r+='<span class="label">'+c(l.title)+"</span>",r+=d(l),r+="</div>"}}return r}function x(e,t){const o=e.slice();switch(t){case"title_asc":o.sort((e,t)=>(e.title||"").localeCompare(t.title||""));break;case"title_desc":o.sort((e,t)=>(t.title||"").localeCompare(e.title||""));break;case"updated_asc":o.sort((e,t)=>(e.user_updated_time||0)-(t.user_updated_time||0));break;case"manual":o.sort((e,t)=>{const o=e.order||0,a=t.order||0;return o!==a?a-o:(t.user_updated_time||0)-(e.user_updated_time||0)});break;default:o.sort((e,t)=>(t.user_updated_time||0)-(e.user_updated_time||0))}return o}joplin.plugins.register({onStart:async function(){const e=(t=await joplin.settings.globalValue("locale")||"en_US",a[t]||a[t.split("_")[0]]||a.en_US);var t;l=e.sharedBadge||l;const o=await joplin.views.panels.create("notesInListPanel");await joplin.views.panels.addScript(o,"webview/panel.css"),await joplin.views.panels.addScript(o,"webview/panel.js"),await joplin.views.panels.setHtml(o,'<div id="notes-in-list-root"><p style="padding:12px;">'+e.loading+"</p></div>"),await joplin.views.panels.show(o,!0);try{await joplin.settings.registerSection("joplinExplorer",{label:"Joplin Explorer",iconName:"fas fa-columns"}),await joplin.settings.registerSettings({pinnedItems:{section:"joplinExplorer",type:2,value:'{"notes":[],"folders":[]}',public:!1,label:"Pinned Items (JSON)"},folderOrder:{section:"joplinExplorer",type:2,value:"{}",public:!1,label:"Folder Manual Order (JSON)"},noteSortMode:{section:"joplinExplorer",type:2,value:"updated_desc",public:!1,label:"Note Sort Mode"},uiState:{section:"joplinExplorer",type:2,value:"{}",public:!1,label:"UI State (JSON)"},showTagsSection:{section:"joplinExplorer",type:3,value:!0,public:!0,label:e.sShowTags,description:e.sShowTagsDesc},autoRefresh:{section:"joplinExplorer",type:3,value:!0,public:!0,label:e.sAutoRefresh,description:e.sAutoRefreshDesc},restoreUiState:{section:"joplinExplorer",type:3,value:!0,public:!0,label:e.sRestoreUi,description:e.sRestoreUiDesc},showSmartFolders:{section:"joplinExplorer",type:3,value:!0,public:!0,label:e.sShowSmart,description:e.sShowSmartDesc},smartFolderRules:{section:"joplinExplorer",type:2,value:"",public:!0,label:e.sSmartRules,description:e.sSmartRulesDesc},smartFolderLimit:{section:"joplinExplorer",type:1,value:5,minimum:1,maximum:50,public:!0,label:e.sSmartLimit,description:e.sSmartLimitDesc},hoverPreview:{section:"joplinExplorer",type:3,value:!0,public:!0,label:e.sHoverPreview,description:e.sHoverPreviewDesc},hoverPreviewLength:{section:"joplinExplorer",type:1,value:200,minimum:50,maximum:1e3,public:!0,label:e.sHoverPreviewLen},toggleArrowPosition:{section:"joplinExplorer",type:2,value:"right",isEnum:!0,options:{right:e.sArrowRight,left:e.sArrowLeft},public:!0,label:e.sArrowPos,description:e.sArrowPosDesc},expandAllMode:{section:"joplinExplorer",type:2,value:"restore",isEnum:!0,options:{restore:e.sExpandRestore,skeleton:e.sExpandSkeleton,all:e.sExpandAllOpt},public:!0,label:e.sExpandMode,description:e.sExpandModeDesc},sectionOrder:{section:"joplinExplorer",type:2,value:"pinned,smart,tree,tags,trash",public:!0,label:e.sSectionOrder,description:e.sSectionOrderDesc},sectionSpacing:{section:"joplinExplorer",type:1,value:5,minimum:0,maximum:30,public:!0,label:e.sSectionGap,description:e.sSectionGapDesc},showFolderToggles:{section:"joplinExplorer",type:3,value:!0,public:!0,label:e.sShowToggles,description:e.sShowTogglesDesc},openFolderIcon:{section:"joplinExplorer",type:2,value:"📂",public:!0,label:e.sOpenFolderIcon,description:e.sOpenFolderIconDesc},closedFolderIcon:{section:"joplinExplorer",type:2,value:"📁",public:!0,label:e.sClosedFolderIcon,description:e.sClosedFolderIconDesc},openPinnedIcon:{section:"joplinExplorer",type:2,value:"📌",public:!0,label:e.sOpenPinnedIcon,description:e.sOpenPinnedIconDesc},closedPinnedIcon:{section:"joplinExplorer",type:2,value:"📌",public:!0,label:e.sClosedPinnedIcon,description:e.sClosedPinnedIconDesc}})}catch(e){console.error("Joplin Explorer: failed to register settings",e)}const s=await joplin.views.dialogs.create("explorerInputDialog"),n=await joplin.views.dialogs.create("explorerConfirmDialog"),i=await joplin.views.dialogs.create("explorerInfoDialog");async function p(t){return await joplin.views.dialogs.setHtml(n,'<div style="padding:10px;min-width:280px;"><div style="font-size:13px;">'+c(t)+"</div></div>"),await joplin.views.dialogs.setButtons(n,[{id:"ok",title:"OK"},{id:"cancel",title:e.cancel||"Cancel"}]),"ok"===(await joplin.views.dialogs.open(n)).id}async function v(e,t){await joplin.views.dialogs.setHtml(i,'<div style="padding:10px;min-width:320px;"><div style="font-size:14px;font-weight:bold;margin-bottom:10px;">'+c(e)+'</div><div style="font-size:12px;line-height:1.8;white-space:pre-wrap;">'+c(t)+"</div></div>"),await joplin.views.dialogs.setButtons(i,[{id:"ok",title:"OK"}]),await joplin.views.dialogs.open(i)}async function _(t,o){await joplin.views.dialogs.setHtml(s,'<div style="padding:10px;min-width:300px;"><div style="margin-bottom:8px;font-size:13px;">'+c(t)+'</div><form name="inputForm"><input name="value" type="text" value="'+c(o||"")+'" style="width:100%;box-sizing:border-box;padding:6px 8px;font-size:13px;" /></form></div>'),await joplin.views.dialogs.setButtons(s,[{id:"ok",title:"OK"},{id:"cancel",title:e.cancel||"Cancel"}]);const a=await joplin.views.dialogs.open(s);return"ok"===a.id&&a.formData&&a.formData.inputForm&&a.formData.inputForm.value||null}let b="",N={},S="updated_desc";try{const e=String(await joplin.settings.value("noteSortMode")||"");["updated_desc","updated_asc","title_asc","title_desc","manual"].indexOf(e)>=0&&(S=e)}catch(e){}let j=[],D={},T=[],k=[],I=!1,R=!1,E=!0,F=!1,O={},C=!0,P=null,A=[],U={},M=!0,L=!1;if(R=!0,!1!==await joplin.settings.value("restoreUiState"))try{const e=String(await joplin.settings.value("uiState")||"{}"),t=JSON.parse(e);t&&"object"==typeof t&&(t.collapsedFolders&&"object"==typeof t.collapsedFolders&&!Array.isArray(t.collapsedFolders)&&(N=t.collapsedFolders,L=!0),"boolean"==typeof t.tagsCollapsed&&(R=t.tagsCollapsed),"boolean"==typeof t.pinnedCollapsed&&(I=t.pinnedCollapsed),"boolean"==typeof t.trashCollapsed&&(E=t.trashCollapsed),"boolean"==typeof t.smartCollapsed&&(F=t.smartCollapsed),t.seenFolders&&"object"==typeof t.seenFolders&&!Array.isArray(t.seenFolders)&&(O=t.seenFolders,C=!1),Array.isArray(t.collapseSnapshot)&&(P=t.collapseSnapshot.map(String)))}catch(e){}let J=null;function H(){J&&clearTimeout(J),J=setTimeout(async()=>{J=null;try{await joplin.settings.setValue("uiState",JSON.stringify({collapsedFolders:N,tagsCollapsed:R,pinnedCollapsed:I,trashCollapsed:E,smartCollapsed:F,seenFolders:O,collapseSnapshot:P}))}catch(e){console.error("Joplin Explorer: failed to save UI state",e)}},500)}const q=await joplin.plugins.dataDir();let z=null;function W(e=600){z&&clearTimeout(z),z=setTimeout(async()=>{z=null,await Z()},e)}let B=null,G={};async function V(){try{await joplin.settings.setValue("pinnedItems",JSON.stringify(k))}catch(e){console.error("Joplin Explorer: failed to save pinned items",e)}}async function K(){try{await joplin.settings.setValue("folderOrder",JSON.stringify(U))}catch(e){console.error("Joplin Explorer: failed to save folder order",e)}}function X(e){let t=e;for(;t;){delete N[t];const e=D[t];t=e?e.parent_id:null}}async function Z(){try{const t=await async function(){let e=[],t=1,o=!0;for(;o;){const a=await joplin.data.get(["folders"],{fields:["id","title","parent_id","icon"],page:t,limit:100});e=e.concat(a.items),o=a.has_more,t++}return e}();await async function(){try{const e=await joplin.settings.value("folderOrder"),t=e?JSON.parse(e):{};U=t&&"object"==typeof t&&!Array.isArray(t)?t:{}}catch(e){U={}}}();let a=!1;const s=new Set(t.map(e=>e.id));for(const e of Object.keys(U))s.has(e)||(delete U[e],a=!0);a&&await K();for(const e of t)e.order=U[e.id]||0;j=t,D={};for(const e of t)D[e.id]=e;let n=!1;for(const e of t)O[e.id]||(O[e.id]=!0,C||(N[e.id]=!0),n=!0);if(C&&(C=!1,n=!0),n&&H(),M){if(!L)for(const e of t)N[e.id]=!0;const e=await joplin.workspace.selectedNote();e&&(b=e.id,X(e.parent_id)),M=!1}const i=await async function(){let e=[],t=1,o=!0;for(;o;){const a=await joplin.data.get(["notes"],{fields:["id","title","parent_id","is_todo","todo_completed","updated_time","user_updated_time","order","is_shared","body"],page:t,limit:100});for(const e of a.items){const t=r(e.body||"");e.cb_total=t.total,e.cb_done=t.done,delete e.body}e=e.concat(a.items),o=a.has_more,t++}return e}(),l={};for(const e of t)l[e.id]=[];for(const e of i)l[e.parent_id]&&l[e.parent_id].push(e);for(const e of Object.keys(l))l[e]=x(l[e],S);const p=[];for(const e of Object.keys(l))for(const t of l[e])p.push(t);T=p;const u=await joplin.settings.value("showFolderToggles"),v=await joplin.settings.value("openFolderIcon"),_=await joplin.settings.value("closedFolderIcon"),J=await joplin.settings.value("openPinnedIcon"),z=await joplin.settings.value("closedPinnedIcon"),W=await f(v,"📂","openFolderIcon",q),B=await f(_,"📁","closedFolderIcon",q),G=await f(J,"📌","openPinnedIcon",q),Z=await f(z,"📌","closedPinnedIcon",q),$=!1!==u,Q=function(e,t){const o={},a={},s={};for(const t of e)o[t.id]={type:"folder",id:t.id,title:t.title,parent_id:t.parent_id,icon:t.icon,order:t.order||0,note_count:0,children:[]},a[t.id]=[],s[t.id]=[];for(const e of Object.keys(t))if(s[e])for(const o of t[e])s[e].push({type:"note",id:o.id,title:o.title||"(untitled)",is_todo:o.is_todo,todo_completed:o.todo_completed,is_shared:o.is_shared,cb_total:o.cb_total,cb_done:o.cb_done});const n=[];for(const t of e){const e=o[t.id];t.parent_id&&o[t.parent_id]?a[t.parent_id].push(e):n.push(e)}function i(e){const t=a[e.id].sort(w);for(const e of t)i(e);e.note_count=s[e.id].length,e.children=t.concat(s[e.id])}n.sort(w);for(const e of n)i(e);const r=n;function l(e){let t=0;if(!e.children)return 0;for(const o of e.children)"note"===o.type?t++:"folder"===o.type&&(l(o),t+=o.total_count||0);return e.total_count=t,t}for(const e of r)l(e);return r}(t,l),ee=y(Q,b,N,0,$,W,B);if(!1!==await joplin.settings.value("showTagsSection"))try{let e=[],t=1,o=!0;for(;o;){const a=await joplin.data.get(["tags"],{fields:["id","title"],page:t,limit:100});e=e.concat(a.items),o=a.has_more,t++}e.sort((e,t)=>(e.title||"").localeCompare(t.title||""));let a=e.map(()=>"");e.length<=200&&(a=await Promise.all(e.map(e=>joplin.data.get(["tags",e.id,"notes"],{fields:["id"],limit:100}).then(e=>0===e.items.length?"0":e.has_more?"100+":String(e.items.length)).catch(()=>""))),e=e.filter((e,t)=>"0"!==a[t]),a=a.filter(e=>"0"!==e)),A=e.map((e,t)=>({id:e.id,title:e.title||"",count:a[t]||""}))}catch(e){A=[]}else A=[];await async function(){try{const e=await joplin.settings.value("pinnedItems");if(!e)return;const t=JSON.parse(e);if(t&&!Array.isArray(t)&&t.notes&&t.folders){k=[];for(const e of t.folders)k.push({id:e,type:"folder"});for(const e of t.notes)k.push({id:e,type:"note"});await V()}else Array.isArray(t)&&(k=t)}catch(e){k=[]}}();const ae=new Set(t.map(e=>e.id)),se=new Set(p.map(e=>e.id)),ne=k.length;k=k.filter(e=>"folder"===e.type?ae.has(e.id):se.has(e.id)),k.length!==ne&&await V();let ie="";const re=k.length;if(re>0){ie+='<div class="pinned-section-header'+(I?" collapsed":"")+'" id="pinned-header">',$&&(ie+='<span class="toggle">'+(I?"▶":"▼")+"</span>"),ie+=m(G,"icon-when-open")+m(Z,"icon-when-collapsed")+'<span class="label">'+e.pinned+'</span><span class="count">'+re+"</span></div>",ie+='<div class="pinned-section-body'+(I?" collapsed":"")+'" id="pinned-body">';for(const e of k)if("folder"===e.type){const t=D[e.id]||null;if(t){const e=g(t,!0,W,B);ie+='<div class="tree-item folder pinned-item" data-id="'+t.id+'" data-type="folder">',ie+=m(e,"folder-icon"),ie+='<span class="label">'+c(t.title)+"</span>",ie+="</div>"}}else{let t=null;for(const o of p)if(o.id===e.id){t=o;break}if(t){const e=t.id===b?" selected":"",o=h(t);ie+='<div class="tree-item note pinned-item'+e+'" data-id="'+t.id+'" data-type="note" data-todo="'+(t.is_todo?1:0)+'">',ie+='<span class="icon note-icon">'+o+"</span>",ie+='<span class="label">'+c(t.title)+"</span>",ie+=d(t),ie+="</div>"}}ie+="</div>"}let le="";if(A.length>0){le+='<div class="tags-section-header'+(R?" collapsed":"")+'" id="tags-header">',$&&(le+='<span class="toggle">'+(R?"▶":"▼")+"</span>"),le+='<span class="icon">🏷️</span><span class="label">'+e.tags+'</span><span class="count">'+A.length+"</span></div>",le+='<div class="tags-section-body'+(R?" collapsed":"")+'" id="tags-body">';for(const e of A)le+='<div class="tree-item folder tag-folder collapsed" data-tag-id="'+e.id+'" data-type="tag">',$&&(le+='<span class="toggle">▶</span>'),le+='<span class="icon">🏷️</span>',le+='<span class="label">'+c(e.title)+"</span>",e.count&&(le+='<span class="count">'+e.count+"</span>"),le+="</div>",le+='<div class="tag-children collapsed" data-tag-id="'+e.id+'"></div>';le+="</div>"}let de="";try{const t={};let o=0,a=!1,s=1,n=!0;for(;n;){const e=await joplin.data.get(["folders"],{fields:["id","deleted_time"],include_deleted:"1",page:s,limit:100});for(const a of e.items||[])a.deleted_time>0&&(t[a.id]=!0,o++);n=e.has_more,s++}const i=(await joplin.data.get(["notes"],{fields:["id","parent_id","deleted_time"],include_deleted:"1",order_by:"deleted_time",order_dir:"DESC",limit:100})).items||[];for(const e of i){if(!e.deleted_time)break;t[e.parent_id]||o++}100===i.length&&i[99].deleted_time>0&&(a=!0),(o>0||a)&&(de+='<div class="trash-section-header'+(E?" collapsed":"")+'" id="trash-header">',$&&(de+='<span class="toggle">'+(E?"▶":"▼")+"</span>"),de+='<span class="icon">🗑️</span><span class="label">'+e.trash+'</span><span class="count">'+o+(a?"+":"")+"</span></div>",de+='<div class="trash-children'+(E?" collapsed":"")+'" id="trash-children"></div>')}catch(e){}let ce="";if(!1!==await joplin.settings.value("showSmartFolders")){const t=[{id:"recent",title:e.smartRecent,query:"updated:day-7"},{id:"todos",title:e.smartTodos,query:"type:todo iscompleted:0"}],o=String(await joplin.settings.value("smartFolderRules")||"").trim();if(o){const e=o.split(";");for(let o=0;o<e.length;o++){const a=e[o].trim();if(!a)continue;const s=a.indexOf(":");s<=0||t.push({id:"rule"+o,title:a.slice(0,s).trim(),query:a.slice(s+1).trim()})}}ce+='<div class="smart-section-header'+(F?" collapsed":"")+'" id="smart-header">',$&&(ce+='<span class="toggle">'+(F?"▶":"▼")+"</span>"),ce+='<span class="icon">🔍</span><span class="label">'+e.smartFolders+"</span></div>",ce+='<div class="smart-section-body'+(F?" collapsed":"")+'" id="smart-body">';for(const e of t){if(!e.title||!e.query)continue;let t=0,o=!1;try{if("recent"===e.id)t=(await te(1)).length;else if("todos"===e.id){const e=await oe(101);t=Math.min(e.length,100),o=e.length>100}else{let a=1,s=!0;for(;s&&t<=100;){const o=await joplin.data.get(["search"],{query:e.query,fields:["id"],page:a,limit:100});t+=(o.items||[]).length,s=o.has_more,a++}t>100&&(t=100,o=!0)}}catch(e){}const a=t>0;ce+='<div class="tree-item folder smart-folder collapsed'+(a?"":" smart-empty")+'" style="padding-left:26px" data-smart-id="'+e.id+'" data-query="'+c(e.query)+'" data-type="smart"><span class="toggle">▶</span><span class="icon">🔍</span><span class="label">'+c(e.title)+"</span>"+(a&&"recent"!==e.id?'<span class="count">'+t+(o?"+":"")+"</span>":"")+"</div>",a&&(ce+='<div class="smart-children collapsed" data-smart-id="'+e.id+'"></div>')}ce+="</div>"}const pe=c(JSON.stringify(k)),me=t.length>0&&t.every(e=>!0===N[e.id]),ue={updated_desc:e.sortUpdatedDesc,updated_asc:e.sortUpdatedAsc,title_asc:e.sortTitleAsc,title_desc:e.sortTitleDesc,manual:e.sortManual},fe=c(JSON.stringify(e)),we=String(await joplin.settings.value("expandAllMode")||"restore"),ge=!1!==await joplin.settings.value("hoverPreview")?"1":"0",he="left"===String(await joplin.settings.value("toggleArrowPosition")||"right")?"left":"right",ye={pinned:ie,smart:ce,tree:'<div id="main-tree">'+ee+"</div>",tags:le,trash:de},xe=[];for(const e of String(await joplin.settings.value("sectionOrder")||"").split(",").map(e=>e.trim().toLowerCase()).filter(e=>!!e))void 0!==ye[e]&&xe.indexOf(e)<0&&xe.push(e);for(const e of["pinned","smart","tree","tags","trash"])xe.indexOf(e)<0&&xe.push(e);const ve=xe.map(e=>ye[e]).join("");let _e=Number(await joplin.settings.value("sectionSpacing"));(!isFinite(_e)||_e<0)&&(_e=5),_e>30&&(_e=30);const be='<div id="notes-in-list-root" style="--sec-gap:'+_e+'px" data-i18n="'+fe+'" data-pinned="'+pe+'" data-sort="'+c(S)+'" data-expand-mode="'+c(we)+'" data-hover-preview="'+ge+'" data-arrow-pos="'+he+'" data-collapse-snapshot="'+c(JSON.stringify(P))+'"> <div class="toolbar"> <button id="btn-new" title="'+e.newItem+'">+</button> <button id="btn-sort" title="'+e.sort+'">'+ue[S]+'</button> <button id="btn-collapse-all" data-mode="'+(me?"expand":"collapse")+'" title="'+(me?e.expandAll:e.collapseAll)+'">'+(me?"▼":"▲")+'</button> <button id="btn-refresh" title="'+e.refresh+'">↻</button> </div> <div class="search-bar"> <input id="search-input" type="text" placeholder="🔍 '+e.search+'" /> </div> <div id="tree-container">'+ve+' <div id="drop-zone-empty" class="drop-zone-empty">+ '+e.dropCreateNotebook+'</div> </div> <div id="search-results" style="display:none;"></div> <div class="bottom-bar"> <button id="btn-sync" title="'+e.sync+'">🔄 '+e.sync+"</button> </div></div>";if(await joplin.views.panels.setHtml(o,be),de&&!E)try{const e=await Y();await joplin.views.panels.postMessage(o,{name:"trashNotes",folders:e.folders,notes:e.notes})}catch(e){}}catch(e){console.error("Notes In List: refresh error",e),await joplin.views.panels.setHtml(o,'<div style="padding:12px;color:red;">Error: '+c(String(e))+"</div>")}}async function $(e){try{const t=T.findIndex(t=>t.id===e),a=await joplin.data.get(["notes",e],{fields:["id","title","parent_id","is_todo","todo_completed","updated_time","user_updated_time","order","is_shared","body"]}),s=r(a.body||"");if(a.cb_total=s.total,a.cb_done=s.done,delete a.body,t<0||T[t].parent_id!==a.parent_id)return void await Z();const n=T[t],i=0===S.indexOf("title_")&&(n.title||"")!==(a.title||""),l=0===S.indexOf("updated_")&&n.user_updated_time!==a.user_updated_time;if(T[t]=a,i||l)return void await Z();await joplin.views.panels.postMessage(o,{name:"updateNote",id:a.id,title:a.title||"(untitled)",icon:h(a),badges:d(a)})}catch(e){await Z()}}async function Q(e){let t=[],o=1,a=!0;for(;a&&t.length<200;){const s=await joplin.data.get(["tags",e,"notes"],{fields:["id","title","is_todo","todo_completed"],page:o,limit:50});t=t.concat(s.items),a=s.has_more,o++}return t.map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed}))}async function Y(){const e=[],t={},o={};try{let a=1,s=!0;for(;s;){const n=await joplin.data.get(["folders"],{fields:["id","title","parent_id","deleted_time"],include_deleted:"1",page:a,limit:100});for(const a of n.items||[])o[a.id]=a.parent_id||"",a.deleted_time>0&&(e.push({id:a.id,title:a.title||"(untitled)",parent_id:a.parent_id}),t[a.id]=!0);s=n.has_more,a++}}catch(e){}const a=[],s={},n=[];for(const o of e)o.parent_id&&t[o.parent_id]?(s[o.parent_id]=s[o.parent_id]||[]).push(o):n.push(o);const i=(e,t)=>{a.push({id:e.id,title:e.title,depth:t});for(const o of s[e.id]||[])i(o,t+1)};for(const e of n)i(e,0);await Promise.all(a.map(async e=>{try{const t=await joplin.data.get(["folders",e.id,"notes"],{fields:["id"],include_deleted:"1",limit:1});e.hasNotes=!(!t.items||!t.items.length)}catch(t){e.hasNotes=!0}}));const r=[];let l=1,d=!0;for(;d&&r.length<200;){const e=await joplin.data.get(["notes"],{fields:["id","title","parent_id","is_todo","todo_completed","deleted_time"],include_deleted:"1",order_by:"deleted_time",order_dir:"DESC",page:l,limit:50});let a=!1;for(const s of e.items||[]){if(!s.deleted_time){a=!0;break}let e=!1,n=s.parent_id,i=0;for(;n&&i++<50;){if(t[n]){e=!0;break}n=o[n]||""}e||r.push({id:s.id,title:s.title||"(untitled)",is_todo:s.is_todo,todo_completed:s.todo_completed})}if(a)break;d=e.has_more,l++}return{folders:a,notes:r}}async function ee(e){const t={};try{let e=1,o=!0;for(;o;){const a=await joplin.data.get(["folders"],{fields:["id","parent_id"],include_deleted:"1",page:e,limit:100});for(const e of a.items||[])e.parent_id&&(t[e.parent_id]=t[e.parent_id]||[]).push(e.id);o=a.has_more,e++}}catch(e){}const o=async e=>{for(const a of t[e]||[])await o(a);try{let t=1,o=!0;for(;o;){const a=await joplin.data.get(["folders",e,"notes"],{fields:["id"],include_deleted:"1",page:t,limit:100});for(const e of a.items||[])try{await joplin.data.delete(["notes",e.id],{permanent:"1"})}catch(e){}o=(a.items||[]).length>0&&a.has_more}}catch(e){}try{await joplin.data.delete(["folders",e],{permanent:"1"})}catch(e){}};await o(e)}async function te(e){return((await joplin.data.get(["notes"],{fields:["id","title","is_todo","todo_completed","user_updated_time"],order_by:"user_updated_time",order_dir:"DESC",limit:Math.min(e,100)})).items||[]).map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed}))}async function oe(e){const t=[];let o=1,a=!0;for(;a&&t.length<e&&o<=10;){const e=await joplin.data.get(["notes"],{fields:["id","title","is_todo","todo_completed","user_updated_time"],order_by:"is_todo",order_dir:"DESC",page:o,limit:100});let s=!1;for(const o of e.items||[]){if(!o.is_todo){s=!0;break}o.todo_completed||t.push({id:o.id,title:o.title||"(untitled)",is_todo:o.is_todo,todo_completed:o.todo_completed,user_updated_time:o.user_updated_time||0})}if(s)break;a=e.has_more,o++}return t.sort((e,t)=>(t.user_updated_time||0)-(e.user_updated_time||0)),t.slice(0,e)}await joplin.settings.onChange(async e=>{e.keys&&e.keys.indexOf("autoRefresh")>=0&&await le(),e.keys&&(e.keys.indexOf("toggleArrowPosition")>=0||e.keys.indexOf("showSmartFolders")>=0||e.keys.indexOf("smartFolderRules")>=0||e.keys.indexOf("hoverPreview")>=0||e.keys.indexOf("expandAllMode")>=0||e.keys.indexOf("showTagsSection")>=0||e.keys.indexOf("sectionOrder")>=0||e.keys.indexOf("sectionSpacing")>=0||e.keys.indexOf("showFolderToggles")>=0||e.keys.indexOf("openFolderIcon")>=0||e.keys.indexOf("closedFolderIcon")>=0||e.keys.indexOf("openPinnedIcon")>=0||e.keys.indexOf("closedPinnedIcon")>=0)&&(function(){for(const e of Object.keys(u))delete u[e]}(),await Z())}),await joplin.views.panels.onMessage(o,async t=>{if("openNote"===t.name)b=t.id,await joplin.commands.execute("openNote",t.id);else if("refresh"===t.name)await Z();else if("toggleFolder"===t.name)N[t.id]?delete N[t.id]:N[t.id]=!0,H();else if("collapseAll"===t.name){for(const e of j)N[e.id]=!0;Array.isArray(t.prevCollapsed)&&(P=t.prevCollapsed.map(String)),H()}else if("expandAll"===t.name){if(N={},Array.isArray(t.collapsedIds))for(const e of t.collapsedIds)N[String(e)]=!0;H()}else if("panelReady"===t.name)await Z();else if("notePreview"===t.name)try{if(!1===await joplin.settings.value("hoverPreview"))return;const e=Number(await joplin.settings.value("hoverPreviewLength"))||200,a=await joplin.data.get(["notes",t.id],{fields:["id","title","body","is_todo","user_created_time","user_updated_time"],include_deleted:"1"});if(!a)return;const s=String(a.body||"").replace(/```[\s\S]*?```/g," ").replace(/!\[[^\]]*\]\([^)]*\)/g," ").replace(/\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/^#{1,6}\s+/gm,"").replace(/[`*_>~]/g,"").replace(/\s+/g," ").trim().slice(0,e);await joplin.views.panels.postMessage(o,{name:"notePreview",id:t.id,title:a.title||"(untitled)",created:a.user_created_time||0,updated:a.user_updated_time||0,isTodo:!!a.is_todo,size:String(a.body||"").length,snippet:s})}catch(e){}else if("refreshView"===t.name)await Z();else if("newNotebook"===t.name){const t=await _(e.promptNewNotebookName,"");if(!t||!t.trim())return;const a=await joplin.data.post(["folders"],null,{title:t.trim()});O[a.id]=!0,delete N[a.id],await Z(),await joplin.views.panels.postMessage(o,{name:"scrollToFolder",folderId:a.id})}else if("newNote"===t.name){await joplin.commands.execute("newNote");const e=await joplin.workspace.selectedNote();e&&(b=e.id,X(e.parent_id)),await Z()}else if("newTodo"===t.name){await joplin.commands.execute("newTodo");const e=await joplin.workspace.selectedNote();e&&(b=e.id,X(e.parent_id)),await Z()}else if("search"===t.name)await async function(e){const t=e.query;if(t&&t.trim())try{const a=t.toLowerCase(),s={};for(const e of j)s[e.id]=e.title;let n=[],i=1,r=!0;for(;r&&n.length<100;){const e=await joplin.data.get(["search"],{query:t,fields:["id","title","body","parent_id","is_todo","todo_completed"],page:i,limit:20});n=n.concat(e.items),r=e.has_more,i++}const l=new Set(n.map(e=>e.id)),d=[];for(const e of T)!l.has(e.id)&&(e.title||"").toLowerCase().indexOf(a)>=0&&d.push(e);for(let e=0;e<d.length&&e<50;e++)try{const t=await joplin.data.get(["notes",d[e].id],{fields:["id","title","body","parent_id","is_todo","todo_completed"]});n.push(t)}catch(e){}const c=[];for(const e of n){let t="";const o=e.body||"",n=o.toLowerCase().indexOf(a);if(n>=0){const e=Math.max(0,n-40),s=Math.min(o.length,n+a.length+80);t=(e>0?"...":"")+o.substring(e,s).replace(/\n/g," ")+(s<o.length?"...":"")}else t=o.substring(0,120).replace(/\n/g," ")+(o.length>120?"...":"");c.push({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed,snippet:t,folderName:s[e.parent_id]||""})}let p=[],m=1,u=!0;for(;u;){const e=await joplin.data.get(["tags"],{fields:["id","title"],page:m,limit:100});p=p.concat(e.items),u=e.has_more,m++}const f=[];for(const e of p)if((e.title||"").toLowerCase().indexOf(a)>=0){let t=0;try{const o=await joplin.data.get(["tags",e.id,"notes"],{fields:["id"],limit:100});t=o.has_more?o.items.length+"+":o.items.length}catch(e){}f.push({id:e.id,title:e.title,noteCount:t})}const w=[];for(const e of j)if((e.title||"").toLowerCase().indexOf(a)>=0){let t="";if(e.icon&&"string"==typeof e.icon)try{const o=JSON.parse(e.icon);o&&o.emoji&&(t=String(o.emoji))}catch(e){}w.push({id:e.id,title:e.title,parent_id:e.parent_id,iconEmoji:t})}await joplin.views.panels.postMessage(o,{name:"searchResults",notes:c,tags:f,folders:w,query:t,searchId:e.searchId})}catch(e){console.error("Joplin Explorer: search error",e)}else await joplin.views.panels.postMessage(o,{name:"searchResults",results:null,query:"",searchId:e.searchId})}(t);else if("loadTagNotes"===t.name)try{const e=t.tagId;let a=[],s=1,n=!0;for(;n&&a.length<100;){const t=await joplin.data.get(["tags",e,"notes"],{fields:["id","title","parent_id","is_todo","todo_completed"],page:s,limit:50});a=a.concat(t.items),n=t.has_more,s++}const i={};for(const e of j)i[e.id]=e.title;const r=a.map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed,snippet:"",folderName:i[e.parent_id]||""}));await joplin.views.panels.postMessage(o,{name:"tagNotes",tagId:e,notes:r})}catch(e){console.error("Joplin Explorer: loadTagNotes error",e)}else if("toggleTagsSection"===t.name)R=!R,H();else if("tagFolderNotes"===t.name)try{const e=await Q(t.tagId);await joplin.views.panels.postMessage(o,{name:"tagFolderNotes",tagId:t.tagId,notes:e})}catch(e){console.error("Joplin Explorer: tagFolderNotes error",e)}else if("tagNoteAdd"===t.name)try{await joplin.data.post(["tags",t.tagId,"notes"],null,{id:t.noteId});const e=await Q(t.tagId);await joplin.views.panels.postMessage(o,{name:"tagFolderNotes",tagId:t.tagId,notes:e})}catch(e){console.error("Joplin Explorer: tagNoteAdd error",e)}else if("toggleSmartSection"===t.name)F=!F,H();else if("smartFolderNotes"===t.name)try{const e=Math.max(1,Number(await joplin.settings.value("smartFolderLimit"))||5);if("recent"===t.smartId||"todos"===t.smartId){const a="recent"===t.smartId?await te(e):await oe(e);return void await joplin.views.panels.postMessage(o,{name:"smartFolderNotes",smartId:t.smartId,notes:a})}let a=[],s=1,n=!0;for(;n&&a.length<100;){const e=await joplin.data.get(["search"],{query:String(t.query||""),fields:["id","title","is_todo","todo_completed","user_updated_time"],page:s,limit:50});a=a.concat((e.items||[]).map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed,user_updated_time:e.user_updated_time||0}))),n=e.has_more,s++}a.sort((e,t)=>(t.user_updated_time||0)-(e.user_updated_time||0)),await joplin.views.panels.postMessage(o,{name:"smartFolderNotes",smartId:t.smartId,notes:a.slice(0,e)})}catch(e){console.error("Joplin Explorer: smartFolderNotes error",e)}else if("toggleTrashSection"===t.name)E=!E,H();else if("trashFolderNotes"===t.name)try{let e=[],a=1,s=!0;for(;s&&e.length<200;){const o=await joplin.data.get(["folders",t.folderId,"notes"],{fields:["id","title","is_todo","todo_completed"],include_deleted:"1",page:a,limit:50});e=e.concat((o.items||[]).map(e=>({id:e.id,title:e.title||"(untitled)",is_todo:e.is_todo,todo_completed:e.todo_completed}))),s=o.has_more,a++}await joplin.views.panels.postMessage(o,{name:"trashFolderNotes",folderId:t.folderId,notes:e})}catch(e){console.error("Joplin Explorer: trashFolderNotes error",e)}else if("trashNotes"===t.name)try{const e=await Y();await joplin.views.panels.postMessage(o,{name:"trashNotes",folders:e.folders,notes:e.notes})}catch(e){console.error("Joplin Explorer: trashNotes error",e)}else if("locateFolder"===t.name)try{X(t.folderId),await Z(),await joplin.views.panels.postMessage(o,{name:"exitSearchAndLocate",folderId:t.folderId})}catch(e){console.error("Joplin Explorer: locateFolder error",e)}else if("locatePinnedFolder"===t.name)try{X(t.folderId),await Z(),await joplin.views.panels.postMessage(o,{name:"scrollToFolder",folderId:t.folderId})}catch(e){console.error("Joplin Explorer: locatePinnedFolder error",e)}else if("reorderPinned"===t.name)try{const e=t.dragId,o=t.targetId,a=t.position,s=k.findIndex(t=>t.id===e);if(s<0)return;const n=k[s];k.splice(s,1);let i=k.findIndex(e=>e.id===o);i<0?k.push(n):("after"===a&&i++,k.splice(i,0,n)),await V(),await Z()}catch(e){console.error("Joplin Explorer: reorderPinned error",e)}else if("togglePinnedCollapse"===t.name)I=!I,H();else if("cycleSort"===t.name){const e=["updated_desc","updated_asc","title_asc","title_desc","manual"],t=e.indexOf(S);S=e[(t+1)%e.length];try{await joplin.settings.setValue("noteSortMode",S)}catch(e){}await Z()}else if("sync"===t.name)try{await joplin.commands.execute("synchronize")}catch(t){console.error("Joplin Explorer: sync command failed",t),await joplin.views.panels.postMessage(o,{name:"syncState",state:"error"});const a=t&&t.message?String(t.message):String(t);await v(e.syncFailed,a)}else if("contextMenu"===t.name)await async function(t){const a=t.action,s=t.id,n=t.itemType;try{if("folder"===n)switch(a){case"newNote":{const t=await joplin.data.post(["notes"],null,{title:e.newNote,parent_id:s});await joplin.commands.execute("openNote",t.id),b=t.id,X(s);break}case"newTodo":{const t=await joplin.data.post(["notes"],null,{title:e.newTodo,parent_id:s,is_todo:1});await joplin.commands.execute("openNote",t.id),b=t.id,X(s);break}case"newSubNotebook":{const t=await _(e.newNotebook,"");if(t&&t.trim()){const e=await joplin.data.post(["folders"],null,{title:t.trim(),parent_id:s});O[e.id]=!0,delete N[s],delete N[e.id]}break}case"deleteFolder":{const t=await joplin.data.get(["folders",s],{fields:["title"]});await p(e.confirmDeleteFolder+"\n\n"+t.title)&&await joplin.data.delete(["folders",s]);break}case"renameFolder":try{const e=(await joplin.data.get(["folders",s],{fields:["updated_time"]})).updated_time,t=b;await joplin.commands.execute("openFolderDialog",{folderId:s}),(async()=>{for(let o=0;o<240;o++){await new Promise(e=>setTimeout(e,500));try{if((await joplin.data.get(["folders",s],{fields:["updated_time"]})).updated_time!==e){if(W(100),t){await new Promise(e=>setTimeout(e,400));try{const e=await joplin.workspace.selectedNote();e&&e.id===t||await joplin.commands.execute("openNote",t)}catch(e){}}return}}catch(e){return void W(100)}}})()}catch(t){const o=await joplin.data.get(["folders",s],{fields:["title"]}),a=await _(e.promptRename,o.title);a&&a.trim()&&await joplin.data.put(["folders",s],null,{title:a.trim()})}break;case"exportFolder":try{await joplin.commands.execute("exportFolders",[s])}catch(e){}break;case"pinFolder":k.some(e=>e.id===s)||(k.push({id:s,type:"folder"}),await V());break;case"unpinFolder":k=k.filter(e=>e.id!==s),await V()}else if("note"===n)switch(a){case"openNote":await joplin.commands.execute("openNote",s),b=s;break;case"openInNewWindow":try{await joplin.commands.execute("openNoteInNewWindow",s)}catch(e){await joplin.commands.execute("openNote",s)}break;case"copyLink":{const e=await joplin.data.get(["notes",s],{fields:["id","title"]}),t="["+e.title+"](:/"+e.id+")";try{await joplin.clipboard.writeText(t)}catch(e){await joplin.views.panels.postMessage(o,{name:"copyText",text:t})}break}case"duplicateNote":{const e=await joplin.data.get(["notes",s],{fields:["title","body","parent_id","is_todo"]}),t=await joplin.data.post(["notes"],null,{title:e.title+" (copy)",body:e.body,parent_id:e.parent_id,is_todo:e.is_todo});await joplin.commands.execute("openNote",t.id),b=t.id;break}case"switchNoteType":{const e=await joplin.data.get(["notes",s],{fields:["is_todo"]});await joplin.data.put(["notes",s],null,{is_todo:e.is_todo?0:1});break}case"toggleTodo":{const e=await joplin.data.get(["notes",s],{fields:["is_todo","todo_completed"]});e.is_todo&&await joplin.data.put(["notes",s],null,{todo_completed:e.todo_completed?0:Date.now()});break}case"publishNote":try{await joplin.commands.execute("showShareNoteDialog",[s])}catch(e){}break;case"exportPdf":try{await joplin.commands.execute("exportPdf",[s])}catch(e){}break;case"exportNote":try{const e=await joplin.views.dialogs.showOpenDialog({properties:["openDirectory"]}),o=Array.isArray(e)?e[0]:e;o&&await joplin.commands.execute("exportNotes",[s],t.format||"md",o)}catch(e){console.error("Joplin Explorer: exportNote error",e)}break;case"setTags":try{await joplin.commands.execute("setTags",[s])}catch(e){}break;case"moveToFolderDialog":try{await joplin.commands.execute("moveToFolder",[s])}catch(e){}break;case"copyExternalLink":{const e="joplin://x-callback-url/openNote?id="+s;try{await joplin.clipboard.writeText(e)}catch(t){await joplin.views.panels.postMessage(o,{name:"copyText",text:e})}break}case"renameNote":{const t=await joplin.data.get(["notes",s],{fields:["title"]}),o=await _(e.promptRename,t.title);o&&o.trim()&&await joplin.data.put(["notes",s],null,{title:o.trim()});break}case"moveNote":if(t.targetFolderName){let e=null;for(const o of j)if(o.title===t.targetFolderName){e=o;break}e&&await joplin.data.put(["notes",s],null,{parent_id:e.id})}break;case"noteInfo":{const t=await joplin.data.get(["notes",s],{fields:["id","title","created_time","updated_time","is_todo","parent_id","body"]}),o=D[t.parent_id]?D[t.parent_id].title:"",a=(t.body||"").length,n="ID: "+t.id+"\n"+(e.ctxRenameNote||"Title")+": "+t.title+"\n"+(e.newNotebook||"Notebook")+": "+o+"\n"+(e.sortUpdatedDesc?e.sortUpdatedDesc.replace(/[↓↑\u2193\u2191]\s*/,""):"Created")+": "+new Date(t.created_time).toLocaleString()+"\n"+(e.sortUpdatedAsc?e.sortUpdatedAsc.replace(/[↓↑\u2193\u2191]\s*/,""):"Updated")+": "+new Date(t.updated_time).toLocaleString()+"\nType: "+(t.is_todo?"To-do":"Note")+"\nSize: "+a+" chars";await v(t.title,n);break}case"deleteNote":{const t=await joplin.data.get(["notes",s],{fields:["title"]});await p(e.confirmDeleteNote+"\n\n"+t.title)&&await joplin.data.delete(["notes",s]);break}case"untagNote":if(t.tagId){await joplin.data.delete(["tags",t.tagId,"notes",s]);try{const e=await Q(t.tagId);await joplin.views.panels.postMessage(o,{name:"tagFolderNotes",tagId:t.tagId,notes:e})}catch(e){}}break;case"pinNote":k.some(e=>e.id===s)||(k.push({id:s,type:"note"}),await V());break;case"unpinNote":k=k.filter(e=>e.id!==s),await V()}else if("tag"===n)switch(a){case"renameTag":{const t=await joplin.data.get(["tags",s],{fields:["title"]}),o=await _(e.ctxRenameTag,t.title);o&&o.trim()&&await joplin.data.put(["tags",s],null,{title:o.trim()});break}case"deleteTag":{const t=await joplin.data.get(["tags",s],{fields:["title"]});await p(e.confirmDeleteTag+"\n\n"+t.title)&&await joplin.data.delete(["tags",s]);break}}else if("trashSection"===n){if("emptyTrash"===a&&await p(e.confirmEmptyTrash)){try{await joplin.commands.execute("emptyTrash")}catch(e){const t=await Y();for(const e of t.folders)0===e.depth&&await ee(e.id);for(const e of t.notes)try{await joplin.data.delete(["notes",e.id],{permanent:"1"})}catch(e){}}try{const e=await Y();await joplin.views.panels.postMessage(o,{name:"trashNotes",folders:e.folders,notes:e.notes})}catch(e){}}}else if("trashNote"===n||"trashFolder"===n){const t="trashFolder"===n;switch(a){case"restoreItem":try{await joplin.commands.execute(t?"restoreFolder":"restoreNote",[s])}catch(e){console.error("Joplin Explorer: restore error",e)}break;case"permanentDeleteItem":{const o=t?"folders":"notes";let a="";try{const e=await joplin.data.get([o,s],{fields:["title"],include_deleted:"1"});a=e?e.title:""}catch(e){}if(await p(e.confirmDeleteNote+"\n\n"+a))if(t)await ee(s);else try{await joplin.data.delete(["notes",s],{permanent:"1"})}catch(e){try{await joplin.commands.execute("permanentlyDeleteNote",[s])}catch(e){}}break}}try{const e=await Y();await joplin.views.panels.postMessage(o,{name:"trashNotes",folders:e.folders,notes:e.notes})}catch(e){}}await Z()}catch(e){console.error("Notes In List: context menu error",e)}}(t);else if("dragDrop"===t.name)await async function(e){try{const t=e.dragId,o=e.dragType,a=e.targetId,s=e.position;if("note"===o)if(D[a])await joplin.data.put(["notes",t],null,{parent_id:a});else{const e=await joplin.data.get(["notes",a],{fields:["parent_id"]});"manual"!==S||"above"!==s&&"below"!==s?await joplin.data.put(["notes",t],null,{parent_id:e.parent_id}):await async function(e,t,o){const a=(await joplin.data.get(["notes",t],{fields:["parent_id"]})).parent_id,s=T.filter(t=>t.parent_id===a&&t.id!==e).sort((e,t)=>{const o=e.order||0,a=t.order||0;return o!==a?a-o:(t.user_updated_time||0)-(e.user_updated_time||0)}),n=s.findIndex(e=>e.id===t),i=n<0?s.length:"above"===o?n:n+1,r=i>0?s[i-1]:null,l=i<s.length?s[i]:null,d=r?r.order||0:null,c=l?l.order||0:null,p=1e6;if(s.every(e=>0===(e.order||0))||null!==d&&null!==c&&d-c<2){const t=Date.now(),o=s.slice();o.splice(i,0,null);let n=t;const r=[];for(let e=0;e<o.length;e++){const a=t-e*p,s=o[e];null===s?n=a:r.push(joplin.data.put(["notes",s.id],null,{order:a}))}return await Promise.all(r),void await joplin.data.put(["notes",e],null,{parent_id:a,order:n})}let m;m=null!==d&&null!==c?(d+c)/2:null!==d?d-p:null!==c?c+p:Date.now(),await joplin.data.put(["notes",e],null,{parent_id:a,order:m})}(t,a,s)}else if("folder"===o){const e=!!D[a];"into"===s?e&&t!==a&&await joplin.data.put(["folders",t],null,{parent_id:a}):!e||"above"!==s&&"below"!==s||await async function(e,t,o){const a=D[t],s=D[e];if(!a||!s||e===t)return;const n=a.parent_id||"";let i=n;for(;i;){if(i===e)return;i=D[i]&&D[i].parent_id||""}const r=j.filter(t=>(t.parent_id||"")===n&&t.id!==e).sort((e,t)=>{const o=e.order||0,a=t.order||0;return o!==a?a-o:(e.title||"").localeCompare(t.title||"")}),l=r.findIndex(e=>e.id===t),d=l<0?r.length:"above"===o?l:l+1,c=d>0?r[d-1]:null,p=d<r.length?r[d]:null,m=c?c.order||0:null,u=p?p.order||0:null,f=r.every(e=>0===(e.order||0)),w=null!==m&&null!==u&&m-u<2,g=1e6;if((s.parent_id||"")!==n&&await joplin.data.put(["folders",e],null,{parent_id:n}),f||w){const t=Date.now(),o=r.slice();o.splice(d,0,null);for(let a=0;a<o.length;a++){const s=t-a*g,n=o[a];null===n?U[e]=s:U[n.id]=s}return void await K()}let h;h=null!==m&&null!==u?(m+u)/2:null!==m?m-g:null!==u?u+g:Date.now(),U[e]=h,await K()}(t,a,s)}await Z()}catch(e){console.error("Notes In List: drag drop error",e)}}(t);else if("dragToEmpty"===t.name)try{const o=t.dragId,a=t.dragType,s=await _(e.promptNewNotebookName,"");if(!s||!s.trim())return;const n=await joplin.data.post(["folders"],null,{title:s.trim()});O[n.id]=!0,delete N[n.id],"note"===a?await joplin.data.put(["notes",o],null,{parent_id:n.id}):"folder"===a&&o!==n.id&&await joplin.data.put(["folders",o],null,{parent_id:n.id}),await Z()}catch(e){console.error("Notes In List: drag to empty error",e)}});let ae="",se=null,ne="";async function ie(){const e=[];let t=1,o=!0;for(;o;){const a=await joplin.data.get(["folders"],{fields:["id","title","parent_id","icon"],page:t,limit:100});for(const t of a.items||[])e.push(t.id+""+(t.title||"")+""+(t.parent_id||"")+""+(t.icon||""));o=a.has_more,t++}const a=e.sort().join("\n"),s=""!==ne&&a!==ne;return ne=a,s}async function re(){try{if(!ae){const e=await joplin.data.get(["events"]);return ae=String(e.cursor||""),void await ie()}let e=!1,t=0;for(;t++<20;){const t=await joplin.data.get(["events"],{cursor:ae});for(const o of t.items||[])2===Number(o.type)&&o.item_id===b||(e=!0);if(t.cursor&&(ae=String(t.cursor)),!t.has_more)break}!e&&await ie()&&(e=!0),e&&W(300)}catch(e){se&&(clearInterval(se),se=null),console.warn("Joplin Explorer: change-events polling disabled",e)}}async function le(){const e=!1!==await joplin.settings.value("autoRefresh");se&&(clearInterval(se),se=null),e&&(ae="",await re(),se=setInterval(re,5e3))}await le(),await joplin.workspace.onNoteSelectionChange(async()=>{const e=await joplin.workspace.selectedNote();e&&e.id!==b&&(b=e.id,await joplin.views.panels.postMessage(o,{name:"selectNote",id:e.id}))}),await joplin.workspace.onNoteChange(async e=>{var t;e&&e.id?(t=e.id,G[t]=!0,B&&clearTimeout(B),B=setTimeout(async()=>{B=null;const e=Object.keys(G);G={};for(const t of e)await $(t)},600)):W()});try{await joplin.workspace.onSyncStart(async()=>{await joplin.views.panels.postMessage(o,{name:"syncState",state:"syncing"})})}catch(e){console.warn("Joplin Explorer: onSyncStart not available",e)}try{await joplin.workspace.onSyncComplete(async t=>{const a=!(!t||!t.withErrors);await Z(),await joplin.views.panels.postMessage(o,{name:"syncState",state:a?"error":"done"}),a&&await v(e.syncFailed,"Joplin reported errors during synchronisation. Open the Synchronisation Status screen (Tools → Synchronisation Status) to see the details.")})}catch(e){console.warn("Joplin Explorer: onSyncComplete not available",e)}await Z()}})})();
@@ -2,7 +2,7 @@
2
2
  "manifest_version": 1,
3
3
  "id": "com.github.joplin-explorer",
4
4
  "app_min_version": "2.6.0",
5
- "version": "1.5.7",
5
+ "version": "1.5.9",
6
6
  "name": "Joplin Explorer",
7
7
  "description": "A unified sidebar that displays notebooks and notes together in a single tree view",
8
8
  "author": "lim0513",
Binary file
@@ -336,7 +336,8 @@ html, body {
336
336
  align-items: center;
337
337
  padding: 4px 8px;
338
338
  gap: 5px;
339
- margin: 5px 4px 1px;
339
+ /* --sec-gap: sectionSpacing setting, set inline on the root (#9) */
340
+ margin: var(--sec-gap, 5px) 4px 1px;
340
341
  min-height: 24px;
341
342
  padding: 3px 8px;
342
343
  border-top: 1px solid rgba(127, 127, 127, 0.22);
@@ -394,7 +395,7 @@ html, body {
394
395
  /* The notebook tree has no header row - its wrapper draws the same
395
396
  * section-opening line as the headers do. */
396
397
  #main-tree {
397
- margin: 5px 4px 1px;
398
+ margin: var(--sec-gap, 5px) 4px 1px;
398
399
  padding-top: 4px;
399
400
  border-top: 1px solid rgba(127, 127, 127, 0.22);
400
401
  }
@@ -1 +1 @@
1
- var _savedScrollTop=0,_isFirstRender=!0;function postMsg(e){webviewApi.postMessage(e)}function currentSortMode(){var e=document.getElementById("notes-in-list-root");return e&&e.dataset.sort||""}postMsg({name:"panelReady"}),document.addEventListener("scroll",function(e){e.target&&"tree-container"===e.target.id&&(_savedScrollTop=e.target.scrollTop)},!0);var _observer=new MutationObserver(function(){var e=document.getElementById("tree-container");if(e)if(_isFirstRender){_isFirstRender=!1;var t=e.querySelector(".tree-item.note.selected");t&&setTimeout(function(){t.scrollIntoView({block:"nearest",behavior:"instant"})},30)}else e.scrollTop=_savedScrollTop});function loadI18n(){var e=document.getElementById("notes-in-list-root");if(e&&e.dataset.i18n)try{window._i18n=JSON.parse(e.dataset.i18n)}catch(e){}}function T(e){return window._i18n||loadI18n(),window._i18n&&window._i18n[e]||e}function getPinnedData(){var e=document.getElementById("notes-in-list-root");if(e&&e.dataset.pinned)try{return JSON.parse(e.dataset.pinned)}catch(e){}return[]}function isPinned(e){for(var t=getPinnedData(),a=0;a<t.length;a++)if(t[a].id===e)return!0;return!1}function showInlineInput(e,t,a){var n=document.getElementById("inline-input-overlay");n&&n.remove();var d=document.createElement("div");d.id="inline-input-overlay",d.className="inline-input-overlay",d.innerHTML='<div class="inline-input-dialog"><div class="inline-input-label">'+e+'</div><input class="inline-input-field" type="text" value="'+(t||"").replace(/"/g,"&quot;")+'" /><div class="inline-input-buttons"><button class="inline-input-ok">OK</button><button class="inline-input-cancel">'+(T("cancel")||"Cancel")+"</button></div></div>",document.body.appendChild(d);var s=d.querySelector(".inline-input-field");function o(){var e=s.value;d.remove(),a(e)}function i(){d.remove(),a(null)}s.focus(),s.select(),d.querySelector(".inline-input-ok").addEventListener("click",o),d.querySelector(".inline-input-cancel").addEventListener("click",i),s.addEventListener("keydown",function(e){"Enter"===e.key&&o(),"Escape"===e.key&&i()}),d.addEventListener("click",function(e){e.target===d&&i()})}function animateExpand(e){e&&(e.classList.remove("anim-expand"),e.offsetWidth,e.classList.add("anim-expand"))}function toggleFolderLocal(e,t){var a=e.classList.toggle("collapsed"),n=document.querySelector('.children[data-folder-id="'+t+'"]');n&&n.classList.toggle("collapsed",a),a||animateExpand(n);var d=e.querySelector(".toggle");d&&(d.textContent=a?"▶":"▼",d.classList.toggle("expanded",!a))}function collapseAllLocal(){var e=document.getElementById("tree-container");e&&(e.querySelectorAll(".tree-item.folder").forEach(function(e){if(!e.classList.contains("pinned-item")){e.classList.add("collapsed");var t=e.querySelector(".toggle");t&&(t.textContent="▶",t.classList.remove("expanded"))}}),e.querySelectorAll(".children").forEach(function(e){e.classList.add("collapsed")}))}function expandAllLocal(){var e=document.getElementById("tree-container");if(!e)return[];var t=[];return e.querySelectorAll(".tree-item.folder").forEach(function(e){if(!e.classList.contains("pinned-item")&&!e.classList.contains("tag-folder")){var a=e.dataset.id,n=document.querySelector('.children[data-folder-id="'+a+'"]'),d=n&&n.querySelector(".tree-item.folder"),s=e.querySelector(".toggle");d?(e.classList.remove("collapsed"),n&&n.classList.remove("collapsed"),s&&(s.textContent="▼",s.classList.add("expanded"))):(e.classList.add("collapsed"),n&&n.classList.add("collapsed"),s&&(s.textContent="▶",s.classList.remove("expanded")),a&&t.push(a))}}),t}function applyCollapsedSet(e){for(var t={},a=0;a<e.length;a++)t[e[a]]=!0;var n=[],d=document.getElementById("tree-container");return d?(d.querySelectorAll(".tree-item.folder").forEach(function(e){if(!e.classList.contains("pinned-item")&&!e.classList.contains("tag-folder")){var a=e.dataset.id,d=document.querySelector('.children[data-folder-id="'+a+'"]'),s=e.querySelector(".toggle"),o=!!t[a];e.classList.toggle("collapsed",o),d&&d.classList.toggle("collapsed",o),s&&(s.textContent=o?"▶":"▼",s.classList.toggle("expanded",!o)),o&&a&&n.push(a)}}),n):n}_observer.observe(document.body,{childList:!0,subtree:!0});var _collapseSnapshot=null;function expandAncestorsLocal(e){for(var t=e.closest(".children");t;){t.classList.remove("collapsed");var a=document.querySelector('.tree-item.folder:not(.pinned-item)[data-id="'+t.dataset.folderId+'"]');if(a){a.classList.remove("collapsed");var n=a.querySelector(".toggle");n&&(n.textContent="▼",n.classList.add("expanded"))}t=t.parentElement?t.parentElement.closest(".children"):null}}var _hoverTimer=null,_hoverNoteId="";function hidePreview(){_hoverTimer&&(clearTimeout(_hoverTimer),_hoverTimer=null),_hoverNoteId="";var e=document.getElementById("note-preview");e&&e.remove()}function hoverPreviewEnabled(){var e=document.getElementById("notes-in-list-root");return!e||"0"!==e.dataset.hoverPreview}function showPreview(e){if(e.id===_hoverNoteId&&!document.getElementById("ctx-menu")){var t=document.querySelector('.tree-item.note[data-id="'+e.id+'"]');if(t&&t.matches(":hover")){var a=document.getElementById("note-preview");a&&a.remove();var n=document.createElement("div");n.id="note-preview";var d=document.createElement("div");d.className="note-preview-title",d.textContent=e.title,n.appendChild(d);var s=document.createElement("div");s.className="note-preview-meta";for(var o=[T("pvType")+": "+(e.isTodo?T("pvTodo"):T("pvNote"))+" · "+T("pvSize")+": "+(e.size||0)+" "+T("pvChars"),T("pvCreated")+": "+p(e.created),T("pvUpdated")+": "+p(e.updated)],i=0;i<o.length;i++){var r=document.createElement("div");r.textContent=o[i],s.appendChild(r)}n.appendChild(s);var c=document.createElement("div");c.className="note-preview-body",c.textContent=e.snippet||"",e.snippet&&n.appendChild(c),document.body.appendChild(n);var l=t.getBoundingClientRect(),v=n.getBoundingClientRect(),m=l.bottom+4;m+v.height>window.innerHeight-8&&(m=Math.max(8,l.top-v.height-4)),n.style.top=m+"px",n.style.left=Math.max(8,Math.min(l.left+20,window.innerWidth-v.width-8))+"px"}}function p(e){if(!e)return"";var t=new Date(e);return t.getFullYear()+"-"+("0"+(t.getMonth()+1)).slice(-2)+"-"+("0"+t.getDate()).slice(-2)+" "+("0"+t.getHours()).slice(-2)+":"+("0"+t.getMinutes()).slice(-2)}}document.addEventListener("mouseover",function(e){if(hoverPreviewEnabled())if(document.getElementById("ctx-menu"))hidePreview();else{var t=e.target.closest?e.target.closest(".tree-item.note"):null;if(t){var a=t.dataset.id;a&&a!==_hoverNoteId&&(hidePreview(),_hoverNoteId=a,_hoverTimer=setTimeout(function(){_hoverNoteId!==a||document.querySelector(".tree-item.dragging")||postMsg({name:"notePreview",id:a})},450))}else hidePreview()}}),document.addEventListener("scroll",function(){hidePreview()},!0),document.addEventListener("mousedown",function(){hidePreview()}),document.addEventListener("dragstart",function(){hidePreview()}),window.addEventListener("blur",function(){var e=document.getElementById("ctx-menu");e&&e.remove(),hidePreview()}),document.addEventListener("click",function(e){var t=e.target.closest(".ctx-item");if(t){if(t.dataset.msg){postMsg({name:t.dataset.msg});var a=document.getElementById("ctx-menu");return void(a&&a.remove())}if(t.classList.contains("ctx-drill")){var n=document.getElementById("ctx-menu"),d=n?n.querySelector(".ctx-export-template"):null;return void(n&&d&&(window._ctxMainHtml=n.innerHTML,n.innerHTML='<div class="ctx-item ctx-back">◂ '+(d.dataset.title||"")+'</div><div class="ctx-sep"></div>'+d.innerHTML))}if(t.classList.contains("ctx-back")){var s=document.getElementById("ctx-menu");return void(s&&window._ctxMainHtml&&(s.innerHTML=window._ctxMainHtml))}if(!t.dataset.action)return;postMsg({name:"contextMenu",action:t.dataset.action,id:t.dataset.id,itemType:t.dataset.type,tagId:t.dataset.tagId,format:t.dataset.format});var o=document.getElementById("ctx-menu");o&&o.remove()}else{var i=document.getElementById("ctx-menu");i&&i.remove();var r=e.target.closest(".shared-badge");if(r){var c=r.closest(".tree-item");c&&c.dataset.id&&postMsg({name:"contextMenu",action:"publishNote",id:c.dataset.id,itemType:"note"})}else{var l=e.target.closest(".search-tag-item");if(l)l.dataset.tagId&&postMsg({name:"loadTagNotes",tagId:l.dataset.tagId});else{var v=e.target.closest(".search-folder-item");if(v)v.dataset.folderId&&postMsg({name:"locateFolder",folderId:v.dataset.folderId});else{var m=e.target.closest(".pinned-section-header");if(m){var p=m.classList.toggle("collapsed"),g=document.getElementById("pinned-body");g&&g.classList.toggle("collapsed",p),p||animateExpand(g);var u=m.querySelector(".toggle");return u&&(u.textContent=p?"▶":"▼"),void postMsg({name:"togglePinnedCollapse"})}var f=e.target.closest(".tags-section-header");if(f){var h=f.classList.toggle("collapsed"),y=document.getElementById("tags-body");y&&y.classList.toggle("collapsed",h),h||animateExpand(y);var x=f.querySelector(".toggle");return x&&(x.textContent=h?"▶":"▼"),void postMsg({name:"toggleTagsSection"})}var L=e.target.closest(".smart-section-header");if(L){var I=L.classList.toggle("collapsed"),E=document.getElementById("smart-body");E&&E.classList.toggle("collapsed",I),I||animateExpand(E);var b=L.querySelector(".toggle");return b&&(b.textContent=I?"▶":"▼"),void postMsg({name:"toggleSmartSection"})}var S=e.target.closest(".smart-folder");if(S){var w=S.dataset.smartId,M=document.querySelector('.smart-children[data-smart-id="'+w+'"]');if(!M)return;var N=M.classList.toggle("collapsed");S.classList.toggle("collapsed",N),N||animateExpand(M);var _=S.querySelector(".toggle");return _&&(_.textContent=N?"▶":"▼"),void(N||postMsg({name:"smartFolderNotes",smartId:w,query:S.dataset.query}))}var q=e.target.closest(".trash-section-header");if(q){var C=q.classList.toggle("collapsed"),B=document.getElementById("trash-children");B&&B.classList.toggle("collapsed",C),C||animateExpand(B);var D=q.querySelector(".toggle");return D&&(D.textContent=C?"▶":"▼"),postMsg({name:"toggleTrashSection"}),void(C||!B||B.dataset.loaded||postMsg({name:"trashNotes"}))}var A=e.target.closest(".tag-folder");if(A){var H=A.dataset.tagId,k=document.querySelector('.tag-children[data-tag-id="'+H+'"]');if(!k)return;var F=k.classList.toggle("collapsed");A.classList.toggle("collapsed",F),F||animateExpand(k);var R=A.querySelector(".toggle");return R&&(R.textContent=F?"▶":"▼"),void(F||k.dataset.loaded||postMsg({name:"tagFolderNotes",tagId:H}))}var P=e.target.closest(".search-section-header");if(P){var O=document.getElementById("search-section-"+P.dataset.section);if(O){var Y=P.querySelector(".section-toggle");O.classList.contains("collapsed")?(O.classList.remove("collapsed"),Y&&(Y.textContent="▼")):(O.classList.add("collapsed"),Y&&(Y.textContent="▶"))}}else{var j=e.target.closest(".tree-item");if(j){if("1"===j.dataset.trash){if("folder"===j.dataset.type){var J=document.querySelector('.trash-folder-children[data-folder-id="'+j.dataset.id+'"]');if(J){var W=J.classList.toggle("collapsed");W||animateExpand(J);var z=j.querySelector(".toggle");z&&(z.textContent=W?"▶":"▼"),W||J.dataset.loaded||postMsg({name:"trashFolderNotes",folderId:j.dataset.id})}}else"note"===j.dataset.type&&postMsg({name:"openNote",id:j.dataset.id});return}var V=j.dataset.type,U=j.dataset.id,X=j.classList.contains("pinned-item");"note"===V?(document.querySelectorAll(".tree-item.note.selected").forEach(function(e){e.classList.remove("selected")}),j.classList.add("selected"),postMsg({name:"openNote",id:U})):"folder"===V&&(X?postMsg({name:"locatePinnedFolder",folderId:U}):(toggleFolderLocal(j,U),postMsg({name:"toggleFolder",id:U})))}else{var $=e.target.closest("button");if($)switch($.id){case"btn-new":var K=document.getElementById("ctx-menu");if(K){K.remove();break}var G=document.getElementById("btn-new");if(!G)break;var Q=G.getBoundingClientRect();document.body.insertAdjacentHTML("beforeend",'<div id="ctx-menu" class="context-menu" style="left:'+Q.left+"px;top:"+(Q.bottom+2)+'px;"><div class="ctx-item" data-msg="newNotebook"><span class="ctx-icon">📁</span>'+T("newNotebook")+'</div><div class="ctx-item" data-msg="newNote"><span class="ctx-icon">📝</span>'+T("newNote")+'</div><div class="ctx-item" data-msg="newTodo"><span class="ctx-icon">☐</span>'+T("newTodo")+"</div></div>");break;case"btn-sort":postMsg({name:"cycleSort"});break;case"btn-collapse-all":var Z=document.getElementById("btn-collapse-all");if(Z&&"expand"===Z.dataset.mode){var ee,te=document.getElementById("notes-in-list-root"),ae=te&&te.dataset.expandMode||"restore";if("all"===ae)ee=applyCollapsedSet([]);else if("restore"===ae){var ne=_collapseSnapshot;if(!ne&&te)try{ne=JSON.parse(te.dataset.collapseSnapshot||"null")}catch(e){ne=null}ee=Array.isArray(ne)?applyCollapsedSet(ne):expandAllLocal()}else ee=expandAllLocal();postMsg({name:"expandAll",collapsedIds:ee}),Z.dataset.mode="collapse",Z.textContent="▲",Z.title=T("collapseAll")}else{var de=[];document.querySelectorAll("#tree-container .tree-item.folder").forEach(function(e){e.classList.contains("pinned-item")||e.classList.contains("tag-folder")||e.classList.contains("collapsed")&&e.dataset.id&&de.push(e.dataset.id)}),_collapseSnapshot=de,collapseAllLocal(),postMsg({name:"collapseAll",prevCollapsed:de}),Z&&(Z.dataset.mode="expand",Z.textContent="▼",Z.title=T("expandAll"))}break;case"btn-refresh":postMsg({name:"refreshView"});break;case"btn-sync":$.disabled||($.disabled=!0,$.classList.add("syncing"),$.textContent="🔄 "+T("syncing"),postMsg({name:"sync"}))}}}}}}}}),document.addEventListener("contextmenu",function(e){hidePreview();var t=document.getElementById("ctx-menu");if(t&&t.remove(),e.target.closest(".trash-section-header"))return e.preventDefault(),void document.body.insertAdjacentHTML("beforeend",'<div id="ctx-menu" class="context-menu" style="left:'+e.pageX+"px;top:"+e.pageY+'px;"><div class="ctx-item ctx-danger" data-action="emptyTrash" data-type="trashSection" data-id="trash">'+T("ctxEmptyTrash")+"</div></div>");var a=e.target.closest(".tree-item");if(a){e.preventDefault();var n=a.dataset.type,d=a.dataset.id;if("smart"!==n){var s="",o=a.querySelector(".label");o&&(s=o.textContent);var i='<div id="ctx-menu" class="context-menu" style="left:'+e.pageX+"px;top:"+e.pageY+'px;">';if("1"===a.dataset.trash){var r="folder"===n?"trashFolder":"trashNote";i+='<div class="ctx-item" data-action="restoreItem" data-id="'+d+'" data-type="'+r+'">'+T("ctxRestoreNote")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item ctx-danger" data-action="permanentDeleteItem" data-id="'+d+'" data-type="'+r+'">'+T("ctxPermanentDelete")+"</div>"}else if("folder"===n){var c=isPinned(d);i+='<div class="ctx-item" data-action="'+(c?"unpinFolder":"pinFolder")+'" data-id="'+d+'" data-type="folder">'+T(c?"ctxUnpin":"ctxPin")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item" data-action="newNote" data-id="'+d+'" data-type="folder">'+T("ctxNewNoteHere")+"</div>",i+='<div class="ctx-item" data-action="newTodo" data-id="'+d+'" data-type="folder">'+T("ctxNewTodoHere")+"</div>",i+='<div class="ctx-item" data-action="newSubNotebook" data-id="'+d+'" data-type="folder">'+T("ctxNewSubNotebook")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item" data-action="renameFolder" data-id="'+d+'" data-type="folder" data-title="'+s.replace(/"/g,"&quot;")+'">'+T("ctxRenameFolder")+"</div>",i+='<div class="ctx-item" data-action="exportFolder" data-id="'+d+'" data-type="folder">'+T("ctxExportFolder")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item ctx-danger" data-action="deleteFolder" data-id="'+d+'" data-type="folder">'+T("ctxDeleteFolder")+"</div>"}else if("note"===n){var l=isPinned(d);i+='<div class="ctx-item" data-action="'+(l?"unpinNote":"pinNote")+'" data-id="'+d+'" data-type="note">'+T(l?"ctxUnpin":"ctxPin")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item" data-action="openNote" data-id="'+d+'" data-type="note">'+T("ctxOpenNote")+"</div>",i+='<div class="ctx-item" data-action="openInNewWindow" data-id="'+d+'" data-type="note">'+T("ctxOpenInNewWindow")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item" data-action="setTags" data-id="'+d+'" data-type="note">'+T("ctxSetTags")+"</div>",i+='<div class="ctx-item" data-action="switchNoteType" data-id="'+d+'" data-type="note">'+T("ctxSwitchNoteType")+"</div>","1"===a.dataset.todo&&(i+='<div class="ctx-item" data-action="toggleTodo" data-id="'+d+'" data-type="note">'+T("ctxToggleTodo")+"</div>"),i+='<div class="ctx-item" data-action="moveToFolderDialog" data-id="'+d+'" data-type="note">'+T("ctxMoveToFolder")+"</div>",i+='<div class="ctx-item" data-action="duplicateNote" data-id="'+d+'" data-type="note">'+T("ctxDuplicateNote")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item" data-action="copyLink" data-id="'+d+'" data-type="note">'+T("ctxCopyLink")+"</div>",i+='<div class="ctx-item" data-action="copyExternalLink" data-id="'+d+'" data-type="note">'+T("ctxCopyExternalLink")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item" data-action="publishNote" data-id="'+d+'" data-type="note">'+T("ctxPublishNote")+"</div>",i+='<div class="ctx-item ctx-drill">'+T("ctxExport")+'<span class="ctx-sub-arrow">▸</span></div>',i+='<div class="ctx-export-template" style="display:none" data-title="'+T("ctxExport")+'"><div class="ctx-item" data-action="exportPdf" data-id="'+d+'" data-type="note">PDF</div><div class="ctx-item" data-action="exportNote" data-format="md" data-id="'+d+'" data-type="note">Markdown</div><div class="ctx-item" data-action="exportNote" data-format="md_frontmatter" data-id="'+d+'" data-type="note">Markdown + Front Matter</div><div class="ctx-item" data-action="exportNote" data-format="jex" data-id="'+d+'" data-type="note">JEX</div><div class="ctx-item" data-action="exportNote" data-format="html" data-id="'+d+'" data-type="note">HTML</div></div>',i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item" data-action="renameNote" data-id="'+d+'" data-type="note" data-title="'+s.replace(/"/g,"&quot;")+'">'+T("ctxRenameNote")+"</div>",i+='<div class="ctx-item" data-action="noteInfo" data-id="'+d+'" data-type="note">'+T("ctxNoteInfo")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item ctx-danger" data-action="deleteNote" data-id="'+d+'" data-type="note">'+T("ctxDeleteNote")+"</div>",a.dataset.tagId&&(i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item" data-action="untagNote" data-id="'+d+'" data-type="note" data-tag-id="'+a.dataset.tagId+'">'+T("ctxUntagNote")+"</div>")}else if("tag"===n){var v=a.dataset.tagId;i+='<div class="ctx-item" data-action="renameTag" data-id="'+v+'" data-type="tag">'+T("ctxRenameTag")+"</div>",i+='<div class="ctx-sep"></div>',i+='<div class="ctx-item ctx-danger" data-action="deleteTag" data-id="'+v+'" data-type="tag">'+T("ctxDeleteTag")+"</div>"}if(!((i+="</div>").indexOf("ctx-item")<0)){document.body.insertAdjacentHTML("beforeend",i);var m=document.getElementById("ctx-menu"),p=m.getBoundingClientRect();p.right>window.innerWidth&&(m.style.left=window.innerWidth-p.width-4+"px"),p.bottom>window.innerHeight&&(m.style.top=window.innerHeight-p.height-4+"px")}}}}),document.addEventListener("mousedown",function(e){if(!e.target.closest("#ctx-menu")){var t=document.getElementById("ctx-menu");t&&t.remove()}}),webviewApi.onMessage(function(e){if(e&&e.message){var t=e.message;if("syncState"===t.name){var a=document.getElementById("btn-sync");if(!a)return;"syncing"===t.state?(a.disabled=!0,a.classList.remove("sync-done","sync-error"),a.classList.add("syncing"),a.textContent="🔄 "+T("syncing")):"done"===t.state?(a.classList.remove("syncing","sync-error"),a.classList.add("sync-done"),a.textContent=T("syncDone"),setTimeout(function(){var e=document.getElementById("btn-sync");e&&(e.disabled=!1,e.classList.remove("sync-done"),e.textContent="🔄 "+T("sync"))},2e3)):"error"===t.state&&(a.classList.remove("syncing","sync-done"),a.classList.add("sync-error"),a.textContent=T("syncFailed"),setTimeout(function(){var e=document.getElementById("btn-sync");e&&(e.disabled=!1,e.classList.remove("sync-error"),e.textContent="🔄 "+T("sync"))},4e3))}else if("searchResults"===t.name){if(void 0!==t.searchId&&t.searchId!==_searchId)return;t.notes||t.tags||t.folders?renderSearchResults(t.notes||[],t.tags||[],t.folders||[],t.query):_searchMode&&exitSearchMode()}else if("tagFolderNotes"===t.name){var n=document.querySelector('.tag-children[data-tag-id="'+t.tagId+'"]');if(n){n.dataset.loaded="1";for(var d="",s=0;s<t.notes.length;s++){var o=t.notes[s],i=o.is_todo?o.todo_completed?"☑":"☐":"📝";d+='<div class="tree-item note tag-note" data-id="'+o.id+'" data-type="note" data-tag-id="'+t.tagId+'" data-todo="'+(o.is_todo?1:0)+'"><span class="icon note-icon">'+i+'</span><span class="label">'+escapeHtml(o.title)+"</span></div>"}t.notes.length||(d='<div class="tag-empty">—</div>'),n.innerHTML=d}}else if("trashNotes"===t.name){var r=document.getElementById("trash-children");if(r){r.dataset.loaded="1";for(var c="",l=t.folders||[],v=0;v<l.length;v++){var m=l[v],p=m.depth||0;c+='<div class="tree-item folder trash-note" style="padding-left:'+(34+16*p)+'px" data-id="'+m.id+'" data-type="folder" data-trash="1" data-depth="'+p+'"><span class="toggle">'+(m.hasNotes?"▶":"")+'</span><span class="icon">📁</span><span class="label">'+escapeHtml(m.title)+"</span></div>",m.hasNotes&&(c+='<div class="trash-folder-children collapsed" data-folder-id="'+m.id+'" data-depth="'+p+'"></div>')}for(var g=t.notes||[],u=0;u<g.length;u++){var f=g[u],h=f.is_todo?f.todo_completed?"☑":"☐":"📝";c+='<div class="tree-item note trash-note" style="padding-left:34px" data-id="'+f.id+'" data-type="note" data-trash="1"><span class="icon note-icon">'+h+'</span><span class="label">'+escapeHtml(f.title)+"</span></div>"}c||(c='<div class="tag-empty">—</div>'),r.innerHTML=c}}else if("smartFolderNotes"===t.name){var y=document.querySelector('.smart-children[data-smart-id="'+t.smartId+'"]');if(y){for(var x="",L=0;L<t.notes.length;L++){var I=t.notes[L],E=I.is_todo?I.todo_completed?"☑":"☐":"📝";x+='<div class="tree-item note smart-note" style="padding-left:44px" data-id="'+I.id+'" data-type="note" data-todo="'+(I.is_todo?1:0)+'"><span class="icon note-icon">'+E+'</span><span class="label">'+escapeHtml(I.title)+"</span></div>"}t.notes.length||(x='<div class="tag-empty">—</div>'),y.innerHTML=x}}else if("notePreview"===t.name)showPreview(t);else if("trashFolderNotes"===t.name){var b=document.querySelector('.trash-folder-children[data-folder-id="'+t.folderId+'"]');if(b){b.dataset.loaded="1";for(var S=34+16*(parseInt(b.dataset.depth||"0",10)+1),w="",M=0;M<t.notes.length;M++){var N=t.notes[M],_=N.is_todo?N.todo_completed?"☑":"☐":"📝";w+='<div class="tree-item note trash-note" style="padding-left:'+S+'px" data-id="'+N.id+'" data-type="note" data-trash="1"><span class="icon note-icon">'+_+'</span><span class="label">'+escapeHtml(N.title)+"</span></div>"}t.notes.length||(w='<div class="tag-empty" style="padding-left:'+S+'px">—</div>'),b.innerHTML=w}}else if("tagNotes"===t.name)expandTagNotes(t.tagId,t.notes);else if("scrollToFolder"===t.name)setTimeout(function(){var e=document.querySelector('.tree-item.folder:not(.pinned-item)[data-id="'+t.folderId+'"]');e&&(expandAncestorsLocal(e),e.scrollIntoView({block:"center",behavior:"smooth"}),e.classList.add("locate-flash"),setTimeout(function(){e.classList.remove("locate-flash")},1500))},80);else if("exitSearch"===t.name){var q=document.getElementById("search-input");q&&(q.value=""),_searchMode&&exitSearchMode()}else if("exitSearchAndLocate"===t.name){var C=document.getElementById("search-input");C&&(C.value=""),_searchMode=!1,showSearchContainer(!1),setTimeout(function(){var e=document.querySelector('.tree-item.folder[data-id="'+t.folderId+'"]');e&&(expandAncestorsLocal(e),e.scrollIntoView({block:"center",behavior:"smooth"}),e.classList.add("locate-flash"),setTimeout(function(){e.classList.remove("locate-flash")},1500))},80)}else if("copyText"===t.name)if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(t.text);else{var B=document.createElement("textarea");B.value=t.text,document.body.appendChild(B),B.select(),document.execCommand("copy"),B.remove()}else if("selectNote"===t.name){document.querySelectorAll(".tree-item.note.selected").forEach(function(e){e.classList.remove("selected")});var D=document.querySelector('.tree-item.note[data-id="'+t.id+'"]');D&&(D.classList.add("selected"),D.scrollIntoView({block:"nearest",behavior:"instant"}))}else"updateNote"===t.name&&document.querySelectorAll('.tree-item.note[data-id="'+t.id+'"]').forEach(function(e){var a=e.querySelector(".label");a&&(a.textContent=t.title);var n=e.querySelector(".search-result-title");n&&(n.textContent=t.title);var d=e.querySelector(".note-icon");d&&(d.textContent=t.icon),e.querySelectorAll(".todo-pie, .shared-badge").forEach(function(e){e.remove()}),t.badges&&e.insertAdjacentHTML("beforeend",t.badges)})}}),document.addEventListener("mousedown",function(e){var t=e.target.closest(".tree-item");t&&0===e.button&&t.setAttribute("draggable","true")}),document.addEventListener("dragstart",function(e){var t=e.target.closest(".tree-item");if(t)if(t.closest(".trash-children")||t.closest(".smart-section-body")||t.classList.contains("tag-folder"))e.preventDefault();else{var a=t.classList.contains("pinned-item");if(e.dataTransfer.setData("text/plain",JSON.stringify({id:t.dataset.id,type:t.dataset.type,pinned:a})),e.dataTransfer.effectAllowed="move",t.classList.add("dragging"),!a){var n=document.getElementById("tree-container");n&&n.classList.add("dragging-active")}}});var _dragScrollDir=0,_dragScrollRaf=null;function dragScrollStep(){var e=document.getElementById("tree-container");e&&_dragScrollDir?(e.scrollTop+=_dragScrollDir,_dragScrollRaf=requestAnimationFrame(dragScrollStep)):_dragScrollRaf=null}function updateDragScroll(e){var t=document.getElementById("tree-container");if(t){var a=t.getBoundingClientRect(),n=a.bottom,d=document.getElementById("drop-zone-empty");if(d&&t.classList.contains("dragging-active")){var s=d.getBoundingClientRect();s.height>0&&s.top>a.top&&(n=s.top)}var o=0;e<a.top+40?o=-Math.ceil((a.top+40-e)/4):e>n?o=0:e>n-40&&(o=Math.ceil((e-(n-40))/4)),_dragScrollDir=o,o&&!_dragScrollRaf&&(_dragScrollRaf=requestAnimationFrame(dragScrollStep))}else _dragScrollDir=0}function clearDropIndicators(){document.querySelectorAll(".drop-target").forEach(function(e){e.classList.remove("drop-target")}),document.querySelectorAll(".drop-above").forEach(function(e){e.classList.remove("drop-above")}),document.querySelectorAll(".drop-below").forEach(function(e){e.classList.remove("drop-below")})}function endDrag(){_dragScrollDir=0,clearDropIndicators();var e=document.getElementById("tree-container");e&&e.classList.remove("dragging-active")}document.addEventListener("dragend",function(e){var t=e.target.closest(".tree-item");t&&(t.classList.remove("dragging"),t.removeAttribute("draggable")),endDrag()}),document.addEventListener("dragover",function(e){document.querySelector(".tree-item.dragging")&&updateDragScroll(e.clientY);var t=e.target;if(t&&3===t.nodeType&&(t=t.parentElement),t){var a=t.closest(".tree-item");if(document.getElementById("tree-container"),t.closest("#drop-zone-empty"))document.querySelector(".tree-item.dragging.pinned-item")||(e.preventDefault(),e.dataTransfer.dropEffect="move");else{if(t.closest(".pinned-section-header"))return e.preventDefault(),e.dataTransfer.dropEffect="move",void clearDropIndicators();if(t.closest(".pinned-section-body")){if(document.querySelector(".tree-item.dragging.pinned-item")&&a&&a.classList.contains("pinned-item")){e.preventDefault(),e.dataTransfer.dropEffect="move",clearDropIndicators();var n=a.getBoundingClientRect();e.clientY-n.top<.5*n.height?a.classList.add("drop-above"):a.classList.add("drop-below")}}else{var d=t.closest(".tag-folder");if(d)document.querySelector(".tree-item.note.dragging")&&(e.preventDefault(),e.dataTransfer.dropEffect="move",clearDropIndicators(),d.classList.add("drop-target"));else if(!(t.closest(".tags-section-body")||t.closest(".tags-section-header")||t.closest(".trash-children")||t.closest(".trash-section-header")||t.closest(".smart-section-body")||t.closest(".smart-section-header"))&&a){var s=document.querySelector(".tree-item.dragging");if(!s||!s.classList.contains("pinned-item")){e.preventDefault(),e.dataTransfer.dropEffect="move",clearDropIndicators();var o=a.dataset.type,i=a.getBoundingClientRect(),r=e.clientY-i.top,c=i.height;"folder"===o?r<.25*c?a.classList.add("drop-above"):r>.75*c?a.classList.add("drop-below"):a.classList.add("drop-target"):"manual"===currentSortMode()?r<.5*c?a.classList.add("drop-above"):a.classList.add("drop-below"):a.classList.add("drop-target")}}}}}}),document.addEventListener("dragleave",function(e){var t=e.target.closest(".tree-item");t&&(t.classList.remove("drop-target"),t.classList.remove("drop-above"),t.classList.remove("drop-below"));var a=document.getElementById("tree-container");a&&e.target===a&&a.classList.remove("drop-empty")}),document.addEventListener("drop",function(e){e.preventDefault();var t=e.target;t&&3===t.nodeType&&(t=t.parentElement);var a,n=t?t.closest(".tree-item"):null;document.getElementById("tree-container");try{a=JSON.parse(e.dataTransfer.getData("text/plain"))}catch(e){return void endDrag()}var d=a.id,s=a.type,o=a.pinned;if(t&&t.closest("#drop-zone-empty")&&!o)return postMsg({name:"dragToEmpty",dragId:d,dragType:s}),void endDrag();if(t&&t.closest(".pinned-section-header")&&!o)return"note"===s?postMsg({name:"contextMenu",action:"pinNote",id:d,itemType:"note"}):"folder"===s&&postMsg({name:"contextMenu",action:"pinFolder",id:d,itemType:"folder"}),void endDrag();if(t&&t.closest(".pinned-section-body")&&o){var i=n&&n.classList.contains("pinned-item")?n:null;if(i&&i.dataset.id!==d){var r=i.getBoundingClientRect(),c=e.clientY-r.top<.5*r.height?"before":"after";postMsg({name:"reorderPinned",dragId:d,dragType:s,targetId:i.dataset.id,position:c})}endDrag()}else{var l=t?t.closest(".tag-folder"):null;if(l)return"note"===s&&postMsg({name:"tagNoteAdd",tagId:l.dataset.tagId,noteId:d}),void endDrag();if(t&&(t.closest(".tags-section-body")||t.closest(".tags-section-header")||t.closest(".trash-children")||t.closest(".trash-section-header")||t.closest(".smart-section-body")||t.closest(".smart-section-header")))endDrag();else if(o)endDrag();else if(n){var v=n.dataset.id,m=n.dataset.type;if(d!==v){var p=n.getBoundingClientRect(),g=e.clientY-p.top,u=p.height;postMsg("folder"===m?g>=.25*u&&g<=.75*u?{name:"dragDrop",dragId:d,dragType:s,targetId:v,position:"into"}:{name:"dragDrop",dragId:d,dragType:s,targetId:v,position:g<.25*u?"above":"below"}:"note"===s?{name:"dragDrop",dragId:d,dragType:s,targetId:v,position:g<.5*u?"above":"below"}:{name:"dragDrop",dragId:d,dragType:s,targetId:v,position:"into"}),endDrag()}else endDrag()}else endDrag()}});var _searchTimer=null,_searchMode=!1,_searchId=0;function escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function escapeHtml(e){return String(null==e?"":e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function highlightText(e,t){var a=escapeHtml(e);if(!t)return a;var n=new RegExp("("+escapeRegex(t)+")","gi");return a.replace(n,'<mark class="search-highlight">$1</mark>')}function showSearchContainer(e){var t=document.getElementById("tree-container"),a=document.getElementById("search-results");t&&(t.style.display=e?"none":""),a&&(a.style.display=e?"":"none")}function renderNoteItem(e,t){var a="📝";e.is_todo&&(a=e.todo_completed?"☑":"☐");var n='<div class="search-result-item tree-item note" data-id="'+e.id+'" data-type="note" data-todo="'+(e.is_todo?1:0)+'">';return n+='<span class="icon note-icon">'+a+"</span>",n+='<div class="search-result-content">',n+='<div class="search-result-title">'+highlightText(e.title,t)+"</div>",e.folderName&&(n+='<div class="search-result-folder">📂 '+escapeHtml(e.folderName)+"</div>"),e.snippet&&(n+='<div class="search-result-snippet">'+highlightText(e.snippet,t)+"</div>"),n+"</div></div>"}function renderSearchResults(e,t,a,n){var d=document.getElementById("search-results");if(d){showSearchContainer(!0);var s=e.length+t.length+a.length;if(0!==s){var o='<div class="search-status">'+T("searchResultCount").replace("{count}",s)+"</div>";if(a.length>0){o+=g("📁",T("searchSectionFolders"),a.length,"folders"),o+='<div class="search-section-body" id="search-section-folders">';for(var i=0;i<a.length;i++){var r=a[i],c=r.iconEmoji||"📁";o+='<div class="search-result-item search-folder-item" data-folder-id="'+r.id+'">',o+='<span class="icon">'+c+"</span>",o+='<div class="search-result-content">',o+='<div class="search-result-title">'+highlightText(r.title,n)+"</div>",o+="</div></div>"}o+="</div>"}if(e.length>0){o+=g("📝",T("searchSectionNotes"),e.length,"notes"),o+='<div class="search-section-body" id="search-section-notes">';for(var l=0;l<e.length;l++)o+=renderNoteItem(e[l],n);o+="</div>"}if(t.length>0){o+=g("🏷️",T("searchSectionTags"),t.length,"tags"),o+='<div class="search-section-body" id="search-section-tags">';for(var v=0;v<t.length;v++){var m=t[v],p=T("searchTagNoteCount").replace("{count}",m.noteCount);o+='<div class="search-result-item search-tag-item" data-tag-id="'+m.id+'">',o+='<span class="icon">🏷️</span>',o+='<div class="search-result-content">',o+='<div class="search-result-title">'+highlightText(m.title,n)+"</div>",o+='<div class="search-result-folder">'+p+"</div>",o+="</div>",o+='<span class="tag-expand-arrow">▶</span>',o+="</div>",o+='<div class="tag-notes-container" id="tag-notes-'+m.id+'"></div>'}o+="</div>"}d.innerHTML=o,_searchMode=!0}else d.innerHTML='<div class="search-status">'+T("searchNoResult")+"</div>"}function g(e,t,a,n){return'<div class="search-section-header" data-section="'+n+'"><span class="section-toggle">▼</span> '+e+" "+t+" ("+a+")</div>"}}function expandTagNotes(e,t){var a=document.getElementById("tag-notes-"+e);if(a){var n;if(a.children.length>0)return a.innerHTML="",void((n=document.querySelector('.search-tag-item[data-tag-id="'+e+'"] .tag-expand-arrow'))&&n.classList.remove("expanded"));for(var d="",s=0;s<t.length;s++)d+=renderNoteItem(t[s],"");0===t.length&&(d='<div class="search-status" style="padding-left:30px;">'+T("searchNoResult")+"</div>"),a.innerHTML=d,(n=document.querySelector('.search-tag-item[data-tag-id="'+e+'"] .tag-expand-arrow'))&&n.classList.add("expanded")}}function exitSearchMode(){_searchMode=!1,showSearchContainer(!1)}document.addEventListener("input",function(e){if("search-input"===e.target.id){var t=e.target.value.trim();_searchTimer&&clearTimeout(_searchTimer);var a=++_searchId;if(t){_searchMode=!0;var n=document.getElementById("search-results");n&&(n.innerHTML='<div class="search-status">'+T("searching")+"</div>"),showSearchContainer(!0),_searchTimer=setTimeout(function(){postMsg({name:"search",query:t,searchId:a})},400)}else _searchMode&&exitSearchMode()}}),document.addEventListener("keydown",function(e){if("Escape"===e.key){var t=document.getElementById("search-input");t&&t.value&&(t.value="",_searchMode&&exitSearchMode())}});
1
+ var _savedScrollTop=0,_isFirstRender=!0;function postMsg(e){webviewApi.postMessage(e)}function currentSortMode(){var e=document.getElementById("notes-in-list-root");return e&&e.dataset.sort||""}postMsg({name:"panelReady"}),document.addEventListener("scroll",function(e){e.target&&"tree-container"===e.target.id&&(_savedScrollTop=e.target.scrollTop)},!0);var _observer=new MutationObserver(function(){var e=document.getElementById("tree-container");if(e)if(_isFirstRender){_isFirstRender=!1;var t=e.querySelector(".tree-item.note.selected");t&&setTimeout(function(){t.scrollIntoView({block:"nearest",behavior:"instant"})},30)}else e.scrollTop=_savedScrollTop});function loadI18n(){var e=document.getElementById("notes-in-list-root");if(e&&e.dataset.i18n)try{window._i18n=JSON.parse(e.dataset.i18n)}catch(e){}}function T(e){return window._i18n||loadI18n(),window._i18n&&window._i18n[e]||e}function getPinnedData(){var e=document.getElementById("notes-in-list-root");if(e&&e.dataset.pinned)try{return JSON.parse(e.dataset.pinned)}catch(e){}return[]}function isPinned(e){for(var t=getPinnedData(),a=0;a<t.length;a++)if(t[a].id===e)return!0;return!1}function showInlineInput(e,t,a){var n=document.getElementById("inline-input-overlay");n&&n.remove();var d=document.createElement("div");d.id="inline-input-overlay",d.className="inline-input-overlay",d.innerHTML='<div class="inline-input-dialog"><div class="inline-input-label">'+e+'</div><input class="inline-input-field" type="text" value="'+(t||"").replace(/"/g,"&quot;")+'" /><div class="inline-input-buttons"><button class="inline-input-ok">OK</button><button class="inline-input-cancel">'+(T("cancel")||"Cancel")+"</button></div></div>",document.body.appendChild(d);var o=d.querySelector(".inline-input-field");function s(){var e=o.value;d.remove(),a(e)}function r(){d.remove(),a(null)}o.focus(),o.select(),d.querySelector(".inline-input-ok").addEventListener("click",s),d.querySelector(".inline-input-cancel").addEventListener("click",r),o.addEventListener("keydown",function(e){"Enter"===e.key&&s(),"Escape"===e.key&&r()}),d.addEventListener("click",function(e){e.target===d&&r()})}function animateExpand(e){e&&(e.classList.remove("anim-expand"),e.offsetWidth,e.classList.add("anim-expand"))}function toggleFolderLocal(e,t){var a=e.classList.toggle("collapsed"),n=document.querySelector('.children[data-folder-id="'+t+'"]');n&&n.classList.toggle("collapsed",a),a||animateExpand(n);var d=e.querySelector(".toggle");d&&(d.textContent=a?"▶":"▼",d.classList.toggle("expanded",!a))}function collapseAllLocal(){var e=document.getElementById("main-tree");e&&(e.querySelectorAll(".tree-item.folder").forEach(function(e){e.classList.add("collapsed");var t=e.querySelector(".toggle");t&&(t.textContent="▶",t.classList.remove("expanded"))}),e.querySelectorAll(".children").forEach(function(e){e.classList.add("collapsed")}))}function expandAllLocal(){var e=document.getElementById("main-tree");if(!e)return[];var t=[];return e.querySelectorAll(".tree-item.folder").forEach(function(e){var a=e.dataset.id,n=document.querySelector('.children[data-folder-id="'+a+'"]'),d=n&&n.querySelector(".tree-item.folder"),o=e.querySelector(".toggle");d?(e.classList.remove("collapsed"),n&&n.classList.remove("collapsed"),o&&(o.textContent="▼",o.classList.add("expanded"))):(e.classList.add("collapsed"),n&&n.classList.add("collapsed"),o&&(o.textContent="▶",o.classList.remove("expanded")),a&&t.push(a))}),t}function applyCollapsedSet(e){for(var t={},a=0;a<e.length;a++)t[e[a]]=!0;var n=[],d=document.getElementById("main-tree");return d?(d.querySelectorAll(".tree-item.folder").forEach(function(e){var a=e.dataset.id,d=document.querySelector('.children[data-folder-id="'+a+'"]'),o=e.querySelector(".toggle"),s=!!t[a];e.classList.toggle("collapsed",s),d&&d.classList.toggle("collapsed",s),o&&(o.textContent=s?"▶":"▼",o.classList.toggle("expanded",!s)),s&&a&&n.push(a)}),n):n}_observer.observe(document.body,{childList:!0,subtree:!0});var _collapseSnapshot=null;function expandAncestorsLocal(e){for(var t=e.closest(".children");t;){t.classList.remove("collapsed");var a=document.querySelector('.tree-item.folder:not(.pinned-item)[data-id="'+t.dataset.folderId+'"]');if(a){a.classList.remove("collapsed");var n=a.querySelector(".toggle");n&&(n.textContent="▼",n.classList.add("expanded"))}t=t.parentElement?t.parentElement.closest(".children"):null}}var _hoverTimer=null,_hoverNoteId="";function hidePreview(){_hoverTimer&&(clearTimeout(_hoverTimer),_hoverTimer=null),_hoverNoteId="";var e=document.getElementById("note-preview");e&&e.remove()}function hoverPreviewEnabled(){var e=document.getElementById("notes-in-list-root");return!e||"0"!==e.dataset.hoverPreview}function showPreview(e){if(e.id===_hoverNoteId&&!document.getElementById("ctx-menu")){var t=document.querySelector('.tree-item.note[data-id="'+e.id+'"]');if(t&&t.matches(":hover")){var a=document.getElementById("note-preview");a&&a.remove();var n=document.createElement("div");n.id="note-preview";var d=document.createElement("div");d.className="note-preview-title",d.textContent=e.title,n.appendChild(d);var o=document.createElement("div");o.className="note-preview-meta";for(var s=[T("pvType")+": "+(e.isTodo?T("pvTodo"):T("pvNote"))+" · "+T("pvSize")+": "+(e.size||0)+" "+T("pvChars"),T("pvCreated")+": "+p(e.created),T("pvUpdated")+": "+p(e.updated)],r=0;r<s.length;r++){var i=document.createElement("div");i.textContent=s[r],o.appendChild(i)}n.appendChild(o);var l=document.createElement("div");l.className="note-preview-body",l.textContent=e.snippet||"",e.snippet&&n.appendChild(l),document.body.appendChild(n);var c=t.getBoundingClientRect(),m=n.getBoundingClientRect(),v=c.bottom+4;v+m.height>window.innerHeight-8&&(v=Math.max(8,c.top-m.height-4)),n.style.top=v+"px",n.style.left=Math.max(8,Math.min(c.left+20,window.innerWidth-m.width-8))+"px"}}function p(e){if(!e)return"";var t=new Date(e);return t.getFullYear()+"-"+("0"+(t.getMonth()+1)).slice(-2)+"-"+("0"+t.getDate()).slice(-2)+" "+("0"+t.getHours()).slice(-2)+":"+("0"+t.getMinutes()).slice(-2)}}document.addEventListener("mouseover",function(e){if(hoverPreviewEnabled())if(document.getElementById("ctx-menu"))hidePreview();else{var t=e.target.closest?e.target.closest(".tree-item.note"):null;if(t){var a=t.dataset.id;a&&a!==_hoverNoteId&&(hidePreview(),_hoverNoteId=a,_hoverTimer=setTimeout(function(){_hoverNoteId!==a||document.querySelector(".tree-item.dragging")||postMsg({name:"notePreview",id:a})},450))}else hidePreview()}}),document.addEventListener("scroll",function(){hidePreview()},!0),document.addEventListener("mousedown",function(){hidePreview()}),document.addEventListener("dragstart",function(){hidePreview()}),window.addEventListener("blur",function(){var e=document.getElementById("ctx-menu");e&&e.remove(),hidePreview()}),document.addEventListener("click",function(e){var t=e.target.closest(".ctx-item");if(t){if(t.dataset.msg){postMsg({name:t.dataset.msg});var a=document.getElementById("ctx-menu");return void(a&&a.remove())}if(t.classList.contains("ctx-drill")){var n=document.getElementById("ctx-menu"),d=n?n.querySelector(".ctx-export-template"):null;return void(n&&d&&(window._ctxMainHtml=n.innerHTML,n.innerHTML='<div class="ctx-item ctx-back">◂ '+(d.dataset.title||"")+'</div><div class="ctx-sep"></div>'+d.innerHTML))}if(t.classList.contains("ctx-back")){var o=document.getElementById("ctx-menu");return void(o&&window._ctxMainHtml&&(o.innerHTML=window._ctxMainHtml))}if(!t.dataset.action)return;postMsg({name:"contextMenu",action:t.dataset.action,id:t.dataset.id,itemType:t.dataset.type,tagId:t.dataset.tagId,format:t.dataset.format});var s=document.getElementById("ctx-menu");s&&s.remove()}else{var r=document.getElementById("ctx-menu");r&&r.remove();var i=e.target.closest(".shared-badge");if(i){var l=i.closest(".tree-item");l&&l.dataset.id&&postMsg({name:"contextMenu",action:"publishNote",id:l.dataset.id,itemType:"note"})}else{var c=e.target.closest(".search-tag-item");if(c)c.dataset.tagId&&postMsg({name:"loadTagNotes",tagId:c.dataset.tagId});else{var m=e.target.closest(".search-folder-item");if(m)m.dataset.folderId&&postMsg({name:"locateFolder",folderId:m.dataset.folderId});else{var v=e.target.closest(".pinned-section-header");if(v){var p=v.classList.toggle("collapsed"),g=document.getElementById("pinned-body");g&&g.classList.toggle("collapsed",p),p||animateExpand(g);var u=v.querySelector(".toggle");return u&&(u.textContent=p?"▶":"▼"),void postMsg({name:"togglePinnedCollapse"})}var f=e.target.closest(".tags-section-header");if(f){var h=f.classList.toggle("collapsed"),y=document.getElementById("tags-body");y&&y.classList.toggle("collapsed",h),h||animateExpand(y);var x=f.querySelector(".toggle");return x&&(x.textContent=h?"▶":"▼"),void postMsg({name:"toggleTagsSection"})}var L=e.target.closest(".smart-section-header");if(L){var I=L.classList.toggle("collapsed"),S=document.getElementById("smart-body");S&&S.classList.toggle("collapsed",I),I||animateExpand(S);var E=L.querySelector(".toggle");return E&&(E.textContent=I?"▶":"▼"),void postMsg({name:"toggleSmartSection"})}var b=e.target.closest(".smart-folder");if(b){var w=b.dataset.smartId,M=document.querySelector('.smart-children[data-smart-id="'+w+'"]');if(!M)return;var N=M.classList.toggle("collapsed");b.classList.toggle("collapsed",N),N||animateExpand(M);var _=b.querySelector(".toggle");return _&&(_.textContent=N?"▶":"▼"),void(N||postMsg({name:"smartFolderNotes",smartId:w,query:b.dataset.query}))}var q=e.target.closest(".trash-section-header");if(q){var C=q.classList.toggle("collapsed"),B=document.getElementById("trash-children");B&&B.classList.toggle("collapsed",C),C||animateExpand(B);var D=q.querySelector(".toggle");return D&&(D.textContent=C?"▶":"▼"),postMsg({name:"toggleTrashSection"}),void(C||!B||B.dataset.loaded||postMsg({name:"trashNotes"}))}var A=e.target.closest(".tag-folder");if(A){var H=A.dataset.tagId,k=document.querySelector('.tag-children[data-tag-id="'+H+'"]');if(!k)return;var F=k.classList.toggle("collapsed");A.classList.toggle("collapsed",F),F||animateExpand(k);var R=A.querySelector(".toggle");return R&&(R.textContent=F?"▶":"▼"),void(F||k.dataset.loaded||postMsg({name:"tagFolderNotes",tagId:H}))}var P=e.target.closest(".search-section-header");if(P){var O=document.getElementById("search-section-"+P.dataset.section);if(O){var Y=P.querySelector(".section-toggle");O.classList.contains("collapsed")?(O.classList.remove("collapsed"),Y&&(Y.textContent="▼")):(O.classList.add("collapsed"),Y&&(Y.textContent="▶"))}}else{var j=e.target.closest(".tree-item");if(j){if("1"===j.dataset.trash){if("folder"===j.dataset.type){var J=document.querySelector('.trash-folder-children[data-folder-id="'+j.dataset.id+'"]');if(J){var W=J.classList.toggle("collapsed");W||animateExpand(J);var z=j.querySelector(".toggle");z&&(z.textContent=W?"▶":"▼"),W||J.dataset.loaded||postMsg({name:"trashFolderNotes",folderId:j.dataset.id})}}else"note"===j.dataset.type&&postMsg({name:"openNote",id:j.dataset.id});return}var V=j.dataset.type,U=j.dataset.id,X=j.classList.contains("pinned-item");"note"===V?(document.querySelectorAll(".tree-item.note.selected").forEach(function(e){e.classList.remove("selected")}),j.classList.add("selected"),postMsg({name:"openNote",id:U})):"folder"===V&&(X?postMsg({name:"locatePinnedFolder",folderId:U}):(toggleFolderLocal(j,U),postMsg({name:"toggleFolder",id:U})))}else{var $=e.target.closest("button");if($)switch($.id){case"btn-new":var K=document.getElementById("ctx-menu");if(K){K.remove();break}var G=document.getElementById("btn-new");if(!G)break;var Q=G.getBoundingClientRect();document.body.insertAdjacentHTML("beforeend",'<div id="ctx-menu" class="context-menu" style="left:'+Q.left+"px;top:"+(Q.bottom+2)+'px;"><div class="ctx-item" data-msg="newNotebook"><span class="ctx-icon">📁</span>'+T("newNotebook")+'</div><div class="ctx-item" data-msg="newNote"><span class="ctx-icon">📝</span>'+T("newNote")+'</div><div class="ctx-item" data-msg="newTodo"><span class="ctx-icon">☐</span>'+T("newTodo")+"</div></div>");break;case"btn-sort":postMsg({name:"cycleSort"});break;case"btn-collapse-all":var Z=document.getElementById("btn-collapse-all");if(Z&&"expand"===Z.dataset.mode){var ee,te=document.getElementById("notes-in-list-root"),ae=te&&te.dataset.expandMode||"restore";if("all"===ae)ee=applyCollapsedSet([]);else if("restore"===ae){var ne=_collapseSnapshot;if(!ne&&te)try{ne=JSON.parse(te.dataset.collapseSnapshot||"null")}catch(e){ne=null}ee=Array.isArray(ne)?applyCollapsedSet(ne):expandAllLocal()}else ee=expandAllLocal();var de=document.querySelectorAll("#main-tree .tree-item.folder").length;de>0&&ee.length>=de&&(ee=applyCollapsedSet([])),postMsg({name:"expandAll",collapsedIds:ee}),Z.dataset.mode="collapse",Z.textContent="▲",Z.title=T("collapseAll")}else{var oe=[],se=0;document.querySelectorAll("#main-tree .tree-item.folder").forEach(function(e){e.dataset.id&&(se++,e.classList.contains("collapsed")&&oe.push(e.dataset.id))}),collapseAllLocal(),oe.length>=se&&se>0?postMsg({name:"collapseAll"}):(_collapseSnapshot=oe,postMsg({name:"collapseAll",prevCollapsed:oe})),Z&&(Z.dataset.mode="expand",Z.textContent="▼",Z.title=T("expandAll"))}break;case"btn-refresh":postMsg({name:"refreshView"});break;case"btn-sync":$.disabled||($.disabled=!0,$.classList.add("syncing"),$.textContent="🔄 "+T("syncing"),postMsg({name:"sync"}))}}}}}}}}),document.addEventListener("contextmenu",function(e){hidePreview();var t=document.getElementById("ctx-menu");if(t&&t.remove(),e.target.closest(".trash-section-header"))return e.preventDefault(),void document.body.insertAdjacentHTML("beforeend",'<div id="ctx-menu" class="context-menu" style="left:'+e.pageX+"px;top:"+e.pageY+'px;"><div class="ctx-item ctx-danger" data-action="emptyTrash" data-type="trashSection" data-id="trash">'+T("ctxEmptyTrash")+"</div></div>");var a=e.target.closest(".tree-item");if(a){e.preventDefault();var n=a.dataset.type,d=a.dataset.id;if("smart"!==n){var o="",s=a.querySelector(".label");s&&(o=s.textContent);var r='<div id="ctx-menu" class="context-menu" style="left:'+e.pageX+"px;top:"+e.pageY+'px;">';if("1"===a.dataset.trash){var i="folder"===n?"trashFolder":"trashNote";r+='<div class="ctx-item" data-action="restoreItem" data-id="'+d+'" data-type="'+i+'">'+T("ctxRestoreNote")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item ctx-danger" data-action="permanentDeleteItem" data-id="'+d+'" data-type="'+i+'">'+T("ctxPermanentDelete")+"</div>"}else if("folder"===n){var l=isPinned(d);r+='<div class="ctx-item" data-action="'+(l?"unpinFolder":"pinFolder")+'" data-id="'+d+'" data-type="folder">'+T(l?"ctxUnpin":"ctxPin")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item" data-action="newNote" data-id="'+d+'" data-type="folder">'+T("ctxNewNoteHere")+"</div>",r+='<div class="ctx-item" data-action="newTodo" data-id="'+d+'" data-type="folder">'+T("ctxNewTodoHere")+"</div>",r+='<div class="ctx-item" data-action="newSubNotebook" data-id="'+d+'" data-type="folder">'+T("ctxNewSubNotebook")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item" data-action="renameFolder" data-id="'+d+'" data-type="folder" data-title="'+o.replace(/"/g,"&quot;")+'">'+T("ctxRenameFolder")+"</div>",r+='<div class="ctx-item" data-action="exportFolder" data-id="'+d+'" data-type="folder">'+T("ctxExportFolder")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item ctx-danger" data-action="deleteFolder" data-id="'+d+'" data-type="folder">'+T("ctxDeleteFolder")+"</div>"}else if("note"===n){var c=isPinned(d);r+='<div class="ctx-item" data-action="'+(c?"unpinNote":"pinNote")+'" data-id="'+d+'" data-type="note">'+T(c?"ctxUnpin":"ctxPin")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item" data-action="openNote" data-id="'+d+'" data-type="note">'+T("ctxOpenNote")+"</div>",r+='<div class="ctx-item" data-action="openInNewWindow" data-id="'+d+'" data-type="note">'+T("ctxOpenInNewWindow")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item" data-action="setTags" data-id="'+d+'" data-type="note">'+T("ctxSetTags")+"</div>",r+='<div class="ctx-item" data-action="switchNoteType" data-id="'+d+'" data-type="note">'+T("ctxSwitchNoteType")+"</div>","1"===a.dataset.todo&&(r+='<div class="ctx-item" data-action="toggleTodo" data-id="'+d+'" data-type="note">'+T("ctxToggleTodo")+"</div>"),r+='<div class="ctx-item" data-action="moveToFolderDialog" data-id="'+d+'" data-type="note">'+T("ctxMoveToFolder")+"</div>",r+='<div class="ctx-item" data-action="duplicateNote" data-id="'+d+'" data-type="note">'+T("ctxDuplicateNote")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item" data-action="copyLink" data-id="'+d+'" data-type="note">'+T("ctxCopyLink")+"</div>",r+='<div class="ctx-item" data-action="copyExternalLink" data-id="'+d+'" data-type="note">'+T("ctxCopyExternalLink")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item" data-action="publishNote" data-id="'+d+'" data-type="note">'+T("ctxPublishNote")+"</div>",r+='<div class="ctx-item ctx-drill">'+T("ctxExport")+'<span class="ctx-sub-arrow">▸</span></div>',r+='<div class="ctx-export-template" style="display:none" data-title="'+T("ctxExport")+'"><div class="ctx-item" data-action="exportPdf" data-id="'+d+'" data-type="note">PDF</div><div class="ctx-item" data-action="exportNote" data-format="md" data-id="'+d+'" data-type="note">Markdown</div><div class="ctx-item" data-action="exportNote" data-format="md_frontmatter" data-id="'+d+'" data-type="note">Markdown + Front Matter</div><div class="ctx-item" data-action="exportNote" data-format="jex" data-id="'+d+'" data-type="note">JEX</div><div class="ctx-item" data-action="exportNote" data-format="html" data-id="'+d+'" data-type="note">HTML</div></div>',r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item" data-action="renameNote" data-id="'+d+'" data-type="note" data-title="'+o.replace(/"/g,"&quot;")+'">'+T("ctxRenameNote")+"</div>",r+='<div class="ctx-item" data-action="noteInfo" data-id="'+d+'" data-type="note">'+T("ctxNoteInfo")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item ctx-danger" data-action="deleteNote" data-id="'+d+'" data-type="note">'+T("ctxDeleteNote")+"</div>",a.dataset.tagId&&(r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item" data-action="untagNote" data-id="'+d+'" data-type="note" data-tag-id="'+a.dataset.tagId+'">'+T("ctxUntagNote")+"</div>")}else if("tag"===n){var m=a.dataset.tagId;r+='<div class="ctx-item" data-action="renameTag" data-id="'+m+'" data-type="tag">'+T("ctxRenameTag")+"</div>",r+='<div class="ctx-sep"></div>',r+='<div class="ctx-item ctx-danger" data-action="deleteTag" data-id="'+m+'" data-type="tag">'+T("ctxDeleteTag")+"</div>"}if(!((r+="</div>").indexOf("ctx-item")<0)){document.body.insertAdjacentHTML("beforeend",r);var v=document.getElementById("ctx-menu"),p=v.getBoundingClientRect();p.right>window.innerWidth&&(v.style.left=window.innerWidth-p.width-4+"px"),p.bottom>window.innerHeight&&(v.style.top=window.innerHeight-p.height-4+"px")}}}}),document.addEventListener("mousedown",function(e){if(!e.target.closest("#ctx-menu")){var t=document.getElementById("ctx-menu");t&&t.remove()}}),webviewApi.onMessage(function(e){if(e&&e.message){var t=e.message;if("syncState"===t.name){var a=document.getElementById("btn-sync");if(!a)return;"syncing"===t.state?(a.disabled=!0,a.classList.remove("sync-done","sync-error"),a.classList.add("syncing"),a.textContent="🔄 "+T("syncing")):"done"===t.state?(a.classList.remove("syncing","sync-error"),a.classList.add("sync-done"),a.textContent=T("syncDone"),setTimeout(function(){var e=document.getElementById("btn-sync");e&&(e.disabled=!1,e.classList.remove("sync-done"),e.textContent="🔄 "+T("sync"))},2e3)):"error"===t.state&&(a.classList.remove("syncing","sync-done"),a.classList.add("sync-error"),a.textContent=T("syncFailed"),setTimeout(function(){var e=document.getElementById("btn-sync");e&&(e.disabled=!1,e.classList.remove("sync-error"),e.textContent="🔄 "+T("sync"))},4e3))}else if("searchResults"===t.name){if(void 0!==t.searchId&&t.searchId!==_searchId)return;t.notes||t.tags||t.folders?renderSearchResults(t.notes||[],t.tags||[],t.folders||[],t.query):_searchMode&&exitSearchMode()}else if("tagFolderNotes"===t.name){var n=document.querySelector('.tag-children[data-tag-id="'+t.tagId+'"]');if(n){n.dataset.loaded="1";for(var d="",o=0;o<t.notes.length;o++){var s=t.notes[o],r=s.is_todo?s.todo_completed?"☑":"☐":"📝";d+='<div class="tree-item note tag-note" data-id="'+s.id+'" data-type="note" data-tag-id="'+t.tagId+'" data-todo="'+(s.is_todo?1:0)+'"><span class="icon note-icon">'+r+'</span><span class="label">'+escapeHtml(s.title)+"</span></div>"}t.notes.length||(d='<div class="tag-empty">—</div>'),n.innerHTML=d}}else if("trashNotes"===t.name){var i=document.getElementById("trash-children");if(i){i.dataset.loaded="1";for(var l="",c=t.folders||[],m=0;m<c.length;m++){var v=c[m],p=v.depth||0;l+='<div class="tree-item folder trash-note" style="padding-left:'+(34+16*p)+'px" data-id="'+v.id+'" data-type="folder" data-trash="1" data-depth="'+p+'"><span class="toggle">'+(v.hasNotes?"▶":"")+'</span><span class="icon">📁</span><span class="label">'+escapeHtml(v.title)+"</span></div>",v.hasNotes&&(l+='<div class="trash-folder-children collapsed" data-folder-id="'+v.id+'" data-depth="'+p+'"></div>')}for(var g=t.notes||[],u=0;u<g.length;u++){var f=g[u],h=f.is_todo?f.todo_completed?"☑":"☐":"📝";l+='<div class="tree-item note trash-note" style="padding-left:34px" data-id="'+f.id+'" data-type="note" data-trash="1"><span class="icon note-icon">'+h+'</span><span class="label">'+escapeHtml(f.title)+"</span></div>"}l||(l='<div class="tag-empty">—</div>'),i.innerHTML=l}}else if("smartFolderNotes"===t.name){var y=document.querySelector('.smart-children[data-smart-id="'+t.smartId+'"]');if(y){for(var x="",L=0;L<t.notes.length;L++){var I=t.notes[L],S=I.is_todo?I.todo_completed?"☑":"☐":"📝";x+='<div class="tree-item note smart-note" style="padding-left:44px" data-id="'+I.id+'" data-type="note" data-todo="'+(I.is_todo?1:0)+'"><span class="icon note-icon">'+S+'</span><span class="label">'+escapeHtml(I.title)+"</span></div>"}t.notes.length||(x='<div class="tag-empty">—</div>'),y.innerHTML=x}}else if("notePreview"===t.name)showPreview(t);else if("trashFolderNotes"===t.name){var E=document.querySelector('.trash-folder-children[data-folder-id="'+t.folderId+'"]');if(E){E.dataset.loaded="1";for(var b=34+16*(parseInt(E.dataset.depth||"0",10)+1),w="",M=0;M<t.notes.length;M++){var N=t.notes[M],_=N.is_todo?N.todo_completed?"☑":"☐":"📝";w+='<div class="tree-item note trash-note" style="padding-left:'+b+'px" data-id="'+N.id+'" data-type="note" data-trash="1"><span class="icon note-icon">'+_+'</span><span class="label">'+escapeHtml(N.title)+"</span></div>"}t.notes.length||(w='<div class="tag-empty" style="padding-left:'+b+'px">—</div>'),E.innerHTML=w}}else if("tagNotes"===t.name)expandTagNotes(t.tagId,t.notes);else if("scrollToFolder"===t.name)setTimeout(function(){var e=document.querySelector('.tree-item.folder:not(.pinned-item)[data-id="'+t.folderId+'"]');e&&(expandAncestorsLocal(e),e.scrollIntoView({block:"center",behavior:"smooth"}),e.classList.add("locate-flash"),setTimeout(function(){e.classList.remove("locate-flash")},1500))},80);else if("exitSearch"===t.name){var q=document.getElementById("search-input");q&&(q.value=""),_searchMode&&exitSearchMode()}else if("exitSearchAndLocate"===t.name){var C=document.getElementById("search-input");C&&(C.value=""),_searchMode=!1,showSearchContainer(!1),setTimeout(function(){var e=document.querySelector('.tree-item.folder[data-id="'+t.folderId+'"]');e&&(expandAncestorsLocal(e),e.scrollIntoView({block:"center",behavior:"smooth"}),e.classList.add("locate-flash"),setTimeout(function(){e.classList.remove("locate-flash")},1500))},80)}else if("copyText"===t.name)if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(t.text);else{var B=document.createElement("textarea");B.value=t.text,document.body.appendChild(B),B.select(),document.execCommand("copy"),B.remove()}else if("selectNote"===t.name){document.querySelectorAll(".tree-item.note.selected").forEach(function(e){e.classList.remove("selected")});var D=document.querySelector('.tree-item.note[data-id="'+t.id+'"]');D&&(D.classList.add("selected"),D.scrollIntoView({block:"nearest",behavior:"instant"}))}else"updateNote"===t.name&&document.querySelectorAll('.tree-item.note[data-id="'+t.id+'"]').forEach(function(e){var a=e.querySelector(".label");a&&(a.textContent=t.title);var n=e.querySelector(".search-result-title");n&&(n.textContent=t.title);var d=e.querySelector(".note-icon");d&&(d.textContent=t.icon),e.querySelectorAll(".todo-pie, .shared-badge").forEach(function(e){e.remove()}),t.badges&&e.insertAdjacentHTML("beforeend",t.badges)})}}),document.addEventListener("mousedown",function(e){var t=e.target.closest(".tree-item");t&&0===e.button&&t.setAttribute("draggable","true")}),document.addEventListener("dragstart",function(e){var t=e.target.closest(".tree-item");if(t)if(t.closest(".trash-children")||t.closest(".smart-section-body")||t.classList.contains("tag-folder"))e.preventDefault();else{var a=t.classList.contains("pinned-item");if(e.dataTransfer.setData("text/plain",JSON.stringify({id:t.dataset.id,type:t.dataset.type,pinned:a})),e.dataTransfer.effectAllowed="move",t.classList.add("dragging"),!a){var n=document.getElementById("tree-container");n&&n.classList.add("dragging-active")}}});var _dragScrollDir=0,_dragScrollRaf=null;function dragScrollStep(){var e=document.getElementById("tree-container");e&&_dragScrollDir?(e.scrollTop+=_dragScrollDir,_dragScrollRaf=requestAnimationFrame(dragScrollStep)):_dragScrollRaf=null}function updateDragScroll(e){var t=document.getElementById("tree-container");if(t){var a=t.getBoundingClientRect(),n=a.bottom,d=document.getElementById("drop-zone-empty");if(d&&t.classList.contains("dragging-active")){var o=d.getBoundingClientRect();o.height>0&&o.top>a.top&&(n=o.top)}var s=0;e<a.top+40?s=-Math.ceil((a.top+40-e)/4):e>n?s=0:e>n-40&&(s=Math.ceil((e-(n-40))/4)),_dragScrollDir=s,s&&!_dragScrollRaf&&(_dragScrollRaf=requestAnimationFrame(dragScrollStep))}else _dragScrollDir=0}function clearDropIndicators(){document.querySelectorAll(".drop-target").forEach(function(e){e.classList.remove("drop-target")}),document.querySelectorAll(".drop-above").forEach(function(e){e.classList.remove("drop-above")}),document.querySelectorAll(".drop-below").forEach(function(e){e.classList.remove("drop-below")})}function endDrag(){_dragScrollDir=0,clearDropIndicators();var e=document.getElementById("tree-container");e&&e.classList.remove("dragging-active")}document.addEventListener("dragend",function(e){var t=e.target.closest(".tree-item");t&&(t.classList.remove("dragging"),t.removeAttribute("draggable")),endDrag()}),document.addEventListener("dragover",function(e){document.querySelector(".tree-item.dragging")&&updateDragScroll(e.clientY);var t=e.target;if(t&&3===t.nodeType&&(t=t.parentElement),t){var a=t.closest(".tree-item");if(document.getElementById("tree-container"),t.closest("#drop-zone-empty"))document.querySelector(".tree-item.dragging.pinned-item")||(e.preventDefault(),e.dataTransfer.dropEffect="move");else{if(t.closest(".pinned-section-header"))return e.preventDefault(),e.dataTransfer.dropEffect="move",void clearDropIndicators();if(t.closest(".pinned-section-body")){if(document.querySelector(".tree-item.dragging.pinned-item")&&a&&a.classList.contains("pinned-item")){e.preventDefault(),e.dataTransfer.dropEffect="move",clearDropIndicators();var n=a.getBoundingClientRect();e.clientY-n.top<.5*n.height?a.classList.add("drop-above"):a.classList.add("drop-below")}}else{var d=t.closest(".tag-folder");if(d)document.querySelector(".tree-item.note.dragging")&&(e.preventDefault(),e.dataTransfer.dropEffect="move",clearDropIndicators(),d.classList.add("drop-target"));else if(!(t.closest(".tags-section-body")||t.closest(".tags-section-header")||t.closest(".trash-children")||t.closest(".trash-section-header")||t.closest(".smart-section-body")||t.closest(".smart-section-header"))&&a){var o=document.querySelector(".tree-item.dragging");if(!o||!o.classList.contains("pinned-item")){e.preventDefault(),e.dataTransfer.dropEffect="move",clearDropIndicators();var s=a.dataset.type,r=a.getBoundingClientRect(),i=e.clientY-r.top,l=r.height;"folder"===s?i<.25*l?a.classList.add("drop-above"):i>.75*l?a.classList.add("drop-below"):a.classList.add("drop-target"):"manual"===currentSortMode()?i<.5*l?a.classList.add("drop-above"):a.classList.add("drop-below"):a.classList.add("drop-target")}}}}}}),document.addEventListener("dragleave",function(e){var t=e.target.closest(".tree-item");t&&(t.classList.remove("drop-target"),t.classList.remove("drop-above"),t.classList.remove("drop-below"));var a=document.getElementById("tree-container");a&&e.target===a&&a.classList.remove("drop-empty")}),document.addEventListener("drop",function(e){e.preventDefault();var t=e.target;t&&3===t.nodeType&&(t=t.parentElement);var a,n=t?t.closest(".tree-item"):null;document.getElementById("tree-container");try{a=JSON.parse(e.dataTransfer.getData("text/plain"))}catch(e){return void endDrag()}var d=a.id,o=a.type,s=a.pinned;if(t&&t.closest("#drop-zone-empty")&&!s)return postMsg({name:"dragToEmpty",dragId:d,dragType:o}),void endDrag();if(t&&t.closest(".pinned-section-header")&&!s)return"note"===o?postMsg({name:"contextMenu",action:"pinNote",id:d,itemType:"note"}):"folder"===o&&postMsg({name:"contextMenu",action:"pinFolder",id:d,itemType:"folder"}),void endDrag();if(t&&t.closest(".pinned-section-body")&&s){var r=n&&n.classList.contains("pinned-item")?n:null;if(r&&r.dataset.id!==d){var i=r.getBoundingClientRect(),l=e.clientY-i.top<.5*i.height?"before":"after";postMsg({name:"reorderPinned",dragId:d,dragType:o,targetId:r.dataset.id,position:l})}endDrag()}else{var c=t?t.closest(".tag-folder"):null;if(c)return"note"===o&&postMsg({name:"tagNoteAdd",tagId:c.dataset.tagId,noteId:d}),void endDrag();if(t&&(t.closest(".tags-section-body")||t.closest(".tags-section-header")||t.closest(".trash-children")||t.closest(".trash-section-header")||t.closest(".smart-section-body")||t.closest(".smart-section-header")))endDrag();else if(s)endDrag();else if(n){var m=n.dataset.id,v=n.dataset.type;if(d!==m){var p=n.getBoundingClientRect(),g=e.clientY-p.top,u=p.height;postMsg("folder"===v?g>=.25*u&&g<=.75*u?{name:"dragDrop",dragId:d,dragType:o,targetId:m,position:"into"}:{name:"dragDrop",dragId:d,dragType:o,targetId:m,position:g<.25*u?"above":"below"}:"note"===o?{name:"dragDrop",dragId:d,dragType:o,targetId:m,position:g<.5*u?"above":"below"}:{name:"dragDrop",dragId:d,dragType:o,targetId:m,position:"into"}),endDrag()}else endDrag()}else endDrag()}});var _searchTimer=null,_searchMode=!1,_searchId=0;function escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function escapeHtml(e){return String(null==e?"":e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function highlightText(e,t){var a=escapeHtml(e);if(!t)return a;var n=new RegExp("("+escapeRegex(t)+")","gi");return a.replace(n,'<mark class="search-highlight">$1</mark>')}function showSearchContainer(e){var t=document.getElementById("tree-container"),a=document.getElementById("search-results");t&&(t.style.display=e?"none":""),a&&(a.style.display=e?"":"none")}function renderNoteItem(e,t){var a="📝";e.is_todo&&(a=e.todo_completed?"☑":"☐");var n='<div class="search-result-item tree-item note" data-id="'+e.id+'" data-type="note" data-todo="'+(e.is_todo?1:0)+'">';return n+='<span class="icon note-icon">'+a+"</span>",n+='<div class="search-result-content">',n+='<div class="search-result-title">'+highlightText(e.title,t)+"</div>",e.folderName&&(n+='<div class="search-result-folder">📂 '+escapeHtml(e.folderName)+"</div>"),e.snippet&&(n+='<div class="search-result-snippet">'+highlightText(e.snippet,t)+"</div>"),n+"</div></div>"}function renderSearchResults(e,t,a,n){var d=document.getElementById("search-results");if(d){showSearchContainer(!0);var o=e.length+t.length+a.length;if(0!==o){var s='<div class="search-status">'+T("searchResultCount").replace("{count}",o)+"</div>";if(a.length>0){s+=g("📁",T("searchSectionFolders"),a.length,"folders"),s+='<div class="search-section-body" id="search-section-folders">';for(var r=0;r<a.length;r++){var i=a[r],l=i.iconEmoji||"📁";s+='<div class="search-result-item search-folder-item" data-folder-id="'+i.id+'">',s+='<span class="icon">'+l+"</span>",s+='<div class="search-result-content">',s+='<div class="search-result-title">'+highlightText(i.title,n)+"</div>",s+="</div></div>"}s+="</div>"}if(e.length>0){s+=g("📝",T("searchSectionNotes"),e.length,"notes"),s+='<div class="search-section-body" id="search-section-notes">';for(var c=0;c<e.length;c++)s+=renderNoteItem(e[c],n);s+="</div>"}if(t.length>0){s+=g("🏷️",T("searchSectionTags"),t.length,"tags"),s+='<div class="search-section-body" id="search-section-tags">';for(var m=0;m<t.length;m++){var v=t[m],p=T("searchTagNoteCount").replace("{count}",v.noteCount);s+='<div class="search-result-item search-tag-item" data-tag-id="'+v.id+'">',s+='<span class="icon">🏷️</span>',s+='<div class="search-result-content">',s+='<div class="search-result-title">'+highlightText(v.title,n)+"</div>",s+='<div class="search-result-folder">'+p+"</div>",s+="</div>",s+='<span class="tag-expand-arrow">▶</span>',s+="</div>",s+='<div class="tag-notes-container" id="tag-notes-'+v.id+'"></div>'}s+="</div>"}d.innerHTML=s,_searchMode=!0}else d.innerHTML='<div class="search-status">'+T("searchNoResult")+"</div>"}function g(e,t,a,n){return'<div class="search-section-header" data-section="'+n+'"><span class="section-toggle">▼</span> '+e+" "+t+" ("+a+")</div>"}}function expandTagNotes(e,t){var a=document.getElementById("tag-notes-"+e);if(a){var n;if(a.children.length>0)return a.innerHTML="",void((n=document.querySelector('.search-tag-item[data-tag-id="'+e+'"] .tag-expand-arrow'))&&n.classList.remove("expanded"));for(var d="",o=0;o<t.length;o++)d+=renderNoteItem(t[o],"");0===t.length&&(d='<div class="search-status" style="padding-left:30px;">'+T("searchNoResult")+"</div>"),a.innerHTML=d,(n=document.querySelector('.search-tag-item[data-tag-id="'+e+'"] .tag-expand-arrow'))&&n.classList.add("expanded")}}function exitSearchMode(){_searchMode=!1,showSearchContainer(!1)}document.addEventListener("input",function(e){if("search-input"===e.target.id){var t=e.target.value.trim();_searchTimer&&clearTimeout(_searchTimer);var a=++_searchId;if(t){_searchMode=!0;var n=document.getElementById("search-results");n&&(n.innerHTML='<div class="search-status">'+T("searching")+"</div>"),showSearchContainer(!0),_searchTimer=setTimeout(function(){postMsg({name:"search",query:t,searchId:a})},400)}else _searchMode&&exitSearchMode()}}),document.addEventListener("keydown",function(e){if("Escape"===e.key){var t=document.getElementById("search-input");t&&t.value&&(t.value="",_searchMode&&exitSearchMode())}});