From c62a7eb0f78eaa76b446837ead30380dd0c2c386 Mon Sep 17 00:00:00 2001 From: natreex Date: Sat, 17 Jan 2026 23:26:22 -0500 Subject: [PATCH] Add advanced generation options with Explicit and Smart modes - Implemented `AdvancedGenerationOptions` component for toggling Explicit and Smart modes with confirmation dialogs. - Integrated generation options into `GhostWriter`, `DraftCompanion`, and `ShortStoryGenerator`. - Introduced `ToggleWithConfirmation` component for user interaction with alerts. - Updated `InputField` to support centered alignment for better layout flexibility. - Localized Explicit and Smart mode strings in English and French. - Enhanced content preview logic to filter placeholder text before display. - Added `autoUpdater` initialization checks and refactored updater setup for improved reliability. --- components/QSTextGeneratedPreview.tsx | 50 ++++++++++--- components/ShortStoryGenerator.tsx | 41 ++++++---- components/editor/DraftCompanion.tsx | 17 ++++- components/form/AdvancedGenerationOptions.tsx | 61 +++++++++++++++ components/form/InputField.tsx | 10 ++- components/form/ToggleWithConfirmation.tsx | 63 ++++++++++++++++ components/ghostwriter/GhostWriter.tsx | 17 ++++- electron/autoUpdater.ts | 75 +++++++++++++++++++ electron/main.ts | 7 +- lib/locales/en.json | 14 ++++ lib/locales/fr.json | 14 ++++ 11 files changed, 335 insertions(+), 34 deletions(-) create mode 100644 components/form/AdvancedGenerationOptions.tsx create mode 100644 components/form/ToggleWithConfirmation.tsx create mode 100644 electron/autoUpdater.ts diff --git a/components/QSTextGeneratedPreview.tsx b/components/QSTextGeneratedPreview.tsx index 2be42c2..3b45a85 100644 --- a/components/QSTextGeneratedPreview.tsx +++ b/components/QSTextGeneratedPreview.tsx @@ -26,6 +26,9 @@ export default function QSTextGeneratedPreview( const [mounted, setMounted] = useState(false); const [isVisible, setIsVisible] = useState(false); const t = useTranslations(); + + const filteredValue: string = value.replace(/^starting\.{0,3}\s*/i, '').trim(); + const hasRealContent: boolean = filteredValue.length > 0; useEffect((): () => void => { setMounted(true); @@ -83,21 +86,46 @@ export default function QSTextGeneratedPreview(
- {isGenerating && !value ? ( -
-
-
-
-
-
-
-
-
+ {isGenerating && !hasRealContent ? ( +
+
+ + + + + + + +
+
+ + + + + + +
+
+ + + + + + + +
+
+ + + + + +
) : (
- {value} + {filteredValue}
)} diff --git a/components/ShortStoryGenerator.tsx b/components/ShortStoryGenerator.tsx index e523dbd..5f75e70 100644 --- a/components/ShortStoryGenerator.tsx +++ b/components/ShortStoryGenerator.tsx @@ -53,6 +53,7 @@ import QuillSense from "@/lib/models/QuillSense"; import {useTranslations} from "next-intl"; import {LangContext, LangContextProps} from "@/context/LangContext"; import {AIUsageContext, AIUsageContextProps} from "@/context/AIUsageContext"; +import AdvancedGenerationOptions from "@/components/form/AdvancedGenerationOptions"; interface ShortStoryGeneratorProps { onClose: () => void; @@ -93,7 +94,10 @@ export default function ShortStoryGenerator({onClose}: ShortStoryGeneratorProps) const [hasGenerated, setHasGenerated] = useState(false); const [abortController, setAbortController] = useState | null>(null); - + + const [useExplicit, setUseExplicit] = useState(false); + const [useSmart, setUseSmart] = useState(false); + const isAnthropicEnabled: boolean = QuillSense.isAnthropicEnabled(session); const isSubTierTwo: boolean = QuillSense.getSubLevel(session) >= 2; const hasAccess: boolean = isAnthropicEnabled || isSubTierTwo; @@ -169,7 +173,9 @@ export default function ShortStoryGenerator({onClose}: ShortStoryGeneratorProps) language: language, dialogueType: dialogueType, directives: directives, - wordsCount: wordsCount + wordsCount: wordsCount, + useExplicit: useExplicit, + useSmart: useSmart, }), }); @@ -338,7 +344,7 @@ export default function ShortStoryGenerator({onClose}: ShortStoryGeneratorProps)
); } - + return (
)} - + {activeTab === 2 && (
@@ -487,7 +493,7 @@ export default function ShortStoryGenerator({onClose}: ShortStoryGeneratorProps) } />
- + } /> - +
)} - + {activeTab === 3 && (
@@ -535,7 +541,7 @@ export default function ShortStoryGenerator({onClose}: ShortStoryGeneratorProps) } />
- +
- + } /> + +
)} - + {activeTab === 4 && (
@@ -600,7 +613,7 @@ export default function ShortStoryGenerator({onClose}: ShortStoryGeneratorProps) )}
- + {isGenerating && !generatedText ? (
)} - + {generatedText && (
@@ -640,7 +653,7 @@ export default function ShortStoryGenerator({onClose}: ShortStoryGeneratorProps) {t("shortStoryGenerator.navigation.previous")} - +
- + {activeTab < 3 ? ( - + { + console.log('[AutoUpdater] Checking for updates...'); + }); + + autoUpdater.on('update-available', (info: UpdateInfo) => { + console.log('[AutoUpdater] Update available:', info.version); + currentWindow?.webContents.send('update:available', info.version); + }); + + autoUpdater.on('update-not-available', () => { + console.log('[AutoUpdater] App is up to date'); + }); + + autoUpdater.on('download-progress', (progress) => { + const percent = Math.round(progress.percent); + console.log(`[AutoUpdater] Downloading: ${percent}%`); + currentWindow?.webContents.send('update:progress', percent); + }); + + autoUpdater.on('update-downloaded', (info: UpdateInfo) => { + console.log('[AutoUpdater] Update ready:', info.version); + currentWindow?.webContents.send('update:ready', info.version); + }); + + autoUpdater.on('error', (error: Error) => { + console.error('[AutoUpdater] Error:', error.message); + }); + + // Check initial + autoUpdater.checkForUpdates().catch((err) => { + console.error('[AutoUpdater] Check failed:', err.message); + }); + + // Re-check périodique + setInterval(() => { + autoUpdater.checkForUpdates().catch((err) => { + console.error('[AutoUpdater] Periodic check failed:', err.message); + }); + }, updateCheckInterval); +} + +// Pour forcer l'installation immédiate (optionnel, appelable depuis le renderer) +export function installUpdateNow(): void { + autoUpdater.quitAndInstall(false, true); +} \ No newline at end of file diff --git a/electron/main.ts b/electron/main.ts index 2a0a9ca..44644a2 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -87,6 +87,9 @@ function createLoginWindow(): void { loginWindow.once('ready-to-show', () => { loginWindow?.show(); + if (loginWindow) { + initAutoUpdater(loginWindow); + } }); loginWindow.on('closed', () => { @@ -145,7 +148,9 @@ function createMainWindow(): void { mainWindow.once('ready-to-show', () => { mainWindow?.show(); - initAutoUpdater(mainWindow); + if (mainWindow) { + initAutoUpdater(mainWindow); + } }); mainWindow.on('closed', () => { diff --git a/lib/locales/en.json b/lib/locales/en.json index ac12577..0833e10 100644 --- a/lib/locales/en.json +++ b/lib/locales/en.json @@ -1,4 +1,18 @@ { + "generationOptions": { + "explicit": { + "label": "Explicit", + "alertTitle": "Explicit Mode", + "alertMessage": "This mode enables mature content generation. Some restrictions remain in effect. For users 18 years and older only." + }, + "smart": { + "label": "Smart", + "alertTitle": "Smart Mode", + "alertMessage": "This mode uses the most powerful models (Claude Opus, Grok 4.1) for superior generation quality. Additional fees apply." + }, + "activate": "Activate", + "cancel": "Cancel" + }, "loginPage": { "title": "Login", "welcome": "Welcome to ERitors", diff --git a/lib/locales/fr.json b/lib/locales/fr.json index 786920d..14c528c 100644 --- a/lib/locales/fr.json +++ b/lib/locales/fr.json @@ -1,4 +1,18 @@ { + "generationOptions": { + "explicit": { + "label": "Explicite", + "alertTitle": "Mode Explicite", + "alertMessage": "Ce mode permet de générer du contenu mature. Certaines restrictions demeurent en vigueur. Réservé aux utilisateurs de 18 ans et plus." + }, + "smart": { + "label": "Intelligent", + "alertTitle": "Mode Intelligent", + "alertMessage": "Ce mode utilise les modèles les plus performants (Claude Opus, Grok 4.1) pour une qualité de génération supérieure. Des frais supplémentaires s'appliquent." + }, + "activate": "Activer", + "cancel": "Annuler" + }, "loginPage": { "title": "Connexion", "welcome": "Bienvenue sur ERitors",