diff --git a/app/src/ai/actions.ts b/app/src/ai/actions.ts
new file mode 100644
index 000000000..a12dcc2c6
--- /dev/null
+++ b/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);
+}
diff --git a/app/src/ai/chat.ts b/app/src/ai/chat.ts
new file mode 100644
index 000000000..fa481dfac
--- /dev/null
+++ b/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: `
+
+
+
+
`,
+ 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);
+ });
+ });
+}
diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts
index 19dabf2a8..cb190c6cd 100644
--- a/app/src/protyle/gutter/index.ts
+++ b/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({
diff --git a/app/src/protyle/hint/index.ts b/app/src/protyle/hint/index.ts
index 5b58a43e8..8708f84c2 100644
--- a/app/src/protyle/hint/index.ts
+++ b/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)}`;
});
return;
} else if (value === Constants.ZWSP + 5) {
- const dialog = new Dialog({
- title: "AI Chat",
- content: `
-
-
-
-
`,
- 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();