From 306262caba00709713d1c151f4fe9138bde1268c Mon Sep 17 00:00:00 2001 From: natreex Date: Tue, 13 Jan 2026 19:52:31 -0500 Subject: [PATCH] Add QuillSense support with settings and integration - Introduced new "QuillSense" feature for AI-assisted book creation. - Added QuillSense settings panel with advanced options and disable/enable functionality. - Updated GhostWriter and TextEditor components to respect QuillSense settings. - Extended models and repositories to track and manage QuillSense state per book. - Localized new strings for English and French. --- components/ScribeControllerBar.tsx | 3 ++- components/book/BookList.tsx | 1 + .../book/settings/BookSettingOption.tsx | 13 +++++++++- .../book/settings/BookSettingSidebar.tsx | 7 +++++- components/editor/TextEditor.tsx | 2 +- components/ghostwriter/GhostWriter.tsx | 22 ++++++++++------ components/rightbar/ComposerRightBar.tsx | 11 +++++++- .../repositories/chaptercontent.repository.ts | 16 ++++-------- lib/locales/en.json | 25 +++++++++++++++++-- lib/locales/fr.json | 25 +++++++++++++++++-- lib/models/Book.ts | 2 ++ lib/models/BookTables.ts | 7 ++++++ 12 files changed, 106 insertions(+), 28 deletions(-) diff --git a/components/ScribeControllerBar.tsx b/components/ScribeControllerBar.tsx index e90759c..8a6d2f5 100644 --- a/components/ScribeControllerBar.tsx +++ b/components/ScribeControllerBar.tsx @@ -77,6 +77,7 @@ export default function ScribeControllerBar() { publicationDate: response.desiredReleaseDate, desiredWordCount: response.desiredWordCount, totalWordCount: response.desiredWordCount, + quillsenseEnabled: response.quillsenseEnabled, }); } catch (e: unknown) { if (e instanceof Error) { @@ -141,7 +142,7 @@ export default function ScribeControllerBar() {
{ - hasAccess && + hasAccess && book?.quillsenseEnabled !== false && }
Promise } | null> = useRef<{ handleSave: () => Promise }>(null); - + const quillSenseRef: RefObject<{ handleSave: () => Promise } | null> = useRef<{ + handleSave: () => Promise + }>(null); + function renderTitle(): string { switch (setting) { case 'basic-information': @@ -54,6 +58,8 @@ export default function BookSettingOption( return t("bookSettingOption.objectsList"); case 'goals': return t("bookSettingOption.bookGoals"); + case 'quillsense': + return t("bookSettingOption.quillsense"); default: return ""; } @@ -79,6 +85,9 @@ export default function BookSettingOption( case 'characters': characterRef.current?.handleSave(); break; + case 'quillsense': + quillSenseRef.current?.handleSave(); + break; default: break; } @@ -109,6 +118,8 @@ export default function BookSettingOption( ) : setting === 'characters' ? ( + ) : setting === 'quillsense' ? ( + ) :
{t("bookSettingOption.notAvailable")}
} diff --git a/components/book/settings/BookSettingSidebar.tsx b/components/book/settings/BookSettingSidebar.tsx index 0fa4939..de1797c 100644 --- a/components/book/settings/BookSettingSidebar.tsx +++ b/components/book/settings/BookSettingSidebar.tsx @@ -1,7 +1,7 @@ 'use client' // Removed Next.js Link import for Electron import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; -import {faBook, faGlobe, faListAlt, faMapMarkedAlt, faPencilAlt, faUser} from "@fortawesome/free-solid-svg-icons"; +import {faBook, faFeather, faGlobe, faListAlt, faMapMarkedAlt, faPencilAlt, faUser} from "@fortawesome/free-solid-svg-icons"; import {Dispatch, SetStateAction} from "react"; import {IconDefinition} from "@fortawesome/fontawesome-svg-core"; import {useTranslations} from "next-intl"; @@ -53,6 +53,11 @@ export default function BookSettingSidebar( name: 'bookSetting.characters', icon: faUser }, + { + id: 'quillsense', + name: 'bookSetting.quillsense', + icon: faFeather + }, // { // id: 'objects', // name: t('bookSetting.objects'), diff --git a/components/editor/TextEditor.tsx b/components/editor/TextEditor.tsx index faea429..b5804c2 100644 --- a/components/editor/TextEditor.tsx +++ b/components/editor/TextEditor.tsx @@ -483,7 +483,7 @@ export default function TextEditor() { onClick={handleShowUserSettings} icon={faCog} /> - {chapter?.chapterContent.version === 2 && !isCurrentlyOffline() && !book?.localBook && ( + {chapter?.chapterContent.version === 2 && !isCurrentlyOffline() && !book?.localBook && book?.quillsenseEnabled !== false && (

{t("ghostWriter.title")}

-

{t("ghostWriter.subscriptionRequired")}

- +

+ {!book?.quillsenseEnabled + ? t("ghostWriter.quillsenseDisabled") + : t("ghostWriter.subscriptionRequired")} +

+ {hasAccess && !book?.quillsenseEnabled ? null : ( + + )}
); diff --git a/components/rightbar/ComposerRightBar.tsx b/components/rightbar/ComposerRightBar.tsx index 736c730..30bcee2 100644 --- a/components/rightbar/ComposerRightBar.tsx +++ b/components/rightbar/ComposerRightBar.tsx @@ -171,7 +171,16 @@ export default function ComposerRightBar() {
{book ? editorComponents .filter((component: PanelComponent):boolean => { - return !((isCurrentlyOffline() || book?.localBook) && component.id === 1); + // Filter QuillSense if offline, local book, or quillsenseEnabled is false + if (component.id === 1) { + if (isCurrentlyOffline() || book?.localBook) { + return false; + } + if (book?.quillsenseEnabled === false) { + return false; + } + } + return true; }) .map((component: PanelComponent) => (