refactor(map): remove MapNoMapWarning component, streamline offline mode handling, and improve coordinate display with tabular formatting

This commit is contained in:
Ivan committed 2026-05-02 04:34:14 -05:00
1 parent 1ac6b41e3d
commit 61b7de27dd
5 files changed
+51 -81

No files matched your search

@@ -49,7 +49,6 @@
: 'text-gray-500 dark:text-gray-300'
"
class="px-2 py-1 text-xs sm:px-3 sm:text-sm font-medium rounded-md transition-all shrink-0"
:disabled="!hasOfflineMap"
@click="toggleOffline(true)"
>
{{ $t("map.offline_mode") }}
@@ -367,8 +366,6 @@
<MapLoadingOverlay v-if="isUploading" />
<MapNoMapWarning v-if="offlineEnabled && !hasOfflineMap" @upload="$refs.fileInput.click()" />
<div
v-if="showMapPingModal"
class="fixed inset-0 z-200 flex items-center justify-center bg-black/40 p-4"
@@ -389,7 +386,7 @@
<MaterialDesignIcon icon-name="close" class="size-5" />
</button>
</div>
<p class="text-xs text-gray-500 dark:text-zinc-400 mb-2 font-mono">
<p class="text-xs text-gray-500 dark:text-zinc-400 mb-2">
{{ mapPingSummary }}
</p>
<label class="block text-[10px] font-bold text-gray-400 uppercase mb-1">{{
@@ -467,15 +464,19 @@
<!-- Lat/Lon Box -->
<div
class="bg-white/80 dark:bg-zinc-900/80 backdrop-blur-sm border border-gray-200 dark:border-zinc-800 p-2 rounded-lg text-[10px] font-mono text-gray-600 dark:text-zinc-400 pointer-events-auto shadow-xs flex flex-col space-y-0.5"
class="bg-white/80 dark:bg-zinc-900/80 backdrop-blur-sm border border-gray-200 dark:border-zinc-800 p-2 rounded-lg text-[10px] text-gray-600 dark:text-zinc-400 pointer-events-auto shadow-xs flex flex-col space-y-0.5"
>
<div class="flex justify-between space-x-4">
<span class="opacity-50 uppercase tracking-tighter">Lat</span>
<span class="text-gray-900 dark:text-zinc-100">{{ displayCoords[1].toFixed(6) }}</span>
<span class="text-gray-900 dark:text-zinc-100 tabular-nums">{{
displayCoords[1].toFixed(6)
}}</span>
</div>
<div class="flex justify-between space-x-4">
<span class="opacity-50 uppercase tracking-tighter">Lon</span>
<span class="text-gray-900 dark:text-zinc-100">{{ displayCoords[0].toFixed(6) }}</span>
<span class="text-gray-900 dark:text-zinc-100 tabular-nums">{{
displayCoords[0].toFixed(6)
}}</span>
</div>
</div>
</div>
@@ -765,7 +766,7 @@
>Zoom</span
>
<span
class="text-[10px] font-mono font-bold text-gray-700 dark:text-zinc-300 leading-none tabular-nums"
class="text-[10px] font-bold text-gray-700 dark:text-zinc-300 leading-none tabular-nums"
>{{ currentZoom.toFixed(1) }}</span
>
</div>
@@ -774,7 +775,7 @@
>Lat</span
>
<span
class="text-[10px] font-mono font-bold text-gray-700 dark:text-zinc-300 leading-none tabular-nums"
class="text-[10px] font-bold text-gray-700 dark:text-zinc-300 leading-none tabular-nums"
>{{ displayCoords[1].toFixed(4) }}</span
>
</div>
@@ -783,7 +784,7 @@
>Lon</span
>
<span
class="text-[10px] font-mono font-bold text-gray-700 dark:text-zinc-300 leading-none tabular-nums"
class="text-[10px] font-bold text-gray-700 dark:text-zinc-300 leading-none tabular-nums"
>{{ displayCoords[0].toFixed(4) }}</span
>
</div>
@@ -1143,7 +1144,6 @@ import MapSearchBar from "./internal/MapSearchBar.vue";
import MapExportInstructions from "./internal/MapExportInstructions.vue";
import MapExportConfigPanel from "./internal/MapExportConfigPanel.vue";
import MapExportProgressPanel from "./internal/MapExportProgressPanel.vue";
import MapNoMapWarning from "./internal/MapNoMapWarning.vue";
import MapLoadingOverlay from "./internal/MapLoadingOverlay.vue";
import MapVectorExchangePanel from "./internal/MapVectorExchangePanel.vue";
import { buildMeshchatMapUri, buildWebHashMapUrl } from "../../js/mapLinkUtils.js";
@@ -1181,7 +1181,6 @@ export default {
MapExportInstructions,
MapExportConfigPanel,
MapExportProgressPanel,
MapNoMapWarning,
MapLoadingOverlay,
MapVectorExchangePanel,
},
@@ -1458,6 +1457,13 @@ export default {
} catch (e) {
console.warn("Failed to load map state from cache", e);
}
try {
const lo = localStorage.getItem("meshchatx.map.offlineMode");
if (lo === "1") this.offlineEnabled = true;
else if (lo === "0") this.offlineEnabled = false;
} catch {
/* ignore */
}
await this.initMap();
@@ -2597,7 +2603,6 @@ export default {
this.hasOfflineMap = false;
this.metadata = null;
if (this.offlineEnabled) {
this.offlineEnabled = false;
await this.updateMapSource();
}
}
@@ -2605,7 +2610,6 @@ export default {
this.hasOfflineMap = false;
this.metadata = null;
if (this.offlineEnabled) {
this.offlineEnabled = false;
await this.updateMapSource();
}
}
@@ -2631,11 +2635,6 @@ export default {
}
},
async toggleOffline(enabled) {
if (enabled && !this.hasOfflineMap) {
ToastUtils.error(this.$t("map.no_map_loaded"));
return;
}
this.tileErrorCount = 0;
this.dismissTileConnectivityBanner();
@@ -2672,6 +2671,11 @@ export default {
}
this.offlineEnabled = enabled;
try {
localStorage.setItem("meshchatx.map.offlineMode", enabled ? "1" : "0");
} catch {
/* ignore */
}
if (enabled) {
this.isExportMode = false;
this.clearSearch();
@@ -2798,6 +2802,11 @@ export default {
this.metadata = response.data.metadata;
this.hasOfflineMap = true;
this.offlineEnabled = true;
try {
localStorage.setItem("meshchatx.map.offlineMode", "1");
} catch {
/* ignore */
}
await this.loadMBTilesList();
await this.checkOfflineMap();
await this.updateMapSource();
@@ -1,24 +1,24 @@
<!-- SPDX-License-Identifier: 0BSD -->
<template>
<div
class="absolute top-4 left-1/2 -translate-x-1/2 z-20 flex flex-col items-center gap-2 max-w-[min(100vw-2rem,36rem)] px-2"
>
<div
class="px-4 py-2 bg-blue-600 text-white rounded-full shadow-lg font-medium text-sm animate-bounce text-center"
>
{{ $t("map.export_instructions") }}
</div>
<div v-if="presets && presets.length" class="flex flex-wrap justify-center gap-2 pointer-events-auto">
<button
v-for="p in presets"
:key="p.id"
type="button"
class="px-2 py-1 text-[10px] font-bold uppercase tracking-tight rounded-lg bg-white/95 dark:bg-zinc-900/95 border border-gray-200 dark:border-zinc-700 text-gray-800 dark:text-zinc-100 shadow-xs hover:bg-gray-50 dark:hover:bg-zinc-800"
@click="$emit('select-preset', p)"
<div class="absolute inset-x-0 top-4 z-20 flex justify-center px-2 pointer-events-none">
<div class="flex flex-col items-center gap-2 max-w-[min(100vw-2rem,36rem)] w-full pointer-events-auto">
<div
class="px-4 py-2 bg-blue-600 text-white rounded-full shadow-lg font-medium text-sm animate-bounce text-center"
>
{{ $t(`map.export_region_${p.id}`) }}
</button>
{{ $t("map.export_instructions") }}
</div>
<div v-if="presets && presets.length" class="flex flex-wrap justify-center gap-2 pointer-events-auto">
<button
v-for="p in presets"
:key="p.id"
type="button"
class="px-2 py-1 text-[10px] font-bold uppercase tracking-tight rounded-lg bg-white/95 dark:bg-zinc-900/95 border border-gray-200 dark:border-zinc-700 text-gray-800 dark:text-zinc-100 shadow-xs hover:bg-gray-50 dark:hover:bg-zinc-800"
@click="$emit('select-preset', p)"
>
{{ $t(`map.export_region_${p.id}`) }}
</button>
</div>
</div>
</div>
</template>
@@ -66,11 +66,11 @@
<div class="grid grid-cols-2 gap-4 text-sm">
<div>
<div class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-0.5">Latitude</div>
<div class="font-mono">{{ marker.discovered.latitude.toFixed(6) }}</div>
<div class="tabular-nums">{{ marker.discovered.latitude.toFixed(6) }}</div>
</div>
<div>
<div class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-0.5">Longitude</div>
<div class="font-mono">{{ marker.discovered.longitude.toFixed(6) }}</div>
<div class="tabular-nums">{{ marker.discovered.longitude.toFixed(6) }}</div>
</div>
</div>
@@ -94,23 +94,23 @@
<div class="grid grid-cols-2 gap-4 text-sm">
<div>
<div class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-0.5">Latitude</div>
<div class="font-mono">
<div class="tabular-nums">
{{ marker.telemetry.telemetry.location.latitude.toFixed(6) }}
</div>
</div>
<div>
<div class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-0.5">Longitude</div>
<div class="font-mono">
<div class="tabular-nums">
{{ marker.telemetry.telemetry.location.longitude.toFixed(6) }}
</div>
</div>
<div>
<div class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-0.5">Altitude</div>
<div>{{ marker.telemetry.telemetry.location.altitude.toFixed(1) }}m</div>
<div class="tabular-nums">{{ marker.telemetry.telemetry.location.altitude.toFixed(1) }}m</div>
</div>
<div>
<div class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-0.5">Speed</div>
<div>{{ marker.telemetry.telemetry.location.speed.toFixed(1) }}km/h</div>
<div class="tabular-nums">{{ marker.telemetry.telemetry.location.speed.toFixed(1) }}km/h</div>
</div>
</div>
@@ -1,28 +0,0 @@
<!-- SPDX-License-Identifier: 0BSD -->
<template>
<div class="absolute inset-0 z-20 flex items-center justify-center p-4">
<div
class="max-w-md bg-white dark:bg-zinc-900 p-6 rounded-xl shadow-xl border border-amber-200 dark:border-amber-900/50 flex flex-col items-center text-center space-y-4"
>
<MaterialDesignIcon icon-name="alert-circle" class="size-12 text-amber-500" />
<p class="text-gray-900 dark:text-zinc-100 font-medium">{{ $t("map.no_map_loaded") }}</p>
<button
class="px-4 py-2 bg-amber-500 hover:bg-amber-600 text-white rounded-lg transition-colors font-medium"
@click="$emit('upload')"
>
{{ $t("map.upload_mbtiles") }}
</button>
</div>
</div>
</template>
<script>
import MaterialDesignIcon from "../../MaterialDesignIcon.vue";
export default {
name: "MapNoMapWarning",
components: { MaterialDesignIcon },
emits: ["upload"],
};
</script>
-11
View File
@@ -6,7 +6,6 @@ import MapDrawingToolbar from "@/components/map/internal/MapDrawingToolbar.vue";
import MapBearingInstructions from "@/components/map/internal/MapBearingInstructions.vue";
import MapSearchBar from "@/components/map/internal/MapSearchBar.vue";
import MapExportInstructions from "@/components/map/internal/MapExportInstructions.vue";
import MapNoMapWarning from "@/components/map/internal/MapNoMapWarning.vue";
import MapLoadingOverlay from "@/components/map/internal/MapLoadingOverlay.vue";
import MapExportConfigPanel from "@/components/map/internal/MapExportConfigPanel.vue";
import MapExportProgressPanel from "@/components/map/internal/MapExportProgressPanel.vue";
@@ -173,16 +172,6 @@ describe("MapExportInstructions", () => {
});
});
describe("MapNoMapWarning", () => {
it("emits upload", async () => {
const wrapper = mount(MapNoMapWarning, {
global: { mocks: { $t: t } },
});
await wrapper.find("button").trigger("click");
expect(wrapper.emitted("upload")).toHaveLength(1);
});
});
describe("MapLoadingOverlay", () => {
it("shows custom message when provided", () => {
const wrapper = mount(MapLoadingOverlay, {