Skip to content

Commit

Permalink
QOL: Autocomplete entries sorted by distance (#390)
Browse files Browse the repository at this point in the history
* implemented

* remove debug & reformat files

* removed low-level getQueryStore().state.queryPoints

* removed obsolete import

* removed more obsolete imports

* cleaned up the Geocoder

* format file
  • Loading branch information
SachsenspieltCoding authored May 27, 2024
1 parent da4bd71 commit e8c8c63
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 9 deletions.
14 changes: 12 additions & 2 deletions src/api/Api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default interface Api {

routeWithDispatch(args: RoutingArgs, zoom: boolean): void

geocode(query: string, provider: string): Promise<GeocodingResult>
geocode(query: string, provider: string, additionalOptions?: Record<string, string>): Promise<GeocodingResult>

supportsGeocoding(): boolean
}
Expand Down Expand Up @@ -79,7 +79,11 @@ export class ApiImpl implements Api {
}
}

async geocode(query: string, provider: string): Promise<GeocodingResult> {
async geocode(
query: string,
provider: string,
additionalOptions?: Record<string, string>
): Promise<GeocodingResult> {
if (!this.supportsGeocoding())
return {
hits: [],
Expand All @@ -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' },
})
Expand Down
21 changes: 14 additions & 7 deletions src/sidebar/search/AddressInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ 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'
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
Expand Down Expand Up @@ -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 (
<div className={containerClass}>
<div
Expand Down Expand Up @@ -166,7 +172,7 @@ export default function AddressInput(props: AddressInputProps) {
onChange={e => {
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}
Expand Down Expand Up @@ -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()
}}
Expand Down Expand Up @@ -271,23 +277,24 @@ 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() {
// invalidates last request if there is one
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<string, string> = 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) {
Expand Down
1 change: 1 addition & 0 deletions src/sidebar/search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit e8c8c63

Please sign in to comment.