From 32cdfe8a3efa83a28cd3625ff2adcbcc3b794cc8 Mon Sep 17 00:00:00 2001 From: frostime Date: Sat, 28 Dec 2024 01:37:47 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E2=9C=A8=20feat:=20=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E8=81=9A=E7=84=A6=E5=9D=97=20close=20#30?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + public/i18n/en_US.yaml | 205 ++++++++++++++++--------------- public/i18n/zh_CN.yaml | 3 + src/components/item.tsx | 14 ++- src/components/select-icon.tsx | 4 +- src/components/setting/index.tsx | 13 ++ src/index.ts | 11 +- src/libs/inject.ts | 19 --- src/model/stores.ts | 6 +- src/types/i18n.d.ts | 5 + 10 files changed, 155 insertions(+), 126 deletions(-) delete mode 100644 src/libs/inject.ts diff --git a/package.json b/package.json index 9ea1060..fc62a22 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "vite-plugin-zip-pack": "^1.2.2" }, "dependencies": { + "@frostime/siyuan-plugin-kits": "^1.3.6", "@frostime/solid-signal-ref": "^2.0.0", "solid-transition-group": "^0.2.3" } diff --git a/public/i18n/en_US.yaml b/public/i18n/en_US.yaml index 9e03fe1..23aa046 100644 --- a/public/i18n/en_US.yaml +++ b/public/i18n/en_US.yaml @@ -1,130 +1,141 @@ ---- -msg: - ruleFailed: 'Failed to correctly parse the configuration rule: {0}' - ruleInvalid: 'The format of the group rule input is incorrect: {0}' - itemHasInGroup: The item is already in the target group - itemNotFoundInGroup: The item was not found in the source group - groupNameEmpty: The name of the bookmark group cannot be empty! -itemErr: - closed: 'The notebook "{0}" is already closed' - deleted: 'Content block not found, it may have been deleted! Old block content: [{0}]' -setting: - replaceDefault: - title: Replace Built-in Bookmarks - description: 'If enabled, the default bookmarks will be blocked, and bookmark shortcut keys (default is Alt+3) will be bound;
Takes effect after restart; Notice: not appliable in mobile devices!' - viewMode: - title: Display Mode - description: Select the style of the bookmark bar display - hideClosed: - title: Hide Closed Items - description: When enabled, hide items from closed notebooks - hideDeleted: - title: Hide Invalid Items - description: When enabled, hide items that have been deleted - grouplist: - title: Bookmark Groups - description: Set up bookmark groups - autoRefreshOnExpand: - title: Auto Refresh on Expand - description: Automatically refreshes the items within a dynamic group when it is expanded from a collapsed state. - ariaLabel: - title: Display Hover Box - description: Display full title of the bookmark item in a hover box when the mouse hovers -viewMode: - bookmark: Bookmark Style - card: Card Style bookmark: - new: Create New Bookmark Group + cache: Cache Current Bookmarks delete: - title: Delete the bookmark group {0}[{1}]? desc: ⚠️ Cannot be recovered after deletion! Are you sure you want to delete? - cache: Cache Current Bookmarks + title: Delete the bookmark group {0}[{1}]? logo: - name: Bookmark - setting: Settings add: Add Bookmark Group - refresh: Refresh - expand: Expand Ctrl+↓ collapse: Collapse Ctrl+↑ + expand: Expand Ctrl+↓ min: Minimize Ctrl+W + name: Bookmark + refresh: Refresh + setting: Settings + new: Create New Bookmark Group +bookmarktype: + composed: Composite Bookmark + dynamic: Dynamic Bookmark + normal: Normal Bookmark group: - msgexist: 'Cannot add: Block with ID [{0}] already exists in the bookmark group' - msg404: 'Cannot add: Block with ID [{0}] not found' - refresh: Refresh - copyref: Copy as Reference List + bottom: Move to Bottom copylink: Copy as Link List - msgcopy: Copy Successful + copyref: Copy as Reference List + currentdoc: Add Current Document Block + delete: Delete Bookmark Group docflow: Document Flow - rename: Rename Bookmark Group + down: Move Down edit: Edit Rule Value - delete: Delete Bookmark Group + fromclipboard: Insert Block from Clipboard move: Move + msg404: 'Cannot add: Block with ID [{0}] not found' + msgcopy: Copy Successful + msgdelconfirm: + - Delete bookmark item {0}? + - ⚠️ Cannot be recovered after deletion! Are you sure you want to delete? + msgexist: 'Cannot add: Block with ID [{0}] already exists in the bookmark group' + msgparse: Unable to parse block from [{0}] + refresh: Refresh + rename: Rename Bookmark Group top: Move to Top up: Move Up - down: Move Down - bottom: Move to Bottom - fromclipboard: Insert Block from Clipboard - msgparse: Unable to parse block from [{0}] - currentdoc: Add Current Document Block - msgdelconfirm: - - Delete bookmark item {0}? - - ⚠️ Cannot be recovered after deletion! Are you sure you want to delete? item: - copyref: Copy as Reference + bottom: Move to Bottom + checkerritem: Check detail + copyitem: Copy to copylink: Copy as Link + copyref: Copy as Reference + del: Delete Bookmark + move: Move msgcopy: Copy Successful style: Style - transfer: Move to - move: Move top: Move to Top - bottom: Move to Bottom - del: Delete Bookmark - checkerritem: Check detail - copyitem: Copy to + transfer: Move to +itemErr: + closed: The notebook "{0}" is already closed + deleted: 'Content block not found, it may have been deleted! Old block content: + [{0}]' +msg: + groupNameEmpty: The name of the bookmark group cannot be empty! + itemHasInGroup: The item is already in the target group + itemNotFoundInGroup: The item was not found in the source group + ruleFailed: 'Failed to correctly parse the configuration rule: {0}' + ruleInvalid: 'The format of the group rule input is incorrect: {0}' newgroup: - name: - - Bookmark Group Name - - Please enter the name of the new bookmark group - type: - - Bookmark Group Type - - Select Bookmark Group Type - rtype: - - Rule Type - - Select Dynamic Rule Type - rinput: Rule Value + choosetemplate: Template desc: - sql: Please enter the SQL query below + attr: Please enter the attribute to search for; You can fill in [attribute name], + or [attribute name][= or like][attribute value] backlinks: Please enter the block ID of the backlink - attr: Please enter the attribute to search for; You can fill in [attribute name], or [attribute name][= or like][attribute value] - choosetemplate: Template + sql: Please enter the SQL query below + icondesc: Select the icon for the group; if not set, the plugin will assign a default + icon based on the group type. + icontitle: Group Icon + name: + - Bookmark Group Name + - Please enter the name of the new bookmark group postprocess: - ariaLabel: 'First child of container: Display the full container block when the referenced block is the first child of a list item or quote block.
Display as document block: Display the document containing the referenced block, rather than the referenced block itself.
See README for details' + ariaLabel: 'First child of container: Display the full container block + when the referenced block is the first child of a list item or quote block.
Display + as document block: Display the document containing the referenced block, + rather than the referenced block itself.
See README for details' + b2doc: Display as document block + fb2p: First child of container name: Post-process omit: No Process - fb2p: First child of container - b2doc: Display as document block - icontitle: Group Icon - # icondesc: 可以手动选择分组的图标;如果不设置,插件会根据分组类型分配默认的图标。 - icondesc: Select the icon for the group; if not set, the plugin will assign a default icon based on the group type. - -bookmarktype: - normal: 'Normal Bookmark' - dynamic: 'Dynamic Bookmark' - composed: 'Composite Bookmark' + rinput: Rule Value + rtype: + - Rule Type + - Select Dynamic Rule Type + type: + - Bookmark Group Type + - Select Bookmark Group Type ruletype: - sql: SQL - backlinks: Backlinks attr: Block Attributes + backlinks: Backlinks js: Javascript + sql: SQL +selecticon: + h3: Please select an icon + reset: Reset + title: Change Group Icon +setting: + ariaLabel: + description: Display full title of the bookmark item in a hover box when the mouse + hovers + title: Display Hover Box + autoRefreshOnExpand: + description: Automatically refreshes the items within a dynamic group when it + is expanded from a collapsed state. + title: Auto Refresh on Expand + grouplist: + description: Set up bookmark groups + title: Bookmark Groups + hideClosed: + description: When enabled, hide items from closed notebooks + title: Hide Closed Items + hideDeleted: + description: When enabled, hide items that have been deleted + title: Hide Invalid Items + replaceDefault: + description: 'If enabled, the default bookmarks will be blocked, and bookmark + shortcut keys (default is Alt+3) will be bound;
Takes effect after restart; + Notice: not appliable in mobile devices!' + title: Replace Built-in Bookmarks + viewMode: + description: Select the style of the bookmark bar display + title: Display Mode + zoomInWhenClick: + description: When clicking on the bookmark item and opening the content block + in the tab, automatically enter the focus mode + title: Enter focus mode after jumping to the block template: + attr: + dailynote: Daily Note sql: random: Random Roam - updated: Recently Updated thisday: On this day todo: Unsolved Task - attr: - dailynote: Daily Note -selecticon: - title: Change Group Icon - h3: Please select an icon - reset: Reset + updated: Recently Updated +viewMode: + bookmark: Bookmark Style + card: Card Style diff --git a/public/i18n/zh_CN.yaml b/public/i18n/zh_CN.yaml index 3b438e8..4799265 100644 --- a/public/i18n/zh_CN.yaml +++ b/public/i18n/zh_CN.yaml @@ -30,6 +30,9 @@ setting: ariaLabel: title: 显示悬浮框 description: 鼠标悬停在书签项目上时,在悬浮框中显示书签项目的完整标题 + zoomInWhenClick: + title: 跳转到块后进入聚焦 + description: 当点击书签项目,在标签页中打开内容块的时候,自动进入聚焦模式 viewMode: bookmark: 书签样式 card: 卡片样式 diff --git a/src/components/item.tsx b/src/components/item.tsx index c33d903..008e813 100644 --- a/src/components/item.tsx +++ b/src/components/item.tsx @@ -3,7 +3,7 @@ import { render } from "solid-js/web"; import { Menu, openTab, showMessage, openMobileFileById } from "siyuan"; import { buildItemDetail } from "../libs/dom"; -import { itemInfo, setGroups, groupMap, configs } from "../model"; +import { itemInfo, setGroups, groupMap, configs, configRef } from "../model"; import { BookmarkContext, itemMoving, setItemMoving } from "./context"; @@ -11,6 +11,7 @@ import { i18n, renderI18n } from "@/utils/i18n"; import { simpleDialog } from "@/libs/dialog"; import Typography from "@/libs/components/typography"; import { getNotebook, isMobile } from "@/utils"; +import { getBlockByID } from "@/api"; interface IProps { group: TBookmarkGroupId; @@ -267,11 +268,20 @@ const Item: Component = (props) => { if (isMobile()) { openMobileFileById(plugin.app, item().id); } else { + let zoomIn = configRef().zoomInWhenClick; + // if (item().type === 'd') { + // zoomIn = false; + // } else { + // let block = await getBlockByID(item().id); + // let root_id = block.root_id; + // let protyle = document.querySelector(`.protyle-title[data-node-id="${root_id}"]`); + // if (protyle) zoomIn = false; //如果文档已经打开了,就直接调整不聚焦 + // } openTab({ app: plugin.app, doc: { id: item().id, - zoomIn: item().type === 'd' ? false : true, + zoomIn: zoomIn, }, }); } diff --git a/src/components/select-icon.tsx b/src/components/select-icon.tsx index 4ee999a..ae37a6e 100644 --- a/src/components/select-icon.tsx +++ b/src/components/select-icon.tsx @@ -1,6 +1,6 @@ import { createSignal, For, Show } from "solid-js"; import Icon from "./icon"; -import { inject } from "@/libs/inject"; +// import { inject } from "@/libs/inject"; import { solidDialog } from "@/libs/dialog"; import { i18n } from "@/utils/i18n"; @@ -20,7 +20,7 @@ const SelectIcons = (props: IProps) => { const [activeTab, setActiveTab] = createSignal<'symbols' | 'emojis'>('symbols'); const symbols = Array.from(document.querySelectorAll('symbol')); - const i18n = inject('i18n'); + // const i18n = inject('i18n'); const ALLOWED_EMOJI_GROUP = ['activity', 'travel', 'people', 'nature', 'food', 'symbols', 'object', 'flags']; let EmojisGroups = (window.siyuan.emojis as ImojiGroup[]).filter(emoji => ALLOWED_EMOJI_GROUP.includes(emoji.id)); diff --git a/src/components/setting/index.tsx b/src/components/setting/index.tsx index 6720c1d..ccebdf9 100644 --- a/src/components/setting/index.tsx +++ b/src/components/setting/index.tsx @@ -94,6 +94,19 @@ const App = () => { }} /> + + { + setConfigs('zoomInWhenClick', v); + }} + /> + { @@ -67,9 +69,9 @@ export default class PluginBookmarkPlus extends Plugin { } async onload() { + //@ts-ignore + registerPlugin(this); setI18n(this.i18n as I18n); - provide('i18n', this.i18n as I18n); - provide('plugin', this); let svgs = Object.values(Svg); this.addIcons(svgs.join('')); @@ -127,7 +129,6 @@ export default class PluginBookmarkPlus extends Plugin { onunload(): void { unloadSdk(); - purge(); destroyBookmark(); bookmarkKeymap.custom = bookmarkKeymap.default; // this.commands = this.commands.filter((command) => command.langKey !== 'F-Misc::Bookmark'); diff --git a/src/libs/inject.ts b/src/libs/inject.ts deleted file mode 100644 index 6867186..0000000 --- a/src/libs/inject.ts +++ /dev/null @@ -1,19 +0,0 @@ -const Storage = {}; - -export const provide = (key: string, value: T) => { - Storage[key] = value; -} - -export const inject = (key: string): T => { - return Storage[key]; -} - -export const purge = (key?: string) => { - if (key) { - delete Storage[key]; - } else { - for (const key in Storage) { - delete Storage[key]; - } - } -} diff --git a/src/model/stores.ts b/src/model/stores.ts index 29967ea..c3e86a9 100644 --- a/src/model/stores.ts +++ b/src/model/stores.ts @@ -3,12 +3,13 @@ * @Author : frostime * @Date : 2024-07-07 14:44:03 * @FilePath : /src/model/stores.ts - * @LastEditTime : 2024-07-15 18:43:34 + * @LastEditTime : 2024-12-28 01:22:56 * @Description : */ import { createStore } from "solid-js/store"; import { createMemo } from "solid-js"; +import { wrapStoreRef } from "@frostime/solid-signal-ref"; export const [itemInfo, setItemInfo] = createStore<{ [key: BlockId]: IBookmarkItemInfo }>({}); @@ -24,6 +25,7 @@ interface IConfig { replaceDefault: boolean; autoRefreshOnExpand: boolean; ariaLabel: boolean; + zoomInWhenClick: boolean; } export const [configs, setConfigs] = createStore({ @@ -33,4 +35,6 @@ export const [configs, setConfigs] = createStore({ replaceDefault: true, autoRefreshOnExpand: false, ariaLabel: false, + zoomInWhenClick: true }); +export const configRef = wrapStoreRef(configs, setConfigs); diff --git a/src/types/i18n.d.ts b/src/types/i18n.d.ts index c92ba1f..293faf5 100644 --- a/src/types/i18n.d.ts +++ b/src/types/i18n.d.ts @@ -39,6 +39,10 @@ interface I18n { title: string; description: string; }; + zoomInWhenClick: { + title: string; + description: string; + }; }; viewMode: { bookmark: string; @@ -125,6 +129,7 @@ interface I18n { sql: string; backlinks: string; attr: string; + js: string; }; template: { sql: { From 6ee5484ddd3602cbda6abd74bdd1f81a1dcba9de Mon Sep 17 00:00:00 2001 From: frostime Date: Sun, 29 Dec 2024 19:56:10 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20perf:=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=88=B7=E6=96=B0=E6=93=8D=E4=BD=9C=EF=BC=8C=E5=9C=A8?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E6=9F=A5=E8=AF=A2=E7=9A=84=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=B9=8B=E5=90=8E=E5=90=8C=E6=A0=B7=E4=B9=9F?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=AF=B9=E5=BA=94=E7=9A=84=E5=9D=97=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=86=85=E5=AE=B9=20close=20#33=20close=20=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E7=BB=84=E6=9F=A5=E8=AF=A2=E6=97=B6=E5=90=8C=E6=A0=B7?= =?UTF-8?q?=E4=B9=9F=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3=20Icon=20#17?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- plugin.json | 2 +- src/components/group.tsx | 27 ++++++++++-------- src/model/index.ts | 60 ++++++++++++++++++++++++++++------------ src/sdk.ts | 11 ++++++++ 5 files changed, 72 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index fc62a22..bc0a2d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sy-bookmark-plus", - "version": "1.4.1", + "version": "1.5.0-dev1", "type": "module", "description": "A more powerful bookmark", "repository": "", diff --git a/plugin.json b/plugin.json index d1a4fba..4fec943 100644 --- a/plugin.json +++ b/plugin.json @@ -2,7 +2,7 @@ "name": "sy-bookmark-plus", "author": "frostime", "url": "https://github.com/frostime/sy-bookmark-plus", - "version": "1.4.1", + "version": "1.5.0-dev1", "minAppVersion": "3.0.12", "backends": [ "all" diff --git a/src/components/group.tsx b/src/components/group.tsx index 4cfdf92..cf527f8 100644 --- a/src/components/group.tsx +++ b/src/components/group.tsx @@ -105,7 +105,9 @@ const Group: Component = (props) => { if (configs['autoRefreshOnExpand'] && isDynamicGroup() && expand === false) { // console.log('auto refresh', props.group.name); - model.updateDynamicGroup(props.group); + model.updateDynamicGroup(props.group).then(() => { + model.updateGroupStaticItemsDebounced(props.group); + }); } setGroups((g) => g.id === props.group.id, 'expand', expand); @@ -167,16 +169,17 @@ const Group: Component = (props) => { const showGroupContextMenu = (e: MouseEvent) => { e.stopPropagation(); const menu = new Menu(); - if (props.group.type === 'dynamic') { - menu.addItem({ - label: i18n_.refresh, - icon: 'iconRefresh', - click: () => { - model.updateDynamicGroup(props.group); + menu.addItem({ + label: i18n_.refresh, + icon: 'iconRefresh', + click: async () => { + if (props.group.type === 'dynamic') { + await model.updateDynamicGroup(props.group); } - }); - menu.addSeparator(); - } + await model.updateGroupStaticItemsDebounced(props.group); + } + }); + menu.addSeparator(); menu.addItem({ label: i18n_.copyref, icon: "iconRef", @@ -498,7 +501,9 @@ const Group: Component = (props) => { class="b3-list-item__action" onClick={(e) => { e.stopPropagation(); - model.updateDynamicGroup(props.group); + model.updateDynamicGroup(props.group).then(() => { + model.updateGroupStaticItemsDebounced(props.group); + }); }} > diff --git a/src/model/index.ts b/src/model/index.ts index 6b8a174..b43e674 100644 --- a/src/model/index.ts +++ b/src/model/index.ts @@ -7,7 +7,7 @@ import { rmItem, insertItem, moveItem } from "../libs/op"; import { showMessage } from "siyuan"; import { batch } from "solid-js"; -import { debounce } from '@/utils'; +import { debounce } from "@frostime/siyuan-plugin-kits"; import { i18n, renderI18n } from "@/utils/i18n"; @@ -98,7 +98,8 @@ export class BookmarkDataModel { await this.plugin.saveData(StorageFileItemSnapshot, itemInfo); } - save = debounce(this.saveCore.bind(this), 1000); + // save = debounce(this.saveCore.bind(this), 1000); + save = debounce(this.saveCore.bind(this) as typeof this.saveCore, 1000); setGroups(gid: TBookmarkGroupId, key: keyof IBookmarkGroup, value: IBookmarkGroup[keyof IBookmarkGroup]) { setGroups((gs) => gs.id === gid, key, value); @@ -131,12 +132,21 @@ export class BookmarkDataModel { toUpdated.push(this.updateDynamicGroup(group)); } }); + // 由于是 async 的,所以很遗憾没法使用 batch 更新 await Promise.all(toUpdated); - await this.updateStaticItems(); + // await this.updateStaticItems(); + let groupsToUpdate = groups.filter(g => g.hidden !== true); + let allIdsSet = new Set(); + groupsToUpdate.forEach(group => { + group.items.forEach(item => { + allIdsSet.add(item.id); + }); + }); + await this.updateStaticItems(allIdsSet); } /** - * 查询动态规则中的块 + * 查询动态规则中的块, 只查询,不更改已有的 item 的信息 * @param group * @returns */ @@ -219,19 +229,35 @@ export class BookmarkDataModel { } - async updateStaticItems() { - console.debug('Update all Bookmark items'); - //1. 获取 block 的最新内容 - let allIds = []; - //一般调用 updateItems 之前会已经调用过 update dynamic group; 如果再次更新就有些冗余了 - //不这么做似乎会造成 item 404 的 bug - const staticGroups = groups.filter(g => g.type !== 'dynamic' && g.hidden !== true); - staticGroups.forEach(g => { - allIds = allIds.concat(g.items.map(it => it.id)); - }) - let allIdsSet = new Set(allIds); - allIds = Array.from(allIdsSet); + async updateGroupStaticItems(group: IBookmarkGroup) { + let allIdsSet = new Set(); + group.items.forEach(item => { + allIdsSet.add(item.id); + }); + await this.updateStaticItems(allIdsSet); + } + // updateGroupStaticItemsDebounced = debounce(this.updateGroupStaticItems.bind(this), 1000); + updateGroupStaticItemsDebounced = debounce( + this.updateGroupStaticItems.bind(this) as typeof this.updateGroupStaticItems, + 1000 + ); + + private async updateStaticItems(allIdsSet: Set) { + // console.debug('Update all Bookmark items'); + // //1. 获取 block 的最新内容 + // let allIds = []; + // //一般调用 updateItems 之前会已经调用过 update dynamic group; 如果再次更新就有些冗余了 + // //不这么做似乎会造成 item 404 的 bug + // const staticGroups = groups.filter(g => g.type !== 'dynamic' && g.hidden !== true); + // staticGroups.forEach(g => { + // allIds = allIds.concat(g.items.map(it => it.id)); + // }) + // let allIdsSet = new Set(allIds); + // allIds = Array.from(allIdsSet); + + let allIds = Array.from(allIdsSet); + //FIX 不确定这里是否会存在块数量大于 64 造成查找不到的问题 let blocks = await getBlocks(...allIds); //2. 更新文档块的 logo @@ -300,7 +326,7 @@ export class BookmarkDataModel { } // ItemInfoStore[id].set({ ...item }); }); - console.debug('更新所有 Bookmark items 完成'); + // console.debug('更新所有 Bookmark items 完成'); //batch 更新 batch(() => { diff --git a/src/sdk.ts b/src/sdk.ts index 610422f..a414246 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -1,3 +1,11 @@ +/* + * Copyright (c) 2024 by frostime. All Rights Reserved. + * @Author : frostime + * @Date : 2024-12-15 23:01:47 + * @FilePath : /src/sdk.ts + * @LastEditTime : 2024-12-28 12:48:12 + * @Description : + */ // import type PluginBookmarkPlus from "."; import { groups, itemInfo } from "./model/stores"; // import { getModel } from "./model"; @@ -15,6 +23,9 @@ export const loadSdk = () => { type: group.type, })); }, + findGroup: (name: string) => { + return groups.find(group => group.name === name); + }, listItems: (groupId: string) => { if (!groupId || typeof groupId !== 'string') { return []; From 7a56a601e4859a5ab1e17515331603b681b421dd Mon Sep 17 00:00:00 2001 From: frostime Date: Sun, 29 Dec 2024 20:46:35 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=94=A8=20refactor:=20=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E9=9D=A2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/item.tsx | 3 +- src/components/setting/group-list.tsx | 11 +- src/components/setting/index.tsx | 259 +++++++++++++++----------- src/index.ts | 20 +- src/libs/dialog.ts | 22 +-- 5 files changed, 169 insertions(+), 146 deletions(-) diff --git a/src/components/item.tsx b/src/components/item.tsx index 008e813..9a8115e 100644 --- a/src/components/item.tsx +++ b/src/components/item.tsx @@ -8,7 +8,8 @@ import { itemInfo, setGroups, groupMap, configs, configRef } from "../model"; import { BookmarkContext, itemMoving, setItemMoving } from "./context"; import { i18n, renderI18n } from "@/utils/i18n"; -import { simpleDialog } from "@/libs/dialog"; +// import { simpleDialog } from "@/libs/dialog"; +import { simpleDialog } from "@frostime/siyuan-plugin-kits"; import Typography from "@/libs/components/typography"; import { getNotebook, isMobile } from "@/utils"; import { getBlockByID } from "@/api"; diff --git a/src/components/setting/group-list.tsx b/src/components/setting/group-list.tsx index 7c8c617..868981c 100644 --- a/src/components/setting/group-list.tsx +++ b/src/components/setting/group-list.tsx @@ -56,12 +56,13 @@ const App = () => { return (
diff --git a/src/components/setting/index.tsx b/src/components/setting/index.tsx index ccebdf9..ff7b3e0 100644 --- a/src/components/setting/index.tsx +++ b/src/components/setting/index.tsx @@ -1,121 +1,162 @@ -import { FormWrap as SettingItemWrap, FormInput as InputItem } from '@/libs/components/Form'; +import Form from "@/libs/components/Form"; import GroupList from './group-list'; import { configs, setConfigs } from "@/model"; import { i18n } from "@/utils/i18n"; +import { children, Component, For, JSXElement } from "solid-js"; +import { useSignalRef } from "@frostime/solid-signal-ref"; +import { Dynamic } from "solid-js/web"; + +interface SettingPanelProps { + group: string; + settingItems?: ISettingItem[]; + // display: boolean; + onChanged?: (e: { group: string, key: string, value: any }) => void; + children?: JSXElement +} + +const SettingPanel: Component = (props) => { + // const fn__none = createMemo(() => props.display === true ? "" : "fn__none"); + const useChildren = children(() => props.children); + + return ( +
+ + {(item) => ( + + props.onChanged({ group: props.group, key: item.key, value: v })} + /> + + )} + + {useChildren()} +
+ ); +}; const App = () => { const i18n_ = i18n.setting; - return ( -
- - { - setConfigs('replaceDefault', v); - }} - /> - - - { - setConfigs('viewMode', v); - }} - options={{ - 'bookmark': i18n.viewMode.bookmark, - 'card': i18n.viewMode.card - }} - /> - - - { - setConfigs('autoRefreshOnExpand', v); - }} - /> - - - { - setConfigs('hideClosed', v); - }} - /> - - - { - setConfigs('hideDeleted', v); - }} - /> - - - { - setConfigs('ariaLabel', v); - }} - /> - - - { - setConfigs('zoomInWhenClick', v); - }} - /> - - { + const settingItems: ISettingItem[] = [ + { + key: 'replaceDefault', + type: 'checkbox', + title: i18n_.replaceDefault.title, + description: i18n_.replaceDefault.description, + value: configs['replaceDefault'] + }, + { + key: 'viewMode', + type: 'select', + title: i18n_.viewMode.title, + description: i18n_.viewMode.description, + value: configs['viewMode'], + options: { + 'bookmark': i18n.viewMode.bookmark, + 'card': i18n.viewMode.card + } + }, + { + key: 'autoRefreshOnExpand', + type: 'checkbox', + title: i18n_.autoRefreshOnExpand.title, + description: i18n_.autoRefreshOnExpand.title, + value: configs['autoRefreshOnExpand'] + }, + { + key: 'hideClosed', + type: 'checkbox', + title: i18n_.hideClosed.title, + description: i18n_.hideClosed.description, + value: configs['hideClosed'] + }, + { + key: 'hideDeleted', + type: 'checkbox', + title: i18n_.hideDeleted.title, + description: i18n_.hideDeleted.description, + value: configs['hideDeleted'] + }, + { + key: 'ariaLabel', + type: 'checkbox', + title: i18n_.ariaLabel.title, + description: i18n_.ariaLabel.description, + value: configs['ariaLabel'] + }, + { + key: 'zoomInWhenClick', + type: 'checkbox', + title: i18n_.zoomInWhenClick.title, + description: i18n_.zoomInWhenClick.description, + value: configs['zoomInWhenClick'] + } + ]; + + return ( + { + //@ts-ignore + setConfigs(key, value); + }} + /> + ); + } + + const PanelGroupList = () => { + return ( + - - + + + ); + } + + const groups = { + 'Basic': PanelBasic, + 'GroupList': PanelGroupList + } + + + return ( +
+
    + + {(group, i) => ( +
  • focused(i())} + onKeyDown={() => { }} + style={{ 'padding-left': "1rem" }} + > + {group} +
  • + )} +
    +
+
+ +
- ) -} + ); +}; export default App; diff --git a/src/index.ts b/src/index.ts index 74b9c3e..52326bc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2024-06-12 19:48:53 * @FilePath : /src/index.ts - * @LastEditTime : 2024-12-28 01:30:14 + * @LastEditTime : 2024-12-29 20:35:01 * @Description : */ import { @@ -12,7 +12,7 @@ import { import { render } from "solid-js/web"; -import { simpleDialog } from "./libs/dialog"; +import { solidDialog } from "./libs/dialog"; import { getModel, rmModel, type BookmarkDataModel } from "./model"; import { configs } from "./model"; @@ -135,12 +135,9 @@ export default class PluginBookmarkPlus extends Plugin { } openSetting(): void { - let container = document.createElement("div") as HTMLDivElement; - container.classList.add("fn__flex-1", "fn__flex"); - render(() => Setting(), container); let size = { - width: '700px', - height: '700px' + width: '900px', + height: '600px' } if (isMobile()) { size = { @@ -148,14 +145,11 @@ export default class PluginBookmarkPlus extends Plugin { height: '90%' } } - simpleDialog({ + solidDialog({ title: window.siyuan.languages.config, - ele: container, - callback: () => { - model.save(); - }, + loader: () => Setting(), ...size - }) + }); } } diff --git a/src/libs/dialog.ts b/src/libs/dialog.ts index c023ba5..8329d55 100644 --- a/src/libs/dialog.ts +++ b/src/libs/dialog.ts @@ -3,28 +3,14 @@ * @Author : frostime * @Date : 2024-03-23 21:37:33 * @FilePath : /src/libs/dialog.ts - * @LastEditTime : 2024-10-03 16:44:41 + * @LastEditTime : 2024-12-29 20:30:34 * @Description : 对话框相关工具 */ import { Dialog } from "siyuan"; import { JSXElement } from "solid-js"; import { render } from "solid-js/web"; -export const simpleDialog = (args: { - title: string, ele: HTMLElement | DocumentFragment, - width?: string, height?: string, - callback?: () => void; -}) => { - const dialog = new Dialog({ - title: args.title, - content: `
`, - width: args.width, - height: args.height, - destroyCallback: args.callback - }); - dialog.element.querySelector(".dialog-content").appendChild(args.ele); - return dialog; -} +import { simpleDialog } from "@frostime/siyuan-plugin-kits"; export const solidDialog = (args: { title: string, loader: () => JSXElement, @@ -34,13 +20,13 @@ export const solidDialog = (args: { let container = document.createElement('div') container.style.display = 'contents'; let disposer = render(args.loader, container); - const dialog = simpleDialog({...args, ele: container, callback: () => { + const {dialog, close} = simpleDialog({...args, ele: container, callback: () => { disposer(); if (args.callback) args.callback();; }}); return { dialog, - close: () => dialog.destroy(), + close, container } } From f85e88753c44c4033e9244394339a96dd169a40e Mon Sep 17 00:00:00 2001 From: frostime Date: Sun, 29 Dec 2024 21:05:06 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=90=9B=20fix:=20=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E4=BA=86=E4=B9=8B=E5=89=8D=E5=87=BA=E7=8E=B0=E2=80=98=E5=A4=A7?= =?UTF-8?q?=E9=87=8F=E2=80=9C=E5=9D=97=E4=B8=A2=E5=A4=B1=E2=80=9D=E8=AF=AF?= =?UTF-8?q?=E6=8A=A5=E7=9A=84=20bug=EF=BC=8C=E5=8E=9F=E6=9D=A5=E6=98=AF=20?= =?UTF-8?q?sql=20limit=20=E5=AF=BC=E8=87=B4=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/{libs => model}/data.ts | 9 +++++---- src/model/index.ts | 36 ++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 20 deletions(-) rename src/{libs => model}/data.ts (87%) diff --git a/src/libs/data.ts b/src/model/data.ts similarity index 87% rename from src/libs/data.ts rename to src/model/data.ts index 823c2db..a011c11 100644 --- a/src/libs/data.ts +++ b/src/model/data.ts @@ -2,8 +2,8 @@ * Copyright (c) 2024 by frostime. All Rights Reserved. * @Author : frostime * @Date : 2024-06-13 14:09:40 - * @FilePath : /src/func/bookmarks/libs/data.ts - * @LastEditTime : 2024-06-20 15:29:04 + * @FilePath : /src/model/data.ts + * @LastEditTime : 2024-12-29 20:58:27 * @Description : */ import { sql, request } from "@/api"; @@ -20,8 +20,9 @@ export { * @param ids * @returns */ -const getBlocks = async (...ids: BlockId[]) => { - const fmt = `select * from blocks where id in (${ids.map((b) => `'${b}'`).join(',')})`; +const getBlocks = async (ids: BlockId[], limit = 64) => { + let fmt = `select * from blocks where id in (${ids.map((b) => `'${b}'`).join(',')})`; + fmt += `limit ${limit}`; let blocks = await sql(fmt); let results: { [key: BlockId]: Block | null } = {}; for (let id of ids) { diff --git a/src/model/index.ts b/src/model/index.ts index b43e674..052785d 100644 --- a/src/model/index.ts +++ b/src/model/index.ts @@ -2,12 +2,12 @@ import { unwrap } from "solid-js/store"; import type PluginBookmarkPlus from "@/index"; -import { getBlocks, getDocInfos } from "../libs/data"; +import { getBlocks, getDocInfos } from "./data"; import { rmItem, insertItem, moveItem } from "../libs/op"; import { showMessage } from "siyuan"; import { batch } from "solid-js"; -import { debounce } from "@frostime/siyuan-plugin-kits"; +import { debounce, PromiseLimitPool } from "@frostime/siyuan-plugin-kits"; import { i18n, renderI18n } from "@/utils/i18n"; @@ -244,21 +244,24 @@ export class BookmarkDataModel { ); private async updateStaticItems(allIdsSet: Set) { - // console.debug('Update all Bookmark items'); - // //1. 获取 block 的最新内容 - // let allIds = []; - // //一般调用 updateItems 之前会已经调用过 update dynamic group; 如果再次更新就有些冗余了 - // //不这么做似乎会造成 item 404 的 bug - // const staticGroups = groups.filter(g => g.type !== 'dynamic' && g.hidden !== true); - // staticGroups.forEach(g => { - // allIds = allIds.concat(g.items.map(it => it.id)); - // }) - // let allIdsSet = new Set(allIds); - // allIds = Array.from(allIdsSet); - let allIds = Array.from(allIdsSet); - //FIX 不确定这里是否会存在块数量大于 64 造成查找不到的问题 - let blocks = await getBlocks(...allIds); + let blocks: Awaited> = {}; + const PAGE_SIZE = 128; + if (allIds.length <= PAGE_SIZE) { + let result = await getBlocks(allIds, PAGE_SIZE); + blocks = result; + } else { + const pool = new PromiseLimitPool(PAGE_SIZE); + for (let i = 0; i < allIds.length; i += PAGE_SIZE) { + let ids = allIds.slice(i, i + PAGE_SIZE); + pool.add(async () => { + let result = await getBlocks(ids, PAGE_SIZE); + blocks = { ...blocks, ...result }; + return result; + }); + } + await pool.awaitAll(); + } //2. 更新文档块的 logo let docsItem: DocumentId[] = []; @@ -428,6 +431,7 @@ export class BookmarkDataModel { }) setItemInfo(item.id, 'ref', (ref) => ref + 1); this.save(); + this.updateStaticItems(new Set([item.id])); return true; } else { return false; From fdf374e0baa6300d5058813565741660d0dcff95 Mon Sep 17 00:00:00 2001 From: frostime Date: Sun, 29 Dec 2024 21:11:08 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=94=96=20new=20ver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- plugin.json | 2 +- src/model/index.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index bc0a2d2..9ae1622 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sy-bookmark-plus", - "version": "1.5.0-dev1", + "version": "1.5.0", "type": "module", "description": "A more powerful bookmark", "repository": "", diff --git a/plugin.json b/plugin.json index 4fec943..0bf1d8f 100644 --- a/plugin.json +++ b/plugin.json @@ -2,7 +2,7 @@ "name": "sy-bookmark-plus", "author": "frostime", "url": "https://github.com/frostime/sy-bookmark-plus", - "version": "1.5.0-dev1", + "version": "1.5.0", "minAppVersion": "3.0.12", "backends": [ "all" diff --git a/src/model/index.ts b/src/model/index.ts index 052785d..786c955 100644 --- a/src/model/index.ts +++ b/src/model/index.ts @@ -431,7 +431,7 @@ export class BookmarkDataModel { }) setItemInfo(item.id, 'ref', (ref) => ref + 1); this.save(); - this.updateStaticItems(new Set([item.id])); + // this.updateStaticItems(new Set([item.id])); return true; } else { return false;