diff options
| author | haoyuren <13851610112@163.com> | 2026-03-13 02:15:10 -0500 |
|---|---|---|
| committer | haoyuren <13851610112@163.com> | 2026-03-13 02:15:10 -0500 |
| commit | 82447ef3229336b914344f5671c4cb8bd589dcdc (patch) | |
| tree | 6f1f89e515c452fdc0cf84ac48ed40b67bb7c3bc /src/renderer | |
| parent | 03477143154462b8c1332f1081fdf400ac80be53 (diff) | |
Fix terminal cwd, selection highlight, comment range preservation
- Terminal now spawns in project sync directory so Claude Code can
read/write .tex files
- Selection highlight uses semi-transparent color to layer above
active line highlight
- External edits use diff-match-patch for minimal changes instead of
full doc replace, preserving comment highlight positions
- Set connection state on project open so status bar shows Connected
- Remove cursor:pointer from comment highlights
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'src/renderer')
| -rw-r--r-- | src/renderer/src/components/Editor.tsx | 7 | ||||
| -rw-r--r-- | src/renderer/src/components/ProjectList.tsx | 2 | ||||
| -rw-r--r-- | src/renderer/src/components/Terminal.tsx | 5 | ||||
| -rw-r--r-- | src/renderer/src/extensions/commentHighlights.ts | 1 | ||||
| -rw-r--r-- | src/renderer/src/ot/overleafSync.ts | 28 | ||||
| -rw-r--r-- | src/renderer/src/stores/appStore.ts | 5 |
6 files changed, 37 insertions, 11 deletions
diff --git a/src/renderer/src/components/Editor.tsx b/src/renderer/src/components/Editor.tsx index 649b238..4328c22 100644 --- a/src/renderer/src/components/Editor.tsx +++ b/src/renderer/src/components/Editor.tsx @@ -32,9 +32,10 @@ const cosmicLatteTheme = EditorView.theme({ color: '#3B3228', padding: '8px 0' }, '.cm-cursor': { borderLeftColor: '#3B3228' }, - '.cm-activeLine': { backgroundColor: '#F5EDD6' }, - '.cm-activeLineGutter': { backgroundColor: '#F5EDD6' }, - '.cm-selectionBackground, ::selection': { backgroundColor: '#B8D4E3 !important' }, + '.cm-activeLine': { backgroundColor: 'rgba(214, 206, 188, 0.3)' }, + '.cm-activeLineGutter': { backgroundColor: 'rgba(214, 206, 188, 0.3)' }, + '.cm-selectionBackground, ::selection': { backgroundColor: 'rgba(120, 170, 210, 0.45) !important' }, + '&.cm-focused .cm-selectionBackground': { backgroundColor: 'rgba(120, 170, 210, 0.45) !important' }, '.cm-gutters': { backgroundColor: '#F5EDD6', color: '#A09880', border: 'none', borderRight: '1px solid #D6CEBC', paddingRight: '8px' diff --git a/src/renderer/src/components/ProjectList.tsx b/src/renderer/src/components/ProjectList.tsx index d5b382c..a3c9c37 100644 --- a/src/renderer/src/components/ProjectList.tsx +++ b/src/renderer/src/components/ProjectList.tsx @@ -65,6 +65,8 @@ export default function ProjectList({ onOpenProject }: Props) { if (result.fileRefs) store.setFileRefs(result.fileRefs) if (result.rootFolderId) store.setRootFolderId(result.rootFolderId) store.setOverleafProjectId(pid) + store.setConnectionState('connected') + if (result.syncDir) store.setSyncDir(result.syncDir) setStatusMessage('Connected') onOpenProject(pid) } else { diff --git a/src/renderer/src/components/Terminal.tsx b/src/renderer/src/components/Terminal.tsx index 3781a53..e2eb5e8 100644 --- a/src/renderer/src/components/Terminal.tsx +++ b/src/renderer/src/components/Terminal.tsx @@ -55,8 +55,9 @@ export default function Terminal() { xtermRef.current = xterm fitAddonRef.current = fitAddon - // Spawn shell - window.api.ptySpawn('/tmp') + // Spawn shell in project sync directory + const syncDir = useAppStore.getState().syncDir || '/tmp' + window.api.ptySpawn(syncDir) // Pipe data const unsubData = window.api.onPtyData((data) => { diff --git a/src/renderer/src/extensions/commentHighlights.ts b/src/renderer/src/extensions/commentHighlights.ts index 3215026..8ea1cd7 100644 --- a/src/renderer/src/extensions/commentHighlights.ts +++ b/src/renderer/src/extensions/commentHighlights.ts @@ -220,7 +220,6 @@ const commentHighlightTheme = EditorView.baseTheme({ backgroundColor: 'rgba(243, 177, 17, 0.25)', borderBottom: '2px solid rgba(243, 177, 17, 0.5)', padding: '1px 0', - cursor: 'pointer', }, '.cm-comment-highlight-hover': { backgroundColor: 'rgba(243, 177, 17, 0.45)', diff --git a/src/renderer/src/ot/overleafSync.ts b/src/renderer/src/ot/overleafSync.ts index 787a458..1c6672b 100644 --- a/src/renderer/src/ot/overleafSync.ts +++ b/src/renderer/src/ot/overleafSync.ts @@ -3,7 +3,8 @@ // Per-document orchestrator: ties CM6 adapter to OT client, IPC bridge import type { EditorView } from '@codemirror/view' -import { ChangeSet, Transaction, type Text } from '@codemirror/state' +import { ChangeSet, Transaction, type ChangeSpec, type Text } from '@codemirror/state' +import { diff_match_patch } from 'diff-match-patch' import { OtClient } from './otClient' import type { OtOp } from './types' import { changeSetToOtOps, otOpsToChangeSpec } from './cmAdapter' @@ -136,10 +137,27 @@ export class OverleafDocSync { const currentContent = this.view.state.doc.toString() if (currentContent === newContent) return - // Dispatch as a local change (NOT remote annotation) so it flows through OT - this.view.dispatch({ - changes: { from: 0, to: this.view.state.doc.length, insert: newContent } - }) + // Use diff to compute minimal changes so comment range positions remap correctly + const dmp = new diff_match_patch() + const diffs = dmp.diff_main(currentContent, newContent) + dmp.diff_cleanupEfficiency(diffs) + + const changes: ChangeSpec[] = [] + let pos = 0 + for (const [type, text] of diffs) { + if (type === 0) { // EQUAL + pos += text.length + } else if (type === -1) { // DELETE + changes.push({ from: pos, to: pos + text.length }) + pos += text.length + } else if (type === 1) { // INSERT + changes.push({ from: pos, to: pos, insert: text }) + } + } + + if (changes.length > 0) { + this.view.dispatch({ changes }) + } } destroy() { diff --git a/src/renderer/src/stores/appStore.ts b/src/renderer/src/stores/appStore.ts index 9e1e141..adb4957 100644 --- a/src/renderer/src/stores/appStore.ts +++ b/src/renderer/src/stores/appStore.ts @@ -90,6 +90,8 @@ interface AppState { setFileRefs: (refs: Array<{ id: string; path: string }>) => void rootFolderId: string setRootFolderId: (id: string) => void + syncDir: string + setSyncDir: (dir: string) => void // Review panel showReviewPanel: boolean @@ -198,6 +200,8 @@ export const useAppStore = create<AppState>((set) => ({ setFileRefs: (refs) => set({ fileRefs: refs }), rootFolderId: '', setRootFolderId: (id) => set({ rootFolderId: id }), + syncDir: '', + setSyncDir: (dir) => set({ syncDir: dir }), showReviewPanel: false, toggleReviewPanel: () => set((s) => ({ showReviewPanel: !s.showReviewPanel })), @@ -240,6 +244,7 @@ export const useAppStore = create<AppState>((set) => ({ overleafProject: null, fileRefs: [], rootFolderId: '', + syncDir: '', commentContexts: {}, overleafDocs: {}, hoveredThreadId: null, |
