mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-30 20:39:46 +02:00
Refactor file naming logic
This commit is contained in:
parent
53d48ab4f3
commit
9de0b4aea2
1 changed files with 46 additions and 36 deletions
|
|
@ -107,6 +107,10 @@ const clampNumber = (value: number, min: number, max: number) =>
|
||||||
Math.min(max, Math.max(min, value))
|
Math.min(max, Math.max(min, value))
|
||||||
|
|
||||||
const untitledBaseName = 'untitled'
|
const untitledBaseName = 'untitled'
|
||||||
|
const untitledIndexedNamePattern = /^untitled-\d+$/
|
||||||
|
|
||||||
|
const isUntitledPlaceholderName = (name: string) =>
|
||||||
|
name === untitledBaseName || untitledIndexedNamePattern.test(name)
|
||||||
|
|
||||||
const getHeadingTitle = (markdown: string) => {
|
const getHeadingTitle = (markdown: string) => {
|
||||||
const lines = markdown.split('\n')
|
const lines = markdown.split('\n')
|
||||||
|
|
@ -848,46 +852,52 @@ function App() {
|
||||||
let renamedTo: string | null = null
|
let renamedTo: string | null = null
|
||||||
try {
|
try {
|
||||||
// Only rename the currently active file (avoids renaming/jumping while user switches rapidly)
|
// Only rename the currently active file (avoids renaming/jumping while user switches rapidly)
|
||||||
if (
|
if (
|
||||||
wasActiveAtStart &&
|
wasActiveAtStart &&
|
||||||
selectedPathRef.current === pathAtStart &&
|
selectedPathRef.current === pathAtStart &&
|
||||||
!renameInProgressRef.current &&
|
!renameInProgressRef.current &&
|
||||||
pathAtStart.startsWith('knowledge/')
|
pathAtStart.startsWith('knowledge/')
|
||||||
) {
|
) {
|
||||||
const headingTitle = getHeadingTitle(debouncedContent)
|
|
||||||
const desiredName = headingTitle ? sanitizeHeadingForFilename(headingTitle) : null
|
|
||||||
const currentBase = getBaseName(pathAtStart)
|
const currentBase = getBaseName(pathAtStart)
|
||||||
if (desiredName && desiredName !== currentBase) {
|
if (isUntitledPlaceholderName(currentBase)) {
|
||||||
const parentDir = pathAtStart.split('/').slice(0, -1).join('/')
|
const headingTitle = getHeadingTitle(debouncedContent)
|
||||||
const targetPath = `${parentDir}/${desiredName}.md`
|
const desiredName = headingTitle ? sanitizeHeadingForFilename(headingTitle) : null
|
||||||
if (targetPath !== pathAtStart) {
|
if (desiredName && desiredName !== currentBase) {
|
||||||
const exists = await window.ipc.invoke('workspace:exists', { path: targetPath })
|
const parentDir = pathAtStart.split('/').slice(0, -1).join('/')
|
||||||
if (!exists.exists) {
|
let targetPath = `${parentDir}/${desiredName}.md`
|
||||||
renameInProgressRef.current = true
|
if (targetPath !== pathAtStart) {
|
||||||
await window.ipc.invoke('workspace:rename', { from: pathAtStart, to: targetPath })
|
let suffix = 1
|
||||||
pathToSave = targetPath
|
while (true) {
|
||||||
renamedFrom = pathAtStart
|
const exists = await window.ipc.invoke('workspace:exists', { path: targetPath })
|
||||||
renamedTo = targetPath
|
if (!exists.exists) break
|
||||||
editorPathRef.current = targetPath
|
targetPath = `${parentDir}/${desiredName}-${suffix}.md`
|
||||||
setFileTabs(prev => prev.map(tab => (tab.path === pathAtStart ? { ...tab, path: targetPath } : tab)))
|
suffix += 1
|
||||||
initialContentByPathRef.current.delete(pathAtStart)
|
}
|
||||||
const cachedContent = editorContentByPathRef.current.get(pathAtStart)
|
renameInProgressRef.current = true
|
||||||
if (cachedContent !== undefined) {
|
await window.ipc.invoke('workspace:rename', { from: pathAtStart, to: targetPath })
|
||||||
editorContentByPathRef.current.delete(pathAtStart)
|
pathToSave = targetPath
|
||||||
editorContentByPathRef.current.set(targetPath, cachedContent)
|
renamedFrom = pathAtStart
|
||||||
setEditorContentByPath((prev) => {
|
renamedTo = targetPath
|
||||||
const oldContent = prev[pathAtStart]
|
editorPathRef.current = targetPath
|
||||||
if (oldContent === undefined) return prev
|
setFileTabs(prev => prev.map(tab => (tab.path === pathAtStart ? { ...tab, path: targetPath } : tab)))
|
||||||
const next = { ...prev }
|
initialContentByPathRef.current.delete(pathAtStart)
|
||||||
delete next[pathAtStart]
|
const cachedContent = editorContentByPathRef.current.get(pathAtStart)
|
||||||
next[targetPath] = oldContent
|
if (cachedContent !== undefined) {
|
||||||
return next
|
editorContentByPathRef.current.delete(pathAtStart)
|
||||||
})
|
editorContentByPathRef.current.set(targetPath, cachedContent)
|
||||||
}
|
setEditorContentByPath((prev) => {
|
||||||
}
|
const oldContent = prev[pathAtStart]
|
||||||
}
|
if (oldContent === undefined) return prev
|
||||||
}
|
const next = { ...prev }
|
||||||
}
|
delete next[pathAtStart]
|
||||||
|
next[targetPath] = oldContent
|
||||||
|
return next
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
await window.ipc.invoke('workspace:writeFile', {
|
await window.ipc.invoke('workspace:writeFile', {
|
||||||
path: pathToSave,
|
path: pathToSave,
|
||||||
data: debouncedContent,
|
data: debouncedContent,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue