diff --git a/app/src/card/newCardTab.ts b/app/src/card/newCardTab.ts index 997663a2b3b..2575ea520c5 100644 --- a/app/src/card/newCardTab.ts +++ b/app/src/card/newCardTab.ts @@ -1,6 +1,6 @@ import {Tab} from "../layout/Tab"; import {Custom} from "../layout/dock/Custom"; -import {bindCardEvent, genCardHTML} from "./openCard"; +import {bindCardEvent, genCardHTML, initCardComponent} from "./openCard"; import {fetchPost} from "../util/fetch"; import {Protyle} from "../protyle"; import {setPanelFocus} from "../layout/util"; @@ -19,6 +19,57 @@ export const newCardModel = (options: { } }) => { let editor: Protyle; + + const fetchCardsData = async (): Promise => { + return new Promise((resolve) => { + fetchPost(options.data.cardType === "all" ? "/api/riff/getRiffDueCards" : + (options.data.cardType === "doc" ? "/api/riff/getTreeRiffDueCards" : "/api/riff/getNotebookRiffDueCards"), { + rootID: options.data.id, + deckID: options.data.id, + notebook: options.data.id, + }, async (response) => { + let cardsData: ICardData = response.data; + for (let i = 0; i < options.app.plugins.length; i++) { + cardsData = await options.app.plugins[i].updateCards(response.data); + } + resolve(cardsData); + }); + }); + }; + + const renderCardsAndBindEvents = async (element: HTMLElement, data: any, cardsData: ICardData, index?: number, isUpdate?: boolean) => { + customObj.editors.forEach(editor => { + editor.destroy(); + }); + customObj.editors.length = 0; + + element.innerHTML = genCardHTML({ + id: data.id, + cardType: data.cardType, + cardsData, + isTab: true, + }); + + const cardOptions = { + app: options.app, + element: element, + id: data.id, + title: data.title, + cardType: data.cardType, + cardsData, + index, + }; + + if (isUpdate) { + const initResult = await initCardComponent(cardOptions); + editor = initResult.editor; + } else { + editor = await bindCardEvent(cardOptions); + } + + customObj.editors.push(editor); + }; + const customObj = new Custom({ app: options.app, type: "siyuan-card", @@ -26,58 +77,18 @@ export const newCardModel = (options: { data: options.data, async init() { if (options.data.cardsData) { + // 使用现有的 cardsData for (let i = 0; i < options.app.plugins.length; i++) { options.data.cardsData = await options.app.plugins[i].updateCards(options.data.cardsData); } - this.element.innerHTML = genCardHTML({ - id: this.data.id, - cardType: this.data.cardType, - cardsData: options.data.cardsData, - isTab: true, - }); - - editor = await bindCardEvent({ - app: options.app, - element: this.element, - id: this.data.id, - title: this.data.title, - cardType: this.data.cardType, - cardsData: options.data.cardsData, - index: options.data.index, - }); - customObj.editors.push(editor); + await renderCardsAndBindEvents(this.element, this.data, options.data.cardsData, options.data.index); // https://github.com/siyuan-note/siyuan/issues/9561#issuecomment-1794473512 delete options.data.cardsData; delete options.data.index; } else { - fetchPost(this.data.cardType === "all" ? "/api/riff/getRiffDueCards" : - (this.data.cardType === "doc" ? "/api/riff/getTreeRiffDueCards" : "/api/riff/getNotebookRiffDueCards"), { - rootID: this.data.id, - deckID: this.data.id, - notebook: this.data.id, - }, async (response) => { - let cardsData: ICardData = response.data; - for (let i = 0; i < options.app.plugins.length; i++) { - cardsData = await options.app.plugins[i].updateCards(response.data); - } - this.element.innerHTML = genCardHTML({ - id: this.data.id, - cardType: this.data.cardType, - cardsData, - isTab: true, - }); - - editor = await bindCardEvent({ - app: options.app, - element: this.element, - id: this.data.id, - title: this.data.title, - cardType: this.data.cardType, - cardsData, - }); - - customObj.editors.push(editor); - }); + // 获取新的 cardsData + const cardsData = await fetchCardsData(); + await renderCardsAndBindEvents(this.element, this.data, cardsData); } }, destroy() { @@ -90,23 +101,9 @@ export const newCardModel = (options: { editor.resize(); } }, - update() { - fetchPost(this.data.cardType === "all" ? "/api/riff/getRiffDueCards" : - (this.data.cardType === "doc" ? "/api/riff/getTreeRiffDueCards" : "/api/riff/getNotebookRiffDueCards"), { - rootID: this.data.id, - deckID: this.data.id, - notebook: this.data.id, - }, async (response) => { - for (let i = 0; i < options.app.plugins.length; i++) { - options.data.cardsData = await options.app.plugins[i].updateCards(options.data.cardsData); - } - this.element.innerHTML = genCardHTML({ - id: this.data.id, - cardType: this.data.cardType, - cardsData: response.data, - isTab: true, - }); - }); + async update() { + const cardsData = await fetchCardsData(); + await renderCardsAndBindEvents(this.element, this.data, cardsData ,undefined, true); } }); customObj.element.addEventListener("click", () => { diff --git a/app/src/card/openCard.ts b/app/src/card/openCard.ts index 37f1a7b479b..bfbbe72bfc0 100644 --- a/app/src/card/openCard.ts +++ b/app/src/card/openCard.ts @@ -227,7 +227,7 @@ const getEditor = (id: string, protyle: IProtyle, element: Element, currentCard: }; -export const bindCardEvent = async (options: { +export const initCardComponent = async (options: { app: App, element: Element, title?: string, @@ -303,6 +303,33 @@ export const bindCardEvent = async (options: { }; countElement.innerHTML = genCardCount(options.cardsData, index); + + return { + editor, + index, + actionElements, + countElement, + filterElement, + fetchNewRound + }; +}; + +export const bindCardEvent = async (options: { + app: App, + element: Element, + title?: string, + cardsData: ICardData + cardType: TCardType, + id?: string, + dialog?: Dialog, + index?: number +}) => { + // 初始化卡片组件 + const initResult = await initCardComponent(options); + const { editor, actionElements, countElement, filterElement, fetchNewRound } = initResult; + let index = initResult.index; + + // 绑定点击事件 options.element.addEventListener("click", (event: MouseEvent) => { const target = event.target as HTMLElement; let type = ""; @@ -491,6 +518,29 @@ export const bindCardEvent = async (options: { const sticktabElement = hasClosestByAttribute(target, "data-type", "sticktab"); if (sticktabElement) { const stickMenu = new Menu(); + stickMenu.addItem({ + id: "openInNewTab", + icon: "iconOpen", + label: window.siyuan.languages.openInNewTab, + click() { + openFile({ + app: options.app, + custom: { + icon: "iconRiffCard", + title: window.siyuan.languages.spaceRepetition, + data: { + cardsData: options.cardsData, + index, + cardType: filterElement.getAttribute("data-cardtype") as TCardType, + id: docId, + title: options.title + }, + id: "siyuan-card" + }, + }); + options.dialog.destroy(); + } + }); stickMenu.addItem({ id: "insertRight", icon: "iconLayoutRight", @@ -529,6 +579,8 @@ export const bindCardEvent = async (options: { "instance": "Custom", "customModelType": "siyuan-card", "customModelData": { + "cardsData": options.cardsData, + "index": index, "cardType": filterElement.getAttribute("data-cardtype"), "id": docId, "title": options.title