From 71401b7ebc31a9bc879a3d9f339fa2cc5cb7f73d Mon Sep 17 00:00:00 2001 From: Stream Date: Tue, 5 May 2026 19:40:01 +0300 Subject: [PATCH] auto-sync: 2026-05-05 19:40:01 --- tasks/enduro-trails/prototype/static/app.css | 35 +++++++++++ tasks/enduro-trails/prototype/static/app.js | 66 +++++++++++++------- 2 files changed, 79 insertions(+), 22 deletions(-) diff --git a/tasks/enduro-trails/prototype/static/app.css b/tasks/enduro-trails/prototype/static/app.css index 3738913..725d6d3 100644 --- a/tasks/enduro-trails/prototype/static/app.css +++ b/tasks/enduro-trails/prototype/static/app.css @@ -409,6 +409,41 @@ body.has-map-mode #sheet-backdrop.visible { pointer-events: none; } #no-data-warning { display: none; position: fixed; bottom: 80px; left: 12px; right: 12px; background: var(--red-bg); border: 1px solid var(--red); border-radius: 12px; padding: 10px 14px; font-size: 13px; color: var(--red); z-index: 200; } #no-data-warning.visible { display: block; } +/* ── Share Dialog (bottom sheet style) ────────── */ +#share-dialog { position: fixed; inset: 0; z-index: 600; display: flex; align-items: flex-end; justify-content: center; } +.share-dialog-backdrop { position: fixed; inset: 0; background: var(--overlay); } +.share-dialog { + position: relative; width: 100%; max-width: 420px; + background: var(--surface); + border-radius: 20px 20px 0 0; + padding: 0 16px calc(20px + env(safe-area-inset-bottom, 0px)); + z-index: 1; + box-shadow: 0 -4px 24px var(--shadow); + animation: shareSheetUp 0.25s cubic-bezier(0.16, 1, 0.3, 1); +} +@keyframes shareSheetUp { + from { transform: translateY(100%); } to { transform: translateY(0); } +} +.share-dialog .sd-handle { width: 36px; height: 4px; background: var(--border); border-radius: 2px; margin: 12px auto 12px; } +.share-dialog .sd-title { font-size: 16px; font-weight: 700; color: var(--text); text-align: center; margin-bottom: 4px; } +.share-dialog .sd-desc { font-size: 13px; color: var(--text2); text-align: center; margin-bottom: 14px; } +.share-dialog .sd-row { display: flex; gap: 8px; margin-bottom: 8px; } +.share-dialog .sd-btn { + flex: 1; height: 48px; border: none; border-radius: 14px; + background: var(--surface2); color: var(--text); + font-size: 14px; font-weight: 600; cursor: pointer; + display: inline-flex; align-items: center; justify-content: center; gap: 8px; + transition: background 0.15s, transform 0.1s; + -webkit-tap-highlight-color: transparent; +} +.share-dialog .sd-btn:active { transform: scale(0.97); background: var(--surface3); } +.share-dialog .sd-btn .sd-icon { font-size: 20px; line-height: 1; } +.share-dialog .sd-btn-primary { background: var(--accent); color: #fff; } +.share-dialog .sd-btn-primary:active { background: var(--accent-hover); } +.share-dialog .sd-btn-full { width: 100%; flex: none; margin-bottom: 8px; } +.share-dialog .sd-cancel { background: var(--surface2); color: var(--text2); } +.share-dialog .sd-cancel:active { background: var(--surface3); } + /* ── Skeleton Loading ────────────────────────── */ .skeleton { background: linear-gradient(90deg, var(--surface2) 0%, var(--surface3) 50%, var(--surface2) 100%); diff --git a/tasks/enduro-trails/prototype/static/app.js b/tasks/enduro-trails/prototype/static/app.js index 26bcfca..3707485 100644 --- a/tasks/enduro-trails/prototype/static/app.js +++ b/tasks/enduro-trails/prototype/static/app.js @@ -802,30 +802,52 @@ async function shareRoute() { const distKm = (route.distance_m / 1000).toFixed(0); const dirtPct = route.stats ? route.stats.dirt_total_pct : 0; - const shareText = `Маршрут: ${distKm} км, ${dirtPct}% грунт`; - const gpx = generateGPX(); - const blob = new Blob([gpx], { type: 'application/gpx+xml' }); - const file = new File([blob], 'enduro-route.gpx', { type: 'application/gpx+xml' }); + const shareText = `Эндуро маршрут: ${distKm} км, ${dirtPct}% грунт`; - // 1. File share (HTTPS only) - if (navigator.share && location.protocol === 'https:') { - try { - const canShare = navigator.canShare && navigator.canShare({ files: [file] }); - if (canShare) { - await navigator.share({ title: 'Enduro Route', text: shareText, files: [file] }); - return; - } - // canShare rejected files → share text only - await navigator.share({ title: 'Enduro Route', text: shareText }); - return; - } catch(e) { - if (e.name === 'AbortError') return; - console.warn('Share failed, falling back to download:', e); - } + const dialog = document.getElementById('share-dialog'); + if (dialog) dialog.remove(); + + const d = document.createElement('div'); + d.id = 'share-dialog'; + d.innerHTML = ` +
+
+
+
Поделиться маршрутом
+
${shareText}
+
+ + +
+ + +
+ `; + document.body.appendChild(d); +} + +function closeShareDialog() { + const el = document.getElementById('share-dialog'); + if (el) el.remove(); +} + +function shareTelegram() { + const url = 'https://t.me/share/url?url=' + encodeURIComponent(window.location.href) + '&text=' + encodeURIComponent('Маршрут эндуро: ' + window.location.href); + window.open(url, '_blank'); + closeShareDialog(); +} + +function shareWhatsApp() { + const url = 'https://wa.me/?text=' + encodeURIComponent('Маршрут эндуро: ' + window.location.href); + window.open(url, '_blank'); + closeShareDialog(); +} + +function shareNative() { + closeShareDialog(); + if (navigator.share) { + navigator.share({ title: 'Enduro Route', text: window.location.href }).catch(() => {}); } - - // 2. HTTPS unavailable → download GPX directly - downloadGPX(); } // ─── Флажки / именованные метки ────────────────────────────────────