From d1ee677591bd5e6e8b1726b2281621adf6131332 Mon Sep 17 00:00:00 2001 From: haoyuren <13851610112@163.com> Date: Sun, 15 Mar 2026 04:27:43 -0500 Subject: v0.3.0: Fix sync exclusions, add editor zoom, cached PDF loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Exclude CLAUDE.md from sync (move to .claude/ dotfile dir, clean up root copy) - Add Ctrl+wheel font zoom for editor (capture phase, disable Electron built-in zoom) - Load cached PDF on project connect (avoid recompile to see last PDF) - Add synctex debug logging for PDF↔source navigation troubleshooting - Fix .claude/ dir creation order (mkdir before write) Co-Authored-By: Claude Opus 4.6 --- src/renderer/src/components/Editor.tsx | 24 ++++++++++++++++++++++++ src/renderer/src/components/PdfViewer.tsx | 10 ++++++---- src/renderer/src/components/ProjectList.tsx | 1 + 3 files changed, 31 insertions(+), 4 deletions(-) (limited to 'src/renderer') diff --git a/src/renderer/src/components/Editor.tsx b/src/renderer/src/components/Editor.tsx index 4edb945..8319e93 100644 --- a/src/renderer/src/components/Editor.tsx +++ b/src/renderer/src/components/Editor.tsx @@ -88,6 +88,7 @@ export default function Editor() { const docSyncRef = useRef(null) const cursorThrottleRef = useRef | null>(null) + const [editorFontSize, setEditorFontSize] = useState(13.5) // Add comment state const [newComment, setNewComment] = useState<{ from: number; to: number; text: string } | null>(null) @@ -358,6 +359,29 @@ export default function Editor() { viewRef.current.dispatch({ effects: highlightThreadEffect.of(hoveredThreadId) }) }, [hoveredThreadId]) + // Ctrl+wheel / pinch zoom on editor (capture phase to beat CodeMirror) + useEffect(() => { + const el = editorRef.current + if (!el) return + const handleWheel = (e: WheelEvent) => { + if (!(e.ctrlKey || e.metaKey)) return + e.preventDefault() + e.stopPropagation() + const delta = e.deltaY > 0 ? -1 : 1 + setEditorFontSize((s) => Math.min(28, Math.max(8, +(s + delta * 0.5).toFixed(1)))) + } + el.addEventListener('wheel', handleWheel, { passive: false, capture: true }) + return () => el.removeEventListener('wheel', handleWheel, { capture: true }) + }, []) + + // Apply font size to editor + useEffect(() => { + if (!viewRef.current) return + const wrapper = viewRef.current.dom + wrapper.style.fontSize = `${editorFontSize}px` + viewRef.current.requestMeasure() + }, [editorFontSize]) + if (!activeTab) { return (
diff --git a/src/renderer/src/components/PdfViewer.tsx b/src/renderer/src/components/PdfViewer.tsx index c5fe8c4..01896d7 100644 --- a/src/renderer/src/components/PdfViewer.tsx +++ b/src/renderer/src/components/PdfViewer.tsx @@ -214,9 +214,9 @@ export default function PdfViewer() { // SyncTeX: double-click PDF → jump to source const handlePdfDoubleClick = useCallback(async (e: MouseEvent) => { - if (!pdfPath) return + if (!pdfPath) { console.log('[synctex-ui] no pdfPath'); return } const canvas = (e.target as HTMLElement).closest('canvas.pdf-page') as HTMLCanvasElement | null - if (!canvas) return + if (!canvas) { console.log('[synctex-ui] no canvas target'); return } const container = containerRef.current if (!container) return @@ -234,12 +234,14 @@ export default function PdfViewer() { // Convert to PDF points (72 DPI coordinate system, origin bottom-left) const vpInfo = pageViewportsRef.current.get(pageNum) - if (!vpInfo) return + if (!vpInfo) { console.log('[synctex-ui] no viewport info for page', pageNum); return } const pdfX = (clickX / rect.width) * vpInfo.width const pdfY = vpInfo.height - (clickY / rect.height) * vpInfo.height + console.log(`[synctex-ui] dblclick page=${pageNum} pdfX=${pdfX.toFixed(1)} pdfY=${pdfY.toFixed(1)} path=${pdfPath}`) const result = await window.api.synctexEdit(pdfPath, pageNum, pdfX, pdfY) - if (!result) return + if (!result) { console.log('[synctex-ui] synctex returned null'); return } + console.log(`[synctex-ui] result: file=${result.file} line=${result.line}`) // Navigate to source — synctex returns relative path (e.g. "latex/main.tex") const store = useAppStore.getState() diff --git a/src/renderer/src/components/ProjectList.tsx b/src/renderer/src/components/ProjectList.tsx index 58a6bb0..2fe23de 100644 --- a/src/renderer/src/components/ProjectList.tsx +++ b/src/renderer/src/components/ProjectList.tsx @@ -69,6 +69,7 @@ export default function ProjectList({ onOpenProject }: Props) { store.setOverleafProjectId(pid) store.setConnectionState('connected') if (result.syncDir) store.setSyncDir(result.syncDir) + if (result.cachedPdfPath) store.setPdfPath(result.cachedPdfPath) setStatusMessage('Connected') onOpenProject(pid) } else { -- cgit v1.2.3