Special-case 'me' values in search queries (#11043)

This commit is contained in:
DS Boyce
2026-07-02 09:35:57 -07:00
committed by GitHub
parent 40df0d773a
commit b0a40145e9
6 changed files with 45 additions and 39 deletions
+8 -26
View File
@@ -47,30 +47,12 @@ export function countLines(str: string | undefined): number {
return str.match(/\n/g)?.length ?? 0
}
// Augments search query with additional syntax like `from:me`
export function augmentSearchQuery(query: string, {did}: {did?: string}) {
// Don't do anything if there's no DID
if (!did) {
return query
}
// replace “smart quotes” with normal ones
// iOS keyboard will add fancy unicode quotes, but only normal ones work
query = query.replaceAll(/[“”]/g, '"')
// We don't want to replace substrings that are being "quoted" because those
// are exact string matches, so what we'll do here is to split them apart
// Even-indexed strings are unquoted, odd-indexed strings are quoted
const splits = query.split(/("(?:[^"\\]|\\.)*")/g)
return splits
.map((str, idx) => {
if (idx % 2 === 0) {
return str.replaceAll(/(^|\s)from:me(\s|$)/g, `$1${did}$2`)
}
return str
})
.join('')
/**
* Normalizes a raw search query for the backend. The iOS keyboard inserts smart
* quotes, but only straight quotes work for exact-phrase matching. Operators
* like `from:me` are passed through untouched - the backend resolves `me` to
* the viewer.
*/
export function augmentSearchQuery(query: string) {
return query.replaceAll(/[“”]/g, '"')
}
+5 -5
View File
@@ -319,18 +319,18 @@ let SearchScreenPostResults = ({
}): React.ReactNode => {
const ax = useAnalytics()
const {t: l} = useLingui()
const {currentAccount, hasSession} = useSession()
const {hasSession} = useSession()
const [isPTR, setIsPTR] = useState(false)
const trackPostView = usePostViewTracking('SearchResults')
const searchV2Enabled = ax.features.enabled(ax.features.SearchV2Enable)
const augmentedV2Query = useMemo(() => {
return augmentSearchQuery(query || '', {did: currentAccount?.did})
}, [query, currentAccount])
return augmentSearchQuery(query || '')
}, [query])
const augmentedV1Query = useMemo(() => {
return augmentSearchQuery(queryWithParams || '', {did: currentAccount?.did})
}, [queryWithParams, currentAccount])
return augmentSearchQuery(queryWithParams || '')
}, [queryWithParams])
/*
* Both hooks are called to keep hook order stable; `enabled` ensures only the
@@ -73,6 +73,12 @@ describe(`AdvancedSearchDialog serialize/parse`, () => {
expect(state.until).toBe('2024-02-01')
})
it(`keeps from:me in the query box rather than lifting it into a row`, () => {
const state = parseAdvancedSearch('from:me', {})
expect(state.query).toBe('from:me')
expect(state.filters.find(f => f.field === 'authors')).toBeUndefined()
})
it(`merges a query-box operator with the matching filter param`, () => {
const state = parseAdvancedSearch('hi from:bob', {author: 'alice'})
expect(state.query).toBe('hi')
@@ -5,7 +5,6 @@ import {augmentSearchQuery} from '#/lib/strings/helpers'
import {codeToLanguageName} from '#/locale/helpers'
import {useLanguagePrefs} from '#/state/preferences/languages'
import {useSearchPostsV2Query} from '#/state/queries/search-posts-v2'
import {useSession} from '#/state/session'
import {type SearchFilters} from '#/screens/Search/searchParams'
import {Admonition} from '#/components/Admonition'
import {createStaticClick, InlineLinkText} from '#/components/Link'
@@ -34,12 +33,8 @@ export function DetectedLanguagesAdmonition({
onPressLanguage: (code: string) => void
}) {
const {appLanguage} = useLanguagePrefs()
const {currentAccount} = useSession()
const augmentedQuery = useMemo(
() => augmentSearchQuery(query || '', {did: currentAccount?.did}),
[query, currentAccount],
)
const augmentedQuery = useMemo(() => augmentSearchQuery(query || ''), [query])
const {data} = useSearchPostsV2Query({
query: augmentedQuery,
@@ -26,6 +26,23 @@ describe(`extractSearchPostsParams`, () => {
input: `cats to:alice`,
output: {q: `cats`, mentions: `alice`},
},
// `me` is resolved by the backend, so the :me operators stay in q verbatim
// instead of being lifted into author/mentions.
{
name: `keeps from:me in q verbatim`,
input: `cats from:me`,
output: {q: `cats from:me`},
},
{
name: `keeps to:me in q verbatim`,
input: `cats to:me`,
output: {q: `cats to:me`},
},
{
name: `keeps mentions:me in q verbatim`,
input: `cats mentions:me`,
output: {q: `cats mentions:me`},
},
{
name: `accumulates multiple hashtags into tag[]`,
input: `#cats #dogs`,
+8 -2
View File
@@ -106,11 +106,17 @@ export function extractSearchPostsParams(query: string): ExtractedSearchParams {
switch (op) {
case 'from':
result.author ??= value
/*
* `me` is resolved to the viewer by the backend, so leave it in the
* query text verbatim rather than lifting it into a structured param.
*/
if (value === 'me') remaining.push(token)
else result.author ??= value
break
case 'mentions':
case 'to':
result.mentions ??= value
if (value === 'me') remaining.push(token)
else result.mentions ??= value
break
case 'domain':
result.domain ??= value