This commit is contained in:
vcoppe
2025-06-21 21:07:36 +02:00
parent f0230d4634
commit 1cc07901f6
803 changed files with 7937 additions and 6329 deletions

View File

@@ -2,9 +2,9 @@
import { Button } from '$lib/components/ui/button';
import DocsContainer from '$lib/components/docs/DocsContainer.svelte';
import Logo from '$lib/components/Logo.svelte';
import ElevationProfile from '$lib/components/ElevationProfile.svelte';
import GPXStatistics from '$lib/components/GPXStatistics.svelte';
import Routing from '$lib/components/toolbar/tools/routing/Routing.svelte';
// import ElevationProfile from '$lib/components/ElevationProfile.svelte';
// import GPXStatistics from '$lib/components/GPXStatistics.svelte';
// import Routing from '$lib/components/toolbar/tools/routing/Routing.svelte';
import {
BookOpenText,
Heart,
@@ -14,35 +14,43 @@
PenLine,
Route,
Scale,
} from 'lucide-svelte';
import { _, locale } from '$lib/i18n';
} from '@lucide/svelte';
import { i18n } from '$lib/i18n.svelte';
import { getURLForLanguage } from '$lib/utils';
import { exampleGPXFile } from '$lib/assets/example';
import { writable } from 'svelte/store';
import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
import { currentTool, Tool } from '$lib/stores';
// import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
// import { tool, Tool } from '$lib/components/toolbar/utils.svelte';
import { onDestroy, onMount } from 'svelte';
export let data: {
fundingModule: any;
translationModule: any;
mapboxModule: any;
};
let {
data,
}: {
data: {
fundingModule: Promise<any>;
translationModule: Promise<any>;
mapboxModule: Promise<any>;
};
} = $props();
let gpxStatistics = writable(exampleGPXFile.getStatistics());
let slicedGPXStatistics = writable(undefined);
let additionalDatasets = writable(['speed', 'atemp']);
let elevationFill = writable<'slope' | 'surface' | undefined>(undefined);
onMount(() => {
$currentTool = Tool.SCISSORS;
});
// onMount(() => {
// tool.current = Tool.SCISSORS;
// });
$: $currentTool, ($currentTool = Tool.SCISSORS);
// $effect(() => {
// if (tool.current !== Tool.SCISSORS) {
// tool.current = Tool.SCISSORS;
// }
// });
onDestroy(() => {
$currentTool = null;
});
// onDestroy(() => {
// tool.current = null;
// });
</script>
<div class="space-y-24 my-24">
@@ -50,23 +58,23 @@
<div class="px-12 w-full flex flex-col items-center">
<div class="flex flex-col gap-6 items-center max-w-3xl">
<h1 class="text-4xl sm:text-6xl font-black text-center">
{$_('metadata.home_title')}
{i18n._('metadata.home_title')}
</h1>
<div class="text-lg sm:text-xl text-muted-foreground text-center">
{$_('metadata.description')}
{i18n._('metadata.description')}
</div>
<div class="w-full flex flex-row justify-center gap-3">
<Button href={getURLForLanguage($locale, '/app')} class="w-1/3 min-w-fit">
<Button href={getURLForLanguage(i18n.lang, '/app')} class="w-1/3 min-w-fit">
<Map size="18" class="mr-1.5" />
{$_('homepage.app')}
{i18n._('homepage.app')}
</Button>
<Button
variant="secondary"
href={getURLForLanguage($locale, '/help')}
href={getURLForLanguage(i18n.lang, '/help')}
class="w-1/3 min-w-fit"
>
<BookOpenText size="18" class="mr-1.5" />
<span>{$_('menu.help')}</span>
<span>{i18n._('menu.help')}</span>
</Button>
</div>
</div>
@@ -89,12 +97,12 @@
<div class="markdown text-center">
<h1>
<Route size="24" class="mr-1 inline-block align-baseline" />
{$_('homepage.route_planning')}
{i18n._('homepage.route_planning')}
</h1>
<p class="text-muted-foreground">{$_('homepage.route_planning_description')}</p>
<p class="text-muted-foreground">{i18n._('homepage.route_planning_description')}</p>
</div>
<div class="p-3 w-fit rounded-md border shadow-xl md:shrink-0">
<Routing minimizable={false} />
<!-- <Routing minimizable={false} /> -->
</div>
</div>
</div>
@@ -105,19 +113,23 @@
<div class="markdown text-center md:hidden">
<h1>
<PencilRuler size="24" class="mr-1 inline-block align-baseline" />
{$_('homepage.file_processing')}
{i18n._('homepage.file_processing')}
</h1>
<p class="text-muted-foreground">{$_('homepage.file_processing_description')}</p>
<p class="text-muted-foreground">
{i18n._('homepage.file_processing_description')}
</p>
</div>
<div class="relative md:shrink-0 max-w-[400px]">
<Toolbar />
<!-- <Toolbar /> -->
</div>
<div class="markdown text-center hidden md:block">
<h1>
<PencilRuler size="24" class="mr-1 inline-block align-baseline" />
{$_('homepage.file_processing')}
{i18n._('homepage.file_processing')}
</h1>
<p class="text-muted-foreground">{$_('homepage.file_processing_description')}</p>
<p class="text-muted-foreground">
{i18n._('homepage.file_processing_description')}
</p>
</div>
</div>
</div>
@@ -128,12 +140,12 @@
<div class="markdown text-center">
<h1>
<Map size="24" class="mr-1 inline-block align-baseline" />
{$_('homepage.maps')}
{i18n._('homepage.maps')}
</h1>
<p class="text-muted-foreground">{$_('homepage.maps_description')}</p>
<p class="text-muted-foreground">{i18n._('homepage.maps_description')}</p>
</div>
<div
class="relative h-60 xs:h-80 aspect-square rounded-2xl shadow-xl overflow-hidden overflow-clip"
class="relative w-full max-w-[320px] aspect-square rounded-2xl shadow-xl overflow-clip"
>
<enhanced:img
src="/src/lib/assets/img/home/mapbox-outdoors.png"
@@ -171,28 +183,28 @@
<div class="markdown text-center px-4 md:px-12">
<h1>
<ChartArea size="24" class="mr-1 inline-block align-baseline" />
{$_('homepage.data_visualization')}
{i18n._('homepage.data_visualization')}
</h1>
<p class="text-muted-foreground mb-6">
{$_('homepage.data_visualization_description')}
{i18n._('homepage.data_visualization_description')}
</p>
</div>
<div class="h-48 w-full">
<ElevationProfile
<!-- <ElevationProfile
{gpxStatistics}
{slicedGPXStatistics}
additionalDatasets={$additionalDatasets}
elevationFill={$elevationFill}
/>
/> -->
</div>
<div class="flex flex-col items-center">
<div class="h-10 w-fit">
<GPXStatistics
<!-- <GPXStatistics
{gpxStatistics}
{slicedGPXStatistics}
panelSize={192}
orientation={'horizontal'}
/>
/> -->
</div>
</div>
</div>
@@ -203,9 +215,9 @@
<div class="markdown text-center md:hidden">
<h1>
<Scale size="24" class="mr-1 inline-block align-baseline" />
{$_('homepage.identity')}
{i18n._('homepage.identity')}
</h1>
<p class="text-muted-foreground">{$_('homepage.identity_description')}</p>
<p class="text-muted-foreground">{i18n._('homepage.identity_description')}</p>
</div>
<a href="https://github.com/gpxstudio/gpx.studio" target="_blank">
<Logo class="h-32" company="github" />
@@ -213,9 +225,9 @@
<div class="markdown text-center hidden md:block">
<h1>
<Scale size="24" class="mr-1 inline-block align-baseline" />
{$_('homepage.identity')}
{i18n._('homepage.identity')}
</h1>
<p class="text-muted-foreground">{$_('homepage.identity_description')}</p>
<p class="text-muted-foreground">{i18n._('homepage.identity_description')}</p>
</div>
</div>
</div>
@@ -244,7 +256,7 @@
fill="rgb(var(--support))"
color="rgb(var(--support))"
/>
<span>{$_('homepage.support_button')}</span>
<span>{i18n._('homepage.support_button')}</span>
</Button>
</div>
<div
@@ -255,7 +267,7 @@
{/await}
<Button href="https://crowdin.com/project/gpxstudio" target="_blank" class="text-base">
<PenLine size="16" class="mr-1" />
<span>{$_('homepage.contribute')}</span>
<span>{i18n._('homepage.contribute')}</span>
</Button>
</div>
</div>
@@ -267,7 +279,7 @@
class="shrink-0 flex flex-col sm:flex-row lg:flex-col items-center gap-x-4 gap-y-2"
>
<div class="text-lg font-semibold text-muted-foreground">
❤️ {$_('homepage.supported_by')}
❤️ {i18n._('homepage.supported_by')}
</div>
<a href="https://www.mapbox.com/" target="_blank">
<Logo company="mapbox" class="w-60" />

