Update tooltip text for search buttons (#23448)

GitOrigin-RevId: d189aac06c5f68e009eeb125d7cc225b41e8cc0c
This commit is contained in:
Alf Eaton 2025-02-14 09:44:07 +00:00 committed by Copybot
parent cd7b1bf649
commit 4611de3f3d
9 changed files with 127 additions and 15 deletions

View file

@ -1413,6 +1413,7 @@
"search_next": "",
"search_only_the_bib_files_in_your_project_only_by_citekeys": "",
"search_previous": "",
"search_project": "",
"search_projects": "",
"search_references": "",
"search_regexp": "",
@ -1421,6 +1422,7 @@
"search_replace_with": "",
"search_search_for": "",
"search_terms": "",
"search_this_file": "",
"search_whole_word": "",
"search_within_selection": "",
"searched_path_for_lines_containing": "",

View file

@ -0,0 +1,33 @@
import { sendMB } from '@/infrastructure/event-tracking'
type SearchEventSegmentation = {
'search-open':
| ({
searchType: 'full-project'
} & ({ method: 'keyboard' } | { method: 'button'; location: 'toolbar' }))
| ({
searchType: 'document'
mode: 'visual' | 'source'
} & ({ method: 'keyboard' } | { method: 'button'; location: 'toolbar' }))
'search-execute': {
searchType: 'full-project'
totalDocs: number
totalResults: number
}
'search-result-click': {
searchType: 'full-project'
}
'search-replace-click': {
searchType: 'document'
method: 'keyboard' | 'button'
action: 'replace' | 'replace-all'
}
}
export const sendSearchEvent = <T extends keyof SearchEventSegmentation>(
eventName: T,
segmentation: SearchEventSegmentation[T]
) => {
sendMB(eventName, segmentation)
}

View file

@ -29,6 +29,7 @@ import { useUserSettingsContext } from '@/shared/context/user-settings-context'
import { getStoredSelection, setStoredSelection } from '../extensions/search'
import { debounce } from 'lodash'
import { EditorSelection, EditorState } from '@codemirror/state'
import { sendSearchEvent } from '@/features/event-tracking/search-events'
const MATCH_COUNT_DEBOUNCE_WAIT = 100 // the amount of ms to wait before counting matches
const MAX_MATCH_COUNT = 999 // the maximum number of matches to count
@ -197,6 +198,11 @@ const CodeMirrorSearchForm: FC = () => {
case 'Enter':
event.preventDefault()
replaceNext(view)
sendSearchEvent('search-replace-click', {
searchType: 'document',
action: 'replace',
method: 'keyboard',
})
break
case 'Tab': {
@ -459,7 +465,14 @@ const CodeMirrorSearchForm: FC = () => {
<OLButton
variant="secondary"
size="sm"
onClick={() => replaceNext(view)}
onClick={() => {
sendSearchEvent('search-replace-click', {
searchType: 'document',
action: 'replace',
method: 'button',
})
replaceNext(view)
}}
>
{t('search_replace')}
</OLButton>
@ -467,7 +480,14 @@ const CodeMirrorSearchForm: FC = () => {
<OLButton
variant="secondary"
size="sm"
onClick={() => replaceAll(view)}
onClick={() => {
sendSearchEvent('search-replace-click', {
searchType: 'document',
action: 'replace-all',
method: 'button',
})
replaceAll(view)
}}
>
{t('search_replace_all')}
</OLButton>

View file

@ -4,11 +4,8 @@ import {
useCodeMirrorStateContext,
useCodeMirrorViewContext,
} from './codemirror-context'
import { searchPanelOpen } from '@codemirror/search'
import { useResizeObserver } from '@/shared/hooks/use-resize-observer'
import { ToolbarButton } from './toolbar/toolbar-button'
import { ToolbarItems } from './toolbar/toolbar-items'
import * as commands from '../extensions/toolbar/commands'
import { ToolbarOverflow } from './toolbar/overflow'
import useDropdown from '../../../shared/hooks/use-dropdown'
import { getPanel } from '@codemirror/view'
@ -21,8 +18,8 @@ import { isVisual } from '../extensions/visual/visual'
import { language } from '@codemirror/language'
import { minimumListDepthForSelection } from '../utils/tree-operations/ancestors'
import { debugConsole } from '@/utils/debugging'
import { bsVersion } from '@/features/utils/bootstrap-5'
import { useTranslation } from 'react-i18next'
import { ToggleSearchButton } from '@/features/source-editor/components/toolbar/toggle-search-button'
export const CodeMirrorToolbar = () => {
const view = useCodeMirrorViewContext()
@ -173,14 +170,7 @@ const Toolbar = memo(function Toolbar() {
className="ol-cm-toolbar-button-group ol-cm-toolbar-end"
ref={handleButtons}
>
<ToolbarButton
id="toolbar-toggle-search"
label="Toggle Search"
command={commands.toggleSearch}
active={searchPanelOpen(state)}
icon={bsVersion({ bs5: 'search', bs3: 'search' })}
/>
<ToggleSearchButton state={state} />
<SwitchToPDFButton />
<DetacherSynctexControl />
<DetachCompileButtonWrapper />

View file

@ -0,0 +1,22 @@
import { FC } from 'react'
import * as commands from '@/features/source-editor/extensions/toolbar/commands'
import { searchPanelOpen } from '@codemirror/search'
import { ToolbarButton } from '@/features/source-editor/components/toolbar/toolbar-button'
import { EditorState } from '@codemirror/state'
import { useTranslation } from 'react-i18next'
import { isMac } from '@/shared/utils/os'
export const ToggleSearchButton: FC<{ state: EditorState }> = ({ state }) => {
const { t } = useTranslation()
return (
<ToolbarButton
id="toolbar-toggle-search"
label={t('search_this_file')}
command={commands.toggleSearch}
active={searchPanelOpen(state)}
icon="search"
shortcut={isMac ? '⌘F' : 'Ctrl+F'}
/>
)
}

View file

@ -9,17 +9,26 @@ import {
highlightSelectionMatches,
togglePanel,
} from '@codemirror/search'
import { Decoration, EditorView, keymap, ViewPlugin } from '@codemirror/view'
import {
Decoration,
EditorView,
KeyBinding,
keymap,
ViewPlugin,
} from '@codemirror/view'
import {
Annotation,
Compartment,
EditorSelection,
EditorState,
Prec,
SelectionRange,
StateEffect,
StateField,
TransactionSpec,
} from '@codemirror/state'
import { sendSearchEvent } from '@/features/event-tracking/search-events'
import { isVisual } from '@/features/source-editor/extensions/visual/visual'
const restoreSearchQueryAnnotation = Annotation.define<boolean>()
@ -122,6 +131,25 @@ const scrollToMatch = (range: SelectionRange, view: EditorView) => {
})
}
const searchEventKeymap: KeyBinding[] = [
// record an event when the search panel is opened using the keyboard shortcut
{
key: 'Mod-f',
preventDefault: true,
scope: 'editor search-panel',
run(view) {
if (!searchPanelOpen(view.state)) {
sendSearchEvent('search-open', {
searchType: 'document',
method: 'keyboard',
mode: isVisual(view) ? 'visual' : 'source',
})
}
return false // continue with the regular search shortcut
},
},
]
/**
* A collection of extensions related to the search feature.
*/
@ -129,6 +157,9 @@ export const search = () => {
let open = false
return [
// keymap for search events
Prec.high(keymap.of(searchEventKeymap)),
// keymap for search
keymap.of(searchKeymap),

View file

@ -20,6 +20,7 @@ import { snippet } from '@codemirror/autocomplete'
import { snippets } from './snippets'
import { minimumListDepthForSelection } from '../../utils/tree-operations/ancestors'
import { isVisual } from '../visual/visual'
import { sendSearchEvent } from '@/features/event-tracking/search-events'
export const toggleBold = toggleRanges('\\textbf')
export const toggleItalic = toggleRanges('\\textit')
@ -151,6 +152,12 @@ export const toggleSearch: Command = view => {
if (searchPanelOpen(view.state)) {
closeSearchPanel(view)
} else {
sendSearchEvent('search-open', {
searchType: 'document',
method: 'button',
location: 'toolbar',
mode: isVisual(view) ? 'visual' : 'source',
})
openSearchPanel(view)
}
return true

View file

@ -20,6 +20,7 @@ import useScopeEventEmitter from '@/shared/hooks/use-scope-event-emitter'
import useEventListener from '@/shared/hooks/use-event-listener'
import { isSplitTestEnabled } from '@/utils/splitTestUtils'
import { isMac } from '@/shared/utils/os'
import { sendSearchEvent } from '@/features/event-tracking/search-events'
export type IdeLayout = 'sideBySide' | 'flat'
export type IdeView = 'editor' | 'file' | 'pdf' | 'history'
@ -142,6 +143,10 @@ export const LayoutProvider: FC = ({ children }) => {
) {
if (isSplitTestEnabled('full-project-search')) {
event.preventDefault()
sendSearchEvent('search-open', {
searchType: 'full-project',
method: 'keyboard',
})
setProjectSearchIsOpen(true)
}
}

View file

@ -1870,6 +1870,7 @@
"search_next": "next",
"search_only_the_bib_files_in_your_project_only_by_citekeys": "Search only the .bib files in your project, only by citekeys.",
"search_previous": "previous",
"search_project": "Search project",
"search_projects": "Search projects",
"search_references": "Search the .bib files in this project",
"search_regexp": "Regular expression",
@ -1878,6 +1879,7 @@
"search_replace_with": "Replace with",
"search_search_for": "Search for",
"search_terms": "Search terms",
"search_this_file": "Search this file",
"search_whole_word": "Whole word",
"search_within_selection": "Within selection",
"searched_path_for_lines_containing": "Searched __path__ for lines containing \"__query__\"",