diff --git a/website/src/lib/components/Menu.svelte b/website/src/lib/components/Menu.svelte
index 3b19207ac..7695d6cb3 100644
--- a/website/src/lib/components/Menu.svelte
+++ b/website/src/lib/components/Menu.svelte
@@ -33,7 +33,13 @@
View,
FilePen,
HeartHandshake,
- PersonStanding
+ PersonStanding,
+ Eye,
+ EyeOff,
+ ClipboardCopy,
+ Scissors,
+ ClipboardPaste,
+ PaintBucket
} from 'lucide-svelte';
import {
@@ -44,9 +50,15 @@
createFile,
loadFiles,
toggleSelectionVisibility,
- updateSelectionFromKey
+ updateSelectionFromKey,
+ showSelection,
+ hideSelection,
+ anyHidden,
+ editMetadata,
+ editStyle
} from '$lib/stores';
import {
+ copied,
copySelection,
cutSelection,
pasteSelection,
@@ -65,6 +77,7 @@
import { languages } from '$lib/languages';
import { goto } from '$app/navigation';
import { base } from '$app/paths';
+ import { allowedPastes, ListFileItem, ListTrackItem } from './file-list/FileList';
const {
distanceUnits,
@@ -180,11 +193,75 @@
+ item instanceof ListFileItem || item instanceof ListTrackItem)}
+ on:click={() => ($editMetadata = true)}
+ >
+
+ {$_('menu.metadata.button')}
+
+ item instanceof ListFileItem || item instanceof ListTrackItem)}
+ on:click={() => ($editStyle = true)}
+ >
+
+ {$_('menu.style.button')}
+
+ {
+ if ($anyHidden) {
+ showSelection();
+ } else {
+ hideSelection();
+ }
+ }}
+ disabled={$selection.size == 0}
+ >
+ {#if $anyHidden}
+
+ {$_('menu.unhide')}
+ {:else}
+
+ {$_('menu.hide')}
+ {/if}
+
+
+
{$_('menu.select_all')}
+ {#if $verticalFileView}
+
+
+
+ {$_('menu.copy')}
+
+
+
+
+ {$_('menu.cut')}
+
+
+ 0 &&
+ !allowedPastes[$copied[0].level].includes($selection.getSelected().pop()?.level))}
+ on:click={pasteSelection}
+ >
+
+ {$_('menu.paste')}
+
+
+ {/if}
diff --git a/website/src/lib/components/file-list/FileListNodeLabel.svelte b/website/src/lib/components/file-list/FileListNodeLabel.svelte
index cd8f186aa..fc02506d7 100644
--- a/website/src/lib/components/file-list/FileListNodeLabel.svelte
+++ b/website/src/lib/components/file-list/FileListNodeLabel.svelte
@@ -35,7 +35,15 @@
} from './Selection';
import { getContext } from 'svelte';
import { get } from 'svelte/store';
- import { gpxLayers, hideSelection, map, showSelection } from '$lib/stores';
+ import {
+ anyHidden,
+ editMetadata,
+ editStyle,
+ gpxLayers,
+ hideSelection,
+ map,
+ showSelection
+ } from '$lib/stores';
import {
GPXTreeElement,
Track,
@@ -54,7 +62,6 @@
| Readonly;
export let item: ListItem;
export let label: string | undefined;
- let hidden = false;
let orientation = getContext<'vertical' | 'horizontal'>('orientation');
@@ -62,9 +69,6 @@
$: singleSelection = $selection.size === 1;
- let openEditMetadata: boolean = false;
- let openEditStyle: boolean = false;
-
let nodeColors: string[] = [];
$: if (node && $map) {
@@ -98,6 +102,15 @@
}
}
}
+
+ let openEditMetadata: boolean = false;
+ let openEditStyle: boolean = false;
+
+ $: openEditMetadata = $editMetadata && singleSelection && $selection.has(item);
+ $: openEditStyle =
+ $editStyle &&
+ $selection.has(item) &&
+ $selection.getSelected().findIndex((i) => i.getFullId() === item.getFullId()) === 0;
@@ -108,10 +121,6 @@
if (!get(selection).has(item)) {
selectItem(item);
}
- let layer = gpxLayers.get(item.getFileId());
- if (layer) {
- hidden = layer.hidden;
- }
}
}}
>
@@ -185,25 +194,25 @@
{#if item instanceof ListFileItem || item instanceof ListTrackItem}
- (openEditMetadata = true)}>
+ ($editMetadata = true)}>
{$_('menu.metadata.button')}
- (openEditStyle = true)}>
+ ($editStyle = true)}>
{$_('menu.style.button')}
{#if item instanceof ListFileItem}
{
- if (hidden) {
+ if ($anyHidden) {
showSelection();
} else {
hideSelection();
}
}}
>
- {#if hidden}
+ {#if $anyHidden}
{$_('menu.unhide')}
{:else}
@@ -252,14 +261,12 @@
{/if}
{/if}
- {#if $verticalFileView || item.level !== ListLevel.WAYPOINTS}
- {#if item.level !== ListLevel.WAYPOINTS}
-
-
- {$_('menu.duplicate')}
-
- {/if}
+ {#if $verticalFileView}
+
+
+ {$_('menu.duplicate')}
+
{#if $verticalFileView}
diff --git a/website/src/lib/components/file-list/MetadataDialog.svelte b/website/src/lib/components/file-list/MetadataDialog.svelte
index 402da627f..317b2f338 100644
--- a/website/src/lib/components/file-list/MetadataDialog.svelte
+++ b/website/src/lib/components/file-list/MetadataDialog.svelte
@@ -9,6 +9,7 @@
import { ListFileItem, ListTrackItem, type ListItem } from './FileList';
import { GPXTreeElement, Track, type AnyGPXTreeElement, Waypoint, GPXFile } from 'gpx';
import { _ } from 'svelte-i18n';
+ import { editMetadata } from '$lib/stores';
export let node:
| GPXTreeElement
@@ -29,6 +30,10 @@
: node instanceof Track
? node.desc ?? ''
: '';
+
+ $: if (!open) {
+ $editMetadata = false;
+ }
diff --git a/website/src/lib/components/file-list/StyleDialog.svelte b/website/src/lib/components/file-list/StyleDialog.svelte
index 0666931f6..88531029f 100644
--- a/website/src/lib/components/file-list/StyleDialog.svelte
+++ b/website/src/lib/components/file-list/StyleDialog.svelte
@@ -8,7 +8,7 @@
import { Save } from 'lucide-svelte';
import { ListFileItem, ListTrackItem, type ListItem } from './FileList';
import { selection } from './Selection';
- import { gpxLayers } from '$lib/stores';
+ import { editStyle, gpxLayers } from '$lib/stores';
import { _ } from 'svelte-i18n';
export let item: ListItem;
@@ -89,6 +89,10 @@
$: if ($selection && open) {
setStyleInputs();
}
+
+ $: if (!open) {
+ $editStyle = false;
+ }
diff --git a/website/src/lib/components/toolbar/tools/Scissors.svelte b/website/src/lib/components/toolbar/tools/Scissors.svelte
index ca9ade908..b20f1de18 100644
--- a/website/src/lib/components/toolbar/tools/Scissors.svelte
+++ b/website/src/lib/components/toolbar/tools/Scissors.svelte
@@ -22,7 +22,9 @@
import { Crop } from 'lucide-svelte';
import { dbUtils } from '$lib/db';
- $: validSelection = $selection.hasAnyChildren(new ListRootItem(), true, ['waypoints']);
+ $: validSelection =
+ $selection.hasAnyChildren(new ListRootItem(), true, ['waypoints']) &&
+ $gpxStatistics.local.points.length > 0;
let maxSliderValue = 100;
let sliderValues = [0, 100];
@@ -82,8 +84,9 @@
variant="outline"
disabled={!validSelection || !canCrop}
on:click={() => dbUtils.cropSelection(sliderValues[0], sliderValues[1])}
- >{$_('toolbar.scissors.crop')}
+ {$_('toolbar.scissors.crop')}
+