feat: Editing large notes (greater than 1.5MB) will result in more optimized syncing, in which changes are saved locally immediately, but sync with the server less frequently (roughly every 30 seconds rather than after every change). (#2768)

This commit is contained in:
Aman Harwara
2024-01-20 15:22:09 +05:30
committed by GitHub
parent c6060aaab3
commit 396ee3f449
32 changed files with 408 additions and 163 deletions

View File

@@ -54,8 +54,6 @@ import ModalOverlay from '../Modal/ModalOverlay'
import NoteConflictResolutionModal from './NoteConflictResolutionModal/NoteConflictResolutionModal'
import Icon from '../Icon/Icon'
const MinimumStatusDuration = 400
function sortAlphabetically(array: ComponentInterface[]): ComponentInterface[] {
return array.sort((a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1))
}
@@ -83,6 +81,7 @@ type State = {
updateSavingIndicator?: boolean
editorFeatureIdentifier?: string
noteType?: NoteType
focusModeEnabled?: boolean
conflictedNotes: SNNote[]
showConflictResolutionModal: boolean
@@ -91,7 +90,6 @@ type State = {
class NoteView extends AbstractComponent<NoteViewProps, State> {
readonly controller!: NoteViewController
private statusTimeout?: NodeJS.Timeout
onEditorComponentLoad?: () => void
private removeTrashKeyObserver?: () => void
@@ -167,8 +165,6 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
;(this.ensureNoteIsInsertedBeforeUIAction as unknown) = undefined
this.onEditorComponentLoad = undefined
this.statusTimeout = undefined
;(this.onPanelResizeFinish as unknown) = undefined
;(this.authorizeAndDismissProtectedWarning as unknown) = undefined
;(this.editorComponentViewerRequestsReload as unknown) = undefined
@@ -235,9 +231,22 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
})
this.autorun(() => {
const syncStatus = this.controller.syncStatus
const isFocusModeEnabled = this.application.paneController.focusModeEnabled
const didFocusModeChange = this.state.focusModeEnabled !== isFocusModeEnabled
this.setState({
showProtectedWarning: this.application.notesController.showProtectedWarning,
noteStatus: syncStatus,
saveError: syncStatus?.type === 'error',
syncTakingTooLong: false,
focusModeEnabled: isFocusModeEnabled,
})
if (!isFocusModeEnabled && didFocusModeChange) {
this.controller.syncOnlyIfLargeNote()
}
})
this.reloadEditorComponent().catch(console.error)
@@ -327,16 +336,18 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
}
if (note.lastSyncBegan || note.dirty) {
const currentStatus = this.controller.syncStatus
const isWaitingToSyncLargeNote = currentStatus?.type === 'waiting'
if (note.lastSyncEnd) {
const shouldShowSavingStatus = note.lastSyncBegan && note.lastSyncBegan.getTime() > note.lastSyncEnd.getTime()
const hasStartedNewSync = note.lastSyncBegan && note.lastSyncBegan.getTime() > note.lastSyncEnd.getTime()
const shouldShowSavedStatus = note.lastSyncBegan && note.lastSyncEnd.getTime() > note.lastSyncBegan.getTime()
if (note.dirty || shouldShowSavingStatus) {
this.showSavingStatus()
} else if (this.state.noteStatus && shouldShowSavedStatus) {
this.showAllChangesSavedStatus()
if (hasStartedNewSync) {
this.controller.showSavingStatus()
} else if (this.state.noteStatus && shouldShowSavedStatus && !isWaitingToSyncLargeNote) {
this.controller.showAllChangesSavedStatus()
}
} else {
this.showSavingStatus()
} else if (note.lastSyncBegan) {
this.controller.showSavingStatus()
}
}
}
@@ -372,7 +383,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
const isInErrorState = this.state.saveError
/** if we're still dirty, don't change status, a sync is likely upcoming. */
if (!this.note.dirty && isInErrorState) {
this.showAllChangesSavedStatus()
this.controller.showAllChangesSavedStatus()
}
break
}
@@ -383,14 +394,14 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
* and we don't want to display an error here.
*/
if (this.note.dirty) {
this.showErrorStatus()
this.controller.showErrorSyncStatus()
}
break
case ApplicationEvent.LocalDatabaseWriteError:
this.showErrorStatus({
this.controller.showErrorSyncStatus({
type: 'error',
message: 'Offline Saving Issue',
desc: 'Changes not saved',
description: 'Changes not saved',
})
break
case ApplicationEvent.UnprotectedSessionBegan: {
@@ -551,59 +562,6 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
return this.application.actions.extensionsInContextOfItem(this.note).length > 0
}
showSavingStatus() {
this.setStatus({ type: 'saving', message: 'Saving…' }, false)
}
showAllChangesSavedStatus() {
this.setState({
saveError: false,
syncTakingTooLong: false,
})
this.setStatus({
type: 'saved',
message: 'All changes saved' + (this.application.sessions.isSignedOut() ? ' offline' : ''),
})
}
showErrorStatus(error?: NoteStatus) {
if (!error) {
error = {
type: 'error',
message: 'Sync Unreachable',
desc: 'Changes saved offline',
}
}
this.setState({
saveError: true,
syncTakingTooLong: false,
})
this.setStatus(error)
}
setStatus(status: NoteStatus, wait = true) {
if (this.statusTimeout) {
clearTimeout(this.statusTimeout)
}
if (wait) {
this.statusTimeout = setTimeout(() => {
this.setState({
noteStatus: status,
})
}, MinimumStatusDuration)
} else {
this.setState({
noteStatus: status,
})
}
}
cancelPendingSetStatus() {
if (this.statusTimeout) {
clearTimeout(this.statusTimeout)
}
}
onTitleEnter: KeyboardEventHandler<HTMLInputElement> = ({ key, currentTarget }) => {
if (key !== KeyboardKey.Enter) {
return
@@ -839,6 +797,10 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
}))
}
triggerSyncOnAction = () => {
this.controller.syncNow()
}
override render() {
if (this.controller.dealloced) {
return null
@@ -923,6 +885,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
/>
</div>
<NoteStatusIndicator
note={this.note}
status={this.state.noteStatus}
syncTakingTooLong={this.state.syncTakingTooLong}
updateSavingIndicator={this.state.updateSavingIndicator}
@@ -930,6 +893,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
</div>
{shouldShowConflictsButton && (
<Button
id={ElementIds.ConflictResolutionButton}
className="flex items-center"
primary
colorStyle="warning"
@@ -946,10 +910,12 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
<>
<LinkedItemsButton
linkingController={this.application.linkingController}
onClick={this.triggerSyncOnAction}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
<ChangeEditorButton
noteViewController={this.controller}
onClick={this.triggerSyncOnAction}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
<PinNoteButton
@@ -960,6 +926,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
)}
<NotesOptionsPanel
notesController={this.application.notesController}
onClick={this.triggerSyncOnAction}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
onButtonBlur={() => {
this.setState({