Client: diagrams in local folders (setting)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
sarahandClaude Opus 5.5 committed 2026-10-13 13:12:28 +02:00
1 parent f99b227cc3
commit db81507b7c
4 files changed
+376 -9

No files matched your search

+33 -7
View File
@@ -1,7 +1,8 @@
"""Mermaid diagrams (```mermaid blocks), like the web view's. Flet can't draw
them, so the server does (POST /api/diagram, Backend/Diagrams.py) and they're
shown as pictures in this client's theme. In a local folder (no server), or
if the server can't draw them, they stay code blocks.
shown as pictures in this client's theme. In a local folder, LocalDiagrams.py
draws them on this computer instead (Settings > General, on by default). If
neither can, they stay code blocks.
A DiagramBlock shows its code straight away and swaps in the picture once it
arrives (fetched on a background thread), so opening a note never waits on
@@ -14,6 +15,7 @@ from typing import Callable, Optional
import flet as ft
import LocalDiagrams
from Core import CodeStyleSheet, MarkdownCodeTheme, MarkdownSheet, Palette
from Sources import SourceError
@@ -51,8 +53,14 @@ def ThemePalette() -> dict[str, str]:
}
def IsLocal(TheApp) -> bool:
return TheApp.Source.Kind != "Server"
def CanDraw(TheApp) -> bool:
return TheApp.Source.Kind == "Server" and not ServerCantDraw
if IsLocal(TheApp):
return TheApp.Config.LocalDiagrams
return not ServerCantDraw
class DiagramBlock(ft.Container):
@@ -83,14 +91,21 @@ class DiagramBlock(ft.Container):
alignment=ft.MainAxisAlignment.CENTER, scroll=ft.ScrollMode.AUTO)
Problem = Problems.get(self.Key)
if Problem is not None:
return ft.Column([self._Code(), ft.Text(f"Diagram error: {Problem}", color=Palette.Red,
size=self.FontSize - 2, selectable=True)], spacing=4)
return self._WithNote(f"Diagram error: {Problem}", Palette.Red)
if self.Fetching and IsLocal(self.TheApp) and not LocalDiagrams.IsSetUp():
return self._WithNote("Setting up diagrams (first time only, can take a few minutes)…", Palette.Overlay0)
return self._Code()
def _WithNote(self, Note: str, Colour: str) -> ft.Control:
return ft.Column([self._Code(), ft.Text(Note, color=Colour, size=self.FontSize - 2, selectable=True)], spacing=4)
def did_mount(self) -> None:
self.Mounted = True
if self.Key not in Pictures and self.Key not in Problems and not self.Fetching and CanDraw(self.TheApp):
self.Fetching = True
if IsLocal(self.TheApp) and not LocalDiagrams.IsSetUp():
self.content = self._Content()
self.update()
self.page.run_thread(self._Fetch)
def will_unmount(self) -> None:
@@ -99,14 +114,25 @@ class DiagramBlock(ft.Container):
def _Fetch(self) -> None:
global ServerCantDraw
try:
Pictures[self.Key] = self.TheApp.Source.Diagram(self.Source, ThemePalette(), self.FontSize)
if IsLocal(self.TheApp):
Pictures[self.Key] = LocalDiagrams.Render(self.Source, ThemePalette(), self.FontSize)
else:
Pictures[self.Key] = self.TheApp.Source.Diagram(self.Source, ThemePalette(), self.FontSize)
except LocalDiagrams.DiagramError as Error:
Problems[self.Key] = str(Error)
except SourceError as Error:
if Error.Status == 422:
Problems[self.Key] = str(Error)
elif Error.Status in (404, 503):
ServerCantDraw = True # an older server, or one without Chromium: stay code blocks
except Exception as Error:
# Can't draw on this computer (setup failed, or it timed out): say why.
Problems[self.Key] = f"Can't draw diagrams here: {Error or type(Error).__name__}"
finally:
self.Fetching = False
self._Finish()
def _Finish(self) -> None:
self.Fetching = False
if self.Mounted:
self.content = self._Content()
self.update()