mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Revert: Desktop: Fixes #5955: Changing the currently opened note from plugins or the data API does not refresh the note content
Causes an infinite rendering loop when creating a new note
This commit is contained in:
parent
1f19072f8f
commit
34c4b832ba
@ -76,18 +76,11 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
}, []);
|
||||
|
||||
const effectiveNoteId = useEffectiveNoteId(props);
|
||||
const effectiveNote = props.notes.find(n => n.id === effectiveNoteId);
|
||||
|
||||
const { formNote, setFormNote, isNewNote, resourceInfos } = useFormNote({
|
||||
syncStarted: props.syncStarted,
|
||||
decryptionStarted: props.decryptionStarted,
|
||||
noteId: effectiveNoteId,
|
||||
|
||||
// The effective updated_time property of the note. It may be different
|
||||
// from the last time the note was saved, if it was modified outside the
|
||||
// editor (eg. via API).
|
||||
dbNote: effectiveNote ? { id: effectiveNote.id, updated_time: effectiveNote.updated_time } : { id: '', updated_time: 0 },
|
||||
|
||||
isProvisional: props.isProvisional,
|
||||
titleInputRef: titleInputRef,
|
||||
editorRef: editorRef,
|
||||
@ -127,32 +120,12 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
return async function() {
|
||||
const note = await formNoteToNote(formNote);
|
||||
reg.logger().debug('Saving note...', note);
|
||||
const noteUpdatedTime = Date.now();
|
||||
|
||||
// First we set the formNote object, then we save the note. We
|
||||
// do it in that order, otherwise `useFormNote` will be rendered
|
||||
// with the newly saved note and the timestamp of that note will
|
||||
// be more recent that the one in the editor, which will trigger
|
||||
// an update. We do not want this since we already have the
|
||||
// latest changes.
|
||||
//
|
||||
// It also means that we manually set the timestamp, so that we
|
||||
// have it before the note is saved.
|
||||
const savedNote: any = await Note.save(note);
|
||||
|
||||
setFormNote((prev: FormNote) => {
|
||||
return {
|
||||
...prev,
|
||||
user_updated_time: noteUpdatedTime,
|
||||
updated_time: noteUpdatedTime,
|
||||
hasChanged: false,
|
||||
};
|
||||
return { ...prev, user_updated_time: savedNote.user_updated_time, hasChanged: false };
|
||||
});
|
||||
|
||||
const savedNote = await Note.save({
|
||||
...note,
|
||||
updated_time: noteUpdatedTime,
|
||||
}, { autoTimestamp: false });
|
||||
|
||||
void ExternalEditWatcher.instance().updateNoteFile(savedNote);
|
||||
|
||||
props.dispatch({
|
||||
|
@ -5,7 +5,6 @@ import { MarkupLanguage } from '@joplin/renderer';
|
||||
import { RenderResult, RenderResultPluginAsset } from '@joplin/renderer/MarkupToHtml';
|
||||
import { MarkupToHtmlOptions } from './useMarkupToHtml';
|
||||
import { Dispatch } from 'redux';
|
||||
import { NoteEntity } from '@joplin/lib/services/database/types';
|
||||
|
||||
export interface AllAssetsOptions {
|
||||
contentMaxWidthTarget?: string;
|
||||
@ -21,7 +20,7 @@ export interface NoteEditorProps {
|
||||
dispatch: Dispatch;
|
||||
selectedNoteIds: string[];
|
||||
selectedFolderId: string;
|
||||
notes: NoteEntity[];
|
||||
notes: any[];
|
||||
watchedNoteFiles: string[];
|
||||
isProvisional: boolean;
|
||||
editorNoteStatuses: any;
|
||||
@ -105,7 +104,6 @@ export interface FormNote {
|
||||
markup_language: number;
|
||||
user_updated_time: number;
|
||||
encryption_applied: number;
|
||||
updated_time: number;
|
||||
|
||||
hasChanged: boolean;
|
||||
|
||||
@ -156,7 +154,6 @@ export function defaultFormNote(): FormNote {
|
||||
hasChanged: false,
|
||||
user_updated_time: 0,
|
||||
encryption_applied: 0,
|
||||
updated_time: 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@ const defaultFormNoteProps: HookDependencies = {
|
||||
editorRef: null,
|
||||
onBeforeLoad: ()=>{},
|
||||
onAfterLoad: ()=>{},
|
||||
dbNote: { id: '', updated_time: 0 },
|
||||
};
|
||||
|
||||
describe('useFormNote', () => {
|
||||
|
@ -7,30 +7,21 @@ import { splitHtml } from '@joplin/renderer/HtmlToHtml';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import usePrevious from '../../hooks/usePrevious';
|
||||
import ResourceEditWatcher from '@joplin/lib/services/ResourceEditWatcher/index';
|
||||
import { MarkupToHtml } from '@joplin/renderer';
|
||||
|
||||
const { MarkupToHtml } = require('@joplin/renderer');
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import { reg } from '@joplin/lib/registry';
|
||||
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
||||
import DecryptionWorker from '@joplin/lib/services/DecryptionWorker';
|
||||
import { NoteEntity } from '@joplin/lib/services/database/types';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
|
||||
const logger = Logger.create('useFormNote');
|
||||
|
||||
export interface OnLoadEvent {
|
||||
formNote: FormNote;
|
||||
updated_time: number;
|
||||
}
|
||||
|
||||
export interface DbNote {
|
||||
id: string;
|
||||
updated_time: number;
|
||||
}
|
||||
|
||||
export interface HookDependencies {
|
||||
syncStarted: boolean;
|
||||
decryptionStarted: boolean;
|
||||
noteId: string;
|
||||
dbNote: DbNote;
|
||||
isProvisional: boolean;
|
||||
titleInputRef: any;
|
||||
editorRef: any;
|
||||
@ -72,7 +63,7 @@ function resourceInfosChanged(a: ResourceInfos, b: ResourceInfos): boolean {
|
||||
|
||||
export default function useFormNote(dependencies: HookDependencies) {
|
||||
const {
|
||||
syncStarted, decryptionStarted, noteId, isProvisional, titleInputRef, editorRef, onBeforeLoad, onAfterLoad, dbNote,
|
||||
syncStarted, decryptionStarted, noteId, isProvisional, titleInputRef, editorRef, onBeforeLoad, onAfterLoad,
|
||||
} = dependencies;
|
||||
|
||||
const [formNote, setFormNote] = useState<FormNote>(defaultFormNote());
|
||||
@ -86,7 +77,7 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
// a new refresh.
|
||||
const [formNoteRefeshScheduled, setFormNoteRefreshScheduled] = useState<number>(0);
|
||||
|
||||
async function initNoteState(n: NoteEntity) {
|
||||
async function initNoteState(n: any) {
|
||||
let originalCss = '';
|
||||
|
||||
if (n.markup_language === MarkupToHtml.MARKUP_LANGUAGE_HTML) {
|
||||
@ -94,7 +85,7 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
originalCss = splitted.css;
|
||||
}
|
||||
|
||||
const newFormNote: FormNote = {
|
||||
const newFormNote = {
|
||||
id: n.id,
|
||||
title: n.title,
|
||||
body: n.body,
|
||||
@ -108,7 +99,6 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
hasChanged: false,
|
||||
user_updated_time: n.user_updated_time,
|
||||
encryption_applied: n.encryption_applied,
|
||||
updated_time: n.updated_time,
|
||||
};
|
||||
|
||||
// Note that for performance reason,the call to setResourceInfos should
|
||||
@ -126,7 +116,7 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
useEffect(() => {
|
||||
if (formNoteRefeshScheduled <= 0) return () => {};
|
||||
|
||||
logger.info('Sync has finished and note has never been changed - reloading it');
|
||||
reg.logger().info('Sync has finished and note has never been changed - reloading it');
|
||||
|
||||
let cancelled = false;
|
||||
|
||||
@ -138,7 +128,7 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
// it would not have been loaded in the editor (due to note selection changing
|
||||
// on delete)
|
||||
if (!n) {
|
||||
logger.warn('Trying to reload note that has been deleted:', noteId);
|
||||
reg.logger().warn('Trying to reload note that has been deleted:', noteId);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -160,19 +150,19 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
}, [formNoteRefeshScheduled]);
|
||||
|
||||
useEffect(() => {
|
||||
// Check that synchronisation has just finished - and if the note has
|
||||
// never been changed, we reload it. If the note has already been
|
||||
// changed, it's a conflict that's already been handled by the
|
||||
// synchronizer.
|
||||
// Check that synchronisation has just finished - and
|
||||
// if the note has never been changed, we reload it.
|
||||
// If the note has already been changed, it's a conflict
|
||||
// that's already been handled by the synchronizer.
|
||||
const decryptionJustEnded = prevDecryptionStarted && !decryptionStarted;
|
||||
const syncJustEnded = prevSyncStarted && !syncStarted;
|
||||
|
||||
if (!decryptionJustEnded && !syncJustEnded) return;
|
||||
if (formNote.hasChanged) return;
|
||||
|
||||
// Refresh the form note. This is kept separate from the above logic so
|
||||
// that when prevSyncStarted is changed from true to false, it doesn't
|
||||
// cancel the note from loading.
|
||||
// Refresh the form note.
|
||||
// This is kept separate from the above logic so that when prevSyncStarted is changed
|
||||
// from true to false, it doesn't cancel the note from loading.
|
||||
refreshFormNote();
|
||||
}, [
|
||||
prevSyncStarted, syncStarted,
|
||||
@ -180,18 +170,6 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
formNote.hasChanged, refreshFormNote,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
// Something's not fully initialised - we skip the check
|
||||
if (!dbNote.id || !dbNote.updated_time || !formNote.updated_time) return;
|
||||
|
||||
// If the note in the database is more recent that the note in editor,
|
||||
// it was modified outside the editor, so we refresh it.
|
||||
if (dbNote.id === formNote.id && dbNote.updated_time > formNote.updated_time) {
|
||||
logger.info('Note has been changed outside the editor - reloading it');
|
||||
refreshFormNote();
|
||||
}
|
||||
}, [dbNote.id, dbNote.updated_time, formNote.updated_time, formNote.id, refreshFormNote]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!noteId) {
|
||||
if (formNote.id) setFormNote(defaultFormNote());
|
||||
@ -202,7 +180,7 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
|
||||
let cancelled = false;
|
||||
|
||||
logger.debug('Loading existing note', noteId);
|
||||
reg.logger().debug('Loading existing note', noteId);
|
||||
|
||||
function handleAutoFocus(noteIsTodo: boolean) {
|
||||
if (!isProvisional) return;
|
||||
@ -222,15 +200,15 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
const n = await Note.load(noteId);
|
||||
if (cancelled) return;
|
||||
if (!n) throw new Error(`Cannot find note with ID: ${noteId}`);
|
||||
logger.debug('Loaded note:', n);
|
||||
reg.logger().debug('Loaded note:', n);
|
||||
|
||||
await onBeforeLoad({ formNote, updated_time: 0 });
|
||||
await onBeforeLoad({ formNote });
|
||||
|
||||
const newFormNote = await initNoteState(n);
|
||||
|
||||
setIsNewNote(isProvisional);
|
||||
|
||||
await onAfterLoad({ formNote: newFormNote, updated_time: n.updated_time });
|
||||
await onAfterLoad({ formNote: newFormNote });
|
||||
|
||||
handleAutoFocus(!!n.is_todo);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user