From bb6e4e5b079f190ec9db8b797411a290c81f375b Mon Sep 17 00:00:00 2001 From: Vardan Hakobyan Date: Tue, 5 Apr 2022 16:48:50 +0400 Subject: [PATCH] refactor: remove `if (application)` checks when application is initialized for sure (#583) --- src/App.tsx | 15 +-- src/hooks/useFiles.ts | 43 +-------- src/hooks/useSafeApplicationContext.ts | 8 ++ src/lib/snjs_helper_hooks.ts | 55 +++++------ src/screens/InputModal/FileInputModal.tsx | 7 +- src/screens/Notes/Notes.tsx | 94 +++++++++---------- src/screens/SideMenu/Files.tsx | 10 +- src/screens/SideMenu/Listed.tsx | 20 +--- src/screens/SideMenu/NoteSideMenu.tsx | 25 ++--- src/screens/SideMenu/TagSelectionList.tsx | 18 +--- .../UploadedFilesList/UploadedFileItem.tsx | 8 +- .../UploadedFilesList/UploadedFilesList.tsx | 13 +-- 12 files changed, 119 insertions(+), 197 deletions(-) create mode 100644 src/hooks/useSafeApplicationContext.ts diff --git a/src/App.tsx b/src/App.tsx index f8d2d422..71b942bf 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -145,15 +145,16 @@ export const App = (props: { env: TEnvironment }) => { return removeAppChangeObserver; }, [applicationGroupRef.current.primaryApplication]); + if (!application) { + return null; + } return ( - {application && ( - - )} + ); }; diff --git a/src/hooks/useFiles.ts b/src/hooks/useFiles.ts index e0a4c7b4..03bf03fa 100644 --- a/src/hooks/useFiles.ts +++ b/src/hooks/useFiles.ts @@ -1,6 +1,6 @@ import { ToastType } from '@Lib/types'; import { useNavigation } from '@react-navigation/native'; -import { ApplicationContext } from '@Root/ApplicationContext'; +import { useSafeApplicationContext } from '@Root/hooks/useSafeApplicationContext'; import { SCREEN_INPUT_MODAL_FILE_NAME } from '@Screens/screens'; import { TAppStackNavigationProp } from '@Screens/UploadedFilesList/UploadedFileItem'; import { @@ -15,7 +15,7 @@ import { SNNote, } from '@standardnotes/snjs'; import { useCustomActionSheet } from '@Style/custom_action_sheet'; -import { useCallback, useContext, useEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { Platform } from 'react-native'; import FileViewer from 'react-native-file-viewer'; import RNFS, { exists } from 'react-native-fs'; @@ -41,7 +41,7 @@ export const isFileTypePreviewable = (fileType: string) => { }; export const useFiles = ({ note }: Props) => { - const application = useContext(ApplicationContext); + const application = useSafeApplicationContext(); const { showActionSheet } = useCustomActionSheet(); const navigation = useNavigation(); @@ -53,9 +53,6 @@ export const useFiles = ({ note }: Props) => { const { Success, Info, Error } = ToastType; const reloadAttachedFiles = useCallback(() => { - if (!application || !note) { - return []; - } setAttachedFiles( application.items .getFilesForNote(note) @@ -64,9 +61,6 @@ export const useFiles = ({ note }: Props) => { }, [application, note]); const reloadAllFiles = useCallback(() => { - if (!application) { - return []; - } setAllFiles( application.items .getItems(ContentType.File) @@ -87,7 +81,7 @@ export const useFiles = ({ note }: Props) => { file, saveInTempLocation = false, }: TDownloadFileAndReturnLocalPathParams): Promise => { - if (isDownloading || !application) { + if (isDownloading) { return; } const filesService = application.getFilesService(); @@ -148,9 +142,6 @@ export const useFiles = ({ note }: Props) => { const shareFile = useCallback( async (file: SNFile) => { - if (!application) { - return; - } const downloadedFilePath = await downloadFileAndReturnLocalPath({ file, saveInTempLocation: true, @@ -201,9 +192,6 @@ export const useFiles = ({ note }: Props) => { const attachFileToNote = useCallback( async (file: SNFile) => { - if (!application || !note) { - return; - } await application.items.associateFileWithNote(file, note); Toast.show({ type: Success, @@ -216,9 +204,6 @@ export const useFiles = ({ note }: Props) => { const detachFileFromNote = useCallback( async (file: SNFile) => { - if (!application || !note) { - return; - } await application.items.disassociateFileWithNote(file, note); Toast.show({ type: Success, @@ -232,9 +217,6 @@ export const useFiles = ({ note }: Props) => { const toggleFileProtection = useCallback( async (file: SNFile) => { try { - if (!application) { - return file.protected; - } let result: SNFile | undefined; if (file.protected) { result = await application.mutator.unprotectFile(file); @@ -253,9 +235,6 @@ export const useFiles = ({ note }: Props) => { const authorizeProtectedActionForFile = useCallback( async (file: SNFile, challengeReason: ChallengeReason) => { - if (!application) { - return false; - } const authorizedFiles = await application.protections.authorizeProtectedActionForFiles( [file], @@ -268,9 +247,6 @@ export const useFiles = ({ note }: Props) => { const renameFile = useCallback( async (file: SNFile, fileName: string) => { - if (!application) { - return; - } await application.items.renameFile(file, fileName); }, [application] @@ -278,10 +254,6 @@ export const useFiles = ({ note }: Props) => { const previewFile = useCallback( async (file: SNFile) => { - if (!application) { - return; - } - let downloadedFilePath: string | undefined = ''; try { const isPreviewable = isFileTypePreviewable(file.mimeType); @@ -327,10 +299,6 @@ export const useFiles = ({ note }: Props) => { ); const handleFileAction = useCallback( async (action: UploadedFileItemAction) => { - if (!application) { - return false; - } - const file = action.type !== UploadedFileItemActionType.RenameFile ? action.payload @@ -395,9 +363,6 @@ export const useFiles = ({ note }: Props) => { ); useEffect(() => { - if (!application) { - return; - } const unregisterFileStream = application.streamItems( ContentType.File, () => { diff --git a/src/hooks/useSafeApplicationContext.ts b/src/hooks/useSafeApplicationContext.ts new file mode 100644 index 00000000..bd1c3c8a --- /dev/null +++ b/src/hooks/useSafeApplicationContext.ts @@ -0,0 +1,8 @@ +import { MobileApplication } from '@Lib/application'; +import { ApplicationContext } from '@Root/ApplicationContext'; +import { useContext } from 'react'; + +export const useSafeApplicationContext = () => { + const application = useContext(ApplicationContext) as MobileApplication; + return application; +}; diff --git a/src/lib/snjs_helper_hooks.ts b/src/lib/snjs_helper_hooks.ts index 0e260a6d..5f4f637c 100644 --- a/src/lib/snjs_helper_hooks.ts +++ b/src/lib/snjs_helper_hooks.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from '@Root/ApplicationContext'; +import { useSafeApplicationContext } from '@Root/hooks/useSafeApplicationContext'; import { SCREEN_NOTES } from '@Screens/screens'; import { ApplicationEvent, @@ -17,7 +18,7 @@ export const useSignedIn = ( signedOutCallback?: () => void ) => { // Context - const application = React.useContext(ApplicationContext); + const application = useSafeApplicationContext(); const [isLocked] = useIsLocked(); @@ -28,24 +29,22 @@ export const useSignedIn = ( let mounted = true; const getSignedIn = async () => { if (mounted && !isLocked) { - setSignedIn(!application?.noAccount()); + setSignedIn(!application.noAccount()); } }; getSignedIn(); - const removeSignedInObserver = application?.addEventObserver( - async event => { - if (event === ApplicationEvent.Launched) { - getSignedIn(); - } - if (event === ApplicationEvent.SignedIn) { - setSignedIn(true); - signedInCallback && signedInCallback(); - } else if (event === ApplicationEvent.SignedOut) { - setSignedIn(false); - signedOutCallback && signedOutCallback(); - } + const removeSignedInObserver = application.addEventObserver(async event => { + if (event === ApplicationEvent.Launched) { + getSignedIn(); } - ); + if (event === ApplicationEvent.SignedIn) { + setSignedIn(true); + signedInCallback && signedInCallback(); + } else if (event === ApplicationEvent.SignedOut) { + setSignedIn(false); + signedOutCallback && signedOutCallback(); + } + }); return () => { mounted = false; @@ -58,7 +57,7 @@ export const useSignedIn = ( export const useOutOfSync = () => { // Context - const application = React.useContext(ApplicationContext); + const application = useSafeApplicationContext(); // State const [outOfSync, setOutOfSync] = React.useState(false); @@ -66,7 +65,7 @@ export const useOutOfSync = () => { React.useEffect(() => { let isMounted = true; const getOutOfSync = async () => { - const outOfSyncInitial = await application?.sync.isOutOfSync(); + const outOfSyncInitial = await application.sync.isOutOfSync(); if (isMounted) { setOutOfSync(Boolean(outOfSyncInitial)); } @@ -78,15 +77,13 @@ export const useOutOfSync = () => { }, [application]); React.useEffect(() => { - const removeSignedInObserver = application?.addEventObserver( - async event => { - if (event === ApplicationEvent.EnteredOutOfSync) { - setOutOfSync(true); - } else if (event === ApplicationEvent.ExitedOutOfSync) { - setOutOfSync(false); - } + const removeSignedInObserver = application.addEventObserver(async event => { + if (event === ApplicationEvent.EnteredOutOfSync) { + setOutOfSync(true); + } else if (event === ApplicationEvent.ExitedOutOfSync) { + setOutOfSync(false); } - ); + }); return removeSignedInObserver; }, [application]); @@ -412,7 +409,7 @@ export const useChangeNoteChecks = ( editor: NoteViewController | undefined = undefined ) => { // Context - const application = React.useContext(ApplicationContext); + const application = useSafeApplicationContext(); const canChangeNote = useCallback(async () => { if (!note) { @@ -420,7 +417,7 @@ export const useChangeNoteChecks = ( } if (note.deleted) { - application?.alertService?.alert( + application.alertService?.alert( 'The note you are attempting to edit has been deleted, and is awaiting sync. Changes you make will be disregarded.' ); return false; @@ -430,8 +427,8 @@ export const useChangeNoteChecks = ( await editor.insertTemplatedNote(); } - if (!application?.items.findItem(note.uuid)) { - application?.alertService!.alert( + if (!application.items.findItem(note.uuid)) { + application.alertService!.alert( "The note you are attempting to save can not be found or has been deleted. Changes you make will not be synced. Please copy this note's text and start a new note." ); return false; diff --git a/src/screens/InputModal/FileInputModal.tsx b/src/screens/InputModal/FileInputModal.tsx index ddb8878a..97e50f86 100644 --- a/src/screens/InputModal/FileInputModal.tsx +++ b/src/screens/InputModal/FileInputModal.tsx @@ -1,7 +1,7 @@ import { ButtonCell } from '@Components/ButtonCell'; import { SectionedTableCell } from '@Components/SectionedTableCell'; import { TableSection } from '@Components/TableSection'; -import { ApplicationContext } from '@Root/ApplicationContext'; +import { useSafeApplicationContext } from '@Root/hooks/useSafeApplicationContext'; import { ModalStackNavigationProp } from '@Root/ModalStack'; import { SCREEN_INPUT_MODAL_FILE_NAME } from '@Screens/screens'; import { UploadedFileItemActionType } from '@Screens/UploadedFilesList/UploadedFileItemAction'; @@ -15,16 +15,13 @@ type Props = ModalStackNavigationProp; export const FileInputModal: FC = props => { const { file, handleFileAction } = props.route.params; const themeService = useContext(ThemeServiceContext); - const application = useContext(ApplicationContext); + const application = useSafeApplicationContext(); const fileNameInputRef = useRef(null); const [fileName, setFileName] = useState(file.name); const onSubmit = async () => { - if (!application) { - return; - } const trimmedFileName = fileName.trim(); if (trimmedFileName === '') { setFileName(file.name); diff --git a/src/screens/Notes/Notes.tsx b/src/screens/Notes/Notes.tsx index 07eb385e..9885b2f8 100644 --- a/src/screens/Notes/Notes.tsx +++ b/src/screens/Notes/Notes.tsx @@ -2,8 +2,8 @@ import { AppStateType } from '@Lib/application_state'; import { PrefKey } from '@Lib/preferences_manager'; import { useSignedIn, useSyncStatus } from '@Lib/snjs_helper_hooks'; import { useFocusEffect, useNavigation } from '@react-navigation/native'; -import { ApplicationContext } from '@Root/ApplicationContext'; import { AppStackNavigationProp } from '@Root/AppStack'; +import { useSafeApplicationContext } from '@Root/hooks/useSafeApplicationContext'; import { SCREEN_COMPOSE, SCREEN_NOTES, @@ -47,7 +47,7 @@ export const Notes = React.memo( keyboardHeight: number | undefined; }) => { // Context - const application = useContext(ApplicationContext); + const application = useSafeApplicationContext(); const theme = useContext(ThemeContext); const navigation = useNavigation< @@ -62,25 +62,25 @@ export const Notes = React.memo( // State const [sortBy, setSortBy] = useState(() => - application! + application .getLocalPreferences() .getValue(PrefKey.SortNotesBy, CollectionSort.CreatedAt) ); const [sortReverse, setSortReverse] = useState(() => - application! + application .getLocalPreferences() .getValue(PrefKey.SortNotesReverse, false) ); const [hideDates, setHideDates] = useState(() => - application!.getLocalPreferences().getValue(PrefKey.NotesHideDate, false) + application.getLocalPreferences().getValue(PrefKey.NotesHideDate, false) ); const [hidePreviews, setHidePreviews] = useState(() => - application! + application .getLocalPreferences() .getValue(PrefKey.NotesHideNotePreview, false) ); const [hideEditorIcon, setHideEditorIcon] = useState(() => - application! + application .getLocalPreferences() .getValue(PrefKey.NotesHideEditorIcon, false) ); @@ -92,8 +92,8 @@ export const Notes = React.memo( useState( () => !( - application!.hasProtectionSources() && - !application!.hasUnprotectedAccessSession() + application.hasProtectionSources() && + !application.hasUnprotectedAccessSession() ) ); const [includeArchivedNotes, setIncludeArchivedNotes] = @@ -106,8 +106,8 @@ export const Notes = React.memo( const haveDisplayOptions = useRef(false); const protectionsEnabled = useRef( - application!.hasProtectionSources() && - !application!.hasUnprotectedAccessSession() + application.hasProtectionSources() && + !application.hasUnprotectedAccessSession() ); const reloadTitle = useCallback( @@ -115,7 +115,7 @@ export const Notes = React.memo( let title = ''; let subTitle: string | undefined; - const selectedTag = application?.getAppState().selectedTag; + const selectedTag = application.getAppState().selectedTag; if (newNotes && (newFilter ?? searchText).length > 0) { const resultCount = newNotes.length; @@ -126,7 +126,7 @@ export const Notes = React.memo( } else if (selectedTag) { title = selectedTag.title; if (selectedTag instanceof SNTag && selectedTag.parentId) { - const parents = application!.items.getTagParentChain( + const parents = application.items.getTagParentChain( selectedTag.uuid ); const hierarchy = parents.map(tag => tag.title).join(' ⫽ '); @@ -161,7 +161,7 @@ export const Notes = React.memo( const openNote = useCallback( async (noteUuid: SNNote['uuid'], replaceScreen: boolean = false) => { - await application!.getAppState().openEditor(noteUuid); + await application.getAppState().openEditor(noteUuid); openCompose(false, replaceScreen); }, [application, openCompose] @@ -169,25 +169,25 @@ export const Notes = React.memo( const onNoteSelect = useCallback( async (noteUuid: SNNote['uuid']) => { - const note = application?.items.findItem(noteUuid) as SNNote; + const note = application.items.findItem(noteUuid) as SNNote; if (note) { if (note.errorDecrypting) { if (note.waitingForKey) { - return application?.presentKeyRecoveryWizard(); + return application.presentKeyRecoveryWizard(); } else { - return application?.alertService.alert( + return application.alertService.alert( 'Standard Notes was unable to decrypt this item. Please sign out of your account and back in to attempt to resolve this issue.', 'Unable to Decrypt' ); } } - if (note.protected && !application?.hasProtectionSources()) { + if (note.protected && !application.hasProtectionSources()) { return navigation.navigate(SCREEN_VIEW_PROTECTED_NOTE, { onPressView: () => openNote(noteUuid, true), }); } - if (await application?.authorizeNoteAccess(note)) { + if (await application.authorizeNoteAccess(note)) { openNote(noteUuid); } } @@ -209,7 +209,7 @@ export const Notes = React.memo( useEffect(() => { let mounted = true; const removeEditorObserver = - application?.editorGroup.addActiveControllerChangeObserver( + application.editorGroup.addActiveControllerChangeObserver( activeEditor => { if (mounted) { setSelectedNoteId(activeEditor?.note?.uuid); @@ -241,7 +241,7 @@ export const Notes = React.memo( includeArchived?: boolean, includeTrashed?: boolean ) => { - const tag = application!.getAppState().selectedTag; + const tag = application.getAppState().selectedTag; const searchQuery = searchText || searchFilter ? { @@ -270,7 +270,7 @@ export const Notes = React.memo( includeTrashed: applyFilters && (includeTrashed ?? includeTrashedNotes), }); - application!.items.setNotesDisplayCriteria(criteria); + application.items.setNotesDisplayCriteria(criteria); }, [ application, @@ -290,7 +290,7 @@ export const Notes = React.memo( if (includeProtected) { setIncludeProtectedStarted(true); allowToggling = - await application?.authorizeSearchingProtectedNotesText(); + await application.authorizeSearchingProtectedNotesText(); } setIncludeProtectedStarted(false); @@ -326,15 +326,15 @@ export const Notes = React.memo( const reloadSearchOptions = useCallback(() => { const protections = - application?.hasProtectionSources() && - !application!.hasUnprotectedAccessSession(); + application.hasProtectionSources() && + !application.hasUnprotectedAccessSession(); if (protections !== protectionsEnabled.current) { protectionsEnabled.current = !!protections; setIncludeProtectedNoteText(!protections); } - const selectedTag = application?.getAppState().selectedTag; + const selectedTag = application.getAppState().selectedTag; const options = [ { label: 'Include Protected Contents', @@ -398,7 +398,7 @@ export const Notes = React.memo( if (note) { onNoteSelect(note.uuid); } else { - application?.getAppState().closeActiveEditor(); + application.getAppState().closeActiveEditor(); } }, [application, getFirstSelectableNote, onNoteSelect] @@ -406,7 +406,7 @@ export const Notes = React.memo( const reloadNotes = useCallback( (reselectNote?: boolean, tagChanged?: boolean, searchFilter?: string) => { - const tag = application!.getAppState().selectedTag; + const tag = application.getAppState().selectedTag; if (!tag) { return; } @@ -419,7 +419,7 @@ export const Notes = React.memo( reloadNotesDisplayOptions(); } - const newNotes = application!.items.getDisplayableItems( + const newNotes = application.items.getDisplayableItems( ContentType.Note ) as SNNote[]; let renderedNotes: SNNote[] = newNotes; @@ -427,22 +427,22 @@ export const Notes = React.memo( setNotes(renderedNotes); reloadTitle(renderedNotes, searchFilter); - if (reselectNote && application?.getAppState().isTabletDevice) { + if (reselectNote && application.getAppState().isTabletDevice) { if (tagChanged) { if (renderedNotes.length > 0) { selectFirstNote(renderedNotes); } else { - application?.getAppState().closeActiveEditor(); + application.getAppState().closeActiveEditor(); } } else { const activeNote = application - ?.getAppState() + .getAppState() .getActiveNoteController()?.note; if (activeNote) { const discarded = activeNote.deleted || activeNote.trashed; const isTrashView = - application?.getAppState().selectedTag instanceof SmartView && - application?.getAppState().selectedTag.uuid === + application.getAppState().selectedTag instanceof SmartView && + application.getAppState().selectedTag.uuid === SystemViewId.TrashedNotes; if (discarded && !isTrashView) { selectNextOrCreateNew(renderedNotes); @@ -464,16 +464,16 @@ export const Notes = React.memo( ); const onNoteCreate = useCallback(async () => { - let title = application!.getAppState().isTabletDevice + let title = application.getAppState().isTabletDevice ? `Note ${notes.length + 1}` : undefined; - await application!.getAppState().createEditor(title); + await application.getAppState().createEditor(title); openCompose(true); reloadNotes(true); }, [application, notes.length, openCompose, reloadNotes]); const streamNotesAndTags = useCallback(() => { - const removeStreamNotes = application!.streamItems( + const removeStreamNotes = application.streamItems( [ContentType.Note], async () => { /** If a note changes, it will be queried against the existing filter; @@ -482,7 +482,7 @@ export const Notes = React.memo( } ); - const removeStreamTags = application!.streamItems( + const removeStreamTags = application.streamItems( [ContentType.Tag], async () => { /** A tag could have changed its relationships, so we need to reload the filter */ @@ -499,20 +499,20 @@ export const Notes = React.memo( const reloadPreferences = useCallback(async () => { const newSortBy = application - ?.getLocalPreferences() + .getLocalPreferences() .getValue(PrefKey.SortNotesBy, CollectionSort.CreatedAt); let displayOptionsChanged = false; const newSortReverse = application - ?.getLocalPreferences() + .getLocalPreferences() .getValue(PrefKey.SortNotesReverse, false); - const newHidePreview = application! + const newHidePreview = application .getLocalPreferences() .getValue(PrefKey.NotesHideNotePreview, false); - const newHideDate = application! + const newHideDate = application .getLocalPreferences() .getValue(PrefKey.NotesHideDate, false); - const newHideEditorIcon = application! + const newHideEditorIcon = application .getLocalPreferences() .getValue(PrefKey.NotesHideEditorIcon, false); @@ -557,7 +557,7 @@ export const Notes = React.memo( const onRefresh = useCallback(() => { startRefreshing(); - application?.sync.sync(); + application.sync.sync(); }, [application, startRefreshing]); const onSearchChange = useCallback( @@ -572,7 +572,7 @@ export const Notes = React.memo( useFocusEffect( useCallback(() => { reloadPreferences(); - const removeAppStateChangeHandler = application! + const removeAppStateChangeHandler = application .getAppState() .addStateChangeObserver(state => { if (state === AppStateType.TagChanged) { @@ -616,7 +616,7 @@ export const Notes = React.memo( hideDates={hideDates} hideEditorIcon={hideEditorIcon} selectedNoteId={ - application?.getAppState().isInTabletMode + application.getAppState().isInTabletMode ? selectedNoteId : undefined } @@ -627,7 +627,7 @@ export const Notes = React.memo( = ({ note }) => { - const application = useContext(ApplicationContext); + const application = useSafeApplicationContext(); const navigation = useNavigation< @@ -30,10 +30,6 @@ export const Files: FC = ({ note }) => { >(); const { showActionsMenu, attachedFiles } = useFiles({ note }); - if (!application) { - return null; - } - const openFilesScreen = () => { navigation.navigate(SCREEN_UPLOADED_FILES_LIST, { note }); }; diff --git a/src/screens/SideMenu/Listed.tsx b/src/screens/SideMenu/Listed.tsx index c07f8d58..96c3bbd0 100644 --- a/src/screens/SideMenu/Listed.tsx +++ b/src/screens/SideMenu/Listed.tsx @@ -1,5 +1,5 @@ import { SnIcon } from '@Components/SnIcon'; -import { ApplicationContext } from '@Root/ApplicationContext'; +import { useSafeApplicationContext } from '@Root/hooks/useSafeApplicationContext'; import { CantLoadActionsText, CreateBlogContainer, @@ -15,7 +15,7 @@ import { SNNote, } from '@standardnotes/snjs'; import { useCustomActionSheet } from '@Style/custom_action_sheet'; -import React, { FC, useCallback, useContext, useEffect, useState } from 'react'; +import React, { FC, useCallback, useEffect, useState } from 'react'; import { ActivityIndicator, FlatList, View } from 'react-native'; type TProps = { @@ -27,7 +27,7 @@ type TListedAccountItem = | Pick; export const Listed: FC = ({ note }) => { - const application = useContext(ApplicationContext); + const application = useSafeApplicationContext(); const [isLoading, setIsLoading] = useState(false); const [isActionInProgress, setIsActionInProgress] = useState(false); @@ -44,9 +44,6 @@ export const Listed: FC = ({ note }) => { const getListedAccountsDetails = useCallback( async (accounts: ListedAccount[]) => { - if (!application) { - return; - } const listedAccountsArray: TListedAccountItem[] = []; for (const listedAccountItem of accounts) { @@ -67,9 +64,6 @@ export const Listed: FC = ({ note }) => { ); const reloadListedAccounts = useCallback(async () => { - if (!application) { - return []; - } setIsLoading(true); const accounts = await application.getListedAccounts(); setListedAccounts(accounts); @@ -79,7 +73,7 @@ export const Listed: FC = ({ note }) => { }, [application, getListedAccountsDetails]); const registerNewAccount = useCallback(() => { - if (!application || isRequestingAccount) { + if (isRequestingAccount) { return; } @@ -125,9 +119,6 @@ export const Listed: FC = ({ note }) => { }; const showActionsMenu = (item: TListedAccountItem, index: number) => { - if (!application) { - return; - } if (!doesListedItemHaveActions(item)) { application.alertService.alert('Unable to load actions.'); return; @@ -163,9 +154,6 @@ export const Listed: FC = ({ note }) => { ); }; - if (!application) { - return null; - } return ( {isLoading && } diff --git a/src/screens/SideMenu/NoteSideMenu.tsx b/src/screens/SideMenu/NoteSideMenu.tsx index 0dc55439..e68e3617 100644 --- a/src/screens/SideMenu/NoteSideMenu.tsx +++ b/src/screens/SideMenu/NoteSideMenu.tsx @@ -7,8 +7,8 @@ import { import { isUnfinishedFeaturesEnabled } from '@Lib/utils'; import { useFocusEffect, useNavigation } from '@react-navigation/native'; import { TEnvironment } from '@Root/App'; -import { ApplicationContext } from '@Root/ApplicationContext'; import { AppStackNavigationProp } from '@Root/AppStack'; +import { useSafeApplicationContext } from '@Root/hooks/useSafeApplicationContext'; import { SCREEN_COMPOSE, SCREEN_INPUT_MODAL_TAG, @@ -80,12 +80,9 @@ type Props = { }; function useEditorComponents(): SNComponent[] { - const application = useContext(ApplicationContext); + const application = useSafeApplicationContext(); const [components, setComponents] = useState([]); useEffect(() => { - if (!application) { - return; - } const removeComponentsObserver = application.streamItems( ContentType.Component, () => { @@ -108,7 +105,7 @@ function useEditorComponents(): SNComponent[] { export const NoteSideMenu = React.memo((props: Props) => { // Context const theme = useContext(ThemeContext); - const application = useContext(ApplicationContext); + const application = useSafeApplicationContext(); const navigation = useNavigation< AppStackNavigationProp['navigation'] @@ -129,8 +126,6 @@ export const NoteSideMenu = React.memo((props: Props) => { ); useEffect(() => { - if (!application) return; - const removeEventObserver = application.addSingleEventObserver( ApplicationEvent.PreferencesChanged, async () => { @@ -155,7 +150,7 @@ export const NoteSideMenu = React.memo((props: Props) => { async () => { await application?.mutator.deleteItem(note!); props.drawerRef?.closeDrawer(); - if (!application?.getAppState().isInTabletMode) { + if (!application.getAppState().isInTabletMode) { navigation.popToTop(); } }, @@ -164,7 +159,7 @@ export const NoteSideMenu = React.memo((props: Props) => { mutator.trashed = true; }, false); props.drawerRef?.closeDrawer(); - if (!application?.getAppState().isInTabletMode) { + if (!application.getAppState().isInTabletMode) { navigation.popToTop(); } }, @@ -172,7 +167,7 @@ export const NoteSideMenu = React.memo((props: Props) => { ); useEffect(() => { - if (!application || !note) { + if (!note) { setAttachedFilesLength(0); return; } @@ -180,7 +175,7 @@ export const NoteSideMenu = React.memo((props: Props) => { }, [application, note]); useEffect(() => { - if (!application || !note) { + if (!note) { return; } const removeFilesObserver = application.streamItems( @@ -282,7 +277,7 @@ export const NoteSideMenu = React.memo((props: Props) => { const onEditorPress = useCallback( async (selectedComponent?: SNComponent) => { - if (!note || !application) { + if (!note) { return; } if (note?.locked) { @@ -413,7 +408,7 @@ export const NoteSideMenu = React.memo((props: Props) => { ); const editors = useMemo(() => { - if (!note || !application) { + if (!note) { return []; } const componentEditor = application.componentManager.editorForNote(note); @@ -606,7 +601,7 @@ export const NoteSideMenu = React.memo((props: Props) => { if (confirmed) { await application?.mutator.emptyTrash(); props.drawerRef?.closeDrawer(); - if (!application?.getAppState().isInTabletMode) { + if (!application.getAppState().isInTabletMode) { navigation.popToTop(); } application?.sync.sync(); diff --git a/src/screens/SideMenu/TagSelectionList.tsx b/src/screens/SideMenu/TagSelectionList.tsx index e45db430..d4a7eb73 100644 --- a/src/screens/SideMenu/TagSelectionList.tsx +++ b/src/screens/SideMenu/TagSelectionList.tsx @@ -1,6 +1,6 @@ import { useNavigation } from '@react-navigation/native'; -import { ApplicationContext } from '@Root/ApplicationContext'; import { AppStackNavigationProp } from '@Root/AppStack'; +import { useSafeApplicationContext } from '@Root/hooks/useSafeApplicationContext'; import { SCREEN_COMPOSE, SCREEN_INPUT_MODAL_TAG } from '@Screens/screens'; import { SideMenuOptionIconDescriptionType } from '@Screens/SideMenu/SideMenuSection'; import { @@ -11,13 +11,7 @@ import { SNTag, } from '@standardnotes/snjs'; import { useCustomActionSheet } from '@Style/custom_action_sheet'; -import React, { - useCallback, - useContext, - useEffect, - useRef, - useState, -} from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { FlatList, ListRenderItem } from 'react-native'; import { SideMenuCell } from './SideMenuCell'; import { EmptyPlaceholder } from './TagSelectionList.styled'; @@ -39,7 +33,7 @@ export const TagSelectionList = React.memo( hasBottomPadding, }: Props) => { // Context - const application = useContext(ApplicationContext); + const application = useSafeApplicationContext(); const navigation = useNavigation< AppStackNavigationProp['navigation'] @@ -124,7 +118,7 @@ export const TagSelectionList = React.memo( }; const isRootTag = (tag: SNTag | SmartView): boolean => - tag instanceof SmartView || !application?.items.getTagParent(tag.uuid); + tag instanceof SmartView || !application.items.getTagParent(tag.uuid); const showFolders = contentType === ContentType.Tag; const renderedTags = showFolders @@ -132,10 +126,6 @@ export const TagSelectionList = React.memo( : tags; const renderItem: ListRenderItem = ({ item }) => { - if (!application) { - return null; - } - let title = item.deleted ? 'Deleting...' : item.title; if (item.errorDecrypting) { title = 'Unable to Decrypt'; diff --git a/src/screens/UploadedFilesList/UploadedFileItem.tsx b/src/screens/UploadedFilesList/UploadedFileItem.tsx index 8800ec53..8fb18be2 100644 --- a/src/screens/UploadedFilesList/UploadedFileItem.tsx +++ b/src/screens/UploadedFilesList/UploadedFileItem.tsx @@ -1,7 +1,7 @@ import { SnIcon } from '@Components/SnIcon'; -import { ApplicationContext } from '@Root/ApplicationContext'; import { AppStackNavigationProp } from '@Root/AppStack'; import { useFiles } from '@Root/hooks/useFiles'; +import { useSafeApplicationContext } from '@Root/hooks/useSafeApplicationContext'; import { SCREEN_COMPOSE } from '@Screens/screens'; import { formatSizeToReadableString } from '@standardnotes/filepicker'; import { SNFile, SNNote } from '@standardnotes/snjs'; @@ -29,7 +29,7 @@ export type TAppStackNavigationProp = AppStackNavigationProp< >['navigation']; export const UploadedFileItem: FC = ({ file, note }) => { - const application = useContext(ApplicationContext); + const application = useSafeApplicationContext(); const theme = useContext(ThemeContext); const { showActionsMenu } = useFiles({ note }); @@ -40,10 +40,6 @@ export const UploadedFileItem: FC = ({ file, note }) => { setFileName(file.name); }, [file.name]); - if (!application) { - return null; - } - const iconType = application.iconsController.getIconForFileType( file.mimeType ); diff --git a/src/screens/UploadedFilesList/UploadedFilesList.tsx b/src/screens/UploadedFilesList/UploadedFilesList.tsx index 67e8a3df..4bb0c234 100644 --- a/src/screens/UploadedFilesList/UploadedFilesList.tsx +++ b/src/screens/UploadedFilesList/UploadedFilesList.tsx @@ -1,7 +1,6 @@ import { SearchBar } from '@Components/SearchBar'; import { SnIcon } from '@Components/SnIcon'; import { useNavigation } from '@react-navigation/native'; -import { ApplicationContext } from '@Root/ApplicationContext'; import { useFiles } from '@Root/hooks/useFiles'; import { ModalStackNavigationProp } from '@Root/ModalStack'; import { SCREEN_UPLOADED_FILES_LIST } from '@Screens/screens'; @@ -16,7 +15,6 @@ import { SNFile } from '@standardnotes/snjs'; import React, { FC, useCallback, - useContext, useEffect, useMemo, useRef, @@ -34,7 +32,6 @@ enum Tabs { type Props = ModalStackNavigationProp; export const UploadedFilesList: FC = props => { - const application = useContext(ApplicationContext); const styles = useUploadedFilesListStyles(); const navigation = useNavigation(); @@ -54,16 +51,12 @@ export const UploadedFilesList: FC = props => { currentTab === Tabs.AttachedFiles ? attachedFiles : allFiles; const filteredList = useMemo(() => { - if (!application) { - return []; - } - return searchString ? filesList.filter(file => file.name.toLowerCase().includes(searchString.toLowerCase()) ) : filesList; - }, [application, filesList, searchString]); + }, [filesList, searchString]); useEffect(() => { let screenTitle = 'Files'; @@ -91,10 +84,6 @@ export const UploadedFilesList: FC = props => { [scrollListToTop] ); - if (!application) { - return null; - } - const { AttachedFiles, AllFiles } = Tabs; const { centeredView,