import {Dialog} from "../dialog"; import {fetchPost} from "../util/fetch"; import {isMobile} from "../util/functions"; import {Protyle} from "../protyle"; import {Constants} from "../constants"; import {disabledProtyle, onGet} from "../protyle/util/onGet"; import {hasClosestByAttribute, hasClosestByClassName} from "../protyle/util/hasClosest"; import {hideElements} from "../protyle/ui/hideElements"; import {needSubscribe} from "../util/needSubscribe"; import {fullscreen} from "../protyle/breadcrumb/action"; import {MenuItem} from "../menus/Menu"; import {escapeHtml} from "../util/escape"; import {getDisplayName, movePathTo} from "../util/pathName"; import {newCardTab} from "./newCardTab"; export const genCardHTML = (options: { id: string, cardType: TCardType, blocks: ICard[], isTab: boolean }) => { return `
${window.siyuan.languages.riffCard}
1/${options.blocks.length}
${isMobile() ? `
` : `
`}
🔮
${window.siyuan.languages.noDueCard}
${window.siyuan.languages.nextRound}
`; }; 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; 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, { blockId: "", action: [Constants.CB_GET_ALL], render: { background: false, title: false, gutter: true, breadcrumbDocName: true, }, typewriterMode: false }); if (window.siyuan.mobile) { window.siyuan.mobile.popEditor = editor; } if (window.siyuan.config.editor.readOnly) { disabledProtyle(editor.protyle); } if (blocks.length > 0) { fetchPost("/api/filetree/getDoc", { id: 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"]'); const fetchNewRound = () => { 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"), }, (treeCards) => { index = 0; blocks = treeCards.data.cards; if (blocks.length > 0) { nextCard({ countElement, editor, actionElements, index, blocks }); } else { allDone(countElement, editor, actionElements); } }); }; dialog.element.addEventListener("click", (event) => { const target = event.target as HTMLElement; let type = ""; if (typeof event.detail === "string") { if (event.detail === "1" || event.detail === "j") { type = "0"; } else if (event.detail === "2" || event.detail === "k") { type = "1"; } else if (event.detail === "3" || event.detail === "l") { type = "2"; } else if (event.detail === "4" || event.detail === ";") { type = "3"; } else if (event.detail === " ") { type = "-1"; } else if (event.detail === "p") { type = "-2"; } else if (event.detail === "0") { type = "-3"; } } else { const fullscreenElement = hasClosestByAttribute(target, "data-type", "fullscreen"); if (fullscreenElement) { fullscreen(dialog.element.querySelector(".card__main"), dialog.element.querySelector('[data-type="fullscreen"]')); event.stopPropagation(); event.preventDefault(); return; } const sticktabElement = hasClosestByAttribute(target, "data-type", "sticktab"); if (sticktabElement) { newCardTab({ type: filterElement.getAttribute("data-cardtype") as TCardType, id: filterElement.getAttribute("data-id"), dialog, }); event.stopPropagation(); event.preventDefault(); return; } const closeElement = hasClosestByAttribute(target, "data-type", "close"); if (closeElement) { dialog.destroy(); event.stopPropagation(); event.preventDefault(); return; } const filterTempElement = hasClosestByAttribute(target, "data-type", "filter"); if (filterTempElement) { fetchPost("/api/riff/getRiffDecks", {}, (response) => { window.siyuan.menus.menu.remove(); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: window.siyuan.languages.all, click() { filterElement.setAttribute("data-id", ""); filterElement.setAttribute("data-cardtype", "all"); fetchNewRound(); }, }).element); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: window.siyuan.languages.fileTree, click() { movePathTo((toPath, toNotebook) => { filterElement.setAttribute("data-id", toPath[0] === "/" ? toNotebook[0] : getDisplayName(toPath[0], true, true)); filterElement.setAttribute("data-cardtype", toPath[0] === "/" ? "notebook" : "doc"); fetchNewRound(); }, [], undefined, window.siyuan.languages.specifyPath, true); } }).element); if (title || response.data.length > 0) { window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element); } if (title) { window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: escapeHtml(title), click() { filterElement.setAttribute("data-id", id); filterElement.setAttribute("data-cardtype", cardType); fetchNewRound(); }, }).element); window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element); } response.data.forEach((deck: { id: string, name: string }) => { window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: escapeHtml(deck.name), click() { filterElement.setAttribute("data-id", deck.id); filterElement.setAttribute("data-cardtype", "all"); fetchNewRound(); }, }).element); }); const filterRect = filterTempElement.getBoundingClientRect(); window.siyuan.menus.menu.popup({x: filterRect.left, y: filterRect.bottom}); }); event.stopPropagation(); event.preventDefault(); return; } const newroundElement = hasClosestByAttribute(target, "data-type", "newround"); if (newroundElement) { fetchNewRound(); event.stopPropagation(); event.preventDefault(); return; } } if (!type) { const buttonElement = hasClosestByClassName(target, "b3-button"); if (buttonElement) { type = buttonElement.getAttribute("data-type"); } } if (!type || !blocks[index]) { return; } event.preventDefault(); event.stopPropagation(); hideElements(["toolbar", "hint", "util"], editor.protyle); if (type === "-1") { // 显示答案 if (actionElements[0].classList.contains("fn__none")) { return; } editor.protyle.element.classList.remove("card__block--hidemark", "card__block--hideli", "card__block--hidesb"); 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]; } }); actionElements[1].classList.remove("fn__none"); return; } if (type === "-2") { // 上一步 if (actionElements[0].classList.contains("fn__none")) { return; } if (index > 0) { index--; nextCard({ countElement, editor, actionElements, index, 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, rating: parseInt(type), reviewedCards: blocks }, () => { /// #if MOBILE if (type !== "-3" && (0 !== window.siyuan.config.sync.provider || (0 === window.siyuan.config.sync.provider && !needSubscribe(""))) && window.siyuan.config.repo.key && window.siyuan.config.sync.enabled) { document.getElementById("toolbarSync").classList.remove("fn__none"); } /// #endif index++; if (index > 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 }, (result) => { index = 0; blocks = result.data.cards; if (blocks.length === 0) { if (result.data.unreviewedCount > 0) { newRound(countElement, editor, actionElements, result.data.unreviewedCount); } else { allDone(countElement, editor, actionElements); } } else { nextCard({ countElement, editor, actionElements, index, blocks }); } }); return; } nextCard({ countElement, editor, actionElements, index, blocks }); }); } }); }; const nextCard = (options: { countElement: Element, editor: Protyle, actionElements: NodeListOf, index: number, blocks: ICard[] }) => { options.editor.protyle.element.classList.add("card__block--hide"); if (window.siyuan.config.flashcard.superBlock) { options.editor.protyle.element.classList.add("card__block--hidesb"); } if (window.siyuan.config.flashcard.list) { options.editor.protyle.element.classList.add("card__block--hideli"); } if (window.siyuan.config.flashcard.mark) { options.editor.protyle.element.classList.add("card__block--hidemark"); } options.actionElements[0].classList.remove("fn__none"); options.actionElements[1].classList.add("fn__none"); options.editor.protyle.element.classList.remove("fn__none"); options.editor.protyle.element.nextElementSibling.classList.add("fn__none"); options.countElement.innerHTML = `${options.index + 1}/${options.blocks.length}`; options.countElement.classList.remove("fn__none"); if (options.index === 0) { options.actionElements[0].firstElementChild.setAttribute("disabled", "disabled"); } else { options.actionElements[0].firstElementChild.removeAttribute("disabled"); } fetchPost("/api/filetree/getDoc", { id: options.blocks[options.index].blockID, mode: 0, size: Constants.SIZE_GET_MAX }, (response) => { onGet(response, options.editor.protyle, [Constants.CB_GET_ALL, Constants.CB_GET_HTML]); }); }; const allDone = (countElement: Element, editor: Protyle, actionElements: NodeListOf) => { countElement.classList.add("fn__none"); editor.protyle.element.classList.add("fn__none"); const emptyElement = editor.protyle.element.nextElementSibling; emptyElement.innerHTML = `
🔮
${window.siyuan.languages.noDueCard}`; emptyElement.classList.remove("fn__none"); actionElements[0].classList.add("fn__none"); actionElements[1].classList.add("fn__none"); }; const newRound = (countElement: Element, editor: Protyle, actionElements: NodeListOf, unreviewedCount: number) => { countElement.classList.add("fn__none"); editor.protyle.element.classList.add("fn__none"); const emptyElement = editor.protyle.element.nextElementSibling; emptyElement.innerHTML = `
♻️
${window.siyuan.languages.continueReview2.replace("${count}", unreviewedCount)}
`; emptyElement.classList.remove("fn__none"); actionElements[0].classList.add("fn__none"); actionElements[1].classList.add("fn__none"); };