Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 53 additions & 10 deletions apps/geolibre-desktop/src/components/layout/DesktopShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
import { buildKmlModelLayer } from "../../lib/kml-model-layer";
import { isPhotoDropFileName, type GeotaggedPhotoResult } from "../../lib/geotagged-photos";
import type { LargeVectorDataset } from "../../lib/duckdb-vector-guard";
import { detectNonGeographicCoordinates } from "@geolibre/core";
import { PANEL_RESIZE_END_EVENT, PANEL_RESIZE_START_EVENT } from "../../lib/panel-resize";
import i18n from "../../i18n";
import {
Expand Down Expand Up @@ -806,6 +807,11 @@
const [mapReadyGeneration, setMapReadyGeneration] = useState(0);
const [dropMessage, setDropMessage] = useState<string | null>(null);
const [dropError, setDropError] = useState<string | null>(null);
// Kept out of `dropError` because the drop handler sets its own success
// message after `addImportedVectorLayers` returns, which would clobber this
// one. A mislabelled-CRS layer loads *successfully* and still renders
// nowhere, so both messages are true at once and need separate slots.
const [crsWarning, setCrsWarning] = useState<string | null>(null);
const [diagnosticsOpen, setDiagnosticsOpen] = useState(false);
const diagnostics = useDiagnosticsSnapshot();
const externalPluginsReady = useExternalPluginsReady(mapControllerRef);
Expand Down Expand Up @@ -1251,6 +1257,9 @@
const addImportedVectorLayers = useCallback(
(importedLayers: ImportedVectorLayer[]) => {
let lastLayerId: string | null = null;
// Layers whose coordinates cannot be WGS84; surfaced together after the
// loop so a multi-file drop reports once rather than per file.
const nonGeographic: string[] = [];
// Frame ids for each time-animated overlay sequence (keyed by the loader's
// group marker), so they can be gathered into one layer group afterward.
const frameGroups = new Map<string, string[]>();
Expand Down Expand Up @@ -1301,13 +1310,30 @@
}
// `||` (not `??`) so an empty-string name falls back to the path, and
// matches the name shown in the drop confirmation toast.
lastLayerId = addGeoJsonLayer(
layer.name || layerNameFromPath(layer.path),
layer.data,
layer.path,
);
const layerName = layer.name || layerNameFromPath(layer.path);
// A file that declares WGS84 but holds projected coordinates loads
// cleanly, lists in the Layers panel, and renders nowhere — the map
// simply never moves. Warn rather than fail: the data is readable and
// only the user knows its true CRS.
const offRange = detectNonGeographicCoordinates(layer.data);
if (offRange) {
nonGeographic.push(layerName);
console.warn(
`[GeoLibre] "${layerName}" declares geographic coordinates but its values are out of range ` +
`(max |x| ${Math.round(offRange.maxAbsX).toLocaleString()}, max |y| ${Math.round(offRange.maxAbsY).toLocaleString()} ` +
`over ${offRange.sampled.toLocaleString()} sampled coordinates). The file's CRS is almost certainly ` +
`mislabelled — reproject it, or correct its .prj/crs, and load it again.`,
);
}
lastLayerId = addGeoJsonLayer(layerName, layer.data, layer.path);
}

setCrsWarning(
nonGeographic.length > 0
? t("addData.nonGeographicCoordinates", { names: nonGeographic.join(", ") })
: null,
);
Comment thread
giswqs marked this conversation as resolved.

// Gather each time-animated overlay's frames into one collapsible group so
// the sequence reads as a single timeline entry, not N stacked layers.
const sequences = [...frameGroups.values()].filter((ids) => ids.length > 1);
Expand Down Expand Up @@ -1372,20 +1398,20 @@
// pyramid, which a path-less browser File cannot support.
const layers =
paths.length === imports.length
? await loadDroppedVectorPaths(paths, {
onLargeDataset: confirmLargeVectorDataset,
})
? await loadDroppedVectorPaths(paths, { onLargeDataset: confirmLargeVectorDataset })
: await loadDroppedVectorFiles(
imports.map(({ file }) => file),
{ onLargeDataset: confirmLargeVectorDataset },
{
onLargeDataset: confirmLargeVectorDataset,
},
);
Comment thread
giswqs marked this conversation as resolved.
addImportedVectorLayers(layers);
} catch (error) {
setDropError(error instanceof Error ? error.message : t("kml.importFailed"));
}
});
return () => setKmlFileImportHandler(null);
}, [addImportedVectorLayers, confirmLargeVectorDataset, t]);
}, [addImportedVectorLayers, t]);
Comment thread
giswqs marked this conversation as resolved.

