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