Fix geolocation: button-triggered, error messages in Russian
This commit is contained in:
parent
31c53cd8d5
commit
7182e6828b
@ -21,6 +21,8 @@ const MapView = {
|
|||||||
<span class="slider"></span>
|
<span class="slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn" id="loc-share-btn" style="margin-top:8px;">📍 Поделиться геолокацией</button>
|
||||||
|
<div class="privacy-note" id="loc-status">Нажми чтобы получить координаты</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="map" style="height:400px;border-radius:12px;overflow:hidden;margin-bottom:12px;"></div>
|
<div id="map" style="height:400px;border-radius:12px;overflow:hidden;margin-bottom:12px;"></div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -63,65 +65,108 @@ const MapView = {
|
|||||||
this.refreshNearby();
|
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) {
|
if (!navigator.geolocation) {
|
||||||
document.getElementById('nearby-count').textContent = 'Геолокация недоступна';
|
const s = document.getElementById('loc-status');
|
||||||
|
if (s) s.textContent = 'Геолокация недоступна в браузере';
|
||||||
return;
|
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(
|
navigator.geolocation.getCurrentPosition(
|
||||||
async (pos) => {
|
async (pos) => {
|
||||||
const lat = pos.coords.latitude;
|
window._lastKnownPos = pos;
|
||||||
const lng = pos.coords.longitude;
|
if (btn) { btn.disabled = false; btn.textContent = '📍 Обновить геолокацию'; }
|
||||||
try {
|
if (status) status.textContent = `✓ ${pos.coords.latitude.toFixed(4)}, ${pos.coords.longitude.toFixed(4)}`;
|
||||||
await API.Auth.updateLocation(lat, lng, this.visible);
|
await this.applyPosition(pos);
|
||||||
} 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();
|
|
||||||
},
|
},
|
||||||
(err) => {
|
(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() {
|
async refreshNearby() {
|
||||||
if (!navigator.geolocation) return;
|
if (!navigator.geolocation) return;
|
||||||
navigator.geolocation.getCurrentPosition(async (pos) => {
|
navigator.geolocation.getCurrentPosition(async (pos) => {
|
||||||
try {
|
this.refreshNearbyFromPos(pos.coords.latitude, pos.coords.longitude);
|
||||||
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: `<div style="width:36px;height:36px;border-radius:50%;background:#FF6B35;color:white;display:flex;align-items:center;justify-content:center;font-weight:700;border:2px solid white;">${escapeHtml((n.name || '?')[0])}</div>`,
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
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: `<div style="width:36px;height:36px;border-radius:50%;background:#FF6B35;color:white;display:flex;align-items:center;justify-content:center;font-weight:700;border:2px solid white;">${escapeHtml((n.name || '?')[0])}</div>`,
|
||||||
|
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;
|
window.MapView = MapView;
|
||||||
Loading…
Reference in New Issue
Block a user