mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-12-02 10:02:12 +00:00
Compare commits
5 Commits
46fcdb4bb2
...
l10n
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fe6565527 | ||
|
|
69b018022d | ||
|
|
467cb2e589 | ||
|
|
f13d8c1e22 | ||
|
|
e230d55b82 |
@@ -17,6 +17,9 @@ import {
|
||||
import { immerable, isDraft, original, freeze } from 'immer';
|
||||
|
||||
function cloneJSON<T>(obj: T): T {
|
||||
if (obj === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (obj === null || typeof obj !== 'object') {
|
||||
return null;
|
||||
}
|
||||
@@ -1492,12 +1495,18 @@ export class Waypoint {
|
||||
this.attributes = waypoint.attributes;
|
||||
this.ele = waypoint.ele;
|
||||
this.time = waypoint.time;
|
||||
this.name = waypoint.name;
|
||||
this.cmt = waypoint.cmt;
|
||||
this.desc = waypoint.desc;
|
||||
this.link = waypoint.link;
|
||||
this.sym = waypoint.sym;
|
||||
this.type = waypoint.type;
|
||||
this.name = waypoint.name === '' ? undefined : waypoint.name;
|
||||
this.cmt = waypoint.cmt === '' ? undefined : waypoint.cmt;
|
||||
this.desc = waypoint.desc === '' ? undefined : waypoint.desc;
|
||||
this.link =
|
||||
!waypoint.link ||
|
||||
!waypoint.link.attributes ||
|
||||
!waypoint.link.attributes.href ||
|
||||
waypoint.link.attributes.href === ''
|
||||
? undefined
|
||||
: waypoint.link;
|
||||
this.sym = waypoint.sym === '' ? undefined : waypoint.sym;
|
||||
this.type = waypoint.type === '' ? undefined : waypoint.type;
|
||||
if (waypoint.hasOwnProperty('_data')) {
|
||||
this._data = waypoint._data;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
{i18n._('homepage.home')}
|
||||
</Button>
|
||||
<Button
|
||||
data-sveltekit-reload
|
||||
variant="link"
|
||||
class="h-6 px-0 has-[>svg]:px-0 text-muted-foreground"
|
||||
href={getURLForLanguage(i18n.lang, '/app')}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
{i18n._('homepage.home')}
|
||||
</Button>
|
||||
<Button
|
||||
data-sveltekit-reload
|
||||
variant="link"
|
||||
class="text-base px-0 has-[>svg]:px-0"
|
||||
href={getURLForLanguage(i18n.lang, '/app')}
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
{:else if anySelectedLayer(node[id])}
|
||||
<CollapsibleTreeNode {id}>
|
||||
{#snippet trigger()}
|
||||
<span>{i18n._(`layers.label.${id}`)}</span>
|
||||
<span>{i18n._(`layers.label.${id}`, id)}</span>
|
||||
{/snippet}
|
||||
{#snippet content()}
|
||||
<div class="ml-2">
|
||||
|
||||
@@ -8,6 +8,7 @@ import { map } from '$lib/components/map/map';
|
||||
const { currentOverlays, previousOverlays, selectedOverlayTree } = settings;
|
||||
|
||||
export type CustomOverlay = {
|
||||
extensionName: string;
|
||||
id: string;
|
||||
name: string;
|
||||
tileUrls: string[];
|
||||
@@ -46,8 +47,16 @@ export class ExtensionAPI {
|
||||
}
|
||||
|
||||
addOrUpdateOverlay(overlay: CustomOverlay) {
|
||||
if (!overlay.id || !overlay.name || !overlay.tileUrls || overlay.tileUrls.length === 0) {
|
||||
throw new Error('Overlay must have an id, name, and at least one tile URL.');
|
||||
if (
|
||||
!overlay.extensionName ||
|
||||
!overlay.id ||
|
||||
!overlay.name ||
|
||||
!overlay.tileUrls ||
|
||||
overlay.tileUrls.length === 0
|
||||
) {
|
||||
throw new Error(
|
||||
'Overlay must have an extensionName, id, name, and at least one tile URL.'
|
||||
);
|
||||
}
|
||||
overlay.id = this.getOverlayId(overlay.id);
|
||||
|
||||
@@ -75,10 +84,17 @@ export class ExtensionAPI {
|
||||
],
|
||||
};
|
||||
|
||||
overlayTree.overlays.world[overlay.id] = true;
|
||||
if (!overlayTree.overlays.hasOwnProperty(overlay.extensionName)) {
|
||||
overlayTree.overlays[overlay.extensionName] = {};
|
||||
}
|
||||
|
||||
overlayTree.overlays[overlay.extensionName][overlay.id] = true;
|
||||
|
||||
selectedOverlayTree.update((selected) => {
|
||||
selected.overlays.world[overlay.id] = true;
|
||||
if (!selected.overlays.hasOwnProperty(overlay.extensionName)) {
|
||||
selected.overlays[overlay.extensionName] = {};
|
||||
}
|
||||
selected.overlays[overlay.extensionName][overlay.id] = true;
|
||||
return selected;
|
||||
});
|
||||
|
||||
@@ -94,7 +110,10 @@ export class ExtensionAPI {
|
||||
}
|
||||
|
||||
currentOverlays.update((current) => {
|
||||
current.overlays.world[overlay.id] = show;
|
||||
if (!current.overlays.hasOwnProperty(overlay.extensionName)) {
|
||||
current.overlays[overlay.extensionName] = {};
|
||||
}
|
||||
current.overlays[overlay.extensionName][overlay.id] = show;
|
||||
return current;
|
||||
});
|
||||
}
|
||||
@@ -133,6 +152,29 @@ export class ExtensionAPI {
|
||||
});
|
||||
}
|
||||
|
||||
updateOverlaysOrder(ids: string[]) {
|
||||
ids = ids.map((id) => this.getOverlayId(id));
|
||||
selectedOverlayTree.update((selected) => {
|
||||
let isSelected: Record<string, boolean> = {};
|
||||
ids.forEach((id) => {
|
||||
const overlay = get(this._overlays).get(id);
|
||||
if (
|
||||
overlay &&
|
||||
selected.overlays.hasOwnProperty(overlay.extensionName) &&
|
||||
selected.overlays[overlay.extensionName].hasOwnProperty(id)
|
||||
) {
|
||||
isSelected[id] = selected.overlays[overlay.extensionName][id];
|
||||
delete selected.overlays[overlay.extensionName][id];
|
||||
}
|
||||
});
|
||||
Object.entries(isSelected).forEach(([id, value]) => {
|
||||
const overlay = get(this._overlays).get(id)!;
|
||||
selected.overlays[overlay.extensionName][id] = value;
|
||||
});
|
||||
return selected;
|
||||
});
|
||||
}
|
||||
|
||||
isLayerFromExtension = derived(this._overlays, ($overlays) => {
|
||||
return (id: string) => $overlays.has(id);
|
||||
});
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
desc: description.length > 0 ? description : undefined,
|
||||
cmt: description.length > 0 ? description : undefined,
|
||||
link: link.length > 0 ? { attributes: { href: link } } : undefined,
|
||||
sym: sym,
|
||||
sym: sym.length > 0 ? sym : undefined,
|
||||
},
|
||||
selectedWaypoint.wpt && selectedWaypoint.fileId
|
||||
? new ListWaypointItem(selectedWaypoint.fileId, selectedWaypoint.wpt._data.index)
|
||||
|
||||
@@ -14,7 +14,7 @@ class Locale {
|
||||
private _isLoadingInitial = $state(true);
|
||||
private _isLoading = $state(true);
|
||||
private dictionary: Dictionary = $state({});
|
||||
private _t = $derived((key: string) => {
|
||||
private _t = $derived((key: string, fallback?: string) => {
|
||||
const keys = key.split('.');
|
||||
let value: string | Dictionary = this.dictionary;
|
||||
|
||||
@@ -22,7 +22,7 @@ class Locale {
|
||||
if (value && typeof value === 'object' && k in value) {
|
||||
value = value[k];
|
||||
} else {
|
||||
return key;
|
||||
return fallback || key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"undo": "撤销",
|
||||
"redo": "恢复",
|
||||
"delete": "删除",
|
||||
"delete_all": "Delete all",
|
||||
"delete_all": "",
|
||||
"select_all": "全选",
|
||||
"view": "显示",
|
||||
"elevation_profile": "海拔剖面图",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
{i18n._('homepage.home')}
|
||||
</Button>
|
||||
<Button
|
||||
data-sveltekit-reload
|
||||
href={getURLForLanguage(i18n.lang, '/app')}
|
||||
class="text-base w-1/4 min-w-fit rounded-full"
|
||||
>
|
||||
|
||||
@@ -64,7 +64,11 @@
|
||||
{i18n._('metadata.description')}
|
||||
</div>
|
||||
<div class="w-full flex flex-row justify-center gap-3">
|
||||
<Button href={getURLForLanguage(i18n.lang, '/app')} class="w-1/3 min-w-fit">
|
||||
<Button
|
||||
data-sveltekit-reload
|
||||
href={getURLForLanguage(i18n.lang, '/app')}
|
||||
class="w-1/3 min-w-fit"
|
||||
>
|
||||
<Map size="18" />
|
||||
{i18n._('homepage.app')}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user