Record screen: 'Отд' button — hand route/roads/track to the live viewer

shareRideContext() gathers the active route, ridden roads and track-so-far and POSTs
them to the server's RAM relay (/api/trackme/share); the viewer pulls them into their
own localStorage. One-shot — press again to resend after the track grows.
This commit is contained in:
4aiman 2026-10-27 00:10:59 +03:00
commit 8a236bae3d
2 changed files with 39 additions and 0 deletions

View file

@ -1318,6 +1318,7 @@ select {
/* Left-hand group (bottom-left), opposite the right control stack: SMS + live toggle. */
.rec-sms-btn { left: 8px; bottom: 48px; font-size: 11px; }
.rec-live-btn { left: 8px; bottom: 86px; font-size: 10px; }
.rec-share-btn { left: 8px; bottom: 124px; font-size: 11px; }
/* Route editor: danger indicator (fords / rough tracks the route passes). */
.re-danger { color: #ff7043; font-size: 13px; font-weight: 600; min-height: 16px; margin: 2px 0; text-align: center; }
/* Dark map: invert ONLY the tile layer (track, route, puck keep their colours).

View file

@ -4875,6 +4875,36 @@ async function sendLocationSms() {
} catch (e) { appAlert("Ошибка отправки: " + e); }
}
// "Отдать смотрящему": hand the viewer the active route + ridden roads + track-so-far. Sent to
// the server's RAM relay (NOT stored on its disk); the viewer pulls it once into their own
// localStorage. One-shot; press again to resend (e.g. after the track grew).
async function shareRideContext() {
let url = (localStorage.getItem("baldav_live_url") || "").trim();
let token = (localStorage.getItem("baldav_live_token") || "").trim();
if (!url || !token) { appAlert("Сначала задай адрес и токен трансляции в профиле"); return; }
let shareUrl = url.endsWith("/push") ? url.slice(0, -5) + "/share" : url.replace(/\/[^/]*$/, "/share");
let track = (GPS.recording.points || []).map(p => [+p.lat, +p.lon]);
let route = [];
try {
let rid = localStorage.getItem("baldav_active_route");
if (rid) { let r = await DB.getRoute(rid); if (r && r.points) route = r.points.map(p => [+p.lat, +p.lon]); }
} catch (e) {}
let roads = [];
try {
let segs = buildRoadSegments(await DB.getRoadPoints());
roads = segs.map(s => ({ p: s.pts.map(q => [+q.lat, +q.lon]), t: s.atype || "b" }));
} catch (e) {}
showToast("Отдаю смотрящему...");
try {
let raw = await window.__TAURI__.core.invoke("http_request", {
url: shareUrl, method: "POST", body: JSON.stringify({ token, route, roads, track })
});
let res = JSON.parse(raw || "{}");
if (res.ok) showToast(`Отдано: маршрут ${route.length}, дороги ${roads.length}, трек ${track.length}`);
else appAlert("Не отдалось: " + (res.error || "ошибка"));
} catch (e) { appAlert("Не отдалось: " + (e.message || e)); }
}
async function renderRecordingInline(container) {
if (!GPS.recording.active) { renderScreen("gps"); return; }
@ -5161,6 +5191,14 @@ async function renderRecordingInline(container) {
smsBtn.onclick = () => sendLocationSms();
btnWrap.appendChild(smsBtn);
// Hand the viewer the route + ridden roads + track (via the server's RAM relay, not its disk).
let shareBtn = document.createElement("button");
shareBtn.className = "rec-map-btn rec-share-btn";
shareBtn.textContent = "Отд";
shareBtn.title = "Отдать смотрящему: маршрут, проезженные дороги и пройденный трек";
shareBtn.onclick = () => shareRideContext();
btnWrap.appendChild(shareBtn);
// Roads toggle button. Roads are viewport-culled onto a canvas pane (only the segments in
// view are drawn, redrawn on pan/zoom) so a huge road network doesn't jank the WebView.
let roadsBtn = document.createElement("button");