diff --git a/app/src/card/newCardTab.ts b/app/src/card/newCardTab.ts
index 24f75754a..1c034c09f 100644
--- a/app/src/card/newCardTab.ts
+++ b/app/src/card/newCardTab.ts
@@ -3,13 +3,15 @@ import {getInstanceById, getWndByLayout} from "../layout/util";
import {Tab} from "../layout/Tab";
import {Custom} from "../layout/dock/Custom";
import {Dialog} from "../dialog";
-import {genCardHTML} from "./openCard";
+import {bindCardEvent, genCardHTML} from "./openCard";
import {fetchPost} from "../util/fetch";
+import {Protyle} from "../protyle";
export const newCardTab = (options: {
- type: TCardType,
+ cardType: TCardType,
id: string,
- dialog: Dialog
+ dialog: Dialog,
+ title?: string
}) => {
let wnd: Wnd;
const element = document.querySelector(".layout__wnd--active");
@@ -19,6 +21,7 @@ export const newCardTab = (options: {
if (!wnd) {
wnd = getWndByLayout(window.siyuan.layout.centerLayout);
}
+ let editor: Protyle
const tab = new Tab({
icon: "iconRiffCard",
title: window.siyuan.languages.spaceRepetition,
@@ -27,23 +30,39 @@ export const newCardTab = (options: {
type: "card",
tab,
data: {
- type: options.type,
+ title: options.title,
+ cardType: options.cardType,
id: options.id
},
init(element) {
- fetchPost(options.type === "all" ? "/api/riff/getRiffDueCards" :
- (options.type === "doc" ? "/api/riff/getTreeRiffDueCards" : "/api/riff/getNotebookRiffDueCards"), {
+ fetchPost(options.cardType === "all" ? "/api/riff/getRiffDueCards" :
+ (options.cardType === "doc" ? "/api/riff/getTreeRiffDueCards" : "/api/riff/getNotebookRiffDueCards"), {
rootID: options.id,
deckID: options.id,
notebook: options.id,
}, (response) => {
element.innerHTML = genCardHTML({
id: options.id,
- cardType: options.type,
- blocks: response.data,
+ cardType: options.cardType,
+ blocks: response.data.cards,
isTab: true,
});
+
+ editor = bindCardEvent({
+ element,
+ id: options.id,
+ title: options.title,
+ cardType: options.cardType,
+ blocks: response.data.cards,
+ dialog: options.dialog,
+ })
});
+ },
+ destroy() {
+ editor.destroy();
+ },
+ resize(){
+ editor.resize();
}
});
tab.addModel(custom);
diff --git a/app/src/card/openCard.ts b/app/src/card/openCard.ts
index ba8cccd7e..94c32114c 100644
--- a/app/src/card/openCard.ts
+++ b/app/src/card/openCard.ts
@@ -33,8 +33,8 @@ export const genCardHTML = (options: {
` : `
${window.siyuan.languages.nextRound}
-
-
+
🙈
${window.siyuan.languages.cardRatingAgain} (1)
-
+
😬
${window.siyuan.languages.cardRatingHard} (2)
-
+
😊
${window.siyuan.languages.cardRatingGood} (3)
-
+
🌈
${window.siyuan.languages.cardRatingEasy} (4)
@@ -91,44 +91,16 @@ export const genCardHTML = (options: {
`;
};
-export const openCard = () => {
- fetchPost("/api/riff/getRiffDueCards", {deckID: ""}, (cardsResponse) => {
- openCardByData(cardsResponse.data, "all");
- });
-};
-
-export const openCardByData = (cardsData: {
- cards: ICard[],
- unreviewedCount: number
-}, cardType: TCardType, id?: string, title?: string) => {
- const exit = window.siyuan.dialogs.find(item => {
- if (item.element.getAttribute("data-key") === window.siyuan.config.keymap.general.riffCard.custom) {
- item.destroy();
- return true;
- }
- });
- if (exit) {
- return;
- }
-
- let blocks = cardsData.cards;
+export const bindCardEvent = (options: {
+ element: Element,
+ title?: string,
+ blocks: ICard[],
+ cardType: TCardType,
+ id?: string,
+ dialog: Dialog,
+}) => {
let index = 0;
- const dialog = new Dialog({
- content: genCardHTML({id, cardType, blocks, isTab: false}),
- width: isMobile() ? "100vw" : "80vw",
- height: isMobile() ? "100vh" : "70vh",
- destroyCallback() {
- if (editor) {
- editor.destroy();
- if (window.siyuan.mobile) {
- window.siyuan.mobile.popEditor = null;
- }
- }
- }
- });
- (dialog.element.querySelector(".b3-dialog__scrim") as HTMLElement).style.backgroundColor = "var(--b3-theme-background)";
- (dialog.element.querySelector(".b3-dialog__container") as HTMLElement).style.maxWidth = "1024px";
- const editor = new Protyle(dialog.element.querySelector("[data-type='render']") as HTMLElement, {
+ const editor = new Protyle(options.element.querySelector("[data-type='render']") as HTMLElement, {
blockId: "",
action: [Constants.CB_GET_ALL],
render: {
@@ -145,20 +117,20 @@ export const openCardByData = (cardsData: {
if (window.siyuan.config.editor.readOnly) {
disabledProtyle(editor.protyle);
}
- if (blocks.length > 0) {
+ if (options.blocks.length > 0) {
fetchPost("/api/filetree/getDoc", {
- id: blocks[index].blockID,
+ id: options.blocks[index].blockID,
mode: 0,
size: Constants.SIZE_GET_MAX
}, (response) => {
onGet(response, editor.protyle, [Constants.CB_GET_ALL, Constants.CB_GET_HTML]);
});
}
- (dialog.element.firstElementChild as HTMLElement).style.zIndex = "200";
- dialog.element.setAttribute("data-key", window.siyuan.config.keymap.general.riffCard.custom);
- const countElement = dialog.element.querySelector('[data-type="count"]');
- const actionElements = dialog.element.querySelectorAll(".card__action");
- const filterElement = dialog.element.querySelector('[data-type="filter"]');
+ (options.element.firstElementChild as HTMLElement).style.zIndex = "200";
+ options.element.setAttribute("data-key", window.siyuan.config.keymap.general.riffCard.custom);
+ const countElement = options.element.querySelector('[data-type="count"]');
+ const actionElements = options.element.querySelectorAll(".card__action");
+ const filterElement = options.element.querySelector('[data-type="filter"]');
const fetchNewRound = () => {
const currentCardType = filterElement.getAttribute("data-cardtype");
fetchPost(currentCardType === "all" ? "/api/riff/getRiffDueCards" :
@@ -168,14 +140,14 @@ export const openCardByData = (cardsData: {
notebook: filterElement.getAttribute("data-id"),
}, (treeCards) => {
index = 0;
- blocks = treeCards.data.cards;
- if (blocks.length > 0) {
+ options.blocks = treeCards.data.cards;
+ if (options.blocks.length > 0) {
nextCard({
countElement,
editor,
actionElements,
index,
- blocks
+ blocks: options.blocks
});
} else {
allDone(countElement, editor, actionElements);
@@ -183,7 +155,7 @@ export const openCardByData = (cardsData: {
});
};
- dialog.element.addEventListener("click", (event) => {
+ options.element.addEventListener("click", (event: MouseEvent) => {
const target = event.target as HTMLElement;
let type = "";
if (typeof event.detail === "string") {
@@ -205,8 +177,8 @@ export const openCardByData = (cardsData: {
} else {
const fullscreenElement = hasClosestByAttribute(target, "data-type", "fullscreen");
if (fullscreenElement) {
- fullscreen(dialog.element.querySelector(".card__main"),
- dialog.element.querySelector('[data-type="fullscreen"]'));
+ fullscreen(options.element.querySelector(".card__main"),
+ options.element.querySelector('[data-type="fullscreen"]'));
event.stopPropagation();
event.preventDefault();
return;
@@ -214,9 +186,10 @@ export const openCardByData = (cardsData: {
const sticktabElement = hasClosestByAttribute(target, "data-type", "sticktab");
if (sticktabElement) {
newCardTab({
- type: filterElement.getAttribute("data-cardtype") as TCardType,
+ cardType: filterElement.getAttribute("data-cardtype") as TCardType,
id: filterElement.getAttribute("data-id"),
- dialog,
+ dialog: options.dialog,
+ title: options.title
});
event.stopPropagation();
event.preventDefault();
@@ -224,7 +197,7 @@ export const openCardByData = (cardsData: {
}
const closeElement = hasClosestByAttribute(target, "data-type", "close");
if (closeElement) {
- dialog.destroy();
+ options.dialog.destroy();
event.stopPropagation();
event.preventDefault();
return;
@@ -253,16 +226,16 @@ export const openCardByData = (cardsData: {
}, [], undefined, window.siyuan.languages.specifyPath, true);
}
}).element);
- if (title || response.data.length > 0) {
+ if (options.title || response.data.length > 0) {
window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element);
}
- if (title) {
+ if (options.title) {
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
- label: escapeHtml(title),
+ label: escapeHtml(options.title),
click() {
- filterElement.setAttribute("data-id", id);
- filterElement.setAttribute("data-cardtype", cardType);
+ filterElement.setAttribute("data-id", options.id);
+ filterElement.setAttribute("data-cardtype", options.cardType);
fetchNewRound();
},
}).element);
@@ -301,7 +274,7 @@ export const openCardByData = (cardsData: {
type = buttonElement.getAttribute("data-type");
}
}
- if (!type || !blocks[index]) {
+ if (!type || !options.blocks[index]) {
return;
}
event.preventDefault();
@@ -315,7 +288,7 @@ export const openCardByData = (cardsData: {
actionElements[0].classList.add("fn__none");
actionElements[1].querySelectorAll(".b3-button").forEach((element, btnIndex) => {
if (btnIndex !== 0) {
- element.previousElementSibling.textContent = blocks[index].nextDues[btnIndex - 1];
+ element.previousElementSibling.textContent = options.blocks[index].nextDues[btnIndex - 1];
}
});
actionElements[1].classList.remove("fn__none");
@@ -332,17 +305,17 @@ export const openCardByData = (cardsData: {
editor,
actionElements,
index,
- blocks
+ blocks: options.blocks
});
}
return;
}
if (["0", "1", "2", "3", "-3"].includes(type) && actionElements[0].classList.contains("fn__none")) {
fetchPost(type === "-3" ? "/api/riff/skipReviewRiffCard" : "/api/riff/reviewRiffCard", {
- deckID: blocks[index].deckID,
- cardID: blocks[index].cardID,
+ deckID: options.blocks[index].deckID,
+ cardID: options.blocks[index].cardID,
rating: parseInt(type),
- reviewedCards: blocks
+ reviewedCards: options.blocks
}, () => {
/// #if MOBILE
if (type !== "-3" &&
@@ -352,18 +325,18 @@ export const openCardByData = (cardsData: {
}
/// #endif
index++;
- if (index > blocks.length - 1) {
+ if (index > options.blocks.length - 1) {
const currentCardType = filterElement.getAttribute("data-cardtype");
fetchPost(currentCardType === "all" ? "/api/riff/getRiffDueCards" :
(currentCardType === "doc" ? "/api/riff/getTreeRiffDueCards" : "/api/riff/getNotebookRiffDueCards"), {
rootID: filterElement.getAttribute("data-id"),
deckID: filterElement.getAttribute("data-id"),
notebook: filterElement.getAttribute("data-id"),
- reviewedCards: blocks
+ reviewedCards: options.blocks
}, (result) => {
index = 0;
- blocks = result.data.cards;
- if (blocks.length === 0) {
+ options.blocks = result.data.cards;
+ if (options.blocks.length === 0) {
if (result.data.unreviewedCount > 0) {
newRound(countElement, editor, actionElements, result.data.unreviewedCount);
} else {
@@ -375,7 +348,7 @@ export const openCardByData = (cardsData: {
editor,
actionElements,
index,
- blocks
+ blocks: options.blocks
});
}
});
@@ -386,11 +359,57 @@ export const openCardByData = (cardsData: {
editor,
actionElements,
index,
- blocks
+ blocks: options.blocks
});
});
}
});
+ return editor;
+};
+
+export const openCard = () => {
+ fetchPost("/api/riff/getRiffDueCards", {deckID: ""}, (cardsResponse) => {
+ openCardByData(cardsResponse.data, "all");
+ });
+};
+
+export const openCardByData = (cardsData: {
+ cards: ICard[],
+ unreviewedCount: number
+}, cardType: TCardType, id?: string, title?: string) => {
+ const exit = window.siyuan.dialogs.find(item => {
+ if (item.element.getAttribute("data-key") === window.siyuan.config.keymap.general.riffCard.custom) {
+ item.destroy();
+ return true;
+ }
+ });
+ if (exit) {
+ return;
+ }
+
+ const dialog = new Dialog({
+ content: genCardHTML({id, cardType, blocks: cardsData.cards, isTab: false}),
+ width: isMobile() ? "100vw" : "80vw",
+ height: isMobile() ? "100vh" : "70vh",
+ destroyCallback() {
+ if (editor) {
+ editor.destroy();
+ if (window.siyuan.mobile) {
+ window.siyuan.mobile.popEditor = null;
+ }
+ }
+ }
+ });
+ (dialog.element.querySelector(".b3-dialog__scrim") as HTMLElement).style.backgroundColor = "var(--b3-theme-background)";
+ (dialog.element.querySelector(".b3-dialog__container") as HTMLElement).style.maxWidth = "1024px";
+ const editor = bindCardEvent({
+ element: dialog.element,
+ blocks: cardsData.cards,
+ title,
+ id,
+ cardType,
+ dialog
+ });
};
const nextCard = (options: {
diff --git a/app/src/editor/util.ts b/app/src/editor/util.ts
index 58bf8e7ed..61cdcde77 100644
--- a/app/src/editor/util.ts
+++ b/app/src/editor/util.ts
@@ -25,6 +25,7 @@ import {zoomOut} from "../menus/protyle";
import {countBlockWord, countSelectWord} from "../layout/status";
import {showMessage} from "../dialog/message";
import {getSearch} from "../util/functions";
+import {resize} from "../protyle/util/resize";
export const openFileById = async (options: {
id: string,
@@ -390,7 +391,7 @@ export const updatePanelByEditor = (protyle?: IProtyle, focus = true, pushBackSt
return;
}
title = protyle.title.editElement.textContent;
- setPadding(protyle);
+ resize(protyle);
if (focus) {
if (protyle.toolbar.range) {
focusByRange(protyle.toolbar.range);
diff --git a/app/src/layout/Wnd.ts b/app/src/layout/Wnd.ts
index 823278711..2b4be1209 100644
--- a/app/src/layout/Wnd.ts
+++ b/app/src/layout/Wnd.ts
@@ -33,6 +33,7 @@ import {escapeHtml} from "../util/escape";
import {isWindow} from "../util/functions";
import {hideAllElements} from "../protyle/ui/hideElements";
import {focusByOffset, getSelectionOffset} from "../protyle/util/selection";
+import {Custom} from "./dock/Custom";
export class Wnd {
public id: string;
@@ -646,6 +647,9 @@ export class Wnd {
model.pdfObject.pdfLoadingTask.destroy();
}
}
+ if (model instanceof Custom) {
+ model.destroy();
+ }
model.send("closews", {});
}
diff --git a/app/src/layout/dock/Custom.ts b/app/src/layout/dock/Custom.ts
index 81114a205..0ac9425b4 100644
--- a/app/src/layout/dock/Custom.ts
+++ b/app/src/layout/dock/Custom.ts
@@ -8,8 +8,10 @@ export class Custom extends Model {
constructor(options: {
tab: Tab,
data: any,
+ destroy?: () => void,
+ resize?: () => void,
type: string, // 同一类型的唯一标识
- init:(element:Element)=>void
+ init: (element: Element) => void
}) {
super({id: options.tab.id});
if (window.siyuan.config.fileTree.openFilesUseCurrentTab) {
@@ -20,10 +22,24 @@ export class Custom extends Model {
this.element.addEventListener("click", () => {
setPanelFocus(this.element.parentElement.parentElement);
});
- this.update();
+ this.data = options.data;
+ this.destroy = options.destroy;
+ this.resize = options.resize;
+ }
+
+ public destroy() {
+ if (this.destroy) {
+ this.destroy();
+ }
+ }
+
+ public resize() {
+ if (this.resize) {
+ this.resize();
+ }
}
private update() {
- this.element.innerHTML = `eee`
+ // TODO
}
}
diff --git a/app/src/layout/getAll.ts b/app/src/layout/getAll.ts
index 78ec37b68..6824443d1 100644
--- a/app/src/layout/getAll.ts
+++ b/app/src/layout/getAll.ts
@@ -9,6 +9,7 @@ import {Search} from "../search";
import {Files} from "./dock/Files";
import {Bookmark} from "./dock/Bookmark";
import {Tag} from "./dock/Tag";
+import {Custom} from "./dock/Custom";
export const getAllModels = () => {
const models: IModels = {
@@ -21,7 +22,8 @@ export const getAllModels = () => {
inbox: [],
files: [],
bookmark: [],
- tag: []
+ tag: [],
+ custom: [],
};
const getTabs = (layout: Layout) => {
for (let i = 0; i < layout.children.length; i++) {
@@ -46,6 +48,8 @@ export const getAllModels = () => {
models.bookmark.push(model);
} else if (model instanceof Tag) {
models.tag.push(model);
+ } else if (model instanceof Custom) {
+ models.custom.push(model);
}
} else {
getTabs(item as Layout);
diff --git a/app/src/layout/util.ts b/app/src/layout/util.ts
index f6faec384..b1474a8f5 100644
--- a/app/src/layout/util.ts
+++ b/app/src/layout/util.ts
@@ -532,34 +532,9 @@ export const resizeTabs = () => {
resizeTimeout = window.setTimeout(() => {
const models = getAllModels();
models.editor.forEach((item) => {
- if (item.editor && item.editor.protyle && item.element.parentElement) {
- hideElements(["gutter"], item.editor.protyle);
- setPadding(item.editor.protyle);
- if (typeof echarts !== "undefined") {
- item.editor.protyle.wysiwyg.element.querySelectorAll('[data-subtype="echarts"], [data-subtype="mindmap"]').forEach((chartItem: HTMLElement) => {
- const chartInstance = echarts.getInstanceById(chartItem.firstElementChild.nextElementSibling.getAttribute("_echarts_instance_"));
- if (chartInstance) {
- chartInstance.resize();
- }
- });
- }
- // 保持光标位置不变 https://ld246.com/article/1673704873983/comment/1673765814595#comments
- if (!item.element.classList.contains("fn__none") && item.editor.protyle.toolbar.range) {
- let rangeRect = item.editor.protyle.toolbar.range.getBoundingClientRect();
- if (rangeRect.height === 0) {
- const blockElement = hasClosestBlock(item.editor.protyle.toolbar.range.startContainer);
- if (blockElement) {
- rangeRect = blockElement.getBoundingClientRect();
- }
- }
- if (rangeRect.height === 0) {
- return;
- }
- const protyleRect = item.editor.protyle.element.getBoundingClientRect();
- if (protyleRect.top + 30 > rangeRect.top || protyleRect.bottom < rangeRect.bottom) {
- item.editor.protyle.toolbar.range.startContainer.parentElement.scrollIntoView(protyleRect.top > rangeRect.top);
- }
- }
+ if (item.editor && item.editor.protyle &&
+ item.element.parentElement && !item.element.classList.contains("fn__none")) {
+ item.editor.resize();
}
});
// https://github.com/siyuan-note/siyuan/issues/6250
@@ -572,6 +547,9 @@ export const resizeTabs = () => {
hideElements(["gutter"], editorItem.protyle);
});
});
+ models.custom.forEach(item => {
+ item.resize();
+ })
pdfResize();
hideAllElements(["gutter"]);
}, 200);
diff --git a/app/src/protyle/index.ts b/app/src/protyle/index.ts
index e027ea817..c707bc990 100644
--- a/app/src/protyle/index.ts
+++ b/app/src/protyle/index.ts
@@ -26,6 +26,7 @@ import {disabledProtyle, enableProtyle, onGet} from "./util/onGet";
import {reloadProtyle} from "./util/reload";
import {renderBacklink} from "./wysiwyg/renderBacklink";
import {setEmpty} from "../mobile/util/setEmpty";
+import {resize} from "./util/resize";
export class Protyle {
@@ -271,4 +272,8 @@ export class Protyle {
public destroy() {
destroy(this.protyle);
}
+
+ public resize() {
+ resize(this.protyle);
+ }
}
diff --git a/app/src/protyle/util/resize.ts b/app/src/protyle/util/resize.ts
new file mode 100644
index 000000000..fb0215948
--- /dev/null
+++ b/app/src/protyle/util/resize.ts
@@ -0,0 +1,33 @@
+import {hideElements} from "../ui/hideElements";
+import {setPadding} from "../ui/initUI";
+import {hasClosestBlock} from "./hasClosest";
+
+export const resize = (protyle: IProtyle) => {
+ hideElements(["gutter"], protyle);
+ setPadding(protyle);
+ if (typeof echarts !== "undefined") {
+ protyle.wysiwyg.element.querySelectorAll('[data-subtype="echarts"], [data-subtype="mindmap"]').forEach((chartItem: HTMLElement) => {
+ const chartInstance = echarts.getInstanceById(chartItem.firstElementChild.nextElementSibling.getAttribute("_echarts_instance_"));
+ if (chartInstance) {
+ chartInstance.resize();
+ }
+ });
+ }
+ // 保持光标位置不变 https://ld246.com/article/1673704873983/comment/1673765814595#comments
+ if (protyle.toolbar.range) {
+ let rangeRect = protyle.toolbar.range.getBoundingClientRect();
+ if (rangeRect.height === 0) {
+ const blockElement = hasClosestBlock(protyle.toolbar.range.startContainer);
+ if (blockElement) {
+ rangeRect = blockElement.getBoundingClientRect();
+ }
+ }
+ if (rangeRect.height === 0) {
+ return;
+ }
+ const protyleRect = protyle.element.getBoundingClientRect();
+ if (protyleRect.top + 30 > rangeRect.top || protyleRect.bottom < rangeRect.bottom) {
+ protyle.toolbar.range.startContainer.parentElement.scrollIntoView(protyleRect.top > rangeRect.top);
+ }
+ }
+};
diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts
index ad88fd425..65041a1aa 100644
--- a/app/src/types/index.d.ts
+++ b/app/src/types/index.d.ts
@@ -658,6 +658,7 @@ declare interface IModels {
tag: import("../layout/dock/Tag").Tag[]
asset: import("../asset").Asset[]
search: import("../search").Search[]
+ custom: import("../layout/dock/Custom").Custom[]
}
declare interface IMenu {