* Refactor mobile search screen * Remove 'staleness' fetch trigger on search * Implement a temporary fulltext search solution * Add missing key from profile search result * A few UI & UX improvements to the search suggestions * Update web search suggestions * Implement search in web build
This commit is contained in:
parent
48e18662f6
commit
a7e3ce2585
16 changed files with 587 additions and 283 deletions
69
src/lib/api/search.ts
Normal file
69
src/lib/api/search.ts
Normal file
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* This is a temporary off-spec search endpoint
|
||||
* TODO removeme when we land this in proto!
|
||||
*/
|
||||
import {AppBskyFeedPost} from '@atproto/api'
|
||||
|
||||
const PROFILES_ENDPOINT = 'https://search.bsky.social/search/profiles'
|
||||
const POSTS_ENDPOINT = 'https://search.bsky.social/search/posts'
|
||||
|
||||
export interface ProfileSearchItem {
|
||||
$type: string
|
||||
avatar: {
|
||||
cid: string
|
||||
mimeType: string
|
||||
}
|
||||
banner: {
|
||||
cid: string
|
||||
mimeType: string
|
||||
}
|
||||
description: string | undefined
|
||||
displayName: string | undefined
|
||||
did: string
|
||||
}
|
||||
|
||||
export interface PostSearchItem {
|
||||
tid: string
|
||||
cid: string
|
||||
user: {
|
||||
did: string
|
||||
handle: string
|
||||
}
|
||||
post: AppBskyFeedPost.Record
|
||||
}
|
||||
|
||||
export async function searchProfiles(
|
||||
query: string,
|
||||
): Promise<ProfileSearchItem[]> {
|
||||
return await doFetch<ProfileSearchItem[]>(PROFILES_ENDPOINT, query)
|
||||
}
|
||||
|
||||
export async function searchPosts(query: string): Promise<PostSearchItem[]> {
|
||||
return await doFetch<PostSearchItem[]>(POSTS_ENDPOINT, query)
|
||||
}
|
||||
|
||||
async function doFetch<T>(endpoint: string, query: string): Promise<T> {
|
||||
const controller = new AbortController()
|
||||
const to = setTimeout(() => controller.abort(), 15e3)
|
||||
|
||||
const uri = new URL(endpoint)
|
||||
uri.searchParams.set('q', query)
|
||||
|
||||
const res = await fetch(String(uri), {
|
||||
method: 'get',
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
},
|
||||
signal: controller.signal,
|
||||
})
|
||||
|
||||
const resHeaders: Record<string, string> = {}
|
||||
res.headers.forEach((value: string, key: string) => {
|
||||
resHeaders[key] = value
|
||||
})
|
||||
let resBody = await res.json()
|
||||
|
||||
clearTimeout(to)
|
||||
|
||||
return resBody as unknown as T
|
||||
}
|
|
@ -32,24 +32,39 @@ export class Router {
|
|||
}
|
||||
|
||||
function createRoute(pattern: string): Route {
|
||||
let matcherReInternal = pattern.replace(
|
||||
/:([\w]+)/g,
|
||||
(_m, name) => `(?<${name}>[^/]+)`,
|
||||
)
|
||||
const pathParamNames: Set<string> = new Set()
|
||||
let matcherReInternal = pattern.replace(/:([\w]+)/g, (_m, name) => {
|
||||
pathParamNames.add(name)
|
||||
return `(?<${name}>[^/]+)`
|
||||
})
|
||||
const matcherRe = new RegExp(`^${matcherReInternal}([?]|$)`, 'i')
|
||||
return {
|
||||
match(path: string) {
|
||||
const res = matcherRe.exec(path)
|
||||
const {pathname, searchParams} = new URL(path, 'http://throwaway.com')
|
||||
const addedParams = Object.fromEntries(searchParams.entries())
|
||||
|
||||
const res = matcherRe.exec(pathname)
|
||||
if (res) {
|
||||
return {params: res.groups || {}}
|
||||
return {params: Object.assign(addedParams, res.groups || {})}
|
||||
}
|
||||
return undefined
|
||||
},
|
||||
build(params: Record<string, string>) {
|
||||
return pattern.replace(
|
||||
const str = pattern.replace(
|
||||
/:([\w]+)/g,
|
||||
(_m, name) => params[name] || 'undefined',
|
||||
)
|
||||
|
||||
let hasQp = false
|
||||
const qp = new URLSearchParams()
|
||||
for (const paramName in params) {
|
||||
if (!pathParamNames.has(paramName)) {
|
||||
qp.set(paramName, params[paramName])
|
||||
hasQp = true
|
||||
}
|
||||
}
|
||||
|
||||
return str + (hasQp ? `?${qp.toString()}` : '')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ export type HomeTabNavigatorParams = CommonNavigatorParams & {
|
|||
}
|
||||
|
||||
export type SearchTabNavigatorParams = CommonNavigatorParams & {
|
||||
Search: undefined
|
||||
Search: {q?: string}
|
||||
}
|
||||
|
||||
export type NotificationsTabNavigatorParams = CommonNavigatorParams & {
|
||||
|
@ -32,7 +32,7 @@ export type NotificationsTabNavigatorParams = CommonNavigatorParams & {
|
|||
|
||||
export type FlatNavigatorParams = CommonNavigatorParams & {
|
||||
Home: undefined
|
||||
Search: undefined
|
||||
Search: {q?: string}
|
||||
Notifications: undefined
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ export type AllNavigatorParams = CommonNavigatorParams & {
|
|||
HomeTab: undefined
|
||||
Home: undefined
|
||||
SearchTab: undefined
|
||||
Search: undefined
|
||||
Search: {q?: string}
|
||||
NotificationsTab: undefined
|
||||
Notifications: undefined
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue