map: replace hardcoded Google Maps with universal directions picker (geo:, OSM, Google, Apple)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
bb89a6d3a5
commit
5edf4d2a9d
1 changed files with 80 additions and 8 deletions
|
|
@ -326,6 +326,80 @@ function StashDrawer() {
|
|||
);
|
||||
}
|
||||
|
||||
// Universal directions picker — works on GrapheneOS, iOS, any browser
|
||||
function DirectionsMenu({ lat, lon, label }: { lat: string; lon: string; label: string }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const options = [
|
||||
{
|
||||
name: 'Maps (device default)',
|
||||
sub: 'Opens your default maps app',
|
||||
href: `geo:${lat},${lon}?q=${lat},${lon}(${label})`,
|
||||
emoji: '📍',
|
||||
},
|
||||
{
|
||||
name: 'OpenStreetMap',
|
||||
sub: 'Privacy-friendly, no account',
|
||||
href: `https://www.openstreetmap.org/?mlat=${lat}&mlon=${lon}&zoom=17`,
|
||||
emoji: '🗺️',
|
||||
},
|
||||
{
|
||||
name: 'Google Maps',
|
||||
sub: 'Opens in browser or app',
|
||||
href: `https://maps.google.com/?q=${lat},${lon}`,
|
||||
emoji: '🔵',
|
||||
},
|
||||
{
|
||||
name: 'Apple Maps',
|
||||
sub: 'iOS & macOS',
|
||||
href: `https://maps.apple.com/?ll=${lat},${lon}&q=${label}`,
|
||||
emoji: '🍎',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="h-12 w-full font-bold text-sm border-white/20 hover:bg-white/10 rounded-xl"
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<Navigation className="h-4 w-4 mr-2 text-[#ccff00]" />
|
||||
Directions
|
||||
</Button>
|
||||
|
||||
{open && (
|
||||
<>
|
||||
{/* Backdrop */}
|
||||
<div className="fixed inset-0 z-[2000]" onClick={() => setOpen(false)} />
|
||||
{/* Menu */}
|
||||
<div className="absolute bottom-14 right-0 z-[2001] bg-black/95 border border-white/15 rounded-2xl shadow-2xl overflow-hidden w-64 backdrop-blur">
|
||||
<div className="px-4 py-3 border-b border-white/8">
|
||||
<p className="text-xs font-black uppercase tracking-widest text-white/50">Open with</p>
|
||||
</div>
|
||||
{options.map(opt => (
|
||||
<a
|
||||
key={opt.name}
|
||||
href={opt.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={() => setOpen(false)}
|
||||
className="flex items-center gap-3 px-4 py-3 hover:bg-white/8 transition-colors"
|
||||
>
|
||||
<span className="text-xl w-7 text-center">{opt.emoji}</span>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="text-sm font-bold text-white">{opt.name}</div>
|
||||
<div className="text-[10px] text-white/40">{opt.sub}</div>
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Bottom sheet shown when a map marker is tapped
|
||||
function SpotBottomSheet({ spot, onClose }: { spot: SkateSpot; onClose: () => void }) {
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -414,15 +488,13 @@ function SpotBottomSheet({ spot, onClose }: { spot: SkateSpot; onClose: () => vo
|
|||
</Button>
|
||||
{spot.geohash && (() => {
|
||||
const { latitude, longitude } = ngeohash.decode(spot.geohash);
|
||||
const lat = latitude.toFixed(6);
|
||||
const lon = longitude.toFixed(6);
|
||||
const label = encodeURIComponent(spot.title);
|
||||
return (
|
||||
<Button
|
||||
variant="outline"
|
||||
className="h-12 font-bold text-sm border-white/20 hover:bg-white/10 rounded-xl"
|
||||
onClick={() => window.open(`https://maps.google.com/?q=${latitude},${longitude}`, '_blank')}
|
||||
>
|
||||
<Navigation className="h-4 w-4 mr-2 text-[#ccff00]" />
|
||||
Directions
|
||||
</Button>
|
||||
<div className="relative">
|
||||
<DirectionsMenu lat={lat} lon={lon} label={label} />
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue