mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-09-01 08:12:32 +00:00
extract tool
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
import * as ContextMenu from '$lib/components/ui/context-menu';
|
import * as ContextMenu from '$lib/components/ui/context-menu';
|
||||||
import Shortcut from '$lib/components/Shortcut.svelte';
|
import Shortcut from '$lib/components/Shortcut.svelte';
|
||||||
import { dbUtils, fileObservers, settings } from '$lib/db';
|
import { dbUtils, getFile, settings } from '$lib/db';
|
||||||
import { Copy, MapPin, Plus, Trash2, Waypoints } from 'lucide-svelte';
|
import { Copy, MapPin, Plus, Trash2, Waypoints } from 'lucide-svelte';
|
||||||
import {
|
import {
|
||||||
ListFileItem,
|
ListFileItem,
|
||||||
@@ -56,9 +56,9 @@
|
|||||||
on:mouseenter={() => {
|
on:mouseenter={() => {
|
||||||
if (item instanceof ListWaypointItem) {
|
if (item instanceof ListWaypointItem) {
|
||||||
let layer = gpxLayers.get(item.getFileId());
|
let layer = gpxLayers.get(item.getFileId());
|
||||||
let fileStore = get(fileObservers).get(item.getFileId());
|
let file = getFile(item.getFileId());
|
||||||
if (layer && fileStore) {
|
if (layer && file) {
|
||||||
let waypoint = get(fileStore)?.file.wpt[item.getWaypointIndex()];
|
let waypoint = file.wpt[item.getWaypointIndex()];
|
||||||
if (waypoint) {
|
if (waypoint) {
|
||||||
layer.showWaypointPopup(waypoint);
|
layer.showWaypointPopup(waypoint);
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { get, writable } from "svelte/store";
|
import { get, writable } from "svelte/store";
|
||||||
import { ListFileItem, ListItem, ListRootItem, ListTrackItem, ListTrackSegmentItem, ListWaypointItem, type ListLevel, sortItems, ListWaypointsItem } from "./FileList";
|
import { ListFileItem, ListItem, ListRootItem, ListTrackItem, ListTrackSegmentItem, ListWaypointItem, type ListLevel, sortItems, ListWaypointsItem } from "./FileList";
|
||||||
import { fileObservers, settings } from "$lib/db";
|
import { fileObservers, getFile, settings } from "$lib/db";
|
||||||
|
|
||||||
export class SelectionTreeType {
|
export class SelectionTreeType {
|
||||||
item: ListItem;
|
item: ListItem;
|
||||||
@@ -174,23 +174,23 @@ export function selectAll() {
|
|||||||
$selection.set(new ListFileItem(fileId), true);
|
$selection.set(new ListFileItem(fileId), true);
|
||||||
});
|
});
|
||||||
} else if (item instanceof ListTrackItem) {
|
} else if (item instanceof ListTrackItem) {
|
||||||
let fileStore = get(fileObservers).get(item.getFileId());
|
let file = getFile(item.getFileId());
|
||||||
if (fileStore) {
|
if (file) {
|
||||||
get(fileStore)?.file.trk.forEach((_track, trackId) => {
|
file.trk.forEach((_track, trackId) => {
|
||||||
$selection.set(new ListTrackItem(item.getFileId(), trackId), true);
|
$selection.set(new ListTrackItem(item.getFileId(), trackId), true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (item instanceof ListTrackSegmentItem) {
|
} else if (item instanceof ListTrackSegmentItem) {
|
||||||
let fileStore = get(fileObservers).get(item.getFileId());
|
let file = getFile(item.getFileId());
|
||||||
if (fileStore) {
|
if (file) {
|
||||||
get(fileStore)?.file.trk[item.getTrackIndex()].trkseg.forEach((_segment, segmentId) => {
|
file.trk[item.getTrackIndex()].trkseg.forEach((_segment, segmentId) => {
|
||||||
$selection.set(new ListTrackSegmentItem(item.getFileId(), item.getTrackIndex(), segmentId), true);
|
$selection.set(new ListTrackSegmentItem(item.getFileId(), item.getTrackIndex(), segmentId), true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (item instanceof ListWaypointItem) {
|
} else if (item instanceof ListWaypointItem) {
|
||||||
let fileStore = get(fileObservers).get(item.getFileId());
|
let file = getFile(item.getFileId());
|
||||||
if (fileStore) {
|
if (file) {
|
||||||
get(fileStore)?.file.wpt.forEach((_waypoint, waypointId) => {
|
file.wpt.forEach((_waypoint, waypointId) => {
|
||||||
$selection.set(new ListWaypointItem(item.getFileId(), waypointId), true);
|
$selection.set(new ListWaypointItem(item.getFileId(), waypointId), true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,7 @@
|
|||||||
</ToolbarItem>
|
</ToolbarItem>
|
||||||
<ToolbarItem tool={Tool.EXTRACT}>
|
<ToolbarItem tool={Tool.EXTRACT}>
|
||||||
<Ungroup slot="icon" size="18" />
|
<Ungroup slot="icon" size="18" />
|
||||||
<span slot="tooltip">{$_('toolbar.extract_tooltip')}</span>
|
<span slot="tooltip">{$_('toolbar.extract.tooltip')}</span>
|
||||||
</ToolbarItem>
|
</ToolbarItem>
|
||||||
<ToolbarItem tool={Tool.REDUCE}>
|
<ToolbarItem tool={Tool.REDUCE}>
|
||||||
<Filter slot="icon" size="18" />
|
<Filter slot="icon" size="18" />
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
import Waypoint from '$lib/components/toolbar/tools/Waypoint.svelte';
|
import Waypoint from '$lib/components/toolbar/tools/Waypoint.svelte';
|
||||||
import Time from '$lib/components/toolbar/tools/Time.svelte';
|
import Time from '$lib/components/toolbar/tools/Time.svelte';
|
||||||
import Merge from '$lib/components/toolbar/tools/Merge.svelte';
|
import Merge from '$lib/components/toolbar/tools/Merge.svelte';
|
||||||
|
import Extract from '$lib/components/toolbar/tools/Extract.svelte';
|
||||||
import Clean from '$lib/components/toolbar/tools/Clean.svelte';
|
import Clean from '$lib/components/toolbar/tools/Clean.svelte';
|
||||||
import Reduce from '$lib/components/toolbar/tools/Reduce.svelte';
|
import Reduce from '$lib/components/toolbar/tools/Reduce.svelte';
|
||||||
import RoutingControlPopup from '$lib/components/toolbar/tools/routing/RoutingControlPopup.svelte';
|
import RoutingControlPopup from '$lib/components/toolbar/tools/routing/RoutingControlPopup.svelte';
|
||||||
@@ -44,6 +45,8 @@
|
|||||||
<Time />
|
<Time />
|
||||||
{:else if $currentTool === Tool.MERGE}
|
{:else if $currentTool === Tool.MERGE}
|
||||||
<Merge />
|
<Merge />
|
||||||
|
{:else if $currentTool === Tool.EXTRACT}
|
||||||
|
<Extract />
|
||||||
{:else if $currentTool === Tool.CLEAN}
|
{:else if $currentTool === Tool.CLEAN}
|
||||||
<Clean />
|
<Clean />
|
||||||
{:else if $currentTool === Tool.REDUCE}
|
{:else if $currentTool === Tool.REDUCE}
|
||||||
|
52
website/src/lib/components/toolbar/tools/Extract.svelte
Normal file
52
website/src/lib/components/toolbar/tools/Extract.svelte
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Button } from '$lib/components/ui/button';
|
||||||
|
import { Ungroup } from 'lucide-svelte';
|
||||||
|
import { selection } from '$lib/components/file-list/Selection';
|
||||||
|
import {
|
||||||
|
ListFileItem,
|
||||||
|
ListTrackItem,
|
||||||
|
ListTrackSegmentItem,
|
||||||
|
ListWaypointItem,
|
||||||
|
ListWaypointsItem
|
||||||
|
} from '$lib/components/file-list/FileList';
|
||||||
|
import Help from '$lib/components/Help.svelte';
|
||||||
|
import { dbUtils, getFile } from '$lib/db';
|
||||||
|
import { _ } from 'svelte-i18n';
|
||||||
|
|
||||||
|
$: validSelection =
|
||||||
|
$selection.size > 0 &&
|
||||||
|
$selection.getSelected().every((item) => {
|
||||||
|
if (
|
||||||
|
item instanceof ListWaypointsItem ||
|
||||||
|
item instanceof ListWaypointItem ||
|
||||||
|
item instanceof ListTrackSegmentItem
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let file = getFile(item.getFileId());
|
||||||
|
if (file) {
|
||||||
|
if (item instanceof ListFileItem) {
|
||||||
|
return file.getSegments().length > 1;
|
||||||
|
} else if (item instanceof ListTrackItem) {
|
||||||
|
if (item.getTrackIndex() < file.trk.length) {
|
||||||
|
return file.trk[item.getTrackIndex()].getSegments().length > 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-3 w-80">
|
||||||
|
<Button variant="outline" disabled={!validSelection} on:click={dbUtils.extractSelection}>
|
||||||
|
<Ungroup size="16" class="mr-1" />
|
||||||
|
{$_('toolbar.extract.button')}
|
||||||
|
</Button>
|
||||||
|
<Help>
|
||||||
|
{#if validSelection}
|
||||||
|
{$_('toolbar.extract.help')}
|
||||||
|
{:else}
|
||||||
|
{$_('toolbar.extract.help_invalid_selection')}
|
||||||
|
{/if}
|
||||||
|
</Help>
|
||||||
|
</div>
|
@@ -13,8 +13,7 @@
|
|||||||
import { Label } from '$lib/components/ui/label/index.js';
|
import { Label } from '$lib/components/ui/label/index.js';
|
||||||
import * as RadioGroup from '$lib/components/ui/radio-group';
|
import * as RadioGroup from '$lib/components/ui/radio-group';
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
import { dbUtils, fileObservers } from '$lib/db';
|
import { dbUtils, getFile } from '$lib/db';
|
||||||
import { get } from 'svelte/store';
|
|
||||||
import { Group } from 'lucide-svelte';
|
import { Group } from 'lucide-svelte';
|
||||||
|
|
||||||
let canMergeTraces = false;
|
let canMergeTraces = false;
|
||||||
@@ -25,29 +24,17 @@
|
|||||||
} else if ($selection.size === 1) {
|
} else if ($selection.size === 1) {
|
||||||
let selected = $selection.getSelected()[0];
|
let selected = $selection.getSelected()[0];
|
||||||
if (selected instanceof ListFileItem) {
|
if (selected instanceof ListFileItem) {
|
||||||
let fileId = selected.getFileId();
|
let file = getFile(selected.getFileId());
|
||||||
let fileStore = $fileObservers.get(fileId);
|
if (file) {
|
||||||
if (fileStore) {
|
canMergeTraces = file.getSegments().length > 1;
|
||||||
let file = get(fileStore)?.file;
|
|
||||||
if (file) {
|
|
||||||
canMergeTraces = file.getSegments().length > 1;
|
|
||||||
} else {
|
|
||||||
canMergeTraces = false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
canMergeTraces = false;
|
canMergeTraces = false;
|
||||||
}
|
}
|
||||||
} else if (selected instanceof ListTrackItem) {
|
} else if (selected instanceof ListTrackItem) {
|
||||||
let fileId = selected.getFileId();
|
|
||||||
let trackIndex = selected.getTrackIndex();
|
let trackIndex = selected.getTrackIndex();
|
||||||
let fileStore = $fileObservers.get(fileId);
|
let file = getFile(selected.getFileId());
|
||||||
if (fileStore) {
|
if (file && trackIndex < file.trk.length) {
|
||||||
let file = get(fileStore)?.file;
|
canMergeTraces = file.trk[trackIndex].getSegments().length > 1;
|
||||||
if (file && trackIndex < file.trk.length) {
|
|
||||||
canMergeTraces = file.trk[trackIndex].getSegments().length > 1;
|
|
||||||
} else {
|
|
||||||
canMergeTraces = false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
canMergeTraces = false;
|
canMergeTraces = false;
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
import { Waypoint } from 'gpx';
|
import { Waypoint } from 'gpx';
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
import { ListWaypointItem } from '$lib/components/file-list/FileList';
|
import { ListWaypointItem } from '$lib/components/file-list/FileList';
|
||||||
import { dbUtils, fileObservers, settings, type GPXFileWithStatistics } from '$lib/db';
|
import { dbUtils, fileObservers, getFile, settings, type GPXFileWithStatistics } from '$lib/db';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import Help from '$lib/components/Help.svelte';
|
import Help from '$lib/components/Help.svelte';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
@@ -36,12 +36,10 @@
|
|||||||
if ($selection.size === 1) {
|
if ($selection.size === 1) {
|
||||||
let item = $selection.getSelected()[0];
|
let item = $selection.getSelected()[0];
|
||||||
if (item instanceof ListWaypointItem) {
|
if (item instanceof ListWaypointItem) {
|
||||||
let fileStore = get(fileObservers).get(item.getFileId());
|
let file = getFile(item.getFileId());
|
||||||
if (fileStore) {
|
let waypoint = file?.wpt[item.getWaypointIndex()];
|
||||||
let waypoint = get(fileStore)?.file.wpt[item.getWaypointIndex()];
|
if (waypoint) {
|
||||||
if (waypoint) {
|
return [waypoint, item.getFileId()];
|
||||||
return [waypoint, item.getFileId()];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import Dexie, { liveQuery } from 'dexie';
|
import Dexie, { liveQuery } from 'dexie';
|
||||||
import { GPXFile, GPXStatistics, Track, type AnyGPXTreeElement, TrackSegment, Waypoint, TrackPoint, type Coordinates, distance } from 'gpx';
|
import { GPXFile, GPXStatistics, Track, TrackSegment, Waypoint, TrackPoint, type Coordinates, distance } from 'gpx';
|
||||||
import { enableMapSet, enablePatches, applyPatches, type Patch, type WritableDraft, castDraft, freeze, produceWithPatches, original, produce } from 'immer';
|
import { enableMapSet, enablePatches, applyPatches, type Patch, type WritableDraft, castDraft, freeze, produceWithPatches, original, produce } from 'immer';
|
||||||
import { writable, get, derived, type Readable, type Writable } from 'svelte/store';
|
import { writable, get, derived, type Readable, type Writable } from 'svelte/store';
|
||||||
import { initTargetMapBounds, splitAs, updateTargetMapBounds } from './stores';
|
import { initTargetMapBounds, splitAs, updateTargetMapBounds } from './stores';
|
||||||
@@ -267,6 +267,16 @@ liveQuery(() => db.fileids.toArray()).subscribe(dbFileIds => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export function getFile(fileId: string): GPXFile | undefined {
|
||||||
|
let fileStore = get(fileObservers).get(fileId);
|
||||||
|
return fileStore ? get(fileStore)?.file : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStatistics(fileId: string): GPXStatisticsTree | undefined {
|
||||||
|
let fileStore = get(fileObservers).get(fileId);
|
||||||
|
return fileStore ? get(fileStore)?.statistics : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const patchIndex: Readable<number> = dexieStore(() => db.settings.get('patchIndex'), -1);
|
const patchIndex: Readable<number> = dexieStore(() => db.settings.get('patchIndex'), -1);
|
||||||
const patchMinMaxIndex: Readable<{ min: number, max: number }> = dexieStore(() => db.patches.orderBy(':id').keys().then(keys => {
|
const patchMinMaxIndex: Readable<{ min: number, max: number }> = dexieStore(() => db.patches.orderBy(':id').keys().then(keys => {
|
||||||
if (keys.length === 0) {
|
if (keys.length === 0) {
|
||||||
@@ -605,6 +615,111 @@ export const dbUtils = {
|
|||||||
}, false);
|
}, false);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
extractSelection: () => {
|
||||||
|
return applyGlobal((draft) => {
|
||||||
|
applyToOrderedSelectedItemsFromFile((fileId, level, items) => {
|
||||||
|
let file = original(draft)?.get(fileId);
|
||||||
|
if (file) {
|
||||||
|
if (level === ListLevel.FILE) {
|
||||||
|
if (file.trk.length > 1) {
|
||||||
|
let fileIds = getFileIds(file.trk.length);
|
||||||
|
|
||||||
|
let closest = file.wpt.map((wpt, wptIndex) => {
|
||||||
|
return {
|
||||||
|
wptIndex: wptIndex,
|
||||||
|
index: [0],
|
||||||
|
distance: Number.MAX_VALUE
|
||||||
|
};
|
||||||
|
})
|
||||||
|
file.trk.forEach((track, index) => {
|
||||||
|
track.getSegments().forEach((segment) => {
|
||||||
|
segment.trkpt.forEach((point) => {
|
||||||
|
file.wpt.forEach((wpt, wptIndex) => {
|
||||||
|
let dist = distance(point.getCoordinates(), wpt.getCoordinates());
|
||||||
|
if (dist < closest[wptIndex].distance) {
|
||||||
|
closest[wptIndex].distance = dist;
|
||||||
|
closest[wptIndex].index = [index];
|
||||||
|
} else if (dist === closest[wptIndex].distance) {
|
||||||
|
closest[wptIndex].index.push(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
file.trk.forEach((track, index) => {
|
||||||
|
let tracks = track.trkseg.map((segment, segmentIndex) => {
|
||||||
|
let t = track.replaceTrackSegments(0, track.trkseg.length - 1, [segment])[0];
|
||||||
|
if (track.name) {
|
||||||
|
t.name = `${track.name} (${segmentIndex + 1})`;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
let newFile = file.replaceTracks(0, file.trk.length - 1, tracks)[0];
|
||||||
|
newFile = newFile.replaceWaypoints(0, file.wpt.length - 1, closest.filter((c) => c.index.includes(index)).map((c) => file.wpt[c.wptIndex]))[0];
|
||||||
|
newFile = produce(newFile, (f) => {
|
||||||
|
f._data.id = fileIds[index];
|
||||||
|
f.metadata.name = track.name ?? `${file.metadata.name} (${index + 1})`;
|
||||||
|
});
|
||||||
|
draft.set(newFile._data.id, freeze(newFile));
|
||||||
|
});
|
||||||
|
} else if (file.trk.length === 1) {
|
||||||
|
let fileIds = getFileIds(file.trk[0].trkseg.length);
|
||||||
|
|
||||||
|
|
||||||
|
let closest = file.wpt.map((wpt, wptIndex) => {
|
||||||
|
return {
|
||||||
|
wptIndex: wptIndex,
|
||||||
|
index: [0],
|
||||||
|
distance: Number.MAX_VALUE
|
||||||
|
};
|
||||||
|
})
|
||||||
|
file.trk[0].trkseg.forEach((segment, index) => {
|
||||||
|
segment.trkpt.forEach((point) => {
|
||||||
|
file.wpt.forEach((wpt, wptIndex) => {
|
||||||
|
let dist = distance(point.getCoordinates(), wpt.getCoordinates());
|
||||||
|
if (dist < closest[wptIndex].distance) {
|
||||||
|
closest[wptIndex].distance = dist;
|
||||||
|
closest[wptIndex].index = [index];
|
||||||
|
} else if (dist === closest[wptIndex].distance) {
|
||||||
|
closest[wptIndex].index.push(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
file.trk[0].trkseg.forEach((segment, index) => {
|
||||||
|
let newFile = file.replaceTrackSegments(0, 0, file.trk[0].trkseg.length - 1, [segment])[0];
|
||||||
|
newFile = newFile.replaceWaypoints(0, file.wpt.length - 1, closest.filter((c) => c.index.includes(index)).map((c) => file.wpt[c.wptIndex]))[0];
|
||||||
|
newFile = produce(newFile, (f) => {
|
||||||
|
f._data.id = fileIds[index];
|
||||||
|
f.metadata.name = `${file.trk[0].name ?? file.metadata.name} (${index + 1})`;
|
||||||
|
});
|
||||||
|
draft.set(newFile._data.id, freeze(newFile));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// TODO waypoints
|
||||||
|
draft.delete(fileId);
|
||||||
|
} else if (level === ListLevel.TRACK) {
|
||||||
|
let newFile = file;
|
||||||
|
for (let item of items) {
|
||||||
|
let trackIndex = (item as ListTrackItem).getTrackIndex();
|
||||||
|
let track = file.trk[trackIndex];
|
||||||
|
let tracks = track.trkseg.map((segment, segmentIndex) => {
|
||||||
|
let t = track.clone().replaceTrackSegments(0, track.trkseg.length - 1, [segment])[0];
|
||||||
|
if (track.name) {
|
||||||
|
t.name = `${track.name} (${segmentIndex + 1})`;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
newFile = newFile.replaceTracks(trackIndex, trackIndex, tracks)[0];
|
||||||
|
}
|
||||||
|
draft.set(newFile._data.id, freeze(newFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
split(fileId: string, trackIndex: number, segmentIndex: number, coordinates: Coordinates) {
|
split(fileId: string, trackIndex: number, segmentIndex: number, coordinates: Coordinates) {
|
||||||
let splitType = get(splitAs);
|
let splitType = get(splitAs);
|
||||||
return applyGlobal((draft) => {
|
return applyGlobal((draft) => {
|
||||||
|
@@ -5,7 +5,7 @@ import { GPXFile, buildGPX, parseGPX, GPXStatistics, type Coordinates } from 'gp
|
|||||||
import { tick } from 'svelte';
|
import { tick } from 'svelte';
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
import type { GPXLayer } from '$lib/components/gpx-layer/GPXLayer';
|
import type { GPXLayer } from '$lib/components/gpx-layer/GPXLayer';
|
||||||
import { dbUtils, fileObservers, settings } from './db';
|
import { dbUtils, fileObservers, getFile, getStatistics, settings } from './db';
|
||||||
import { applyToOrderedSelectedItemsFromFile, selectFile, selection } from '$lib/components/file-list/Selection';
|
import { applyToOrderedSelectedItemsFromFile, selectFile, selection } from '$lib/components/file-list/Selection';
|
||||||
import { ListFileItem, ListWaypointItem, ListWaypointsItem } from '$lib/components/file-list/FileList';
|
import { ListFileItem, ListWaypointItem, ListWaypointsItem } from '$lib/components/file-list/FileList';
|
||||||
import type { RoutingControls } from '$lib/components/toolbar/tools/routing/RoutingControls';
|
import type { RoutingControls } from '$lib/components/toolbar/tools/routing/RoutingControls';
|
||||||
@@ -21,18 +21,15 @@ export const slicedGPXStatistics: Writable<[GPXStatistics, number, number] | und
|
|||||||
function updateGPXData() {
|
function updateGPXData() {
|
||||||
let statistics = new GPXStatistics();
|
let statistics = new GPXStatistics();
|
||||||
applyToOrderedSelectedItemsFromFile((fileId, level, items) => {
|
applyToOrderedSelectedItemsFromFile((fileId, level, items) => {
|
||||||
let fileStore = get(fileObservers).get(fileId);
|
let stats = getStatistics(fileId);
|
||||||
if (fileStore) {
|
if (stats) {
|
||||||
let stats = get(fileStore)?.statistics;
|
let first = true;
|
||||||
if (stats) {
|
items.forEach((item) => {
|
||||||
let first = true;
|
if (!(item instanceof ListWaypointItem || item instanceof ListWaypointsItem) || first) {
|
||||||
items.forEach((item) => {
|
statistics.mergeWith(stats.getStatisticsFor(item));
|
||||||
if (!(item instanceof ListWaypointItem || item instanceof ListWaypointsItem) || first) {
|
first = false;
|
||||||
statistics.mergeWith(stats.getStatisticsFor(item));
|
}
|
||||||
first = false;
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
gpxStatistics.set(statistics);
|
gpxStatistics.set(statistics);
|
||||||
@@ -210,13 +207,10 @@ function selectFileWhenLoaded(fileId: string) {
|
|||||||
export function exportSelectedFiles() {
|
export function exportSelectedFiles() {
|
||||||
get(selection).forEach(async (item) => {
|
get(selection).forEach(async (item) => {
|
||||||
if (item instanceof ListFileItem) {
|
if (item instanceof ListFileItem) {
|
||||||
let fileStore = get(fileObservers).get(item.getFileId());
|
let file = getFile(item.getFileId());
|
||||||
if (fileStore) {
|
if (file) {
|
||||||
let file = get(fileStore)?.file;
|
exportFile(file);
|
||||||
if (file) {
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
exportFile(file);
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 200));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -141,7 +141,12 @@
|
|||||||
"help_merge_contents": "Merging the contents of the selected file items will group all the contents inside the first file item",
|
"help_merge_contents": "Merging the contents of the selected file items will group all the contents inside the first file item",
|
||||||
"help_cannot_merge_contents": "Your selection needs to contain several file items to merge their contents"
|
"help_cannot_merge_contents": "Your selection needs to contain several file items to merge their contents"
|
||||||
},
|
},
|
||||||
"extract_tooltip": "Extract contents",
|
"extract": {
|
||||||
|
"tooltip": "Extract contents to separate file items",
|
||||||
|
"button": "Extract",
|
||||||
|
"help": "Extracting the contents of the selected file items will create a separate file item for each of their contents",
|
||||||
|
"help_invalid_selection": "Your selection needs to contain file items with multiple traces to extract them"
|
||||||
|
},
|
||||||
"waypoint": {
|
"waypoint": {
|
||||||
"tooltip": "Create and edit points of interest",
|
"tooltip": "Create and edit points of interest",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
|
Reference in New Issue
Block a user