diff --git a/package-lock.json b/package-lock.json index e6d6a781..c96cbe99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "@types/react": "17.0.0", "@types/react-datepicker": "^4.1.7", "@types/react-dom": "17.0.0", - "@types/vscode": "^1.63.0", + "@types/vscode": "^1.70.0", "@typescript-eslint/eslint-plugin": "^5.50.0", "@typescript-eslint/parser": "^5.50.0", "@vscode/codicons": "0.0.20", @@ -111,7 +111,7 @@ "yawn-yaml": "^1.5.0" }, "engines": { - "vscode": "^1.63.0" + "vscode": "^1.70.0" } }, "node_modules/@actions/core": { @@ -1225,9 +1225,10 @@ "license": "MIT" }, "node_modules/@types/vscode": { - "version": "1.63.0", - "dev": true, - "license": "MIT" + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.76.0.tgz", + "integrity": "sha512-CQcY3+Fe5hNewHnOEAVYj4dd1do/QHliXaknAEYSXx2KEHUzFibDZSKptCon+HPgK55xx20pR+PBJjf0MomnBA==", + "dev": true }, "node_modules/@types/vscode-webview": { "version": "1.57.0", @@ -13752,7 +13753,9 @@ "dev": true }, "@types/vscode": { - "version": "1.63.0", + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.76.0.tgz", + "integrity": "sha512-CQcY3+Fe5hNewHnOEAVYj4dd1do/QHliXaknAEYSXx2KEHUzFibDZSKptCon+HPgK55xx20pR+PBJjf0MomnBA==", "dev": true }, "@types/vscode-webview": { diff --git a/package.json b/package.json index 2f40df56..21c9004d 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "qna": "https://github.com/estruyf/vscode-front-matter/discussions", "engines": { - "vscode": "^1.63.0" + "vscode": "^1.70.0" }, "categories": [ "Other" @@ -96,6 +96,12 @@ "configuration": { "title": "Front Matter: use frontmatter.json for shared team settings", "properties": { + "frontMatter.sponsors.ai.titleEnabled": { + "type": "boolean", + "default": false, + "markdownDescription": "Specify if you want to enable AI suggestions for content titles. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.sponsors.ai.titleenabled)", + "scope": "Sponsors" + }, "frontMatter.extensibility.scripts": { "type": "array", "markdownDescription": "Specify the list of scripts to load in the Front Matter CMS. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.extensibility.scripts)", @@ -2285,7 +2291,7 @@ "@types/react": "17.0.0", "@types/react-datepicker": "^4.1.7", "@types/react-dom": "17.0.0", - "@types/vscode": "^1.63.0", + "@types/vscode": "^1.70.0", "@typescript-eslint/eslint-plugin": "^5.50.0", "@typescript-eslint/parser": "^5.50.0", "@vscode/codicons": "0.0.20", diff --git a/src/constants/settings.ts b/src/constants/settings.ts index 1d4b8e80..330d7f80 100644 --- a/src/constants/settings.ts +++ b/src/constants/settings.ts @@ -90,6 +90,11 @@ export const SETTING_SITE_BASEURL = 'site.baseURL'; export const SETTING_GIT_ENABLED = 'git.enabled'; export const SETTING_GIT_COMMIT_MSG = 'git.commitMessage'; +/** + * Sponsors only settings + */ +export const SETTING_SPONSORS_AI_TITLE = 'sponsors.ai.titleEnabled'; + /** * @deprecated */ diff --git a/src/helpers/Questions.ts b/src/helpers/Questions.ts index a9b43297..38fe044d 100644 --- a/src/helpers/Questions.ts +++ b/src/helpers/Questions.ts @@ -1,7 +1,12 @@ -import { window } from 'vscode'; +import { QuickPickItem, QuickPickItemKind, window } from 'vscode'; +import { Backers } from '../commands'; import { Folders } from '../commands/Folders'; +import { SETTING_SEO_TITLE_LENGTH, SETTING_SPONSORS_AI_TITLE } from '../constants'; import { ContentType } from './ContentType'; import { Notifications } from './Notifications'; +import { Settings } from './SettingsHelper'; +import { Logger } from './Logger'; +import fetch from 'node-fetch'; export class Questions { /** @@ -24,12 +29,87 @@ export class Questions { * @returns */ public static async ContentTitle(showWarning: boolean = true): Promise { - const title = await window.showInputBox({ - title: 'Title', - prompt: `What would you like to use as a title for the content to create?`, - placeHolder: `Content title`, - ignoreFocusOut: true - }); + const aiContentTitle = Settings.get(SETTING_SPONSORS_AI_TITLE); + const username = await Backers.getUsername(); + + let title: string | undefined = ''; + + if (aiContentTitle && username) { + title = await window.showInputBox({ + title: 'Title or description', + prompt: `What would you like to write about?`, + placeHolder: `Content title or description`, + ignoreFocusOut: true + }); + + if (title) { + try { + const response = await fetch(`https://frontmatter.codes/api/ai-title`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + accept: 'application/json' + }, + body: JSON.stringify({ + title: title, + username: username, + nrOfCharacters: Settings.get(SETTING_SEO_TITLE_LENGTH) || 60 + }) + }); + const data: string[] = await response.json(); + + if (data && data.length > 0) { + const options: QuickPickItem[] = [ + { + label: `✏️ your title/description`, + kind: QuickPickItemKind.Separator + }, + { + label: title + }, + { + label: `🤖 AI generated title`, + kind: QuickPickItemKind.Separator + }, + ...data.map((d: string) => ({ + label: d + })) + ]; + + const selectedTitle = await window.showQuickPick(options, { + title: 'Select a title', + placeHolder: `Select a title for your content`, + ignoreFocusOut: true + }); + + if (selectedTitle) { + title = selectedTitle.label; + } else if (!selectedTitle) { + // Reset the title, so the user can enter their own title + title = undefined; + } + } + } catch (e) { + Logger.error((e as Error).message); + Notifications.error( + `Failed fetching the AI title. Please try to use your own title or try again later.` + ); + title = undefined; + } + } else if (!title && showWarning) { + Notifications.warning(`You did not specify a title for your content.`); + return; + } + } + + if (!title) { + title = await window.showInputBox({ + title: 'Title', + prompt: `What would you like to use as a title for the content to create?`, + placeHolder: `Content title`, + ignoreFocusOut: true + }); + } if (!title && showWarning) { Notifications.warning(`You did not specify a title for your content.`);