diff --git a/public/js/views/map.js b/public/js/views/map.js index dd6ea56..1d7fe08 100644 --- a/public/js/views/map.js +++ b/public/js/views/map.js @@ -21,6 +21,8 @@ const MapView = { + +
Нажми чтобы получить координаты
@@ -63,65 +65,108 @@ const MapView = { this.refreshNearby(); }); - this.refreshLocation(); + document.getElementById('loc-share-btn').onclick = (e) => { + e.preventDefault(); + this.requestLocation(); + }; + + // Если уже есть сохранённые координаты — покажем на карте + if (window._lastKnownPos) { + this.applyPosition(window._lastKnownPos); + } }, - async refreshLocation() { + requestLocation() { if (!navigator.geolocation) { - document.getElementById('nearby-count').textContent = 'Геолокация недоступна'; + const s = document.getElementById('loc-status'); + if (s) s.textContent = 'Геолокация недоступна в браузере'; return; } + const btn = document.getElementById('loc-share-btn'); + const status = document.getElementById('loc-status'); + if (btn) { btn.disabled = true; btn.textContent = '⏳ Запрашиваю…'; } + if (status) status.textContent = 'Браузер спросит разрешение…'; + navigator.geolocation.getCurrentPosition( async (pos) => { - const lat = pos.coords.latitude; - const lng = pos.coords.longitude; - try { - await API.Auth.updateLocation(lat, lng, this.visible); - } catch (e) { - console.warn(e); - } - this.map.setView([lat, lng], 13); - L.circle([lat, lng], { - radius: this.radius * 1000, - color: '#FF6B35', fillColor: '#FF6B35', fillOpacity: 0.1, weight: 2, - }).addTo(this.map); - this.refreshNearby(); + window._lastKnownPos = pos; + if (btn) { btn.disabled = false; btn.textContent = '📍 Обновить геолокацию'; } + if (status) status.textContent = `✓ ${pos.coords.latitude.toFixed(4)}, ${pos.coords.longitude.toFixed(4)}`; + await this.applyPosition(pos); }, (err) => { - document.getElementById('nearby-count').textContent = 'Нет доступа к GPS: ' + err.message; + if (btn) { btn.disabled = false; btn.textContent = '📍 Попробовать снова'; } + if (status) status.textContent = '⚠️ ' + this.geolocationErrorText(err); + console.warn('geolocation error:', err); }, - { enableHighAccuracy: true, timeout: 15000 } + { enableHighAccuracy: true, timeout: 15000, maximumAge: 60000 } ); }, + geolocationErrorText(err) { + switch (err.code) { + case err.PERMISSION_DENIED: return 'Доступ к геолокации запрещён. Разреши в настройках браузера.'; + case err.POSITION_UNAVAILABLE: return 'Не удалось определить координаты (нет GPS/Wi-Fi).'; + case err.TIMEOUT: return 'Таймаут запроса геолокации.'; + default: return 'Неизвестная ошибка геолокации.'; + } + }, + + async applyPosition(pos) { + const lat = pos.coords.latitude; + const lng = pos.coords.longitude; + try { + await API.Auth.updateLocation(lat, lng, this.visible); + } catch (e) { + console.warn('updateLocation:', e); + } + if (this.map) { + this.map.setView([lat, lng], 13); + // удалим старый круг + this.map.eachLayer((layer) => { + if (layer instanceof L.Circle) this.map.removeLayer(layer); + }); + L.circle([lat, lng], { + radius: this.radius * 1000, + color: '#FF6B35', fillColor: '#FF6B35', fillOpacity: 0.1, weight: 2, + }).addTo(this.map); + this.refreshNearbyFromPos(lat, lng); + } + }, + async refreshNearby() { if (!navigator.geolocation) return; navigator.geolocation.getCurrentPosition(async (pos) => { - try { - const r = await API.Auth.searchNearby(pos.coords.latitude, pos.coords.longitude, this.radius); - this.nearby = r.results || []; - document.getElementById('nearby-count').textContent = this.nearby.length + ' чел. рядом'; - - // удалить старые маркеры (кроме своего круга) - this.markers.forEach(m => this.map.removeLayer(m)); - this.markers = []; - - this.nearby.forEach((n) => { - const icon = L.divIcon({ - className: 'custom-marker', - html: `
${escapeHtml((n.name || '?')[0])}
`, - iconSize: [36, 36], - }); - const m = L.marker([n.lat, n.lng], { icon }).addTo(this.map); - m.bindTooltip(n.name + ' • ' + (n.distance_m / 1000).toFixed(1) + ' км', { direction: 'top' }); - m.on('click', () => App.openUserProfile(n.user_id, n.name)); - this.markers.push(m); - }); - } catch (e) { - console.warn(e); - } + this.refreshNearbyFromPos(pos.coords.latitude, pos.coords.longitude); }); }, + + async refreshNearbyFromPos(lat, lng) { + try { + const r = await API.Auth.searchNearby(lat, lng, this.radius); + this.nearby = r.results || []; + const c = document.getElementById('nearby-count'); + if (c) c.textContent = this.nearby.length + ' чел. рядом'; + + // удалить старые маркеры (кроме своего круга) + this.markers.forEach(m => this.map.removeLayer(m)); + this.markers = []; + + this.nearby.forEach((n) => { + const icon = L.divIcon({ + className: 'custom-marker', + html: `
${escapeHtml((n.name || '?')[0])}
`, + iconSize: [36, 36], + }); + const m = L.marker([n.lat, n.lng], { icon }).addTo(this.map); + m.bindTooltip(n.name + ' • ' + (n.distance_m / 1000).toFixed(1) + ' км', { direction: 'top' }); + m.on('click', () => App.openUserProfile(n.user_id, n.name)); + this.markers.push(m); + }); + } catch (e) { + console.warn(e); + } + }, }; window.MapView = MapView; \ No newline at end of file