Skip to content

Commit 2ebf04e

Browse files
authored
Update App.tsx
1 parent 8547b66 commit 2ebf04e

1 file changed

Lines changed: 55 additions & 5 deletions

File tree

App.tsx

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ const getDistance = (c1: Coordinates, c2: Coordinates) => {
1919
};
2020

2121
const App: React.FC = () => {
22+
// Use a ref for tracking state to access it synchronously in geolocation callback
23+
const trackingRef = useRef(true);
2224
const [state, setState] = useState<AppState>({
2325
location: { lat: 51.5074, lng: -0.1278 },
2426
radius: 1000,
2527
articles: [],
2628
mode: SonificationMode.AMBIENT,
2729
isAudioEnabled: false,
2830
isLoading: false,
31+
isTracking: true,
2932
heading: 0,
3033
});
3134

@@ -52,18 +55,27 @@ const App: React.FC = () => {
5255
}
5356
}, []);
5457

58+
useEffect(() => {
59+
loadArticles(state.location.lat, state.location.lng, state.radius);
60+
}, []);
61+
5562
useEffect(() => {
5663
if (navigator.geolocation) {
5764
const watchId = navigator.geolocation.watchPosition((pos) => {
65+
// CRITICAL: Immediately exit if tracking is disabled.
66+
// This prevents desktop geolocation ticks from overwriting manual typing.
67+
if (!trackingRef.current) return;
68+
5869
const currentCoords = { lat: pos.coords.latitude, lng: pos.coords.longitude };
70+
5971
setState(prev => {
6072
const dist = lastFetchedLocation.current ? getDistance(lastFetchedLocation.current, currentCoords) : Infinity;
6173
if (dist > 30) {
6274
loadArticles(currentCoords.lat, currentCoords.lng, prev.radius);
6375
}
76+
setManualInput(mi => ({ ...mi, lat: currentCoords.lat.toString(), lng: currentCoords.lng.toString() }));
6477
return { ...prev, location: currentCoords };
6578
});
66-
setManualInput(prev => ({ ...prev, lat: currentCoords.lat.toString(), lng: currentCoords.lng.toString() }));
6779
}, (err) => {
6880
console.warn("Geolocation watch error or denied.", err);
6981
}, { enableHighAccuracy: true, maximumAge: 5000, timeout: 10000 });
@@ -127,11 +139,35 @@ const App: React.FC = () => {
127139
const lng = parseFloat(manualInput.lng);
128140
const rad = parseInt(manualInput.radius);
129141
if (!isNaN(lat) && !isNaN(lng) && !isNaN(rad)) {
130-
setState(prev => ({ ...prev, location: { lat, lng }, radius: rad }));
142+
trackingRef.current = false;
143+
setState(prev => ({ ...prev, location: { lat, lng }, radius: rad, isTracking: false }));
131144
loadArticles(lat, lng, rad);
132145
}
133146
};
134147

148+
const toggleTracking = () => {
149+
const newTracking = !state.isTracking;
150+
trackingRef.current = newTracking;
151+
setState(prev => {
152+
if (newTracking && navigator.geolocation) {
153+
navigator.geolocation.getCurrentPosition((pos) => {
154+
const c = { lat: pos.coords.latitude, lng: pos.coords.longitude };
155+
setManualInput(mi => ({ ...mi, lat: c.lat.toString(), lng: c.lng.toString() }));
156+
loadArticles(c.lat, c.lng, state.radius);
157+
});
158+
}
159+
return { ...prev, isTracking: newTracking };
160+
});
161+
};
162+
163+
const handleInputChange = (key: 'lat' | 'lng', val: string) => {
164+
setManualInput(prev => ({ ...prev, [key]: val }));
165+
if (trackingRef.current) {
166+
trackingRef.current = false;
167+
setState(s => ({ ...s, isTracking: false }));
168+
}
169+
};
170+
135171
return (
136172
<div className="min-h-screen p-4 md:p-8 flex flex-col items-center bg-black selection:bg-violet-500 selection:text-white font-sans">
137173
<header className="max-w-2xl w-full text-center mb-12 space-y-6">
@@ -146,14 +182,28 @@ const App: React.FC = () => {
146182
<main className="max-w-6xl w-full grid grid-cols-1 lg:grid-cols-12 gap-8 items-start">
147183
<div className="lg:col-span-4 space-y-8 bg-neutral-900/40 p-6 rounded-2xl border border-neutral-800/60 backdrop-blur-md">
148184
<section className="space-y-4">
149-
<h2 className="text-[10px] font-bold uppercase tracking-[0.3em] text-violet-400 font-mono">Environment</h2>
185+
<div className="flex justify-between items-center mb-2">
186+
<h2 className="text-[10px] font-bold uppercase tracking-[0.3em] text-violet-400 font-mono">Environment</h2>
187+
<button
188+
onClick={toggleTracking}
189+
className={`flex items-center gap-2 px-2 py-1 rounded-md border text-[9px] font-mono uppercase tracking-wider transition-all ${
190+
state.isTracking
191+
? 'border-emerald-500/50 text-emerald-400 bg-emerald-500/10'
192+
: 'border-neutral-700 text-neutral-500 bg-black/40'
193+
}`}
194+
>
195+
<div className={`w-1.5 h-1.5 rounded-full ${state.isTracking ? 'bg-emerald-400 animate-pulse' : 'bg-neutral-600'}`} />
196+
{state.isTracking ? 'Auto-Follow On' : 'Follow Disabled'}
197+
</button>
198+
</div>
199+
150200
<div className="grid grid-cols-2 gap-4">
151201
<div className="flex flex-col gap-1">
152202
<label className="text-[9px] text-neutral-500 font-mono uppercase tracking-wider">Lat</label>
153203
<input
154204
type="text"
155205
value={manualInput.lat}
156-
onChange={e => setManualInput({...manualInput, lat: e.target.value})}
206+
onChange={e => handleInputChange('lat', e.target.value)}
157207
className="bg-black border border-neutral-800 rounded px-3 py-2 text-xs focus:border-violet-500 outline-none transition-colors font-mono"
158208
/>
159209
</div>
@@ -162,7 +212,7 @@ const App: React.FC = () => {
162212
<input
163213
type="text"
164214
value={manualInput.lng}
165-
onChange={e => setManualInput({...manualInput, lng: e.target.value})}
215+
onChange={e => handleInputChange('lng', e.target.value)}
166216
className="bg-black border border-neutral-800 rounded px-3 py-2 text-xs focus:border-violet-500 outline-none transition-colors font-mono"
167217
/>
168218
</div>

0 commit comments

Comments
 (0)