From e8c8c630140fc4bd839557462d3f65c15be04c81 Mon Sep 17 00:00:00 2001 From: Finn | Sachsenspielt Date: Mon, 27 May 2024 13:04:14 +0200 Subject: [PATCH] QOL: Autocomplete entries sorted by distance (#390) * implemented * remove debug & reformat files * removed low-level getQueryStore().state.queryPoints * removed obsolete import * removed more obsolete imports * cleaned up the Geocoder * format file --- src/api/Api.ts | 14 ++++++++++++-- src/sidebar/search/AddressInput.tsx | 21 ++++++++++++++------- src/sidebar/search/Search.tsx | 1 + 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/api/Api.ts b/src/api/Api.ts index bc8b8e93..2dab99f9 100644 --- a/src/api/Api.ts +++ b/src/api/Api.ts @@ -28,7 +28,7 @@ export default interface Api { routeWithDispatch(args: RoutingArgs, zoom: boolean): void - geocode(query: string, provider: string): Promise + geocode(query: string, provider: string, additionalOptions?: Record): Promise supportsGeocoding(): boolean } @@ -79,7 +79,11 @@ export class ApiImpl implements Api { } } - async geocode(query: string, provider: string): Promise { + async geocode( + query: string, + provider: string, + additionalOptions?: Record + ): Promise { if (!this.supportsGeocoding()) return { hits: [], @@ -96,6 +100,12 @@ export class ApiImpl implements Api { url.searchParams.append('osm_tag', '!boundary') url.searchParams.append('osm_tag', '!historic') + if (additionalOptions) { + for (const key in additionalOptions) { + url.searchParams.append(key, additionalOptions[key]) + } + } + const response = await fetch(url.toString(), { headers: { Accept: 'application/json' }, }) diff --git a/src/sidebar/search/AddressInput.tsx b/src/sidebar/search/AddressInput.tsx index 03874e11..ea54f461 100644 --- a/src/sidebar/search/AddressInput.tsx +++ b/src/sidebar/search/AddressInput.tsx @@ -13,7 +13,7 @@ import Cross from '@/sidebar/times-solid-thin.svg' import styles from './AddressInput.module.css' import Api, { getApi } from '@/api/Api' import { tr } from '@/translation/Translation' -import { hitToItem, nominatimHitToItem, textToCoordinate } from '@/Converters' +import { coordinateToText, hitToItem, nominatimHitToItem, textToCoordinate } from '@/Converters' import { useMediaQuery } from 'react-responsive' import PopUp from '@/sidebar/search/PopUp' import PlainButton from '@/PlainButton' @@ -21,6 +21,7 @@ import { onCurrentLocationSelected } from '@/map/MapComponent' export interface AddressInputProps { point: QueryPoint + points: QueryPoint[] onCancel: () => void onAddressSelected: (queryText: string, coord: Coordinate | undefined, bbox: Bbox | undefined) => void onChange: (value: string) => void @@ -134,6 +135,11 @@ export default function AddressInput(props: AddressInputProps) { const containerClass = hasFocus ? styles.fullscreen : '' const type = props.point.type + // get the bias point for the geocoder + // (the query point above the current one) + const autocompleteIndex = props.points.findIndex(point => !point.isInitialized) + const biasPoint = props.points[autocompleteIndex - 1] + return (
{ setText(e.target.value) const coordinate = textToCoordinate(e.target.value) - if (!coordinate) geocoder.request(e.target.value, 'default') + if (!coordinate) geocoder.request(e.target.value, biasPoint, 'default') props.onChange(e.target.value) }} onKeyDown={onKeypress} @@ -213,7 +219,7 @@ export default function AddressInput(props: AddressInputProps) { } else if (item instanceof MoreResultsItem) { // do not hide autocomplete items const coordinate = textToCoordinate(item.search) - if (!coordinate) geocoder.request(item.search, 'nominatim') + if (!coordinate) geocoder.request(item.search, biasPoint, 'nominatim') } searchInput.current!.blur() }} @@ -271,8 +277,8 @@ class Geocoder { this.onSuccess = onSuccess } - request(query: string, provider: string) { - this.requestAsync(query, provider).then(() => {}) + request(query: string, biasPoint: QueryPoint, provider: string) { + this.requestAsync(query, biasPoint, provider).then(() => {}) } cancel() { @@ -280,14 +286,15 @@ class Geocoder { this.getNextId() } - async requestAsync(query: string, provider: string) { + async requestAsync(query: string, biasPoint: QueryPoint, provider: string) { const currentId = this.getNextId() this.timeout.cancel() if (!query || query.length < 2) return await this.timeout.wait() try { - const result = await this.api.geocode(query, provider) + const options: Record = biasPoint ? { point: coordinateToText(biasPoint.coordinate) } : {} + const result = await this.api.geocode(query, provider, options) const hits = Geocoder.filterDuplicates(result.hits) if (currentId === this.requestId) this.onSuccess(query, provider, hits) } catch (reason) { diff --git a/src/sidebar/search/Search.tsx b/src/sidebar/search/Search.tsx index f825cdcd..2a28214b 100644 --- a/src/sidebar/search/Search.tsx +++ b/src/sidebar/search/Search.tsx @@ -166,6 +166,7 @@ const SearchBox = ({ dropPreviewIndex={dropPreviewIndex} index={index} point={point} + points={points} onCancel={() => console.log('cancel')} onAddressSelected={(queryText, coordinate) => { const initCount = points.filter(p => p.isInitialized).length