import {Dialog} from "../dialog";
import {fetchPost} from "../util/fetch";
import {isMobile} from "../util/functions";
import {Protyle} from "../protyle";
import {Constants} from "../constants";
import {onGet} from "../protyle/util/onGet";
import {hasClosestByAttribute, hasClosestByClassName} from "../protyle/util/hasClosest";
import {hideElements} from "../protyle/ui/hideElements";
import {isPaidUser, needSubscribe} from "../util/needSubscribe";
import {fullscreen} from "../protyle/breadcrumb/action";
import {MenuItem} from "../menus/Menu";
import {escapeHtml} from "../util/escape";
/// #if !MOBILE
import {openFile} from "../editor/util";
/// #endif
/// #if !BROWSER
import {ipcRenderer} from "electron";
/// #endif
import * as dayjs from "dayjs";
import {getDisplayName, movePathTo} from "../util/pathName";
import {App} from "../index";
import {resize} from "../protyle/util/resize";
import {setStorageVal} from "../protyle/util/compatibility";
import {focusByRange} from "../protyle/util/selection";
import {updateCardHV} from "./util";
import {showMessage} from "../dialog/message";
import {Menu} from "../plugin/Menu";
import {transaction} from "../protyle/wysiwyg/transaction";
const genCardCount = (cardsData: ICardData, allIndex = 0) => {
let newIndex = 0;
let oldIndex = 0;
cardsData.cards.forEach((item, index) => {
if (index > allIndex) {
return;
}
if (item.state === 0) {
newIndex++;
} else {
oldIndex++;
}
});
return `
${newIndex} /
${cardsData.unreviewedNewCardCount}
+
${oldIndex} /
${cardsData.unreviewedOldCardCount}
`;
};
export const genCardHTML = (options: {
id: string,
cardType: TCardType,
cardsData: ICardData,
isTab: boolean
}) => {
let iconsHTML: string;
/// #if MOBILE
iconsHTML = `
${iconsHTML}
🔮
${window.siyuan.languages.noDueCard}
`;
};
const getEditor = (id: string, protyle: IProtyle, element: Element, currentCard: ICard) => {
fetchPost("/api/block/getDocInfo", {
id,
}, (docResponse) => {
protyle.wysiwyg.renderCustom(docResponse.data.ial);
fetchPost("/api/filetree/getDoc", {
id,
mode: 0,
size: Constants.SIZE_GET_MAX
}, (response) => {
onGet({
updateReadonly: true,
data: response,
protyle,
action: response.data.rootID === response.data.id ? [] : [Constants.CB_GET_ALL],
afterCB: () => {
if (protyle.element.classList.contains("fn__none")) {
return;
}
let hasHide = false;
if (!window.siyuan.config.flashcard.superBlock &&
!window.siyuan.config.flashcard.heading &&
!window.siyuan.config.flashcard.list &&
!window.siyuan.config.flashcard.mark) {
hasHide = false;
} else {
if (window.siyuan.config.flashcard.superBlock) {
if (protyle.wysiwyg.element.querySelector(":scope > .sb")) {
hasHide = true;
}
}
if (window.siyuan.config.flashcard.heading) {
if (protyle.wysiwyg.element.querySelector(':scope > [data-type="NodeHeading"]')) {
hasHide = true;
}
}
if (window.siyuan.config.flashcard.list) {
if (protyle.wysiwyg.element.querySelector(".list, .li")) {
hasHide = true;
}
}
if (window.siyuan.config.flashcard.mark) {
if (protyle.wysiwyg.element.querySelector('span[data-type~="mark"]')) {
hasHide = true;
}
}
}
const actionElements = element.querySelectorAll(".card__action");
if (!hasHide) {
protyle.element.classList.remove("card__block--hidemark", "card__block--hideli", "card__block--hidesb", "card__block--hideh");
actionElements[0].classList.add("fn__none");
actionElements[1].querySelectorAll("button.b3-button").forEach((element, btnIndex) => {
if (btnIndex < 2) {
return;
}
element.previousElementSibling.textContent = currentCard.nextDues[btnIndex - 1];
});
actionElements[1].classList.remove("fn__none");
} else {
if (window.siyuan.config.flashcard.superBlock) {
protyle.element.classList.add("card__block--hidesb");
}
if (window.siyuan.config.flashcard.heading) {
protyle.element.classList.add("card__block--hideh");
}
if (window.siyuan.config.flashcard.list) {
protyle.element.classList.add("card__block--hideli");
}
if (window.siyuan.config.flashcard.mark) {
protyle.element.classList.add("card__block--hidemark");
}
actionElements[0].classList.remove("fn__none");
actionElements[1].classList.add("fn__none");
}
}
});
});
});
};
export const bindCardEvent = async (options: {
app: App,
element: Element,
title?: string,
cardsData: ICardData
cardType: TCardType,
id?: string,
dialog?: Dialog,
index?: number,
}) => {
if (window.siyuan.storage[Constants.LOCAL_FLASHCARD].fullscreen) {
fullscreen(options.element.querySelector(".card__main"),
options.element.querySelector('[data-type="fullscreen"]'));
}
let index = 0;
if (typeof options.index === "number") {
index = options.index;
}
const editor = new Protyle(options.app, options.element.querySelector("[data-type='render']") as HTMLElement, {
blockId: "",
action: [Constants.CB_GET_ALL],
render: {
background: false,
gutter: true,
breadcrumbDocName: true,
title: true,
hideTitleOnZoom: true,
},
typewriterMode: false
});
if (window.siyuan.mobile) {
window.siyuan.mobile.popEditor = editor;
}
if (options.cardsData.cards.length > 0) {
getEditor(options.cardsData.cards[index].blockID, editor.protyle, options.element, options.cardsData.cards[index]);
}
options.element.setAttribute("data-key", Constants.DIALOG_OPENCARD);
const actionElements = options.element.querySelectorAll(".card__action");
if (options.index === 0 || typeof options.index === "undefined") {
actionElements[0].firstElementChild.setAttribute("disabled", "disabled");
actionElements[1].querySelector(".b3-button").setAttribute("disabled", "disabled");
} else {
actionElements[0].firstElementChild.removeAttribute("disabled");
actionElements[1].querySelector(".b3-button").removeAttribute("disabled");
}
const countElement = options.element.querySelector('[data-type="count"]');
const filterElement = options.element.querySelector('[data-type="filter"]');
const fetchNewRound = () => {
const currentCardType = filterElement.getAttribute("data-cardtype");
const docId = filterElement.getAttribute("data-id");
fetchPost(currentCardType === "all" ? "/api/riff/getRiffDueCards" :
(currentCardType === "doc" ? "/api/riff/getTreeRiffDueCards" : "/api/riff/getNotebookRiffDueCards"), {
rootID: docId,
deckID: docId,
notebook: docId,
}, async (treeCards) => {
index = 0;
options.cardsData = treeCards.data;
for (let i = 0; i < options.app.plugins.length; i++) {
options.cardsData = await options.app.plugins[i].updateCards(options.cardsData);
}
if (options.cardsData.cards.length > 0) {
nextCard({
countElement,
editor,
actionElements,
index,
cardsData: options.cardsData
});
} else {
allDone(countElement, editor, actionElements);
}
});
};
countElement.innerHTML = genCardCount(options.cardsData, index);
options.element.firstChild.addEventListener("click", (event: MouseEvent) => {
const target = event.target as HTMLElement;
let type = "";
const currentCard = options.cardsData.cards[index];
const docId = filterElement.getAttribute("data-id");
if (typeof event.detail === "string") {
if (["1", "j", "a"].includes(event.detail)) {
type = "1";
} else if (["2", "k", "s"].includes(event.detail)) {
type = "2";
} else if (["3", "l", "d"].includes(event.detail)) {
type = "3";
} else if (["4", ";", "f"].includes(event.detail)) {
type = "4";
} else if ([" ", "enter"].includes(event.detail)) {
type = "-1";
} else if (["p", "q"].includes(event.detail)) {
type = "-2";
} else if (["0", "x"].includes(event.detail)) {
type = "-3";
}
} else {
const fullscreenElement = hasClosestByAttribute(target, "data-type", "fullscreen");
if (fullscreenElement) {
fullscreen(options.element.querySelector(".card__main"),
options.element.querySelector('[data-type="fullscreen"]'));
resize(editor.protyle);
window.siyuan.storage[Constants.LOCAL_FLASHCARD].fullscreen = !window.siyuan.storage[Constants.LOCAL_FLASHCARD].fullscreen;
setStorageVal(Constants.LOCAL_FLASHCARD, window.siyuan.storage[Constants.LOCAL_FLASHCARD]);
event.stopPropagation();
event.preventDefault();
return;
}
const moreElement = hasClosestByAttribute(target, "data-type", "more");
if (moreElement && currentCard) {
event.stopPropagation();
event.preventDefault();
if (filterElement.getAttribute("data-cardtype") === "all" && filterElement.getAttribute("data-id")) {
showMessage(window.siyuan.languages.noSupportTip);
return;
}
const menu = new Menu();
menu.addItem({
id: "setDueTime",
icon: "iconClock",
label: window.siyuan.languages.setDueTime,
click() {
const timedialog = new Dialog({
title: window.siyuan.languages.setDueTime,
content: `
${window.siyuan.languages.cardStatus}
${currentCard.state === 0 ? window.siyuan.languages.flashcardNewCard : window.siyuan.languages.flashcardReviewCard}