浏览代码

:art: https://github.com/siyuan-note/siyuan/issues/7954

Vanessa 2 年之前
父节点
当前提交
62e86cbf04
共有 3 个文件被更改,包括 107 次插入63 次删除
  1. 104 60
      app/src/card/openCard.ts
  2. 2 2
      app/src/menus/navigation.ts
  3. 1 1
      app/src/protyle/header/Title.ts

+ 104 - 60
app/src/card/openCard.ts

@@ -8,6 +8,9 @@ import {hasClosestByAttribute, hasClosestByClassName} from "../protyle/util/hasC
 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";
 
 export const openCard = () => {
     const exit = window.siyuan.dialogs.find(item => {
@@ -19,31 +22,27 @@ export const openCard = () => {
     if (exit) {
         return;
     }
-    let decksHTML = '<option value="">All</option>';
-    fetchPost("/api/riff/getRiffDecks", {}, (response) => {
-        response.data.forEach((deck: { id: string, name: string }) => {
-            decksHTML += `<option value="${deck.id}">${deck.name}</option>`;
-        });
-        fetchPost("/api/riff/getRiffDueCards", {deckID: ""}, (cardsResponse) => {
-            openCardByData(cardsResponse.data, `<select class="b3-select">${decksHTML}</select>`);
-        });
+    fetchPost("/api/riff/getRiffDueCards", {deckID: ""}, (cardsResponse) => {
+        openCardByData(cardsResponse.data, "all");
     });
 };
 
-export const openCardByData = (cardsData: { cards: ICard[], unreviewedCount: number }, html = "") => {
+export const openCardByData = (cardsData: {
+    cards: ICard[],
+    unreviewedCount: number
+}, cardType: "doc" | "notebook" | "all", id?: string, title?: string) => {
     let blocks = cardsData.cards;
     let index = 0;
-    if (blocks.length > 0) {
-        html += `<div class="fn__flex" style="align-items: center" data-type="count">
-    <span class="fn__space"></span>
-    <div class="ft__on-surface ft__smaller"><span>1</span>/<span>${blocks.length}</span></div>
-</div>`;
-    }
     const dialog = new Dialog({
         content: `<div class="card__main">
     <div class="card__header">
         <span class="fn__flex-1 fn__flex-center">${window.siyuan.languages.riffCard}</span>
-        ${html}
+        <span class="fn__space"></span>
+        <div data-type="count" class="ft__on-surface ft__smaller fn__flex-center${blocks.length === 0 ? " fn__none" : ""}">1/${blocks.length}</span></div>
+        <div class="fn__space"></div>
+        <div data-id="${id}" data-cardtype="${cardType}" data-type="filter" class="block__icon block__icon--show">
+            <svg><use xlink:href="#iconFilter"></use></svg>
+        </div>
         <div class="fn__space"></div>
         ${isMobile() ? `<div data-type="close" class="block__icon block__icon--show">
             <svg><use xlink:href="#iconCloseRound"></use></svg>
@@ -145,10 +144,33 @@ export const openCardByData = (cardsData: { cards: ICard[], unreviewedCount: num
     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 selectElement = dialog.element.querySelector("select");
+    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;
-        const titleElement = countElement?.previousElementSibling;
         let type = "";
         if (typeof event.detail === "string") {
             if (event.detail === "1" || event.detail === "j") {
@@ -182,28 +204,69 @@ export const openCardByData = (cardsData: { cards: ICard[], unreviewedCount: num
                 event.preventDefault();
                 return;
             }
-            const newroundElement = hasClosestByAttribute(target, "data-type", "newround");
-            if (newroundElement) {
-                fetchPost(selectElement ? "/api/riff/getRiffDueCards" :
-                    (titleElement.getAttribute("data-id") ? "/api/riff/getTreeRiffDueCards" : "/api/riff/getNotebookRiffDueCards"), {
-                    rootID: titleElement.getAttribute("data-id"),
-                    deckID: selectElement?.value,
-                    notebook: titleElement.getAttribute("data-notebookid"),
-                }, (treeCards) => {
-                    index = 0;
-                    blocks = treeCards.data.cards;
-                    nextCard({
-                        countElement,
-                        editor,
-                        actionElements,
-                        index,
-                        blocks
+            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))
+                                filterElement.setAttribute("data-cardtype", toPath[0] === "/" ? "notebook" : "doc")
+                                fetchNewRound();
+                            })
+                        }
+                    }).element);
+                    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");
@@ -263,11 +326,12 @@ export const openCardByData = (cardsData: { cards: ICard[], unreviewedCount: num
                 /// #endif
                 index++;
                 if (index > blocks.length - 1) {
-                    fetchPost(selectElement ? "/api/riff/getRiffDueCards" :
-                        (titleElement.getAttribute("data-id") ? "/api/riff/getTreeRiffDueCards" : "/api/riff/getNotebookRiffDueCards"), {
-                        rootID: titleElement.getAttribute("data-id"),
-                        deckID: selectElement?.value,
-                        notebook: titleElement.getAttribute("data-notebookid"),
+                    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;
@@ -300,26 +364,6 @@ export const openCardByData = (cardsData: { cards: ICard[], unreviewedCount: num
             });
         }
     });
-    if (!selectElement) {
-        return;
-    }
-    selectElement.addEventListener("change", () => {
-        fetchPost("/api/riff/getRiffDueCards", {deckID: selectElement.value}, (cardsChangeResponse) => {
-            blocks = cardsChangeResponse.data.cards;
-            index = 0;
-            if (blocks.length > 0) {
-                nextCard({
-                    countElement,
-                    editor,
-                    actionElements,
-                    index,
-                    blocks
-                });
-            } else {
-                allDone(countElement, editor, actionElements);
-            }
-        });
-    });
 };
 
 const nextCard = (options: {
@@ -339,7 +383,7 @@ const nextCard = (options: {
     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.lastElementChild.innerHTML = `<span>${options.index + 1}</span>/${options.blocks.length}`;
+    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");

+ 2 - 2
app/src/menus/navigation.ts

@@ -133,7 +133,7 @@ export const initNavigationMenu = (liElement: HTMLElement) => {
             label: window.siyuan.languages.spaceRepetition,
             click: () => {
                 fetchPost("/api/riff/getNotebookRiffDueCards", {notebook: notebookId}, (response) => {
-                    openCardByData(response.data, `<span data-notebookid="${notebookId}" class="fn__flex-center">${escapeHtml(name)}</span>`);
+                    openCardByData(response.data, "notebook", notebookId, title);
                 });
                 /// #if MOBILE
                 closePanel();
@@ -342,7 +342,7 @@ export const initFileMenu = (notebookId: string, pathString: string, liElement:
                 label: window.siyuan.languages.spaceRepetition,
                 click: () => {
                     fetchPost("/api/riff/getTreeRiffDueCards", {rootID: id}, (response) => {
-                        openCardByData(response.data, `<span data-id="${id}"  class="fn__flex-center">${name}</span>`);
+                        openCardByData(response.data, "doc", id, name);
                     });
                     /// #if MOBILE
                     closePanel();

+ 1 - 1
app/src/protyle/header/Title.ts

@@ -343,7 +343,7 @@ export class Title {
                 label: window.siyuan.languages.spaceRepetition,
                 click: () => {
                     fetchPost("/api/riff/getTreeRiffDueCards", {rootID: protyle.block.rootID}, (response) => {
-                        openCardByData(response.data, `<span data-id="${protyle.block.rootID}"  class="fn__flex-center">${escapeHtml(this.editElement.textContent)}</span>`);
+                        openCardByData(response.data, "doc", protyle.block.rootID, this.editElement.textContent);
                     });
                 }
             }, {