Browse Source

:sparkles: https://github.com/siyuan-note/siyuan/issues/7566

Vanessa 2 years ago
parent
commit
c4359cf20c
4 changed files with 129 additions and 33 deletions
  1. 85 0
      app/src/ai/actions.ts
  2. 39 0
      app/src/ai/chat.ts
  3. 3 0
      app/src/protyle/gutter/index.ts
  4. 2 33
      app/src/protyle/hint/index.ts

+ 85 - 0
app/src/ai/actions.ts

@@ -0,0 +1,85 @@
+import {MenuItem} from "../menus/Menu";
+import {fetchPost} from "../util/fetch";
+import {focusByRange} from "../protyle/util/selection";
+import {insertHTML} from "../protyle/util/insertHTML";
+
+export const AIActions = (elements: Element[], protyle: IProtyle) => {
+    const ids: string[] = []
+    elements.forEach(item => {
+        ids.push(item.getAttribute("data-node-id"))
+    })
+    window.siyuan.menus.menu.append(new MenuItem({
+        icon: "iconRefresh",
+        label: window.siyuan.languages.ai,
+        type: "submenu",
+        submenu: [{
+            label: window.siyuan.languages.aiContinueWrite,
+            click() {
+                fetchPost("/api/ai/chatGPTWithAction", {ids, action: "Continue writing"}, (response) => {
+                    focusByRange(protyle.toolbar.range);
+                    insertHTML(response.data, protyle, true);
+                });
+            }
+        }, {
+            label: window.siyuan.languages.aiTranslate,
+            type: "submenu",
+            submenu: [{
+                label: window.siyuan.languages.aiTranslate_zh_CN,
+                click() {
+                    fetchPost("/api/ai/chatGPTWithAction", {ids, action: "Translate"}, (response) => {
+                        focusByRange(protyle.toolbar.range);
+                        insertHTML(response.data, protyle, true);
+                    });
+                }
+            }, {
+                label: window.siyuan.languages.aiTranslate_ja_JP,
+                click() {
+                    fetchPost("/api/ai/chatGPTWithAction", {ids, action: "Translate"}, (response) => {
+                        focusByRange(protyle.toolbar.range);
+                        insertHTML(response.data, protyle, true);
+                    });
+                }
+            }, {
+                label: window.siyuan.languages.aiTranslate_ko_KR,
+                click() {
+                    fetchPost("/api/ai/chatGPTWithAction", {ids, action: "Translate"}, (response) => {
+                        focusByRange(protyle.toolbar.range);
+                        insertHTML(response.data, protyle, true);
+                    });
+                }
+            }, {
+                label: window.siyuan.languages.aiTranslate_en_US,
+                click() {
+                    fetchPost("/api/ai/chatGPTWithAction", {ids, action: "Translate"}, (response) => {
+                        focusByRange(protyle.toolbar.range);
+                        insertHTML(response.data, protyle, true);
+                    });
+                }
+            }, {
+                label: window.siyuan.languages.aiTranslate_es_ES,
+                click() {
+                    fetchPost("/api/ai/chatGPTWithAction", {ids, action: "Translate"}, (response) => {
+                        focusByRange(protyle.toolbar.range);
+                        insertHTML(response.data, protyle, true);
+                    });
+                }
+            }, {
+                label: window.siyuan.languages.aiTranslate_fr_FR,
+                click() {
+                    fetchPost("/api/ai/chatGPTWithAction", {ids, action: "Translate"}, (response) => {
+                        focusByRange(protyle.toolbar.range);
+                        insertHTML(response.data, protyle, true);
+                    });
+                }
+            }, {
+                label: window.siyuan.languages.aiTranslate_de_DE,
+                click() {
+                    fetchPost("/api/ai/chatGPTWithAction", {ids, action: "Translate"}, (response) => {
+                        focusByRange(protyle.toolbar.range);
+                        insertHTML(response.data, protyle, true);
+                    });
+                }
+            }]
+        }]
+    }).element);
+}

+ 39 - 0
app/src/ai/chat.ts

