diff --git a/frontend/css/styles.css b/frontend/css/styles.css
index 5e192c7..9f23112 100644
--- a/frontend/css/styles.css
+++ b/frontend/css/styles.css
@@ -879,20 +879,12 @@ body {
z-index: 1;
}
-.gps-controls {
+.gps-header {
padding: 10px 12px;
background: var(--surface);
border-bottom: 1px solid var(--border);
}
-.gps-stats {
- display: flex;
- justify-content: space-around;
- padding: 6px 0 10px;
- font-size: 16px;
- font-weight: 600;
-}
-
.gps-btns {
display: flex;
gap: 8px;
@@ -1040,6 +1032,15 @@ body {
font-size: 16px;
}
+.zoom-display {
+ background: rgba(0,0,0,0.6);
+ color: #fff;
+ font-size: 13px;
+ font-weight: 700;
+ padding: 2px 6px;
+ border-radius: 4px;
+}
+
.gps-download-status {
text-align: center;
font-size: 12px;
diff --git a/frontend/js/main.js b/frontend/js/main.js
index 62890b9..80aa14e 100644
--- a/frontend/js/main.js
+++ b/frontend/js/main.js
@@ -674,13 +674,7 @@ async function renderGpsScreen(container) {
container.innerHTML = `
-
-
-
- 0 м
- 0 км/ч
- 0:00
-
+ `;
- // Init Leaflet map
- setTimeout(() => {
- const mapEl = container.querySelector("#gps-map");
- if (!mapEl) return;
-
- L.Icon.Default.imagePath = "lib/";
- gpsMap = L.map(mapEl, { attributionControl: false }).setView([55.75, 37.62], 13);
- const CachedLayer = TileCache.createLayer();
- new CachedLayer({ maxZoom: 19 }).addTo(gpsMap);
-
- L.polyline([], { color: "#ffffff", weight: 6, opacity: 0.8 }).addTo(gpsMap); // border
- gpsTrailLine = L.polyline([], { color: "#bb86fc", weight: 3 }).addTo(gpsMap);
-
- // If recording, restore trail
- if (GPS.recording.active && GPS.recording.points.length > 0) {
- const coords = GPS.recording.points.map(p => [p.lat, p.lon]);
- gpsTrailLine.setLatLngs(coords);
- gpsMap.fitBounds(gpsTrailLine.getBounds().pad(0.1));
- } else {
- // Try to center on user location
- navigator.geolocation?.getCurrentPosition(
- pos => gpsMap.setView([pos.coords.latitude, pos.coords.longitude], 14),
- () => {}, { timeout: 5000 }
- );
- }
- }, 100);
// Recording button
container.querySelector("#gps-rec-btn").onclick = async () => {
@@ -890,11 +858,11 @@ function showMapDownloadModal() {
-
+
-
+
`,
async overlay => {
@@ -1069,6 +1037,7 @@ async function showSessionDetail(sessionId) {
L.Icon.Default.imagePath = "lib/";
const map = L.map(mapEl, { attributionControl: false, zoomControl: false });
+ addZoomDisplay(map);
const CachedLayer = TileCache.createLayer();
new CachedLayer({ maxZoom: 19 }).addTo(map);
@@ -1142,6 +1111,33 @@ async function showSessionDetail(sessionId) {
return fsDiv;
};
fsBtn.addTo(map);
+
+ // Locate me button
+ const locBtn = L.control({ position: "topleft" });
+ locBtn.onAdd = () => {
+ const div = L.DomUtil.create("div", "sd-map-fs-btn");
+ div.innerHTML = "◎";
+ div.title = "Моё местоположение";
+ div.onclick = (e) => {
+ e.stopPropagation();
+ navigator.geolocation?.getCurrentPosition(
+ pos => {
+ const ll = [pos.coords.latitude, pos.coords.longitude];
+ map.setView(ll, 15);
+ L.circleMarker(ll, { radius: 8, color: "#4285f4", fillColor: "#4285f4", fillOpacity: 0.8, weight: 2 }).addTo(map);
+ },
+ err => alert("GPS: " + err.message),
+ { enableHighAccuracy: true, timeout: 10000 }
+ );
+ };
+ return div;
+ };
+ locBtn.addTo(map);
+
+ // Click map to toggle fullscreen (same as button)
+ map.on("click", () => {
+ if (!mapEl.classList.contains("sd-map-full")) toggleMapFs();
+ });
}, 200);
// Render speed chart
@@ -1444,18 +1440,34 @@ async function renderSettings(container) {
+