const addDroppedPhotos = useCallback(
(result: GeotaggedPhotoResult | null): number => {
Expand Down Expand Up @@ -1661,7 +1687,7 @@
disposed = true;
unlisten?.();
};
}, [

Check warning on line 1690 in apps/geolibre-desktop/src/components/layout/DesktopShell.tsx

View workflow job for this annotation

GitHub Actions / Build and test

React Hook useEffect has a missing dependency: 't'. Either include it or remove the dependency array
clearDropMessageLater,
finishDrop,
addDroppedRasters,
Expand Down Expand Up @@ -1805,7 +1831,7 @@
clearDropMessageLater();
}
},
[

Check warning on line 1834 in apps/geolibre-desktop/src/components/layout/DesktopShell.tsx

View workflow job for this annotation

GitHub Actions / Build and test

React Hook useCallback has a missing dependency: 't'. Either include it or remove the dependency array
clearDropMessageLater,
finishDrop,
addDroppedRasters,
Expand Down Expand Up @@ -2642,6 +2668,23 @@
{projectUrlLoadState.error}
</div>
) : null}
{crsWarning ? (
<div
data-testid="crs-warning"
role="status"
aria-live="polite"
className="absolute bottom-24 left-1/2 z-50 max-w-[min(90vw,36rem)] -translate-x-1/2 rounded-md border border-destructive/40 bg-background px-3 py-2 text-center text-sm text-destructive shadow-lg"
>
{crsWarning}
<button
type="button"
onClick={() => setCrsWarning(null)}
className="ms-2 underline underline-offset-2"
>
{t("common.close")}
</button>
</div>
) : null}
{dropMessage || dropError ? (
<div
data-testid="drop-status"
Expand Down
15 changes: 14 additions & 1 deletion apps/geolibre-desktop/src/hooks/useProjectHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,20 @@ export function useProjectHistory(mapControllerRef: RefObject<MapController | nu
if (timerRef.current !== null) window.clearTimeout(timerRef.current);
timerRef.current = window.setTimeout(() => {
timerRef.current = null;
const content = serializeProject(buildProjectSnapshot(mapControllerRef));
// `serializeProject` runs synchronously, so its failure cannot be caught
// by the promise chain below. A project embedding a large vector layer
// serializes to more than V8's 536,870,888-byte string cap and throws
// `RangeError: Invalid string length`, which previously escaped as an
// unhandled error on every autosave tick. Autosave is best-effort — a
// project too large to snapshot must degrade to "no crash recovery",
// never to a crash.
let content: string;
try {
content = serializeProject(buildProjectSnapshot(mapControllerRef));
} catch (error) {
console.warn("Project autosave skipped: the project is too large to serialize.", error);
return;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
giswqs marked this conversation as resolved.
void addProjectSnapshot(content, currentProjectKey()).catch((error) =>
console.error("Could not autosave the project.", error),
);
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,8 @@
"errorMaxFeatures": "أدخل قيمة للحد الأقصى للمعالم تساوي 1 أو أكثر.",
"errorBbox": "أدخل الصندوق المحيط بالصيغة «غرب,جنوب,شرق,شمال».",
"errorNoFeatures": "لم تُرجع هذه المجموعة أي معالم."
}
},
"nonGeographicCoordinates": "تم تحميل {{names}}، لكن إحداثياته ليست خط طول/عرض، لذا لن يظهر على الخريطة. نظام الإحداثيات المذكور في الملف خاطئ — أعد إسقاطه (أو صحّح ملف .prj) ثم حمّله مرة أخرى."
},
"offline": {
"title": "تنزيل منطقة دون اتصال",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@
"errorMaxFeatures": "Geben Sie für die maximale Objektanzahl einen Wert von 1 oder mehr ein.",
"errorBbox": "Geben Sie den Begrenzungsrahmen als „West,Süd,Ost,Nord“ an.",
"errorNoFeatures": "Diese Collection hat keine Objekte zurückgegeben."
}
},
"nonGeographicCoordinates": "{{names}} wurde geladen, aber die Koordinaten sind keine geografische Länge/Breite, daher erscheint die Ebene nicht auf der Karte. Das CRS der Datei ist falsch angegeben — projizieren Sie sie um (oder korrigieren Sie die .prj) und laden Sie sie erneut."
},
"offline": {
"title": "Offline-Bereich herunterladen",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,8 @@
"lineWidth": "Line width",
"extrusion": "3D extrusion",
"modelUrlPlaceholder": "https://example.com/model.glb"
}
},
"nonGeographicCoordinates": "{{names}} loaded, but its coordinates are not longitude/latitude, so it will not appear on the map. The file's CRS is mislabelled — reproject it (or fix its .prj) and load it again."
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
},
"offline": {
"title": "Download Offline Area",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@
"errorMaxFeatures": "Introduzca un máximo de entidades de 1 o más.",
"errorBbox": "Introduzca el cuadro delimitador como «oeste,sur,este,norte».",
"errorNoFeatures": "Esta colección no devolvió ninguna entidad."
}
},
"nonGeographicCoordinates": "{{names}} se cargó, pero sus coordenadas no son de longitud/latitud, por lo que no aparecerá en el mapa. El CRS del archivo está mal declarado: reproyéctelo (o corrija su .prj) y vuelva a cargarlo."
},
"offline": {
"title": "Descargar área sin conexión",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@
"errorMaxFeatures": "Saisissez un nombre maximal d'entités égal ou supérieur à 1.",
"errorBbox": "Saisissez la boîte englobante sous la forme « ouest,sud,est,nord ».",
"errorNoFeatures": "Cette collection n'a renvoyé aucune entité."
}
},
"nonGeographicCoordinates": "{{names}} a été chargé, mais ses coordonnées ne sont pas des longitudes/latitudes : la couche n'apparaîtra pas sur la carte. Le SCR du fichier est mal déclaré — reprojetez-le (ou corrigez son .prj) puis rechargez-le."
},
"offline": {
"title": "Télécharger une zone hors ligne",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@
"errorMaxFeatures": "अधिकतम फ़ीचर के लिए 1 या उससे अधिक मान दर्ज करें।",
"errorBbox": "बाउंडिंग बॉक्स को «पश्चिम,दक्षिण,पूर्व,उत्तर» के रूप में दर्ज करें।",
"errorNoFeatures": "इस कलेक्शन ने कोई फ़ीचर नहीं लौटाया।"
}
},
"nonGeographicCoordinates": "{{names}} लोड हो गया, लेकिन इसके निर्देशांक देशांतर/अक्षांश नहीं हैं, इसलिए यह मानचित्र पर नहीं दिखेगा। फ़ाइल का CRS ग़लत दर्ज है — इसे पुनःप्रक्षेपित करें (या .prj ठीक करें) और दोबारा लोड करें।"
},
"offline": {
"title": "ऑफ़लाइन क्षेत्र डाउनलोड करें",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/id.json
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,8 @@
"errorMaxFeatures": "Masukkan nilai jumlah fitur maksimum 1 atau lebih.",
"errorBbox": "Masukkan kotak pembatas sebagai \"barat,selatan,timur,utara\".",
"errorNoFeatures": "Koleksi ini tidak mengembalikan fitur apa pun."
}
},
"nonGeographicCoordinates": "{{names}} dimuat, tetapi koordinatnya bukan bujur/lintang sehingga tidak akan tampil di peta. CRS berkas salah — proyeksikan ulang (atau perbaiki .prj-nya) lalu muat kembali."
},
"offline": {
"title": "Unduh Area Offline",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@
"errorMaxFeatures": "Inserisci un numero massimo di elementi pari a 1 o superiore.",
"errorBbox": "Inserisci il rettangolo di delimitazione come «ovest,sud,est,nord».",
"errorNoFeatures": "Questa collection non ha restituito alcun elemento."
}
},
"nonGeographicCoordinates": "{{names}} è stato caricato, ma le sue coordinate non sono longitudine/latitudine, quindi non comparirà sulla mappa. Il CRS del file è errato: riproiettalo (o correggi il .prj) e ricaricalo."
},
"offline": {
"title": "Scarica area offline",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,8 @@
"errorMaxFeatures": "最大フィーチャ数には1以上の値を入力してください。",
"errorBbox": "バウンディングボックスを「西,南,東,北」の形式で入力してください。",
"errorNoFeatures": "このコレクションはフィーチャを返しませんでした。"
}
},
"nonGeographicCoordinates": "{{names}} は読み込まれましたが、座標が経緯度ではないため地図上に表示されません。ファイルの CRS が誤って記録されています — 再投影する(または .prj を修正する)と読み込み直してください。"
},
"offline": {
"title": "オフラインエリアをダウンロード",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/ka.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@
"lineWidth": "ხაზის სიგანე",
"extrusion": "3D ამოწევა",
"modelUrlPlaceholder": "https://example.com/model.glb"
}
},
"nonGeographicCoordinates": "{{names}} ჩაიტვირთა, მაგრამ მისი კოორდინატები არ არის გრძედი/განედი, ამიტომ რუკაზე არ გამოჩნდება. ფაილის CRS არასწორადაა მითითებული — გადააპროექტეთ (ან შეასწორეთ .prj) და ხელახლა ჩატვირთეთ."
},
"offline": {
"title": "ოფლაინ ტერიტორიის ჩამოტვირთვა",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,8 @@
"errorMaxFeatures": "최대 피처 수를 1 이상으로 입력하세요.",
"errorBbox": "경계 상자를 “서,남,동,북” 형식으로 입력하세요.",
"errorNoFeatures": "이 컬렉션은 피처를 반환하지 않았습니다."
}
},
"nonGeographicCoordinates": "{{names}}을(를) 불러왔지만 좌표가 경위도가 아니어서 지도에 표시되지 않습니다. 파일의 CRS가 잘못 지정되어 있습니다 — 재투영하거나 .prj를 수정한 뒤 다시 불러오세요."
},
"offline": {
"title": "오프라인 지역 다운로드",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@
"errorMaxFeatures": "Voer voor het maximale aantal features een waarde van 1 of hoger in.",
"errorBbox": "Voer het begrenzingskader in als ‘west,zuid,oost,noord’.",
"errorNoFeatures": "Deze collectie leverde geen features op."
}
},
"nonGeographicCoordinates": "{{names}} is geladen, maar de coördinaten zijn geen lengte-/breedtegraad, dus de laag verschijnt niet op de kaart. Het CRS van het bestand klopt niet — herprojecteer het (of corrigeer de .prj) en laad het opnieuw."
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
},
"offline": {
"title": "Offline gebied downloaden",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@
"errorMaxFeatures": "Informe um valor de máximo de feições igual ou maior que 1.",
"errorBbox": "Informe a caixa delimitadora como “oeste,sul,leste,norte”.",
"errorNoFeatures": "Esta coleção não retornou nenhuma feição."
}
},
"nonGeographicCoordinates": "{{names}} foi carregado, mas suas coordenadas não são de longitude/latitude, então não aparecerá no mapa. O CRS do arquivo está incorreto — reprojete-o (ou corrija o .prj) e carregue novamente."
},
"offline": {
"title": "Baixar área offline",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,8 @@
"errorMaxFeatures": "Введите максимальное количество объектов, равное 1 или больше.",
"errorBbox": "Введите ограничивающий прямоугольник в виде «запад,юг,восток,север».",
"errorNoFeatures": "Эта коллекция не вернула ни одного объекта."
}
},
"nonGeographicCoordinates": "{{names}} загружен, но его координаты не являются долготой/широтой, поэтому слой не появится на карте. СК файла указана неверно — перепроецируйте его (или исправьте .prj) и загрузите снова."
},
"offline": {
"title": "Скачать офлайн-область",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/th.json
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,8 @@
"lineWidth": "ความหนาเส้น",
"extrusion": "การยกตัวแบบ 3 มิติ",
"modelUrlPlaceholder": "https://example.com/model.glb"
}
},
"nonGeographicCoordinates": "{{names}} ถูกโหลดแล้ว แต่พิกัดไม่ใช่ลองจิจูด/ละติจูด จึงจะไม่ปรากฏบนแผนที่ ระบบพิกัดของไฟล์ระบุไว้ผิด — โปรดฉายพิกัดใหม่ (หรือแก้ไฟล์ .prj) แล้วโหลดอีกครั้ง"
},
"offline": {
"title": "ดาวน์โหลดพื้นที่แบบออฟไลน์",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@
"errorMaxFeatures": "Maksimum öğe değeri olarak 1 veya daha büyük bir sayı girin.",
"errorBbox": "Sınırlayıcı kutuyu «batı,güney,doğu,kuzey» biçiminde girin.",
"errorNoFeatures": "Bu koleksiyon hiç öğe döndürmedi."
}
},
"nonGeographicCoordinates": "{{names}} yüklendi, ancak koordinatları boylam/enlem değil, bu yüzden haritada görünmeyecek. Dosyanın CRS bilgisi yanlış — yeniden projelendirin (veya .prj dosyasını düzeltin) ve tekrar yükleyin."
},
"offline": {
"title": "Çevrimdışı Alan İndir",
Expand Down
3 changes: 2 additions & 1 deletion apps/geolibre-desktop/src/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,8 @@
"errorMaxFeatures": "请输入不小于 1 的最大要素数。",
"errorBbox": "请按“西,南,东,北”的格式输入边界框。",
"errorNoFeatures": "此集合未返回任何要素。"
}
},
"nonGeographicCoordinates": "{{names}} 已加载,但其坐标不是经纬度,因此不会显示在地图上。该文件的坐标参考系标注有误 — 请重新投影(或修正 .prj)后再次加载。"
},
"offline": {
"title": "下载离线区域",
Expand Down
Loading
Loading