@@ -0,0 +1,39 @@
+import {Dialog} from "../dialog";
+import {isMobile} from "../util/functions";
+import {fetchPost} from "../util/fetch";
+import {focusByRange} from "../protyle/util/selection";
+import {insertHTML} from "../protyle/util/insertHTML";
+
+export const AIChat = (protyle:IProtyle) => {
+    const dialog = new Dialog({
+        title: "AI Chat",
+        content: `<div class="b3-dialog__content"><input class="b3-text-field fn__block" value=""></div>
+<div class="b3-dialog__action">
+    <button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
+    <button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
+</div>`,
+        width: isMobile() ? "80vw" : "520px",
+    });
+    const inputElement = dialog.element.querySelector("input") as HTMLInputElement;
+    const btnsElement = dialog.element.querySelectorAll(".b3-button");
+    dialog.bindInput(inputElement, () => {
+        (btnsElement[1] as HTMLButtonElement).click();
+    });
+    inputElement.focus();
+    btnsElement[0].addEventListener("click", () => {
+        dialog.destroy();
+    });
+    btnsElement[1].addEventListener("click", () => {
+        fetchPost("/api/ai/chatGPT", {
+            msg: inputElement.value,
+        }, (response) => {
+            dialog.destroy();
+            focusByRange(protyle.toolbar.range);
+            let respContent = "";
+            if (response.data && "" !== response.data) {
+                respContent = "\n\n" + response.data;
+            }
+            insertHTML(`${inputElement.value}${respContent}`, protyle, true);
+        });
+    });
+}

+ 3 - 0
app/src/protyle/gutter/index.ts

@@ -35,6 +35,7 @@ import {hintMoveBlock} from "../hint/extend";
 import {makeCard, quickMakeCard} from "../../card/makeCard";
 import {transferBlockRef} from "../../menus/block";
 import {isMobile} from "../../util/functions";
+import {AIActions} from "../../ai/actions";
 
 export class Gutter {
     public element: HTMLElement;
@@ -433,6 +434,7 @@ export class Gutter {
                 return true;
             }
         });
+        AIActions(selectsElement, protyle);
         if (!isList && !protyle.disabled) {
             const turnIntoSubmenu: IMenu[] = [];
             if (isContinue) {
@@ -732,6 +734,7 @@ export class Gutter {
         hideElements(["select"], protyle);
         nodeElement.classList.add("protyle-wysiwyg--select");
         countBlockWord([id], protyle.block.rootID);
+        AIActions([nodeElement], protyle);
         // "heading1-6", "list", "ordered-list", "check", "quote", "code", "table", "line", "math", "paragraph"
         if (type === "NodeParagraph" && !protyle.disabled) {
             turnIntoSubmenu.push(this.turnsIntoOne({

+ 2 - 33
app/src/protyle/hint/index.ts

@@ -29,8 +29,7 @@ import {openFileById} from "../../editor/util";
 import {openMobileFileById} from "../../mobile/editor";
 import {getIconByType} from "../../editor/getIcon";
 import {processRender} from "../util/processCode";
-import {Dialog} from "../../dialog";
-import {isMobile} from "../../util/functions";
+import {AIChat} from "../../ai/chat";
 
 export class Hint {
     public timeId: number;
@@ -552,37 +551,7 @@ ${unicode2Emoji(emoji.unicode, true)}</button>`;
                 });
                 return;
             } else if (value === Constants.ZWSP + 5) {
-                const dialog = new Dialog({
-                    title: "AI Chat",
-                    content: `<div class="b3-dialog__content"><input class="b3-text-field fn__block" value=""></div>
-<div class="b3-dialog__action">
-    <button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
-    <button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
-</div>`,
-                    width: isMobile() ? "80vw" : "520px",
-                });
-                const inputElement = dialog.element.querySelector("input") as HTMLInputElement;
-                const btnsElement = dialog.element.querySelectorAll(".b3-button");
-                dialog.bindInput(inputElement, () => {
-                    (btnsElement[1] as HTMLButtonElement).click();
-                });
-                inputElement.focus();
-                btnsElement[0].addEventListener("click", () => {
-                    dialog.destroy();
-                });
-                btnsElement[1].addEventListener("click", () => {
-                    fetchPost("/api/ai/chatGPT", {
-                        msg: inputElement.value,
-                    }, (response) => {
-                        dialog.destroy();
-                        focusByRange(protyle.toolbar.range);
-                        let respContent = "";
-                        if (response.data && "" !== response.data) {
-                            respContent = "\n\n" + response.data;
-                        }
-                        insertHTML(`${inputElement.value}${respContent}`, protyle, true);
-                    });
-                });
+                AIChat(protyle);
                 return;
             } else if (Constants.INLINE_TYPE.includes(value)) {
                 range.deleteContents();