mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
feat(voice): add reusable geometry actions
- turn named places and mapped landmarks into reusable bounded areas - count loaded records inside resolved, drawn and annotated geometry - find recent imagery for an area, the view or the pointer snapshot - keep osm place search behind an operator-configured overpass endpoint - preserve cancellation, ownership and follow-up memory across every action - cover geometry, provider lifecycle, cache isolation and voice routing
This commit is contained in:
1 parent
01979bba1e
commit
b234d7b427
84 files changed
+14262
-1681
No files matched your search
@@ -124,6 +124,8 @@ export function createNominatimOutlineClient({
|
||||
const outline = {
|
||||
polygons,
|
||||
name: body.outline.name || null,
|
||||
adminArea: body.outline.adminArea || null,
|
||||
adminLevel: body.outline.adminLevel || null,
|
||||
class: body.outline.class || null,
|
||||
type: body.outline.type || null,
|
||||
osm: body.outline.osm || null,
|
||||
|
||||
@@ -29,14 +29,31 @@ test('an accepted outline comes back with its polygons and is remembered', async
|
||||
const { calls, lookup } = client(() =>
|
||||
reply(200, {
|
||||
status: 'OK',
|
||||
outline: { name: 'Paris', class: 'boundary', type: 'administrative', polygons: [[ring]] },
|
||||
outline: {
|
||||
name: 'Bagmati Province',
|
||||
adminArea: 'Bagmati Province',
|
||||
adminLevel: 'admin1',
|
||||
class: 'boundary',
|
||||
type: 'administrative',
|
||||
polygons: [[ring]],
|
||||
},
|
||||
}),
|
||||
);
|
||||
const ask = { query: 'Paris', kind: 'city', lat: 48.85, lon: 2.35 };
|
||||
const ask = {
|
||||
query: 'Bagmati Province',
|
||||
kind: 'admin',
|
||||
lat: 27.72,
|
||||
lon: 85.32,
|
||||
};
|
||||
const outline = await lookup(ask);
|
||||
assert.deepEqual(outline.polygons, [[ring]]);
|
||||
assert.equal(outline.class, 'boundary');
|
||||
assert.match(calls[0], /^\/api\/geocode\/outline\?q=Paris&kind=city&lat=48\.850&lon=2\.350$/);
|
||||
assert.equal(outline.adminArea, 'Bagmati Province');
|
||||
assert.equal(outline.adminLevel, 'admin1');
|
||||
assert.match(
|
||||
calls[0],
|
||||
/^\/api\/geocode\/outline\?q=Bagmati\+Province&kind=admin&lat=27\.720&lon=85\.320$/,
|
||||
);
|
||||
await lookup(ask);
|
||||
assert.equal(calls.length, 1, 'one request per ask in a session');
|
||||
});
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Browser client for `/api/osm/features`: one curated preset inside a box,
|
||||
* as a count or as features. The server writes and bounds the Overpass
|
||||
* query and answers only when an operator configured Overpass; this only
|
||||
* names the preset, box, mode and limit.
|
||||
* @module sources/osmFeatures
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {{fetchImpl?: typeof fetch, endpoint?: string}} [options]
|
||||
* @returns {(request: {preset: string, bbox: number[], mode?: 'count'|'features', limit?: number}, options?: {signal?: AbortSignal}) => Promise<object>}
|
||||
*/
|
||||
export function createOsmFeatureSource({
|
||||
fetchImpl = (...args) => globalThis.fetch(...args),
|
||||
endpoint = '/api/osm/features',
|
||||
} = {}) {
|
||||
return async function searchOsmFeatures(
|
||||
{ preset, bbox, mode = 'features', limit },
|
||||
{ signal } = {},
|
||||
) {
|
||||
const params = new URLSearchParams({
|
||||
preset,
|
||||
bbox: bbox.map((v) => Number(v).toFixed(5)).join(','),
|
||||
mode,
|
||||
});
|
||||
if (Number.isFinite(limit)) params.set('limit', String(limit));
|
||||
let response;
|
||||
try {
|
||||
response = await fetchImpl(`${endpoint}?${params}`, { signal });
|
||||
} catch (error) {
|
||||
if (signal?.aborted) throw error;
|
||||
return {
|
||||
ok: false,
|
||||
status: 0,
|
||||
error: 'OpenStreetMap search is unreachable.',
|
||||
};
|
||||
}
|
||||
let body = null;
|
||||
try {
|
||||
body = await response.json();
|
||||
} catch {
|
||||
body = null;
|
||||
}
|
||||
if (!response.ok)
|
||||
return {
|
||||
ok: false,
|
||||
status: response.status,
|
||||
code: body?.code || null,
|
||||
error:
|
||||
body?.error || `OpenStreetMap search failed (${response.status}).`,
|
||||
};
|
||||
return { ok: true, ...body };
|
||||
};
|
||||
}
|
||||
@@ -281,6 +281,10 @@ test('shared decoded tiles are isolated from consumer mutation', async () => {
|
||||
secondResult.tiles[0][0].name = 'second mutation';
|
||||
secondResult.tiles[0][0].coordinates[0][0] = 1;
|
||||
|
||||
const secondCachedResult = await second.fetchBounds(box, { zoom: 14, tiles });
|
||||
assert.equal(secondCachedResult.tiles[0][0].name, 'Congress Avenue');
|
||||
assert.equal(secondCachedResult.tiles[0][0].coordinates[0][0], -97);
|
||||
|
||||
const thirdResult = await third.fetchBounds(box, { zoom: 14, tiles });
|
||||
assert.equal(thirdResult.tiles[0][0].name, 'Congress Avenue');
|
||||
assert.equal(thirdResult.tiles[0][0].coordinates[0][0], -97);
|
||||
@@ -334,6 +338,12 @@ test('one source isolates in-flight and completed cache results from consumer mu
|
||||
const cachedResult = await source.fetchBounds(box, { zoom: 14, tiles });
|
||||
assert.equal(cachedResult.tiles[0][0].name, 'Congress Avenue');
|
||||
assert.equal(cachedResult.tiles[0][0].coordinates[0][0], -97);
|
||||
|
||||
cachedResult.tiles[0][0].name = 'cached mutation';
|
||||
cachedResult.tiles[0][0].coordinates[0][0] = 2;
|
||||
const revisitedResult = await source.fetchBounds(box, { zoom: 14, tiles });
|
||||
assert.equal(revisitedResult.tiles[0][0].name, 'Congress Avenue');
|
||||
assert.equal(revisitedResult.tiles[0][0].coordinates[0][0], -97);
|
||||
assert.equal(requests, 1);
|
||||
assert.equal(decodes, 1);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user