rework map bounds logic when opening files from url

This commit is contained in:
vcoppe
2024-09-19 10:35:02 +02:00
parent a27de23fa4
commit aa50f1f2b0
3 changed files with 146 additions and 144 deletions

View File

@@ -180,7 +180,7 @@ function dexieGPXFileStore(id: string): Readable<GPXFileWithStatistics> & { dest
let statistics = new GPXStatisticsTree(gpx);
if (!fileState.has(id)) { // Update the map bounds for new files
updateTargetMapBounds(statistics.getStatisticsFor(new ListFileItem(id)).global.bounds);
updateTargetMapBounds(id, statistics.getStatisticsFor(new ListFileItem(id)).global.bounds);
}
fileState.set(id, gpx);
@@ -287,12 +287,13 @@ export const fileObservers: Writable<Map<string, Readable<GPXFileWithStatistics
const fileState: Map<string, GPXFile> = new Map(); // Used to generate patches
// Observe the file ids in the database, and maintain a map of file observers for the corresponding files
export function observeFilesFromDatabase() {
export function observeFilesFromDatabase(fitBounds: boolean) {
let initialize = true;
liveQuery(() => db.fileids.toArray()).subscribe(dbFileIds => {
if (initialize) {
if (dbFileIds.length > 0) {
initTargetMapBounds(dbFileIds.length);
console.log('fitBounds', fitBounds);
if (fitBounds && dbFileIds.length > 0) {
initTargetMapBounds(dbFileIds);
}
initialize = false;
}
@@ -453,13 +454,14 @@ export const dbUtils = {
});
},
addMultiple: (files: GPXFile[]) => {
return applyGlobal((draft) => {
let ids = getFileIds(files.length);
applyGlobal((draft) => {
files.forEach((file, index) => {
file._data.id = ids[index];
draft.set(file._data.id, freeze(file));
});
});
return ids;
},
applyToFile: (id: string, callback: (file: WritableDraft<GPXFile>) => void) => {
applyToFiles([id], callback);

View File

@@ -84,16 +84,20 @@ gpxStatistics.subscribe(() => {
slicedGPXStatistics.set(undefined);
});
const targetMapBounds = writable({
const targetMapBounds = writable<{
bounds: mapboxgl.LngLatBounds;
ids: string[];
total: number;
}>({
bounds: new mapboxgl.LngLatBounds([180, 90, -180, -90]),
count: 0,
total: -1
ids: [],
total: 0,
});
derived([targetMapBounds, map], (x) => x).subscribe(([bounds, $map]) => {
if (
$map === null ||
bounds.count !== bounds.total ||
bounds.ids.length > 0 ||
(bounds.bounds.getSouth() === 90 &&
bounds.bounds.getWest() === 180 &&
bounds.bounds.getNorth() === -90 &&
@@ -102,10 +106,13 @@ derived([targetMapBounds, map], (x) => x).subscribe(([bounds, $map]) => {
return;
}
let currentZoom = $map.getZoom();
let currentBounds = $map.getBounds();
if (bounds.count !== get(fileObservers).size && currentBounds) {
if (bounds.total !== get(fileObservers).size &&
currentBounds &&
currentZoom > 2 // Extend current bounds only if the map is zoomed in
) {
// There are other files on the map
if (
currentBounds.contains(bounds.bounds.getSouthEast()) &&
currentBounds.contains(bounds.bounds.getNorthWest())
@@ -120,33 +127,32 @@ derived([targetMapBounds, map], (x) => x).subscribe(([bounds, $map]) => {
$map.fitBounds(bounds.bounds, { padding: 80, linear: true, easing: () => 1 });
});
export function initTargetMapBounds(total: number) {
export function initTargetMapBounds(ids: string[]) {
targetMapBounds.set({
bounds: new mapboxgl.LngLatBounds([180, 90, -180, -90]),
count: 0,
total: total
ids,
total: ids.length,
});
}
export function updateTargetMapBounds(bounds: { southWest: Coordinates; northEast: Coordinates }) {
if (
bounds.southWest.lat == 90 &&
bounds.southWest.lon == 180 &&
bounds.northEast.lat == -90 &&
bounds.northEast.lon == -180
) {
// Avoid update for empty (new) files
targetMapBounds.update((target) => {
target.count += 1;
return target;
});
export function updateTargetMapBounds(id: string, bounds: { southWest: Coordinates; northEast: Coordinates }) {
if (get(targetMapBounds).ids.indexOf(id) === -1) {
return;
}
targetMapBounds.update((target) => {
target.ids = target.ids.filter((x) => x !== id);
if (
bounds.southWest.lat !== 90 ||
bounds.southWest.lon !== 180 ||
bounds.northEast.lat !== -90 ||
bounds.northEast.lon !== -180
) {
// Avoid update for empty (new) files
target.bounds.extend(bounds.southWest);
target.bounds.extend(bounds.northEast);
target.count += 1;
}
return target;
});
}
@@ -246,7 +252,7 @@ export function triggerFileInput() {
}
export async function loadFiles(list: FileList | File[]) {
let files = [];
let files: GPXFile[] = [];
for (let i = 0; i < list.length; i++) {
let file = await loadFile(list[i]);
if (file) {
@@ -254,11 +260,10 @@ export async function loadFiles(list: FileList | File[]) {
}
}
initTargetMapBounds(list.length);
let ids = dbUtils.addMultiple(files);
dbUtils.addMultiple(files);
selectFileWhenLoaded(files[0]._data.id);
initTargetMapBounds(ids);
selectFileWhenLoaded(ids[0]);
}
export async function loadFile(file: File): Promise<GPXFile | null> {

View File

@@ -29,12 +29,12 @@
} = settings;
onMount(() => {
observeFilesFromDatabase();
let files: string[] = JSON.parse($page.url.searchParams.get('files') || '[]');
let ids: string[] = JSON.parse($page.url.searchParams.get('ids') || '[]');
let urls: string[] = files.concat(ids.map(getURLForGoogleDriveFile));
observeFilesFromDatabase(urls.length === 0);
if (urls.length > 0) {
let downloads: Promise<File | null>[] = [];
urls.forEach((url) => {
@@ -74,12 +74,7 @@
{/if}
</div>
{#if $elevationProfile}
<Resizer
orientation="row"
bind:after={$bottomPanelSize}
minAfter={100}
maxAfter={300}
/>
<Resizer orientation="row" bind:after={$bottomPanelSize} minAfter={100} maxAfter={300} />
{/if}
<div
class="{$elevationProfile ? '' : 'h-10'} flex flex-row gap-2 px-2 sm:px-4"