auto-sync: 2026-05-06 09:30:01

This commit is contained in:
Stream
2026-05-06 09:30:01 +03:00
parent 00b7cd9ab2
commit 9d91792871
4 changed files with 80 additions and 15 deletions

View File

@@ -100,6 +100,8 @@ docker restart prototype-enduro-trails-1
| F-17 | PWA + офлайн | Service Worker, MBTiles, GPS-трекинг | ⏳ Бэклог | 7 |
| F-18 | Светлая карта | Создать `style-light.json` — светлый стиль карты для светлой темы. Сейчас при светлой теме карта остаётся тёмной (`style-light.json` отсутствует) | ⏳ Бэклог | 5.1 |
| F-19 | Иконка колеса + спиннер | Заменить иконку колеса в мини-баре на нормальную мотокросс (спицы, кноблинг). Спиннер в основном листе маршрута пока строится | ⏳ Бэклог | 5.1 |
| F-20 | Линейка: перетаскивание точек | Возможность перетащить уже поставленную точку линейки на новое место | ⏳ Бэклог | 5.x |
| F-21 | Линейка: сохранение между сессиями | Сохранять точки линейки в localStorage, восстанавливать при перезагрузке | ⏳ Бэклог | 5.x |
---

View File

@@ -441,7 +441,9 @@ body.has-map-mode #sheet-backdrop.visible { pointer-events: none; }
#ruler-info {
position: fixed;
top: calc(max(env(safe-area-inset-top,0px),12px) + 58px);
left: 12px; right: 12px;
left: 12px;
width: fit-content;
max-width: 320px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
@@ -454,22 +456,49 @@ body.has-map-mode #sheet-backdrop.visible { pointer-events: none; }
#ruler-info #ruler-dist { flex: 1; }
.ruler-action-btn {
flex-shrink: 0;
height: 28px;
padding: 0 10px;
height: 32px;
min-width: 32px;
padding: 4px 10px;
background: var(--surface2);
border: 1px solid var(--border);
border-radius: 8px;
color: var(--text);
font-size: 12px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
white-space: nowrap;
display: flex;
align-items: center;
justify-content: center;
-webkit-tap-highlight-color: transparent;
}
.ruler-action-btn--danger {
color: var(--danger, #e05252);
border-color: var(--danger, #e05252);
font-size: 16px;
padding: 4px 8px;
}
/* ── Ruler toast hint ────────────────────────── */
#ruler-toast {
position: fixed;
top: calc(max(env(safe-area-inset-top,0px),12px) + 100px);
left: 50%;
transform: translateX(-50%);
background: rgba(20,20,20,0.82);
color: #fff;
font-size: 13px;
font-weight: 600;
padding: 8px 16px;
border-radius: 20px;
z-index: 210;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s;
white-space: nowrap;
}
#ruler-toast.visible { opacity: 1; }
/* ── Fix: MapLibre markers must stay absolute ────── */
.maplibregl-marker {
position: absolute !important;
@@ -510,7 +539,7 @@ body.has-map-mode #sheet-backdrop.visible { pointer-events: none; }
.bottom-sheet.swiping { transition: none; }
#map-controls-r { right: 12px; bottom: 12px; }
#sheet-backdrop { display: none; }
#ruler-info { left: 84px; }
#ruler-info { left: 84px; max-width: 320px; }
}
/* ═══════════════════════════════════════════════════

View File

@@ -1631,6 +1631,8 @@ function toggleRuler() {
window._map.getCanvas().style.cursor = 'crosshair';
clearRuler();
document.getElementById('ruler-info').classList.add('visible');
// Fix 4: Show toast hint on activation
showRulerToast();
} else {
btn.classList.remove('active');
window._map.getCanvas().style.cursor = '';
@@ -1640,6 +1642,14 @@ function toggleRuler() {
updateMapModeClass();
}
// Fix 4: Toast hint helper
function showRulerToast() {
const toast = document.getElementById('ruler-toast');
if (!toast) return;
toast.classList.add('visible');
setTimeout(() => toast.classList.remove('visible'), 3000);
}
// Exit ruler mode without clearing points/markers ("Завершить")
function exitRulerMode() {
if (!rulerMode) return;
@@ -1702,11 +1712,19 @@ function updateRulerLabels() {
rulerTotal = 0;
for (let i = 0; i < rulerMarkers.length; i++) {
const markerEl = rulerMarkers[i].getElement();
const dot = markerEl.querySelector('.ruler-dot');
const label = markerEl.querySelector('.ruler-label');
const btn = markerEl.querySelector('.ruler-remove-btn');
const labelText = label ? label.querySelector('span') : null;
// Fix 5: Update dot color for first point
if (dot) {
const dotColor = i === 0 ? '#2EA043' : '#0088ff';
dot.style.background = dotColor;
}
if (i === 0) {
if (labelText) labelText.textContent = '';
if (labelText) labelText.textContent = 'Старт';
} else {
const segDist = haversineKm(rulerPoints[i - 1], rulerPoints[i]);
rulerTotal += segDist;
@@ -1738,34 +1756,41 @@ function addRulerPoint(lngLat) {
rulerTotal += segDist;
}
// Hide toast on first tap
if (idx === 0) {
const toast = document.getElementById('ruler-toast');
if (toast) toast.classList.remove('visible');
}
// Wrapper element for dot + label row
const wrapper = document.createElement('div');
wrapper.style.cssText = 'position:relative;display:flex;flex-direction:column;align-items:center;';
// Dot
// Dot - Fix 5: first point green
const dot = document.createElement('div');
dot.className = 'ruler-dot';
dot.style.cssText = 'width:10px;height:10px;background:#0088ff;border:2px solid #fff;border-radius:50%;box-shadow:0 0 4px rgba(0,0,0,0.3);display:block;flex-shrink:0;';
const dotColor = idx === 0 ? '#2EA043' : '#0088ff';
dot.style.cssText = `width:10px;height:10px;background:${dotColor};border:2px solid #fff;border-radius:50%;box-shadow:0 0 4px rgba(0,0,0,0.3);display:block;flex-shrink:0;`;
// Label row: [distance text][× button] in one line
const label = document.createElement('div');
label.className = 'ruler-label';
label.style.cssText = 'margin-top:3px;display:flex;align-items:center;gap:2px;background:rgba(20,20,20,0.75);color:#fff;font-size:10px;padding:1px 4px;border-radius:3px;white-space:nowrap;';
label.style.cssText = 'margin-top:3px;display:flex;align-items:center;gap:4px;background:rgba(20,20,20,0.75);color:#fff;font-size:10px;padding:2px 6px;border-radius:3px;white-space:nowrap;';
const labelText = document.createElement('span');
if (idx === 0) {
labelText.textContent = '';
labelText.textContent = 'Старт';
} else {
labelText.textContent = segDist >= 1
? segDist.toFixed(1) + ' км'
: Math.round(segDist * 1000) + ' м';
}
// Remove button × inline with label
// Remove button × inline with label - Fix 1: bigger tap target
const btn = document.createElement('span');
btn.className = 'ruler-remove-btn';
btn.textContent = '×';
btn.style.cssText = 'cursor:pointer;font-size:11px;line-height:1;opacity:0.85;padding-left:2px;';
btn.style.cssText = 'cursor:pointer;font-size:16px;line-height:1;opacity:0.85;padding:4px 8px;min-width:32px;min-height:32px;display:flex;align-items:center;justify-content:center;margin:-2px -6px -2px 0;';
btn.onclick = (e) => { e.stopPropagation(); removeRulerPoint(idx); };
label.appendChild(labelText);
@@ -1791,12 +1816,19 @@ function initRulerClicks(map) {
e.preventDefault();
exitRulerMode();
});
// Fix 3: tap on ruler line restores panel
// Fix 2 & 6: tap on ruler line shows panel AND resumes ruler mode
map.on('click', 'ruler-line', (e) => {
if (rulerMode) return; // already active
e.originalEvent.stopPropagation();
if (rulerPoints.length > 0) {
// Fix 6: Resume ruler mode
if (!rulerMode) {
rulerMode = true;
const btn = document.getElementById('tb-ruler');
btn.classList.add('active');
window._map.getCanvas().style.cursor = 'crosshair';
updateMapModeClass();
}
document.getElementById('ruler-info').classList.add('visible');
e.preventDefault();
}
});
}

View File

@@ -26,6 +26,8 @@
<button class="ruler-action-btn" onclick="exitRulerMode()" title="Завершить">✓ Завершить</button>
<button class="ruler-action-btn ruler-action-btn--danger" onclick="toggleRuler()" title="Удалить линейку"></button>
</div>
<!-- ── Ruler toast hint ───────────────────── -->
<div id="ruler-toast">Тапни на карту чтобы добавить точку</div>
<!-- ── No data warning ───────────────────── -->
<div id="no-data-warning">⚠️ База данных недоступна</div>