View File

@@ -1,24 +1,25 @@
<script lang="ts">
import GPXLayers from '$lib/components/gpx-layer/GPXLayers.svelte';
import ElevationProfile from '$lib/components/ElevationProfile.svelte';
import FileList from '$lib/components/file-list/FileList.svelte';
import GPXStatistics from '$lib/components/GPXStatistics.svelte';
import Map from '$lib/components/Map.svelte';
import Menu from '$lib/components/Menu.svelte';
import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
import StreetViewControl from '$lib/components/street-view-control/StreetViewControl.svelte';
import LayerControl from '$lib/components/layer-control/LayerControl.svelte';
import CoordinatesPopup from '$lib/components/CoordinatesPopup.svelte';
// import GPXLayers from '$lib/components/map/gpx-layer/GPXLayers.svelte';
// import ElevationProfile from '$lib/components/ElevationProfile.svelte';
// import FileList from '$lib/components/file-list/FileList.svelte';
// import GPXStatistics from '$lib/components/GPXStatistics.svelte';
import Map from '$lib/components/map/Map.svelte';
// import Menu from '$lib/components/Menu.svelte';
// import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
import StreetViewControl from '$lib/components/map/street-view-control/StreetViewControl.svelte';
import LayerControl from '$lib/components/map/layer-control/LayerControl.svelte';
// import CoordinatesPopup from '$lib/components/map/CoordinatesPopup.svelte';
import Resizer from '$lib/components/Resizer.svelte';
import { Toaster } from '$lib/components/ui/sonner';
import { observeFilesFromDatabase, settings } from '$lib/db';
import { gpxStatistics, loadFiles, slicedGPXStatistics } from '$lib/stores';
import { onMount } from 'svelte';
import { page } from '$app/stores';
// import { observeFilesFromDatabase } from '$lib/db';
// import { gpxStatistics, loadFiles, slicedGPXStatistics } from '$lib/stores';
// import { onMount } from 'svelte';
// import { page } from '$app/state';
import { languages } from '$lib/languages';
import { getURLForLanguage } from '$lib/utils';
import { getURLForGoogleDriveFile } from '$lib/components/embedding/Embedding';
import { _ } from '$lib/i18n';
// import { getURLForGoogleDriveFile } from '$lib/components/embedding/Embedding';
import { i18n } from '$lib/i18n.svelte';
import { settings } from '$lib/logic/settings.svelte';
const {
treeFileView,
@@ -29,116 +30,124 @@
elevationFill,
} = settings;
onMount(() => {
let files: string[] = JSON.parse($page.url.searchParams.get('files') || '[]');
let ids: string[] = JSON.parse($page.url.searchParams.get('ids') || '[]');
let urls: string[] = files.concat(ids.map(getURLForGoogleDriveFile));
// onMount(() => {
// let files: string[] = JSON.parse(page.url.searchParams.get('files') || '[]');
// let ids: string[] = JSON.parse(page.url.searchParams.get('ids') || '[]');
// let urls: string[] = files.concat(ids.map(getURLForGoogleDriveFile));
observeFilesFromDatabase(urls.length === 0);
// observeFilesFromDatabase(urls.length === 0);
if (urls.length > 0) {
let downloads: Promise<File | null>[] = [];
urls.forEach((url) => {
downloads.push(
fetch(url)
.then((response) => response.blob())
.then((blob) => new File([blob], url.split('/').pop()))
);
});
// if (urls.length > 0) {
// let downloads: Promise<File | null>[] = [];
// urls.forEach((url) => {
// downloads.push(
// fetch(url)
// .then((response) => response.blob())
// .then((blob) => new File([blob], url.split('/').pop() ?? ''))
// );
// });
Promise.all(downloads).then((files) => {
files = files.filter((file) => file !== null);
loadFiles(files);
});
}
});
// Promise.all(downloads).then((files) => {
// loadFiles(files.filter((file) => file !== null));
// });
// }
// });
</script>
<div class="fixed -z-10 text-transparent">
<h1>{$_('metadata.home_title')}{$_('metadata.app_title')}</h1>
<p>{$_('metadata.description')}</p>
<h2>{$_('toolbar.routing.tooltip')}</h2>
<p>{$_('toolbar.routing.help_no_file')}</p>
<p>{$_('toolbar.routing.help')}</p>
<h3>{$_('toolbar.routing.reverse.button')}</h3>
<p>{$_('toolbar.routing.reverse.tooltip')}</p>
<h3>{$_('toolbar.routing.route_back_to_start.button')}</h3>
<p>{$_('toolbar.routing.route_back_to_start.tooltip')}</p>
<h3>{$_('toolbar.routing.round_trip.button')}</h3>
<p>{$_('toolbar.routing.round_trip.tooltip')}</p>
<h3>{$_('toolbar.routing.start_loop_here')}</h3>
<h2>{$_('toolbar.scissors.tooltip')}</h2>
<p>{$_('toolbar.scissors.help')}</p>
<h2>{$_('toolbar.time.tooltip')}</h2>
<p>{$_('toolbar.time.help')}</p>
<h2>{$_('toolbar.merge.tooltip')}</h2>
<h3>{$_('toolbar.merge.merge_traces')}</h3>
<p>{$_('toolbar.merge.help_merge_traces')}</p>
<h3>{$_('toolbar.merge.merge_contents')}</h3>
<p>{$_('toolbar.merge.help_merge_contents')}</p>
<h2>{$_('toolbar.elevation.button')}</h2>
<p>{$_('toolbar.elevation.help')}</p>
<h2>{$_('toolbar.waypoint.tooltip')}</h2>
<p>{$_('toolbar.waypoint.help')}</p>
<h2>{$_('toolbar.reduce.tooltip')}</h2>
<p>{$_('toolbar.reduce.help')}</p>
<h2>{$_('toolbar.clean.tooltip')}</h2>
<p>{$_('toolbar.clean.help')}</p>
<h2>{$_('gpx.files')}, {$_('gpx.tracks')}, {$_('gpx.segments')}, {$_('gpx.waypoints')}</h2>
<h1>{i18n._('metadata.home_title')}{i18n._('metadata.app_title')}</h1>
<p>{i18n._('metadata.description')}</p>
<h2>{i18n._('toolbar.routing.tooltip')}</h2>
<p>{i18n._('toolbar.routing.help_no_file')}</p>
<p>{i18n._('toolbar.routing.help')}</p>
<h3>{i18n._('toolbar.routing.reverse.button')}</h3>
<p>{i18n._('toolbar.routing.reverse.tooltip')}</p>
<h3>{i18n._('toolbar.routing.route_back_to_start.button')}</h3>
<p>{i18n._('toolbar.routing.route_back_to_start.tooltip')}</p>
<h3>{i18n._('toolbar.routing.round_trip.button')}</h3>
<p>{i18n._('toolbar.routing.round_trip.tooltip')}</p>
<h3>{i18n._('toolbar.routing.start_loop_here')}</h3>
<h2>{i18n._('toolbar.scissors.tooltip')}</h2>
<p>{i18n._('toolbar.scissors.help')}</p>
<h2>{i18n._('toolbar.time.tooltip')}</h2>
<p>{i18n._('toolbar.time.help')}</p>
<h2>{i18n._('toolbar.merge.tooltip')}</h2>
<h3>{i18n._('toolbar.merge.merge_traces')}</h3>
<p>{i18n._('toolbar.merge.help_merge_traces')}</p>
<h3>{i18n._('toolbar.merge.merge_contents')}</h3>
<p>{i18n._('toolbar.merge.help_merge_contents')}</p>
<h2>{i18n._('toolbar.elevation.button')}</h2>
<p>{i18n._('toolbar.elevation.help')}</p>
<h2>{i18n._('toolbar.waypoint.tooltip')}</h2>
<p>{i18n._('toolbar.waypoint.help')}</p>
<h2>{i18n._('toolbar.reduce.tooltip')}</h2>
<p>{i18n._('toolbar.reduce.help')}</p>
<h2>{i18n._('toolbar.clean.tooltip')}</h2>
<p>{i18n._('toolbar.clean.help')}</p>
<h2>
{i18n._('gpx.files')}, {i18n._('gpx.tracks')}, {i18n._('gpx.segments')}, {i18n._(
'gpx.waypoints'
)}
</h2>
</div>
<div class="fixed flex flex-row w-screen h-screen supports-dvh:h-dvh">
<div class="flex flex-col grow h-full min-w-0">
<div class="grow relative">
<Menu />
<!-- <Menu /> -->
<div
class="absolute top-0 bottom-0 left-0 z-20 flex flex-col justify-center pointer-events-none"
>
<Toolbar />
<!-- <Toolbar /> -->
</div>
<Map class="h-full {$treeFileView ? '' : 'horizontal'}" />
<Map class="h-full {treeFileView.value ? '' : 'horizontal'}" />
<StreetViewControl />
<LayerControl />
<GPXLayers />
<CoordinatesPopup />
<!-- <GPXLayers /> -->
<!-- <CoordinatesPopup /> -->
<Toaster richColors />
{#if !$treeFileView}
<!-- {#if !treeFileView.value}
<div class="h-10 -translate-y-10 w-full pointer-events-none absolute z-30">
<FileList orientation="horizontal" />
</div>
{/if}
{/if} -->
</div>
{#if $elevationProfile}
{#if elevationProfile.value}
<Resizer
orientation="row"
bind:after={$bottomPanelSize}
bind:after={bottomPanelSize.value}
minAfter={100}
maxAfter={300}
/>
{/if}
<div
class="{$elevationProfile ? '' : 'h-10'} flex flex-row gap-2 px-2 sm:px-4"
style={$elevationProfile ? `height: ${$bottomPanelSize}px` : ''}
class="{elevationProfile.value ? '' : 'h-10'} flex flex-row gap-2 px-2 sm:px-4"
style={elevationProfile.value ? `height: ${bottomPanelSize.value}px` : ''}
>
<GPXStatistics
<!-- <GPXStatistics
{gpxStatistics}
{slicedGPXStatistics}
panelSize={$bottomPanelSize}
orientation={$elevationProfile ? 'vertical' : 'horizontal'}
/>
{#if $elevationProfile}
/> -->
<!-- {#if $elevationProfile}
<ElevationProfile
{gpxStatistics}
{slicedGPXStatistics}
bind:additionalDatasets={$additionalDatasets}
bind:elevationFill={$elevationFill}
/>
{/if}
{/if} -->
</div>
</div>
{#if $treeFileView}
<Resizer orientation="col" bind:after={$rightPanelSize} minAfter={100} maxAfter={400} />
<FileList orientation="vertical" recursive={true} style="width: {$rightPanelSize}px" />
{#if treeFileView.value}
<Resizer
orientation="col"
bind:after={rightPanelSize.value}
minAfter={100}
maxAfter={400}
/>
<!-- <FileList orientation="vertical" recursive={true} style="width: {$rightPanelSize}px" /> -->
{/if}
</div>
@@ -152,6 +161,8 @@
</div>
<style lang="postcss">
@reference "tailwindcss";
div :global(.toaster.group) {
@apply absolute;
@apply right-2;

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { page } from '$app/stores';
import { page } from '$app/state';
import { onMount } from 'svelte';
import Embedding from '$lib/components/embedding/Embedding.svelte';
// import Embedding from '$lib/components/embedding/Embedding.svelte';
import {
getMergedEmbeddingOptions,
type EmbeddingOptions,
@@ -10,7 +10,7 @@
let embeddingOptions: EmbeddingOptions | undefined = undefined;
onMount(() => {
let options = $page.url.searchParams.get('options');
let options = page.url.searchParams.get('options');
if (options === null) {
return;
}
@@ -23,5 +23,5 @@
</script>
{#if embeddingOptions}
<Embedding options={embeddingOptions} hash={$page.url.hash} />
<!-- <Embedding options={embeddingOptions} hash={$page.url.hash} /> -->
{/if}

View File

@@ -1,13 +1,20 @@
<script lang="ts">
import { Button } from '$lib/components/ui/button';
import { getURLForLanguage } from '$lib/utils';
import { locale } from '$lib/i18n';
import { page } from '$app/stores';
import { i18n } from '$lib/i18n.svelte';
import { page } from '$app/state';
import { guides } from '$lib/components/docs/docs';
import type { Snippet } from 'svelte';
export let data: {
guideTitles: Record<string, string>;
};
let {
data,
children,
}: {
data: {
guideTitles: Record<string, string>;
};
children: Snippet;
} = $props();
</script>
<div class="grow px-12 pt-6 pb-12 flex flex-row gap-24">
@@ -17,8 +24,8 @@
{#each Object.keys(guides) as guide}
<Button
variant="link"
href={getURLForLanguage($locale, `/help/${guide}`)}
class="min-h-5 h-fit p-0 w-fit text-muted-foreground hover:text-foreground hover:no-underline font-normal hover:font-semibold items-start whitespace-normal {$page
href={getURLForLanguage(i18n.lang, `/help/${guide}`)}
class="min-h-5 h-fit p-0 w-fit text-muted-foreground hover:text-foreground hover:no-underline font-normal hover:font-semibold items-start whitespace-normal {page
.params.guide === guide
? 'font-semibold text-foreground'
: ''}"
@@ -28,8 +35,8 @@
{#each guides[guide] as subGuide}
<Button
variant="link"
href={getURLForLanguage($locale, `/help/${guide}/${subGuide}`)}
class="min-h-5 h-fit p-0 w-fit text-muted-foreground hover:text-foreground hover:no-underline font-normal hover:font-semibold items-start whitespace-normal ml-3 {$page
href={getURLForLanguage(i18n.lang, `/help/${guide}/${subGuide}`)}
class="min-h-5 h-fit p-0 w-fit text-muted-foreground hover:text-foreground hover:no-underline font-normal hover:font-semibold items-start whitespace-normal ml-3 {page
.params.guide ===
guide + '/' + subGuide
? 'font-semibold text-foreground'
@@ -41,6 +48,6 @@
{/each}
</div>
<div class="grow">
<slot />
{@render children()}
</div>
</div>

View File

@@ -1,19 +1,23 @@
<script lang="ts">
import { Button } from '$lib/components/ui/button';
import { getURLForLanguage } from '$lib/utils';
import { locale } from '$lib/i18n';
import { i18n } from '$lib/i18n.svelte';
import { guides, guideIcons } from '$lib/components/docs/docs';
export let data: {
guideTitles: Record<string, string>;
};
let {
data,
}: {
data: {
guideTitles: Record<string, string>;
};
} = $props();
</script>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
{#each Object.keys(guides) as guide}
<Button
variant="outline"
href={getURLForLanguage($locale, `/help/${guide}`)}
href={getURLForLanguage(i18n.lang, `/help/${guide}`)}
class="min-h-36 h-full pt-6 pb-3 px-0"
>
<div class="flex flex-col w-full">
@@ -27,14 +31,15 @@
{#each guides[guide] as subGuide}
<Button
variant="link"
href={getURLForLanguage($locale, `/help/${guide}/${subGuide}`)}
href={getURLForLanguage(i18n.lang, `/help/${guide}/${subGuide}`)}
class="min-h-8 h-fit min-w-24 px-0 py-1 text-muted-foreground text-base text-center whitespace-normal"
>
<svelte:component
this={guideIcons[subGuide]}
size="16"
class="mr-1 shrink-0"
/>
{#if typeof guideIcons[subGuide] === 'string'}
{guideIcons[subGuide]}
{:else}
{@const GuideIcon = guideIcons[subGuide]}
<GuideIcon size="16" class="mr-1 shrink-0" />
{/if}
{data.guideTitles[`${guide}/${subGuide}`]}
</Button>
{/each}

View File

@@ -1,19 +1,16 @@
<script lang="ts">
import { page } from '$app/stores';
import { page } from '$app/state';
import { getNextGuide, getPreviousGuide } from '$lib/components/docs/docs';
import DocsContainer from '$lib/components/docs/DocsContainer.svelte';
import { Button } from '$lib/components/ui/button';
import { getURLForLanguage } from '$lib/utils';
import { ChevronLeft, ChevronRight, PenLine, CornerDownRight } from 'lucide-svelte';
import { _, locale } from '$lib/i18n';
import { ChevronLeft, ChevronRight, PenLine, CornerDownRight } from '@lucide/svelte';
import { i18n } from '$lib/i18n.svelte';
export let data: {
guideModule: any;
guideTitles: Record<string, string>;
};
let { data }: { data: { guideModule: any; guideTitles: Record<string, string> } } = $props();
$: previousGuide = getPreviousGuide($page.params.guide);
$: nextGuide = getNextGuide($page.params.guide);
let previousGuide = $derived(getPreviousGuide(page.params.guide));
let nextGuide = $derived(getNextGuide(page.params.guide));
</script>
<div class="markdown flex flex-col gap-3">
@@ -25,9 +22,9 @@
<Button
variant="outline"
class="mr-auto"
href={getURLForLanguage($locale, `/help/${previousGuide}`)}
href={getURLForLanguage(i18n.lang, `/help/${previousGuide}`)}
>
<ChevronLeft size="14" class="mr-1 mt-0.5" />
<ChevronLeft size="14" class="mt-0.5" />
{data.guideTitles[previousGuide]}
</Button>
{/if}
@@ -35,47 +32,47 @@
<Button
variant="outline"
class="ml-auto"
href={getURLForLanguage($locale, `/help/${nextGuide}`)}
href={getURLForLanguage(i18n.lang, `/help/${nextGuide}`)}
>
{data.guideTitles[nextGuide]}
<ChevronRight size="14" class="ml-1 mt-0.5" />
<ChevronRight size="14" class="mt-0.5" />
</Button>
{/if}
</div>
<div class="flex flex-row flex-wrap justify-between items-start mt-10 gap-3">
<div class="flex flex-col items-start">
<p class="text-sm text-muted-foreground">{$_('docs.answer_not_found')}</p>
<p class="text-sm text-muted-foreground">{i18n._('docs.answer_not_found')}</p>
<Button
variant="link"
href="https://www.reddit.com/r/gpxstudio/"
target="_blank"
class="p-0 h-6 text-link"
>
<CornerDownRight size="16" class="mr-1" />
{$_('docs.ask_on_reddit')}
<CornerDownRight size="16" />
{i18n._('docs.ask_on_reddit')}
</Button>
</div>
{#if $locale === 'en'}
{#if i18n.lang === 'en'}
<Button
variant="link"
href="https://github.com/gpxstudio/gpx.studio/edit/dev/website/src/lib/docs/en/{$page
href="https://github.com/gpxstudio/gpx.studio/edit/dev/website/src/lib/docs/en/{page
.params.guide}.mdx"
target="_blank"
class="p-0 h-6 ml-auto text-link"
>
<PenLine size="16" class="mr-1" />
<PenLine size="16" />
Edit this page on GitHub
</Button>
{:else}
<Button
variant="link"
href="https://crowdin.com/project/gpxstudio/{$locale}"
href="https://crowdin.com/project/gpxstudio/{i18n.lang}"
target="_blank"
class="p-0 h-6 ml-auto text-link"
>
<PenLine size="16" class="mr-1" />
{$_('docs.translate')}
<PenLine size="16" />
{i18n._('docs.translate')}
</Button>
{/if}
</div>