web: name a position that lands before the account is known

A photo restored from the session reaches the stage while /me is still in
flight, so the account reading that put it there saw `pro` as false, the place
lookup was skipped, and reloading a photo left the stamp with bare coordinates.

Naming now happens in one effect that watches the position itself: the first
moment it is on the stage unnamed and the account is PRO, it gets a name,
wherever it came from. A position typed in by hand earns its name too, and a
guest's photo is named the moment they sign in.

The two call sites that used to ask for the name — in locateMe and adoptPhoto —
are gone, since the effect covers both.
This commit is contained in:
2026-09-23 09:33:26 +07:00
parent 3bfa82e7f2
commit cf0091b741
+11 -6
View File
@@ -695,6 +695,15 @@ export function Workspace() {
.catch(() => undefined);
}, []);
// Every position that reaches the stage still without a name is named here,
// once: a photo restored from the session lands at boot, before /me has
// answered, so the account reading that put it there saw `pro` as false — and
// a guest's photo earns its name the moment they sign in. PRO only, and a
// position the user has named by hand is left alone.
useEffect(() => {
if (pro && gps && !gps.locality) resolvePlace(gps.latitude, gps.longitude);
}, [pro, gps, resolvePlace]);
// iPhone Safari returns a frame shot through the in-page camera with no EXIF
// at all (WebKit bug 207088), so the device's own position is the only
// automatic source left. Tried the moment such a photo lands (see adoptPhoto)
@@ -717,7 +726,6 @@ export function Workspace() {
setGps({ latitude, longitude, locality: place, timestamp: when ?? capturedAt ?? Date.now(), source: 'device' });
setUseGeotag(true);
setLocating(false);
resolvePlace(latitude, longitude);
},
() => {
setLocating(false);
@@ -726,7 +734,7 @@ export function Workspace() {
},
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 0 }
);
}, [place, t, resolvePlace, capturedAt]);
}, [place, t, capturedAt]);
const adoptPhoto = useCallback(
async (bytes: Uint8Array, name: string, blob: Blob, keepGeo = false) => {
@@ -761,9 +769,6 @@ export function Workspace() {
previewJobRef.current++;
setPreviewBytes(preview);
setGps(found);
// EXIF gave a position but never a name; ask the API for one. PRO only —
// the stamp is a PRO tool, and the lookup is a call to a public geocoder.
if (found && pro) resolvePlace(found.latitude, found.longitude);
setIso(foundIso);
// A new photo starts a new history whose floor is the default look, so
// UNDO walks all the way back and still leaves the photo loaded. REDO has
@@ -779,7 +784,7 @@ export function Workspace() {
// location prompt.
if (!found && pro && canLocate && !locDeniedRef.current) locateMe(taken);
},
[defaultLook, pro, locateMe, resolvePlace]
[defaultLook, pro, locateMe]
);
const loadFile = useCallback(