Add From: Me to advanced search filters (#11126)
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import {describe, expect, it} from '@jest/globals'
|
||||
|
||||
import {
|
||||
appendFromMe,
|
||||
buildSearchPostsV2Filters,
|
||||
extractFromMe,
|
||||
extractSearchPostsParams,
|
||||
} from '#/state/queries/search-posts-params'
|
||||
|
||||
@@ -139,6 +141,39 @@ describe(`extractSearchPostsParams`, () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe(`extractFromMe / appendFromMe`, () => {
|
||||
it(`strips a bare from:me token and reports it`, () => {
|
||||
expect(extractFromMe(`cats from:me`)).toEqual({q: `cats`, fromMe: true})
|
||||
expect(extractFromMe(`from:me`)).toEqual({q: ``, fromMe: true})
|
||||
})
|
||||
|
||||
it(`reports fromMe false when the token is absent`, () => {
|
||||
expect(extractFromMe(`cats from:alice`)).toEqual({
|
||||
q: `cats from:alice`,
|
||||
fromMe: false,
|
||||
})
|
||||
})
|
||||
|
||||
it(`leaves a quoted from:me in the query text`, () => {
|
||||
expect(extractFromMe(`"from:me"`)).toEqual({q: `"from:me"`, fromMe: false})
|
||||
})
|
||||
|
||||
it(`re-appends the token only when the filter is active`, () => {
|
||||
expect(appendFromMe(`cats`, true)).toBe(`cats from:me`)
|
||||
expect(appendFromMe(`cats`, false)).toBe(`cats`)
|
||||
expect(appendFromMe(``, true)).toBe(`from:me`)
|
||||
})
|
||||
|
||||
it(`does not duplicate an existing from:me token`, () => {
|
||||
expect(appendFromMe(`cats from:me`, true)).toBe(`cats from:me`)
|
||||
})
|
||||
|
||||
it(`round-trips through extract and append`, () => {
|
||||
const {q, fromMe} = extractFromMe(`cats from:me`)
|
||||
expect(appendFromMe(q, fromMe)).toBe(`cats from:me`)
|
||||
})
|
||||
})
|
||||
|
||||
describe(`buildSearchPostsV2Filters`, () => {
|
||||
it(`maps embedded operators alone into v2 plural params`, () => {
|
||||
expect(
|
||||
|
||||
@@ -83,6 +83,30 @@ export function tokenizeQuery(raw: string): string[] {
|
||||
return tokens
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a bare `from:me` token out of a query. The "Me" author filter always
|
||||
* travels inside `q` as a `from:me` token (the backend resolves `me` to the
|
||||
* viewer), but the UI never shows it as text: the search input strips it for
|
||||
* display and the advanced-search dialog represents it in the From dropdown.
|
||||
* Tokenization keeps quoted phrases intact, so a `from:me` inside quotes stays
|
||||
* in the query text.
|
||||
*/
|
||||
export function extractFromMe(query: string): {q: string; fromMe: boolean} {
|
||||
const tokens = tokenizeQuery(query)
|
||||
const kept = tokens.filter(token => token !== 'from:me')
|
||||
return {q: kept.join(' '), fromMe: kept.length !== tokens.length}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-appends the `from:me` token when the "Me" author filter is active.
|
||||
* Idempotent: a query that already carries a bare `from:me` is returned as-is.
|
||||
*/
|
||||
export function appendFromMe(query: string, fromMe: boolean): string {
|
||||
if (!fromMe) return query
|
||||
if (tokenizeQuery(query).includes('from:me')) return query
|
||||
return query ? `${query} from:me` : 'from:me'
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifts the operators that `app.bsky.feed.searchPosts` accepts as structured
|
||||
* params out of the free-text query, so the backend filters on them directly.
|
||||
|
||||
@@ -16,6 +16,7 @@ import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {type SearchFilters} from '#/screens/Search/searchParams'
|
||||
import {
|
||||
appendFromMe,
|
||||
buildSearchPostsV2Filters,
|
||||
extractSearchPostsParams,
|
||||
} from './search-posts-params'
|
||||
@@ -51,10 +52,11 @@ export function useSearchPostsV2Query({
|
||||
const moderationOpts = useModerationOpts()
|
||||
const selectArgs = useMemo(
|
||||
() => ({
|
||||
isSearchingSpecificUser: /from:(\w+)/.test(query) || !!filters?.author,
|
||||
isSearchingSpecificUser:
|
||||
/from:(\w+)/.test(query) || !!filters?.author || filters?.from === 'me',
|
||||
moderationOpts,
|
||||
}),
|
||||
[query, filters?.author, moderationOpts],
|
||||
[query, filters?.author, filters?.from, moderationOpts],
|
||||
)
|
||||
const lastRun = useRef<{
|
||||
data: InfiniteData<AppBskyFeedSearchPostsV2.OutputSchema>
|
||||
@@ -78,9 +80,10 @@ export function useSearchPostsV2Query({
|
||||
*/
|
||||
const {q, ...embedded} = extractSearchPostsParams(query)
|
||||
const builtFilters = buildSearchPostsV2Filters(embedded, filters)
|
||||
const finalQuery = appendFromMe(q, filters?.from === 'me')
|
||||
const res = await agent.app.bsky.feed.searchPostsV2({
|
||||
...builtFilters,
|
||||
query: q,
|
||||
query: finalQuery,
|
||||
limit: 25,
|
||||
cursor: pageParam,
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user