Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 60 additions & 63 deletions app/src/card/newCardTab.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -19,65 +19,76 @@ export const newCardModel = (options: {
}
}) => {
let editor: Protyle;

const fetchCardsData = async (): Promise<ICardData> => {
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",
tab: options.tab,
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() {
Expand All @@ -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);
Copy link
Member

@Vanessa219 Vanessa219 Sep 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不太理解为什么一定要这么重构,可以只改业务么?看上去多了 push

Copy link
Contributor Author

@TCOTC TCOTC Sep 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

之前的 update 方法完全是坏的,修复之后重复的代码太多所以又抽象成一个函数了

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renderCardsAndBindEvents 和 fetchCardsData 看上去是一个重构。并且修改了原有代码业务:在原有的 108 行 添加了 customObj.editors.push(editor); 。这个用肉眼看上去并不能修复之前完全坏的 update 方法,可能还会引出更多的问题。

}
});
customObj.element.addEventListener("click", () => {
Expand Down
54 changes: 53 additions & 1 deletion app/src/card/openCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 = "";
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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
Expand Down