mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-10-23 11:42:26 +00:00
refactor(map): remove MapNoMapWarning component, streamline offline mode handling, and improve coordinate display with tabular formatting
This commit is contained in:
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>
|
||||
@@ -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, {
|
||||
|
||||
Reference in new issue
Block a user