1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-07-06 23:56:13 +02:00

Desktop: Add support for OCR (#8975)

This commit is contained in:
Laurent Cozic
2023-12-13 19:24:58 +00:00
committed by GitHub
parent 0e847685ff
commit bce94f1775
79 changed files with 2381 additions and 445 deletions

View File

@ -19,10 +19,10 @@ import ResourceEditWatcher from '@joplin/lib/services/ResourceEditWatcher/index'
import CommandService from '@joplin/lib/services/CommandService';
import ToolbarButton from '../ToolbarButton/ToolbarButton';
import Button, { ButtonLevel } from '../Button/Button';
import eventManager from '@joplin/lib/eventManager';
import eventManager, { EventName } from '@joplin/lib/eventManager';
import { AppState } from '../../app.reducer';
import ToolbarButtonUtils from '@joplin/lib/services/commands/ToolbarButtonUtils';
import { _ } from '@joplin/lib/locale';
import { _, _n } from '@joplin/lib/locale';
import TagList from '../TagList';
import NoteTitleBar from './NoteTitle/NoteTitleBar';
import markupLanguageUtils from '../../utils/markupLanguageUtils';
@ -48,6 +48,7 @@ import ItemChange from '@joplin/lib/models/ItemChange';
import PlainEditor from './NoteBody/PlainEditor/PlainEditor';
import CodeMirror6 from './NoteBody/CodeMirror/v6/CodeMirror';
import CodeMirror5 from './NoteBody/CodeMirror/v5/CodeMirror';
import { openItemById } from './utils/contextMenu';
import { namespacedKey } from '@joplin/lib/services/plugins/api/JoplinSettings';
const commands = [
@ -135,7 +136,7 @@ function NoteEditor(props: NoteEditorProps) {
id: formNote.id,
});
eventManager.emit('noteContentChange', { note: savedNote });
eventManager.emit(EventName.NoteContentChange, { note: savedNote });
};
};
@ -367,11 +368,11 @@ function NoteEditor(props: NoteEditorProps) {
}, []);
useEffect(() => {
eventManager.on('alarmChange', onNotePropertyChange);
eventManager.on(EventName.AlarmChange, onNotePropertyChange);
ExternalEditWatcher.instance().on('noteChange', externalEditWatcher_noteChange);
return () => {
eventManager.off('alarmChange', onNotePropertyChange);
eventManager.off(EventName.AlarmChange, onNotePropertyChange);
ExternalEditWatcher.instance().off('noteChange', externalEditWatcher_noteChange);
};
}, [externalEditWatcher_noteChange, onNotePropertyChange]);
@ -499,6 +500,12 @@ function NoteEditor(props: NoteEditorProps) {
setShowRevisions(false);
}, []);
const onBannerResourceClick = useCallback(async (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
const resourceId = event.currentTarget.getAttribute('data-resource-id');
await openItemById(resourceId, props.dispatch);
}, [props.dispatch]);
if (showRevisions) {
const theme = themeStyle(props.themeId);
@ -568,6 +575,24 @@ function NoteEditor(props: NoteEditorProps) {
);
}
const renderResourceInSearchResultsNotification = () => {
const resourceResults = props.searchResults.filter(r => r.id === props.noteId && r.item_type === ModelType.Resource);
if (!resourceResults.length) return null;
const renderResource = (id: string, title: string) => {
return <li key={id}><a data-resource-id={id} onClick={onBannerResourceClick} href="#">{title}</a></li>;
};
return (
<div style={styles.resourceWatchBanner}>
<p style={styles.resourceWatchBannerLine}>{_n('The following attachment matches your search query:', 'The following attachments match your search query:', resourceResults.length)}</p>
<ul>
{resourceResults.map(r => renderResource(r.item_id, r.title))}
</ul>
</div>
);
};
function renderSearchInfo() {
const theme = themeStyle(props.themeId);
if (formNoteFolder && ['Search', 'Tag', 'SmartFilter'].includes(props.notesParentType)) {
@ -603,6 +628,7 @@ function NoteEditor(props: NoteEditorProps) {
<div style={styles.root} onDrop={onDrop}>
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
{renderResourceWatchingNotification()}
{renderResourceInSearchResultsNotification()}
<NoteTitleBar
titleInputRef={titleInputRef}
themeId={props.themeId}
@ -675,6 +701,7 @@ const mapStateToProps = (state: AppState) => {
useCustomPdfViewer: false,
syncUserId: state.settings['sync.userId'],
shareCacheSetting: state.settings['sync.shareCache'],
searchResults: state.searchResults,
};
};