2024-06-10 20:03:57 +02:00
|
|
|
<script lang="ts" context="module">
|
|
|
|
export enum SplitType {
|
|
|
|
FILES = 'files',
|
|
|
|
TRACKS = 'tracks',
|
|
|
|
SEGMENTS = 'segments'
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
import Help from '$lib/components/Help.svelte';
|
|
|
|
import { ListRootItem } from '$lib/components/file-list/FileList';
|
|
|
|
import { selection } from '$lib/components/file-list/Selection';
|
|
|
|
import { Label } from '$lib/components/ui/label/index.js';
|
|
|
|
import { Button } from '$lib/components/ui/button';
|
|
|
|
import { Slider } from '$lib/components/ui/slider';
|
|
|
|
import * as Select from '$lib/components/ui/select';
|
|
|
|
import { Separator } from '$lib/components/ui/separator';
|
|
|
|
import { gpxStatistics, slicedGPXStatistics, splitAs } from '$lib/stores';
|
|
|
|
import { get } from 'svelte/store';
|
|
|
|
import { _ } from 'svelte-i18n';
|
2024-06-12 12:13:30 +02:00
|
|
|
import { onDestroy, tick } from 'svelte';
|
2024-06-10 20:03:57 +02:00
|
|
|
import { Crop } from 'lucide-svelte';
|
|
|
|
import { dbUtils } from '$lib/db';
|
|
|
|
|
2024-06-27 18:23:11 +02:00
|
|
|
$: validSelection =
|
|
|
|
$selection.hasAnyChildren(new ListRootItem(), true, ['waypoints']) &&
|
|
|
|
$gpxStatistics.local.points.length > 0;
|
2024-06-10 20:03:57 +02:00
|
|
|
|
|
|
|
let maxSliderValue = 100;
|
|
|
|
let sliderValues = [0, 100];
|
|
|
|
|
2024-06-12 14:53:43 +02:00
|
|
|
$: canCrop = sliderValues[0] != 0 || sliderValues[1] != maxSliderValue;
|
|
|
|
|
2024-06-10 20:03:57 +02:00
|
|
|
function updateSlicedGPXStatistics() {
|
2024-06-12 14:53:43 +02:00
|
|
|
if (validSelection && canCrop) {
|
2024-07-10 15:09:52 +02:00
|
|
|
$slicedGPXStatistics = [
|
2024-06-12 12:46:59 +02:00
|
|
|
get(gpxStatistics).slice(sliderValues[0], sliderValues[1]),
|
|
|
|
sliderValues[0],
|
|
|
|
sliderValues[1]
|
2024-07-10 15:09:52 +02:00
|
|
|
];
|
2024-06-10 20:03:57 +02:00
|
|
|
} else {
|
2024-07-10 15:09:52 +02:00
|
|
|
$slicedGPXStatistics = undefined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateSliderValues() {
|
|
|
|
if ($slicedGPXStatistics !== undefined) {
|
|
|
|
sliderValues = [$slicedGPXStatistics[1], $slicedGPXStatistics[2]];
|
2024-06-10 20:03:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function updateSliderLimits() {
|
2024-06-12 14:53:43 +02:00
|
|
|
if (validSelection && $gpxStatistics.local.points.length > 0) {
|
2024-06-12 12:46:59 +02:00
|
|
|
maxSliderValue = $gpxStatistics.local.points.length - 1;
|
2024-06-10 20:03:57 +02:00
|
|
|
} else {
|
|
|
|
maxSliderValue = 100;
|
|
|
|
}
|
|
|
|
await tick();
|
|
|
|
sliderValues = [0, maxSliderValue];
|
|
|
|
}
|
|
|
|
|
2024-06-12 12:46:59 +02:00
|
|
|
$: if ($gpxStatistics.local.points.length - 1 != maxSliderValue) {
|
2024-06-10 20:03:57 +02:00
|
|
|
updateSliderLimits();
|
|
|
|
}
|
|
|
|
|
|
|
|
$: if (sliderValues) {
|
|
|
|
updateSlicedGPXStatistics();
|
|
|
|
}
|
|
|
|
|
2024-07-10 15:09:52 +02:00
|
|
|
$: if (
|
|
|
|
$slicedGPXStatistics !== undefined &&
|
|
|
|
($slicedGPXStatistics[1] !== sliderValues[0] || $slicedGPXStatistics[2] !== sliderValues[1])
|
|
|
|
) {
|
|
|
|
updateSliderValues();
|
|
|
|
}
|
|
|
|
|
2024-06-10 20:03:57 +02:00
|
|
|
const splitTypes = [
|
|
|
|
{ value: SplitType.FILES, label: $_('gpx.files') },
|
|
|
|
{ value: SplitType.TRACKS, label: $_('gpx.tracks') },
|
|
|
|
{ value: SplitType.SEGMENTS, label: $_('gpx.segments') }
|
|
|
|
];
|
|
|
|
|
|
|
|
let splitType = splitTypes[0];
|
|
|
|
|
|
|
|
$: splitAs.set(splitType.value);
|
2024-06-12 12:13:30 +02:00
|
|
|
|
|
|
|
onDestroy(() => {
|
2024-07-10 15:09:52 +02:00
|
|
|
$slicedGPXStatistics = undefined;
|
2024-06-12 12:13:30 +02:00
|
|
|
});
|
2024-06-10 20:03:57 +02:00
|
|
|
</script>
|
|
|
|
|
2024-07-09 22:49:57 +02:00
|
|
|
<div class="flex flex-col gap-3 w-full max-w-80 {$$props.class ?? ''}">
|
2024-06-10 20:03:57 +02:00
|
|
|
<div class="p-2">
|
|
|
|
<Slider bind:value={sliderValues} max={maxSliderValue} step={1} disabled={!validSelection} />
|
|
|
|
</div>
|
|
|
|
<Button
|
|
|
|
variant="outline"
|
2024-06-12 14:53:43 +02:00
|
|
|
disabled={!validSelection || !canCrop}
|
2024-06-10 20:03:57 +02:00
|
|
|
on:click={() => dbUtils.cropSelection(sliderValues[0], sliderValues[1])}
|
|
|
|
>
|
2024-06-27 18:23:11 +02:00
|
|
|
<Crop size="16" class="mr-1" />{$_('toolbar.scissors.crop')}
|
|
|
|
</Button>
|
2024-06-10 20:03:57 +02:00
|
|
|
<Separator />
|
2024-07-10 15:09:52 +02:00
|
|
|
<Label class="flex flex-row flex-wrap gap-3 items-center">
|
2024-06-10 20:03:57 +02:00
|
|
|
<span class="shrink-0">
|
|
|
|
{$_('toolbar.scissors.split_as')}
|
|
|
|
</span>
|
|
|
|
<Select.Root bind:selected={splitType}>
|
2024-07-10 15:09:52 +02:00
|
|
|
<Select.Trigger class="h-8 w-fit grow">
|
2024-06-10 20:03:57 +02:00
|
|
|
<Select.Value />
|
|
|
|
</Select.Trigger>
|
|
|
|
<Select.Content>
|
|
|
|
{#each splitTypes as { value, label }}
|
|
|
|
<Select.Item {value}>{label}</Select.Item>
|
|
|
|
{/each}
|
|
|
|
</Select.Content>
|
|
|
|
</Select.Root>
|
|
|
|
</Label>
|
|
|
|
<Help>
|
|
|
|
{#if validSelection}
|
|
|
|
{$_('toolbar.scissors.help')}
|
|
|
|
{:else}
|
|
|
|
{$_('toolbar.scissors.help_invalid_selection')}
|
|
|
|
{/if}
|
|
|
|
</Help>
|
|
|
|
</div>
|