wrap file collection in single object

This commit is contained in:
vcoppe
2024-04-22 17:22:21 +02:00
parent c61b559343
commit 8f6c1fc88d
6 changed files with 60 additions and 43 deletions

View File

@@ -1,9 +1,9 @@
<script lang="ts">
import GPX from './GPX.svelte';
import { files } from '$lib/stores';
import { fileCollection } from '$lib/stores';
</script>
{#each $files as file}
{#each $fileCollection.files as file}
<GPX {file} />
{/each}

View File

@@ -6,7 +6,7 @@
import Chart from 'chart.js/auto';
import mapboxgl from 'mapbox-gl';
import { map, files, fileOrder, selectedFiles } from '$lib/stores';
import { map, fileCollection, fileOrder, selectedFiles } from '$lib/stores';
import { onDestroy, onMount } from 'svelte';
import {
@@ -75,10 +75,10 @@
},
tooltip: {
callbacks: {
title: function (context) {
title: function () {
return '';
},
label: function (context) {
label: function (context: Chart.TooltipContext) {
let point = context.raw;
if (context.datasetIndex === 0) {
let elevation = point.y.toFixed(0);
@@ -104,7 +104,7 @@
return `Power: ${power} W`;
}
},
afterBody: function (contexts) {
afterBody: function (contexts: Chart.TooltipContext[]) {
let context = contexts.filter((context) => context.datasetIndex === 0);
if (context.length === 0) return;
let point = context[0].raw;
@@ -124,7 +124,13 @@
stacked: false
};
let datasets = {
let datasets: {
[key: string]: {
id: string;
label: string;
units: string;
};
} = {
speed: {
id: 'speed',
label: 'Speed',
@@ -179,7 +185,7 @@
{
id: 'toggleMarker',
events: ['mouseout'],
afterEvent: function (chart, args) {
afterEvent: function (chart: Chart, args: { event: Chart.ChartEvent }) {
if (args.event.type === 'mouseout') {
if ($map && marker) {
marker.remove();
@@ -194,7 +200,7 @@
$: if (chart) {
let gpxFiles = new GPXFiles(Array.from($selectedFiles));
let order = $fileOrder.length == 0 ? $files : $fileOrder;
let order = $fileOrder.length == 0 ? $fileCollection.files : $fileOrder;
gpxFiles.files.sort(function (a, b) {
return order.indexOf(a) - order.indexOf(b);
});

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { fileOrder, files, selectedFiles, selectFiles } from '$lib/stores';
import { fileOrder, fileCollection, selectedFiles, selectFiles } from '$lib/stores';
import { ScrollArea } from '$lib/components/ui/scroll-area/index';
import Sortable from 'sortablejs/Sortable';
@@ -30,7 +30,7 @@
function selectAllFiles() {
selectedFiles.update((selectedFiles) => {
get(files).forEach((file) => {
get(fileCollection).files.forEach((file) => {
selectedFiles.add(file);
});
return selectedFiles;
@@ -53,12 +53,12 @@
avoidImplicitDeselect: true,
onSelect: (e) => {
const index = parseInt(e.item.getAttribute('data-id'));
addSelectFile($files[index]);
addSelectFile($fileCollection.files[index]);
if (!e.originalEvent.shiftKey && $selectedFiles.size > 1) {
$selectedFiles.forEach((file) => {
if (file !== $files[index]) {
if (file !== $fileCollection.files[index]) {
deselectFile(file);
const index = $files.indexOf(file);
const index = $fileCollection.files.indexOf(file);
Sortable.utils.deselect(buttons[index]);
}
});
@@ -66,10 +66,12 @@
},
onDeselect: (e) => {
const index = parseInt(e.item.getAttribute('data-id'));
deselectFile($files[index]);
deselectFile($fileCollection.files[index]);
},
onSort: () => {
$fileOrder = sortable.toArray().map((index) => $files[parseInt(index)]);
$fileOrder = sortable
.toArray()
.map((index: string) => $fileCollection.files[parseInt(index)]);
}
});
});
@@ -82,23 +84,23 @@
Sortable.utils.deselect(button);
}
});
const index = $files.indexOf(file);
const index = $fileCollection.files.indexOf(file);
Sortable.utils.select(buttons[index]);
selectFile(file);
},
addSelect: (file: GPXFile) => {
const index = $files.indexOf(file);
const index = $fileCollection.files.indexOf(file);
Sortable.utils.select(buttons[index]);
addSelectFile(file);
},
selectAllFiles: () => {
$files.forEach((file, index) => {
$fileCollection.files.forEach((file, index) => {
Sortable.utils.select(buttons[index]);
});
selectAllFiles();
},
removeSelect: (file: GPXFile) => {
const index = $files.indexOf(file);
const index = $fileCollection.files.indexOf(file);
Sortable.utils.deselect(buttons[index]);
deselectFile(file);
}
@@ -109,7 +111,7 @@
<div class="absolute h-10 -translate-y-10 w-fit max-w-full bg-secondary rounded-t">
<ScrollArea orientation="horizontal" class="w-full h-full" scrollbarXClasses="h-2">
<div bind:this={tabs} class="flex flex-row gap-1">
{#each $files as file, index}
{#each $fileCollection.files as file, index}
<button
bind:this={buttons[index]}
data-id={index}

View File

@@ -41,7 +41,7 @@
<script lang="ts">
import { onDestroy, onMount } from 'svelte';
import { GPXFile } from 'gpx';
import { map, selectedFiles, selectFiles, files } from '$lib/stores';
import { map, selectedFiles, selectFiles, fileCollection } from '$lib/stores';
import { get } from 'svelte/store';
export let file: GPXFile;
@@ -127,7 +127,7 @@
onMount(() => {
addGPXLayer();
if ($map) {
if ($files.length == 1) {
if ($fileCollection.files.length == 1) {
$map.fitBounds([file.statistics.bounds.southWest, file.statistics.bounds.northEast], {
padding: 60,
linear: true,

View File

@@ -15,7 +15,7 @@
} from 'lucide-svelte';
import {
files,
fileCollection,
selectedFiles,
duplicateSelectedFiles,
exportAllFiles,
@@ -62,7 +62,7 @@
<Menubar.Item on:click={exportSelectedFiles} disabled={$selectedFiles.size == 0}>
<Download size="16" class="mr-1" /> Export... <Menubar.Shortcut>⌘S</Menubar.Shortcut>
</Menubar.Item>
<Menubar.Item on:click={exportAllFiles} disabled={$files.length == 0}>
<Menubar.Item on:click={exportAllFiles} disabled={$fileCollection.files.length == 0}>
<Download size="16" class="mr-1" /> Export all... <Menubar.Shortcut
>⇧⌘S</Menubar.Shortcut
>
@@ -86,7 +86,7 @@
<Menubar.Item
class="text-destructive data-[highlighted]:text-destructive"
on:click={removeAllFiles}
disabled={$files.length == 0}
disabled={$fileCollection.files.length == 0}
>
<Trash2 size="16" class="mr-1" /> Delete all<Menubar.Shortcut>⇧⌘⌫</Menubar.Shortcut
></Menubar.Item

View File

@@ -1,14 +1,21 @@
import { writable, get } from 'svelte/store';
import mapboxgl from 'mapbox-gl';
import { GPXFile, buildGPX, parseGPX } from 'gpx';
import { GPXFile, GPXFiles, buildGPX, parseGPX } from 'gpx';
export const map = writable<mapboxgl.Map | null>(null);
export const files = writable<GPXFile[]>([]);
export const fileCollection = writable<GPXFiles>(new GPXFiles([]));
export const fileOrder = writable<GPXFile[]>([]);
export const selectedFiles = writable<Set<GPXFile>>(new Set());
export const selectFiles = writable<{ [key: string]: (file?: GPXFile) => void }>({});
export function addFile(file: GPXFile) {
fileCollection.update($files => {
$files.files.push(file);
return $files;
});
}
export function triggerFileInput() {
const input = document.createElement('input');
input.type = 'file';
@@ -25,15 +32,15 @@ export function triggerFileInput() {
export async function loadFiles(list: FileList) {
for (let i = 0; i < list.length; i++) {
await loadFile(list[i]);
if (i == 0) {
get(selectFiles).select(get(files)[get(files).length - 1]);
let file = await loadFile(list[i]);
if (i == 0 && file) {
get(selectFiles).select(file);
}
}
}
export async function loadFile(file: File) {
let result = await new Promise<void>((resolve) => {
let result = await new Promise<GPXFile | null>((resolve) => {
const reader = new FileReader();
reader.onload = () => {
let data = reader.result?.toString() ?? null;
@@ -42,9 +49,11 @@ export async function loadFile(file: File) {
if (gpx.metadata.name === undefined) {
gpx.metadata['name'] = file.name.split('.').slice(0, -1).join('.');
}
files.update($files => [...$files, gpx]);
addFile(gpx);
resolve(gpx);
} else {
resolve(null);
}
resolve();
};
reader.readAsText(file);
});
@@ -59,15 +68,15 @@ export function duplicateSelectedFiles() {
export function duplicateFile(file: GPXFile) {
let clone = file.clone();
files.update($files => [...$files, clone]);
addFile(clone);
}
export function removeSelectedFiles() {
let index = 0;
while (index < get(files).length) {
if (get(selectedFiles).has(get(files)[index])) {
files.update($files => {
$files.splice(index, 1);
while (index < get(fileCollection).files.length) {
if (get(selectedFiles).has(get(fileCollection).files[index])) {
fileCollection.update($files => {
$files.files.splice(index, 1);
return $files;
});
} else {
@@ -78,8 +87,8 @@ export function removeSelectedFiles() {
}
export function removeAllFiles() {
files.update($files => {
$files.splice(0, $files.length);
fileCollection.update($files => {
$files.files.splice(0, $files.files.length);
return $files;
});
get(selectedFiles).clear();
@@ -90,8 +99,8 @@ export function exportSelectedFiles() {
}
export async function exportAllFiles() {
for (let i = 0; i < get(files).length; i++) {
exportFile(get(files)[i]);
for (let file of get(fileCollection).files) {
exportFile(file);
await new Promise(resolve => setTimeout(resolve, 200));
}
}