✨ set project title
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
import { join } from 'path'
|
import { join, basename } from 'path'
|
||||||
import { homedir } from 'os'
|
import { homedir } from 'os'
|
||||||
import { readFileSync, writeFileSync, mkdirSync } from 'fs'
|
import { readFileSync, writeFileSync, mkdirSync } from 'fs'
|
||||||
|
|
||||||
export interface GlobalConfig {
|
export interface GlobalConfig {
|
||||||
apiKey?: string
|
apiKey?: string
|
||||||
projectPath?: string
|
projectPath?: string
|
||||||
|
projectTitle?: string
|
||||||
fontSize?: number
|
fontSize?: number
|
||||||
theme?: 'dark' | 'light'
|
theme?: 'dark' | 'light'
|
||||||
}
|
}
|
||||||
@@ -28,6 +29,9 @@ export const getDraftRoot = (): string =>
|
|||||||
export const getApiKey = (): string | undefined =>
|
export const getApiKey = (): string | undefined =>
|
||||||
_config.apiKey ?? process.env.ANTHROPIC_API_KEY
|
_config.apiKey ?? process.env.ANTHROPIC_API_KEY
|
||||||
|
|
||||||
|
export const getProjectTitle = (): string =>
|
||||||
|
_config.projectTitle?.trim() || basename(getDraftRoot())
|
||||||
|
|
||||||
export function readGlobalConfig(): GlobalConfig {
|
export function readGlobalConfig(): GlobalConfig {
|
||||||
return { ..._config }
|
return { ..._config }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { listDraftFiles, readMarkdownFile, writeMarkdownFile, getProjectWordCoun
|
|||||||
import type { SearchOptions } from './fileSystem'
|
import type { SearchOptions } from './fileSystem'
|
||||||
import { streamMessage, resetClient } from './aiService'
|
import { streamMessage, resetClient } from './aiService'
|
||||||
import type { AIPayload, Attachment } from '../renderer/types/editor'
|
import type { AIPayload, Attachment } from '../renderer/types/editor'
|
||||||
import { readGlobalConfig, writeGlobalConfig, getDraftRoot } from './globalConfig'
|
import { readGlobalConfig, writeGlobalConfig, getProjectTitle } from './globalConfig'
|
||||||
import type { GlobalConfig } from './globalConfig'
|
import type { GlobalConfig } from './globalConfig'
|
||||||
|
|
||||||
export function registerIpcHandlers(): void {
|
export function registerIpcHandlers(): void {
|
||||||
@@ -278,7 +278,7 @@ export function registerIpcHandlers(): void {
|
|||||||
|
|
||||||
ipcMain.handle('export:projectPdf', async (event): Promise<void> => {
|
ipcMain.handle('export:projectPdf', async (event): Promise<void> => {
|
||||||
const win = BrowserWindow.fromWebContents(event.sender)
|
const win = BrowserWindow.fromWebContents(event.sender)
|
||||||
const projectName = basename(getDraftRoot())
|
const projectName = getProjectTitle()
|
||||||
|
|
||||||
const result = await dialog.showSaveDialog(win!, {
|
const result = await dialog.showSaveDialog(win!, {
|
||||||
defaultPath: `${projectName}.pdf`,
|
defaultPath: `${projectName}.pdf`,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ interface Props {
|
|||||||
export function SettingsDialog({ onClose, onProjectChanged, isSetup }: Props): JSX.Element {
|
export function SettingsDialog({ onClose, onProjectChanged, isSetup }: Props): JSX.Element {
|
||||||
const [apiKey, setApiKey] = useState('')
|
const [apiKey, setApiKey] = useState('')
|
||||||
const [projectPath, setProjectPath] = useState('')
|
const [projectPath, setProjectPath] = useState('')
|
||||||
|
const [projectTitle, setProjectTitle] = useState('')
|
||||||
const [originalPath, setOriginalPath] = useState('')
|
const [originalPath, setOriginalPath] = useState('')
|
||||||
const [saved, setSaved] = useState(false)
|
const [saved, setSaved] = useState(false)
|
||||||
const overlayRef = useRef<HTMLDivElement>(null)
|
const overlayRef = useRef<HTMLDivElement>(null)
|
||||||
@@ -18,6 +19,7 @@ export function SettingsDialog({ onClose, onProjectChanged, isSetup }: Props): J
|
|||||||
window.api.readConfig().then((cfg) => {
|
window.api.readConfig().then((cfg) => {
|
||||||
setApiKey(cfg.apiKey ?? '')
|
setApiKey(cfg.apiKey ?? '')
|
||||||
setProjectPath(cfg.projectPath ?? '')
|
setProjectPath(cfg.projectPath ?? '')
|
||||||
|
setProjectTitle(cfg.projectTitle ?? '')
|
||||||
setOriginalPath(cfg.projectPath ?? '')
|
setOriginalPath(cfg.projectPath ?? '')
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
@@ -41,7 +43,7 @@ export function SettingsDialog({ onClose, onProjectChanged, isSetup }: Props): J
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSave = async (): Promise<void> => {
|
const handleSave = async (): Promise<void> => {
|
||||||
await window.api.writeConfig({ apiKey: apiKey || undefined, projectPath: projectPath || undefined })
|
await window.api.writeConfig({ apiKey: apiKey || undefined, projectPath: projectPath || undefined, projectTitle: projectTitle.trim() || undefined })
|
||||||
if (projectPath !== originalPath) onProjectChanged?.()
|
if (projectPath !== originalPath) onProjectChanged?.()
|
||||||
setOriginalPath(projectPath)
|
setOriginalPath(projectPath)
|
||||||
setSaved(true)
|
setSaved(true)
|
||||||
@@ -79,6 +81,20 @@ export function SettingsDialog({ onClose, onProjectChanged, isSetup }: Props): J
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="settings-field">
|
||||||
|
<label className="settings-label" htmlFor="settings-project-title">Project Title</label>
|
||||||
|
<input
|
||||||
|
id="settings-project-title"
|
||||||
|
className="settings-input"
|
||||||
|
type="text"
|
||||||
|
value={projectTitle}
|
||||||
|
onChange={(e) => setProjectTitle(e.target.value)}
|
||||||
|
placeholder="My Novel"
|
||||||
|
spellCheck={false}
|
||||||
|
/>
|
||||||
|
<p className="settings-hint">Used as the title in PDF exports. Defaults to the project folder name if left blank.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="settings-field">
|
<div className="settings-field">
|
||||||
<label className="settings-label" htmlFor="settings-api-key">Anthropic API Key</label>
|
<label className="settings-label" htmlFor="settings-api-key">Anthropic API Key</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export interface GlobalConfig {
|
export interface GlobalConfig {
|
||||||
apiKey?: string
|
apiKey?: string
|
||||||
projectPath?: string
|
projectPath?: string
|
||||||
|
projectTitle?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileNode {
|
export interface FileNode {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user