import * as React from 'react'; import { themeStyle } from '@joplin/lib/theme'; import { _ } from '@joplin/lib/locale'; import { focus } from '@joplin/lib/utils/focusHandler'; interface Props { themeId: number; // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied onNext: Function; // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied onPrevious: Function; // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied onClose: Function; // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied onChange: Function; query: string; searching: boolean; resultCount: number; selectedIndex: number; visiblePanes: string[]; editorType: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied style: any; } class NoteSearchBar extends React.Component { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied private backgroundColor: any; private searchInputRef: React.RefObject; public constructor(props: Props) { super(props); this.searchInput_change = this.searchInput_change.bind(this); this.searchInput_keyDown = this.searchInput_keyDown.bind(this); this.previousButton_click = this.previousButton_click.bind(this); this.nextButton_click = this.nextButton_click.bind(this); this.closeButton_click = this.closeButton_click.bind(this); // eslint-disable-next-line no-restricted-properties this.focus = this.focus.bind(this); this.backgroundColor = undefined; this.searchInputRef = React.createRef(); } public style() { const theme = themeStyle(this.props.themeId); const style = { root: { ...theme.textStyle, backgroundColor: theme.backgroundColor, color: theme.colorFaded }, }; return style; } // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied public buttonIconComponent(iconName: string, clickHandler: any, isEnabled: boolean) { const theme = themeStyle(this.props.themeId); const searchButton = { paddingLeft: 4, paddingRight: 4, paddingTop: 2, paddingBottom: 2, textDecoration: 'none', marginRight: 5, }; const iconStyle = { display: 'flex', fontSize: Math.round(theme.fontSize) * 1.2, color: theme.color, opacity: isEnabled ? 1.0 : theme.disabledOpacity, }; const icon = ; return ( {icon} ); } // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied private searchInput_change(event: any) { const query = event.currentTarget.value; this.triggerOnChange(query); } // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied private searchInput_keyDown(event: any) { if (event.keyCode === 13) { // ENTER event.preventDefault(); if (!event.shiftKey) { if (this.props.onNext) this.props.onNext(); } else { if (this.props.onPrevious) this.props.onPrevious(); } } if (event.keyCode === 27) { // ESCAPE event.preventDefault(); if (this.props.onClose) this.props.onClose(); } if (event.keyCode === 70) { // F key if (event.ctrlKey) { event.target.select(); } } } private previousButton_click() { if (this.props.onPrevious) this.props.onPrevious(); } private nextButton_click() { if (this.props.onNext) this.props.onNext(); } private closeButton_click() { if (this.props.onClose) this.props.onClose(); } public triggerOnChange(query: string) { if (this.props.onChange) this.props.onChange(query); } public focus() { focus('NoteSearchBar::focus', this.searchInputRef.current); this.searchInputRef.current?.select(); } public render() { const query = this.props.query ? this.props.query : ''; // backgroundColor needs to cached to a local variable to prevent the // colour from blinking. // For more info: https://github.com/laurent22/joplin/pull/2329#issuecomment-578376835 const theme = themeStyle(this.props.themeId); if (!this.props.searching) { if (this.props.resultCount === 0 && query.length > 0) { this.backgroundColor = theme.warningBackgroundColor; } else { this.backgroundColor = theme.backgroundColor; } } if (this.backgroundColor === undefined) { this.backgroundColor = theme.backgroundColor; } const buttonEnabled = (this.backgroundColor === theme.backgroundColor); const closeButton = this.buttonIconComponent('fa-times', this.closeButton_click, true); const previousButton = this.buttonIconComponent('fa-chevron-up', this.previousButton_click, buttonEnabled); const nextButton = this.buttonIconComponent('fa-chevron-down', this.nextButton_click, buttonEnabled); const textStyle = { fontSize: theme.fontSize, fontFamily: theme.fontFamily, color: theme.colorFaded, backgroundColor: theme.backgroundColor }; const matchesFoundString = (query.length > 0) ? (
{`${this.props.resultCount === 0 ? 0 : this.props.selectedIndex + 1} / ${this.props.resultCount}`}
) : null; const editorVisible = this.props.visiblePanes.includes('editor'); const usesEditorSearch = this.props.editorType === 'CodeMirror6' && editorVisible; const allowScrolling = editorVisible; const viewerWarning = (
{'Jumping between matches is not available in the viewer, please toggle the editor'}
); if (usesEditorSearch) return null; return (
{closeButton} {allowScrolling ? previousButton : null} {allowScrolling ? nextButton : null} {allowScrolling ? matchesFoundString : null} {!allowScrolling ? viewerWarning : null}
); } } export default NoteSearchBar;