From a36dbc7ce82846f5f4e6e830fdc04606adbc7066 Mon Sep 17 00:00:00 2001 From: giswqs Date: Mon, 10 Aug 2026 01:02:13 -0400 Subject: [PATCH 1/4] Write embedded GeoJSON compactly when saving a project (#1829) `serializeProject` pretty-printed the entire `.geolibre.json`, so every coordinate value got its own indented line. Coordinate arrays are never hand-edited, and the whitespace cost roughly three bytes for every byte of data: a project embedding 367k features weighed 158 MB and 5.9M lines pretty-printed, but 61 MB and 668 lines compact. Files that large made reopening unreliable, with layers rendering briefly and then vanishing as the tab ran out of memory. Serialization now indents the project structure as before but hands each GeoJSON feature, geometry and collection to `JSON.stringify` with no spacing, so files stay readable and diffable while dropping the bloat. This applies everywhere projects are serialized: save, share, autosave, collaboration sync and the embed bridge. Two related fixes on the save path: - `buildCurrentProject` no longer serializes the project it returns. Every caller re-serialized after redacting credentials, so the unused string doubled the peak memory of a save. - Serialization throws `RangeError: Invalid string length` past V8's ~536 MB string cap. That escaped `void handleSave()` as an unhandled rejection, so Save silently did nothing; it now reports a visible error suggesting PMTiles or FlatGeobuf. The embed prompt also warns above 50 MB of embedded data, pointing at PMTiles/FlatGeobuf rather than embedding features. --- .../layout/toolbar/ProjectFileDialogs.tsx | 15 ++- .../src/hooks/useProjectFileActions.ts | 52 +++++++++-- .../geolibre-desktop/src/i18n/locales/ar.json | 2 + .../geolibre-desktop/src/i18n/locales/de.json | 2 + .../geolibre-desktop/src/i18n/locales/en.json | 2 + .../geolibre-desktop/src/i18n/locales/es.json | 2 + .../geolibre-desktop/src/i18n/locales/fa.json | 2 + .../geolibre-desktop/src/i18n/locales/fr.json | 2 + .../geolibre-desktop/src/i18n/locales/hi.json | 2 + .../geolibre-desktop/src/i18n/locales/id.json | 2 + .../geolibre-desktop/src/i18n/locales/it.json | 2 + .../geolibre-desktop/src/i18n/locales/ja.json | 2 + .../geolibre-desktop/src/i18n/locales/ka.json | 2 + .../geolibre-desktop/src/i18n/locales/ko.json | 2 + .../geolibre-desktop/src/i18n/locales/nl.json | 2 + .../geolibre-desktop/src/i18n/locales/pt.json | 2 + .../geolibre-desktop/src/i18n/locales/ru.json | 2 + .../geolibre-desktop/src/i18n/locales/th.json | 2 + .../geolibre-desktop/src/i18n/locales/tr.json | 2 + .../geolibre-desktop/src/i18n/locales/zh.json | 2 + packages/core/src/project.ts | 85 ++++++++++++++++- tests/core-project.test.ts | 91 +++++++++++++++++++ 22 files changed, 268 insertions(+), 11 deletions(-) diff --git a/apps/geolibre-desktop/src/components/layout/toolbar/ProjectFileDialogs.tsx b/apps/geolibre-desktop/src/components/layout/toolbar/ProjectFileDialogs.tsx index 25dc296fd..7e1fd00cd 100644 --- a/apps/geolibre-desktop/src/components/layout/toolbar/ProjectFileDialogs.tsx +++ b/apps/geolibre-desktop/src/components/layout/toolbar/ProjectFileDialogs.tsx @@ -11,7 +11,10 @@ import { } from "@geolibre/ui"; import { useRef } from "react"; import { useTranslation } from "react-i18next"; -import type { ProjectFileActions } from "../../../hooks/useProjectFileActions"; +import { + LARGE_EMBED_WARNING_BYTES, + type ProjectFileActions, +} from "../../../hooks/useProjectFileActions"; import { SaveTemplateDialog } from "../SaveTemplateDialog"; interface ProjectFileDialogsProps { @@ -250,6 +253,16 @@ export function ProjectFileDialogs({ projectFiles }: ProjectFileDialogsProps) { )} + {(projectFiles.embedVectorDataPrompt?.bytes ?? 0) >= LARGE_EMBED_WARNING_BYTES ? ( +

+ {t("toolbar.item.embedVectorLargeWarning", { + size: formatByteSize(projectFiles.embedVectorDataPrompt?.bytes ?? 0), + })} +

+ ) : null}