Files
gpx.studio/website/src/lib/components/toolbar/tools/Merge.svelte

110 lines
4.6 KiB
Svelte
Raw Normal View History

2025-10-17 23:54:45 +02:00
<script lang="ts" module>
enum MergeType {
TRACES = 'traces',
CONTENTS = 'contents',
}
2024-06-08 17:19:22 +02:00
</script>
<script lang="ts">
2025-10-05 19:34:05 +02:00
import { ListFileItem, ListTrackItem } from '$lib/components/file-list/file-list';
import Help from '$lib/components/Help.svelte';
import { Button } from '$lib/components/ui/button';
import { Label } from '$lib/components/ui/label/index.js';
import { Checkbox } from '$lib/components/ui/checkbox';
import * as RadioGroup from '$lib/components/ui/radio-group';
2025-06-21 21:07:36 +02:00
import { i18n } from '$lib/i18n.svelte';
import { Group } from '@lucide/svelte';
import { getURLForLanguage } from '$lib/utils';
import Shortcut from '$lib/components/Shortcut.svelte';
2025-10-17 23:54:45 +02:00
import { selection } from '$lib/logic/selection';
import { fileStateCollection } from '$lib/logic/file-state';
import { fileActions } from '$lib/logic/file-actions';
2025-10-18 16:10:08 +02:00
import { gpxStatistics } from '$lib/logic/statistics';
2024-06-08 17:19:22 +02:00
2025-10-05 19:34:05 +02:00
let props: {
class?: string;
} = $props();
2024-06-08 17:19:22 +02:00
2025-10-05 19:34:05 +02:00
let canMergeTraces = $derived.by(() => {
2025-10-18 16:10:08 +02:00
if ($selection.size > 1) {
2025-10-05 19:34:05 +02:00
return true;
2025-10-18 16:10:08 +02:00
} else if ($selection.size === 1) {
let selected = $selection.getSelected()[0];
2025-10-05 19:34:05 +02:00
if (selected instanceof ListFileItem) {
let file = fileStateCollection.getFile(selected.getFileId());
if (file) {
return file.getSegments().length > 1;
}
} else if (selected instanceof ListTrackItem) {
let trackIndex = selected.getTrackIndex();
let file = fileStateCollection.getFile(selected.getFileId());
if (file && trackIndex < file.trk.length) {
return file.trk[trackIndex].getSegments().length > 1;
}
}
2025-10-05 19:34:05 +02:00
return false;
}
2025-10-05 19:34:05 +02:00
});
2024-06-08 17:19:22 +02:00
2025-10-05 19:34:05 +02:00
let canMergeContents = $derived(
2025-10-18 16:10:08 +02:00
$selection.size > 1 &&
$selection
2025-10-05 19:34:05 +02:00
.getSelected()
.some((item) => item instanceof ListFileItem || item instanceof ListTrackItem)
);
2024-06-08 17:19:22 +02:00
2025-10-05 19:34:05 +02:00
let removeGaps = $state(false);
let mergeType = $state(MergeType.TRACES);
2024-06-08 17:19:22 +02:00
</script>
2025-10-05 19:34:05 +02:00
<div class="flex flex-col gap-3 w-full max-w-80 {props.class ?? ''}">
<RadioGroup.Root bind:value={mergeType}>
<Label class="flex flex-row items-center gap-1.5 leading-5">
<RadioGroup.Item value={MergeType.TRACES} />
2025-06-21 21:07:36 +02:00
{i18n._('toolbar.merge.merge_traces')}
</Label>
<Label class="flex flex-row items-center gap-1.5 leading-5">
<RadioGroup.Item value={MergeType.CONTENTS} />
2025-06-21 21:07:36 +02:00
{i18n._('toolbar.merge.merge_contents')}
</Label>
</RadioGroup.Root>
{#if mergeType === MergeType.TRACES && $gpxStatistics.global.time.total > 0}
<div class="flex flex-row items-center gap-1.5">
<Checkbox id="remove-gaps" bind:checked={removeGaps} />
2025-06-21 21:07:36 +02:00
<Label for="remove-gaps">{i18n._('toolbar.merge.remove_gaps')}</Label>
</div>
{/if}
<Button
variant="outline"
class="whitespace-normal h-fit"
disabled={(mergeType === MergeType.TRACES && !canMergeTraces) ||
(mergeType === MergeType.CONTENTS && !canMergeContents)}
2025-06-21 21:07:36 +02:00
onclick={() => {
2025-10-05 19:34:05 +02:00
fileActions.mergeSelection(
mergeType === MergeType.TRACES,
mergeType === MergeType.TRACES && $gpxStatistics.global.time.total > 0 && removeGaps
);
}}
>
<Group size="16" class="mr-1 shrink-0" />
2025-06-21 21:07:36 +02:00
{i18n._('toolbar.merge.merge_selection')}
</Button>
2025-06-21 21:07:36 +02:00
<Help link={getURLForLanguage(i18n.lang, '/help/toolbar/merge')}>
{#if mergeType === MergeType.TRACES && canMergeTraces}
2025-06-21 21:07:36 +02:00
{i18n._('toolbar.merge.help_merge_traces')}
{:else if mergeType === MergeType.TRACES && !canMergeTraces}
2025-06-21 21:07:36 +02:00
{i18n._('toolbar.merge.help_cannot_merge_traces')}
{i18n._('toolbar.merge.selection_tip').split('{KEYBOARD_SHORTCUT}')[0]}
2025-10-18 18:51:11 +02:00
<Shortcut ctrl={true} click={true} class="border" />
2025-06-21 21:07:36 +02:00
{i18n._('toolbar.merge.selection_tip').split('{KEYBOARD_SHORTCUT}')[1]}
{:else if mergeType === MergeType.CONTENTS && canMergeContents}
2025-06-21 21:07:36 +02:00
{i18n._('toolbar.merge.help_merge_contents')}
{:else if mergeType === MergeType.CONTENTS && !canMergeContents}
2025-06-21 21:07:36 +02:00
{i18n._('toolbar.merge.help_cannot_merge_contents')}
{i18n._('toolbar.merge.selection_tip').split('{KEYBOARD_SHORTCUT}')[0]}
2025-10-18 18:51:11 +02:00
<Shortcut ctrl={true} click={true} class="border" />
2025-06-21 21:07:36 +02:00
{i18n._('toolbar.merge.selection_tip').split('{KEYBOARD_SHORTCUT}')[1]}
{/if}
</Help>
2024-06-08 17:19:22 +02:00
</div>