refactor: component viewer use state for timeout so timeout isnt set if no render eventually occurs
This commit is contained in:
@@ -54,10 +54,6 @@ export abstract class PureComponent<P = PureComponentProps, S = PureComponentSta
|
|||||||
this.deinit()
|
this.deinit()
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
|
||||||
return <div>Must override</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
public get appState(): AppState {
|
public get appState(): AppState {
|
||||||
return this.application.getAppState()
|
return this.application.getAppState()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
} from '@standardnotes/snjs'
|
} from '@standardnotes/snjs'
|
||||||
import { WebApplication } from '@/UIModels/Application'
|
import { WebApplication } from '@/UIModels/Application'
|
||||||
import { FunctionalComponent } from 'preact'
|
import { FunctionalComponent } from 'preact'
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks'
|
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
|
||||||
import { observer } from 'mobx-react-lite'
|
import { observer } from 'mobx-react-lite'
|
||||||
import { OfflineRestricted } from '@/Components/ComponentView/OfflineRestricted'
|
import { OfflineRestricted } from '@/Components/ComponentView/OfflineRestricted'
|
||||||
import { UrlMissing } from '@/Components/ComponentView/UrlMissing'
|
import { UrlMissing } from '@/Components/ComponentView/UrlMissing'
|
||||||
@@ -25,7 +25,6 @@ interface IProps {
|
|||||||
componentViewer: ComponentViewer
|
componentViewer: ComponentViewer
|
||||||
requestReload?: (viewer: ComponentViewer, force?: boolean) => void
|
requestReload?: (viewer: ComponentViewer, force?: boolean) => void
|
||||||
onLoad?: (component: SNComponent) => void
|
onLoad?: (component: SNComponent) => void
|
||||||
manualDealloc?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,7 +38,7 @@ const MSToWaitAfterIframeLoadToAvoidFlicker = 35
|
|||||||
export const ComponentView: FunctionalComponent<IProps> = observer(
|
export const ComponentView: FunctionalComponent<IProps> = observer(
|
||||||
({ application, onLoad, componentViewer, requestReload }) => {
|
({ application, onLoad, componentViewer, requestReload }) => {
|
||||||
const iframeRef = useRef<HTMLIFrameElement>(null)
|
const iframeRef = useRef<HTMLIFrameElement>(null)
|
||||||
const excessiveLoadingTimeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)
|
const [loadTimeout, setLoadTimeout] = useState<ReturnType<typeof setTimeout> | undefined>(undefined)
|
||||||
|
|
||||||
const [hasIssueLoading, setHasIssueLoading] = useState(false)
|
const [hasIssueLoading, setHasIssueLoading] = useState(false)
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
@@ -88,7 +87,8 @@ export const ComponentView: FunctionalComponent<IProps> = observer(
|
|||||||
}
|
}
|
||||||
}, [hasIssueLoading, componentViewer, requestReload])
|
}, [hasIssueLoading, componentViewer, requestReload])
|
||||||
|
|
||||||
const handleIframeTakingTooLongToLoad = useCallback(async () => {
|
useEffect(() => {
|
||||||
|
const loadTimeout = setTimeout(() => {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
setHasIssueLoading(true)
|
setHasIssueLoading(true)
|
||||||
|
|
||||||
@@ -98,24 +98,25 @@ export const ComponentView: FunctionalComponent<IProps> = observer(
|
|||||||
} else {
|
} else {
|
||||||
document.addEventListener(VisibilityChangeKey, onVisibilityChange)
|
document.addEventListener(VisibilityChangeKey, onVisibilityChange)
|
||||||
}
|
}
|
||||||
}, [didAttemptReload, onVisibilityChange, componentViewer, requestReload])
|
|
||||||
|
|
||||||
useMemo(() => {
|
|
||||||
const loadTimeout = setTimeout(() => {
|
|
||||||
handleIframeTakingTooLongToLoad().catch(console.error)
|
|
||||||
}, MaxLoadThreshold)
|
}, MaxLoadThreshold)
|
||||||
|
|
||||||
excessiveLoadingTimeout.current = loadTimeout
|
setLoadTimeout(loadTimeout)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
excessiveLoadingTimeout.current && clearTimeout(excessiveLoadingTimeout.current)
|
if (loadTimeout) {
|
||||||
|
clearTimeout(loadTimeout)
|
||||||
}
|
}
|
||||||
}, [handleIframeTakingTooLongToLoad])
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [componentViewer])
|
||||||
|
|
||||||
const onIframeLoad = useCallback(() => {
|
const onIframeLoad = useCallback(() => {
|
||||||
const iframe = iframeRef.current as HTMLIFrameElement
|
const iframe = iframeRef.current as HTMLIFrameElement
|
||||||
const contentWindow = iframe.contentWindow as Window
|
const contentWindow = iframe.contentWindow as Window
|
||||||
excessiveLoadingTimeout.current && clearTimeout(excessiveLoadingTimeout.current)
|
|
||||||
|
if (loadTimeout) {
|
||||||
|
clearTimeout(loadTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
componentViewer.setWindow(contentWindow)
|
componentViewer.setWindow(contentWindow)
|
||||||
@@ -128,7 +129,7 @@ export const ComponentView: FunctionalComponent<IProps> = observer(
|
|||||||
setHasIssueLoading(false)
|
setHasIssueLoading(false)
|
||||||
onLoad?.(component)
|
onLoad?.(component)
|
||||||
}, MSToWaitAfterIframeLoadToAvoidFlicker)
|
}, MSToWaitAfterIframeLoadToAvoidFlicker)
|
||||||
}, [componentViewer, onLoad, component, excessiveLoadingTimeout])
|
}, [componentViewer, onLoad, component, loadTimeout])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const removeFeaturesChangedObserver = componentViewer.addEventObserver((event) => {
|
const removeFeaturesChangedObserver = componentViewer.addEventObserver((event) => {
|
||||||
|
|||||||
@@ -264,21 +264,26 @@ export class NoteView extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
let title = this.state.editorTitle,
|
let title = this.state.editorTitle,
|
||||||
text = this.state.editorText
|
text = this.state.editorText
|
||||||
|
|
||||||
if (isPayloadSourceRetrieved(source)) {
|
if (isPayloadSourceRetrieved(source)) {
|
||||||
title = note.title
|
title = note.title
|
||||||
text = note.text
|
text = note.text
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.editorTitle) {
|
if (!this.state.editorTitle) {
|
||||||
title = note.title
|
title = note.title
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.editorText) {
|
if (!this.state.editorText) {
|
||||||
text = note.text
|
text = note.text
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title !== this.state.editorTitle) {
|
if (title !== this.state.editorTitle) {
|
||||||
this.setState({
|
this.setState({
|
||||||
editorTitle: title,
|
editorTitle: title,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text !== this.state.editorText) {
|
if (text !== this.state.editorText) {
|
||||||
this.setState({
|
this.setState({
|
||||||
editorText: text,
|
editorText: text,
|
||||||
@@ -317,6 +322,7 @@ export class NoteView extends PureComponent<Props, State> {
|
|||||||
if (this.state.editorComponentViewer) {
|
if (this.state.editorComponentViewer) {
|
||||||
this.application.componentManager?.destroyComponentViewer(this.state.editorComponentViewer)
|
this.application.componentManager?.destroyComponentViewer(this.state.editorComponentViewer)
|
||||||
}
|
}
|
||||||
|
|
||||||
super.componentWillUnmount()
|
super.componentWillUnmount()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,12 +407,15 @@ export class NoteView extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
dismissProtectedWarning = async () => {
|
dismissProtectedWarning = async () => {
|
||||||
let showNoteContents = true
|
let showNoteContents = true
|
||||||
|
|
||||||
if (this.application.hasProtectionSources()) {
|
if (this.application.hasProtectionSources()) {
|
||||||
showNoteContents = await this.application.authorizeNoteAccess(this.note)
|
showNoteContents = await this.application.authorizeNoteAccess(this.note)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showNoteContents) {
|
if (!showNoteContents) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setShowProtectedOverlay(false)
|
this.setShowProtectedOverlay(false)
|
||||||
this.focusTitle()
|
this.focusTitle()
|
||||||
}
|
}
|
||||||
@@ -1021,6 +1030,7 @@ export class NoteView extends PureComponent<Props, State> {
|
|||||||
{this.state.editorComponentViewer && (
|
{this.state.editorComponentViewer && (
|
||||||
<div className="component-view">
|
<div className="component-view">
|
||||||
<ComponentView
|
<ComponentView
|
||||||
|
key={this.state.editorComponentViewer.identifier}
|
||||||
componentViewer={this.state.editorComponentViewer}
|
componentViewer={this.state.editorComponentViewer}
|
||||||
onLoad={this.onEditorComponentLoad}
|
onLoad={this.onEditorComponentLoad}
|
||||||
requestReload={this.editorComponentViewerRequestsReload}
|
requestReload={this.editorComponentViewerRequestsReload}
|
||||||
@@ -1099,7 +1109,6 @@ export class NoteView extends PureComponent<Props, State> {
|
|||||||
<ComponentView
|
<ComponentView
|
||||||
key={viewer.identifier}
|
key={viewer.identifier}
|
||||||
componentViewer={viewer}
|
componentViewer={viewer}
|
||||||
manualDealloc={true}
|
|
||||||
application={this.application}
|
application={this.application}
|
||||||
appState={this.appState}
|
appState={this.appState}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
SNTag,
|
SNTag,
|
||||||
SystemViewId,
|
SystemViewId,
|
||||||
} from '@standardnotes/snjs'
|
} from '@standardnotes/snjs'
|
||||||
import { action, computed, makeObservable, observable, reaction } from 'mobx'
|
import { action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'
|
||||||
import { AppState, AppStateEvent } from '.'
|
import { AppState, AppStateEvent } from '.'
|
||||||
import { WebApplication } from '../Application'
|
import { WebApplication } from '../Application'
|
||||||
import { AbstractState } from './AbstractState'
|
import { AbstractState } from './AbstractState'
|
||||||
@@ -228,7 +228,9 @@ export class NotesViewState extends AbstractState {
|
|||||||
|
|
||||||
this.notes = notes
|
this.notes = notes
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
this.renderedNotes = renderedNotes
|
this.renderedNotes = renderedNotes
|
||||||
|
})
|
||||||
|
|
||||||
await this.recomputeSelectionAfterNotesReload()
|
await this.recomputeSelectionAfterNotesReload()
|
||||||
|
|
||||||
@@ -258,7 +260,7 @@ export class NotesViewState extends AbstractState {
|
|||||||
|
|
||||||
const noteExistsInUpdatedResults = this.notes.find((note) => note.uuid === activeNote.uuid)
|
const noteExistsInUpdatedResults = this.notes.find((note) => note.uuid === activeNote.uuid)
|
||||||
if (!noteExistsInUpdatedResults && !isSearching) {
|
if (!noteExistsInUpdatedResults && !isSearching) {
|
||||||
this.application.noteControllerGroup.closeNoteController(activeController)
|
this.closeNoteController(activeController)
|
||||||
|
|
||||||
this.selectNextNote()
|
this.selectNextNote()
|
||||||
|
|
||||||
@@ -318,11 +320,12 @@ export class NotesViewState extends AbstractState {
|
|||||||
reloadPreferences = async () => {
|
reloadPreferences = async () => {
|
||||||
const freshDisplayOptions = {} as DisplayOptions
|
const freshDisplayOptions = {} as DisplayOptions
|
||||||
const currentSortBy = this.displayOptions.sortBy
|
const currentSortBy = this.displayOptions.sortBy
|
||||||
|
|
||||||
let sortBy = this.application.getPreference(PrefKey.SortNotesBy, CollectionSort.CreatedAt)
|
let sortBy = this.application.getPreference(PrefKey.SortNotesBy, CollectionSort.CreatedAt)
|
||||||
if (sortBy === CollectionSort.UpdatedAt || (sortBy as string) === 'client_updated_at') {
|
if (sortBy === CollectionSort.UpdatedAt || (sortBy as string) === 'client_updated_at') {
|
||||||
/** Use UserUpdatedAt instead */
|
|
||||||
sortBy = CollectionSort.UpdatedAt
|
sortBy = CollectionSort.UpdatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
freshDisplayOptions.sortBy = sortBy
|
freshDisplayOptions.sortBy = sortBy
|
||||||
freshDisplayOptions.sortReverse = this.application.getPreference(PrefKey.SortNotesReverse, false)
|
freshDisplayOptions.sortReverse = this.application.getPreference(PrefKey.SortNotesReverse, false)
|
||||||
freshDisplayOptions.showArchived = this.application.getPreference(PrefKey.NotesShowArchived, false)
|
freshDisplayOptions.showArchived = this.application.getPreference(PrefKey.NotesShowArchived, false)
|
||||||
@@ -468,17 +471,29 @@ export class NotesViewState extends AbstractState {
|
|||||||
|
|
||||||
selectNextNote = () => {
|
selectNextNote = () => {
|
||||||
const displayableNotes = this.notes
|
const displayableNotes = this.notes
|
||||||
|
|
||||||
const currentIndex = displayableNotes.findIndex((candidate) => {
|
const currentIndex = displayableNotes.findIndex((candidate) => {
|
||||||
return candidate.uuid === this.activeControllerNote?.uuid
|
return candidate.uuid === this.activeControllerNote?.uuid
|
||||||
})
|
})
|
||||||
|
|
||||||
if (currentIndex + 1 < displayableNotes.length) {
|
let nextIndex = currentIndex + 1
|
||||||
const nextNote = displayableNotes[currentIndex + 1]
|
|
||||||
|
while (nextIndex < displayableNotes.length) {
|
||||||
|
const nextNote = displayableNotes[nextIndex]
|
||||||
|
|
||||||
|
nextIndex++
|
||||||
|
|
||||||
|
if (nextNote.protected) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
this.selectNoteWithScrollHandling(nextNote).catch(console.error)
|
this.selectNoteWithScrollHandling(nextNote).catch(console.error)
|
||||||
|
|
||||||
const nextNoteElement = document.getElementById(`note-${nextNote.uuid}`)
|
const nextNoteElement = document.getElementById(`note-${nextNote.uuid}`)
|
||||||
|
|
||||||
nextNoteElement?.focus()
|
nextNoteElement?.focus()
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,20 +510,31 @@ export class NotesViewState extends AbstractState {
|
|||||||
selectPreviousNote = () => {
|
selectPreviousNote = () => {
|
||||||
const displayableNotes = this.notes
|
const displayableNotes = this.notes
|
||||||
|
|
||||||
if (this.activeControllerNote) {
|
if (!this.activeControllerNote) {
|
||||||
const currentIndex = displayableNotes.indexOf(this.activeControllerNote)
|
return
|
||||||
if (currentIndex - 1 >= 0) {
|
|
||||||
const previousNote = displayableNotes[currentIndex - 1]
|
|
||||||
this.selectNoteWithScrollHandling(previousNote).catch(console.error)
|
|
||||||
const previousNoteElement = document.getElementById(`note-${previousNote.uuid}`)
|
|
||||||
previousNoteElement?.focus()
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined
|
const currentIndex = displayableNotes.indexOf(this.activeControllerNote)
|
||||||
|
|
||||||
|
let previousIndex = currentIndex - 1
|
||||||
|
|
||||||
|
while (previousIndex >= 0) {
|
||||||
|
const previousNote = displayableNotes[previousIndex]
|
||||||
|
|
||||||
|
previousIndex--
|
||||||
|
|
||||||
|
if (previousNote.protected) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectNoteWithScrollHandling(previousNote).catch(console.error)
|
||||||
|
|
||||||
|
const previousNoteElement = document.getElementById(`note-${previousNote.uuid}`)
|
||||||
|
|
||||||
|
previousNoteElement?.focus()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setNoteFilterText = (text: string) => {
|
setNoteFilterText = (text: string) => {
|
||||||
@@ -543,10 +569,14 @@ export class NotesViewState extends AbstractState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private closeNoteController(controller: NoteViewController): void {
|
||||||
|
this.application.noteControllerGroup.closeNoteController(controller)
|
||||||
|
}
|
||||||
|
|
||||||
handleTagChange = () => {
|
handleTagChange = () => {
|
||||||
const activeNoteController = this.getActiveNoteController()
|
const activeNoteController = this.getActiveNoteController()
|
||||||
if (activeNoteController?.isTemplateNote) {
|
if (activeNoteController?.isTemplateNote) {
|
||||||
this.application.noteControllerGroup.closeNoteController(activeNoteController)
|
this.closeNoteController(activeNoteController)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resetScrollPosition()
|
this.resetScrollPosition()
|
||||||
@@ -591,7 +621,9 @@ export class NotesViewState extends AbstractState {
|
|||||||
if (this.searchSubmitted) {
|
if (this.searchSubmitted) {
|
||||||
this.searchSubmitted = false
|
this.searchSubmitted = false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.reloadNotesDisplayOptions()
|
this.reloadNotesDisplayOptions()
|
||||||
|
|
||||||
void this.reloadNotes()
|
void this.reloadNotes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user