mirror of
https://github.com/standardnotes/mobile.git
synced 2026-05-24 14:34:31 -04:00
refactor: remove if (application) checks when application is initialized for sure (#583)
This commit is contained in:
15
src/App.tsx
15
src/App.tsx
@@ -145,15 +145,16 @@ export const App = (props: { env: TEnvironment }) => {
|
||||
return removeAppChangeObserver;
|
||||
}, [applicationGroupRef.current.primaryApplication]);
|
||||
|
||||
if (!application) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ApplicationContext.Provider value={application}>
|
||||
{application && (
|
||||
<AppComponent
|
||||
env={props.env}
|
||||
key={application.Uuid}
|
||||
application={application}
|
||||
/>
|
||||
)}
|
||||
<AppComponent
|
||||
env={props.env}
|
||||
key={application.Uuid}
|
||||
application={application}
|
||||
/>
|
||||
</ApplicationContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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<TAppStackNavigationProp>();
|
||||
@@ -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<string | undefined> => {
|
||||
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,
|
||||
() => {
|
||||
|
||||
8
src/hooks/useSafeApplicationContext.ts
Normal file
8
src/hooks/useSafeApplicationContext.ts
Normal file
@@ -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;
|
||||
};
|
||||
@@ -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<boolean>(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;
|
||||
|
||||
@@ -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<typeof SCREEN_INPUT_MODAL_FILE_NAME>;
|
||||
export const FileInputModal: FC<Props> = props => {
|
||||
const { file, handleFileAction } = props.route.params;
|
||||
const themeService = useContext(ThemeServiceContext);
|
||||
const application = useContext(ApplicationContext);
|
||||
const application = useSafeApplicationContext();
|
||||
|
||||
const fileNameInputRef = useRef<TextInput>(null);
|
||||
|
||||
const [fileName, setFileName] = useState(file.name);
|
||||
|
||||
const onSubmit = async () => {
|
||||
if (!application) {
|
||||
return;
|
||||
}
|
||||
const trimmedFileName = fileName.trim();
|
||||
if (trimmedFileName === '') {
|
||||
setFileName(file.name);
|
||||
|
||||
@@ -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<CollectionSort>(() =>
|
||||
application!
|
||||
application
|
||||
.getLocalPreferences()
|
||||
.getValue(PrefKey.SortNotesBy, CollectionSort.CreatedAt)
|
||||
);
|
||||
const [sortReverse, setSortReverse] = useState<boolean>(() =>
|
||||
application!
|
||||
application
|
||||
.getLocalPreferences()
|
||||
.getValue(PrefKey.SortNotesReverse, false)
|
||||
);
|
||||
const [hideDates, setHideDates] = useState<boolean>(() =>
|
||||
application!.getLocalPreferences().getValue(PrefKey.NotesHideDate, false)
|
||||
application.getLocalPreferences().getValue(PrefKey.NotesHideDate, false)
|
||||
);
|
||||
const [hidePreviews, setHidePreviews] = useState<boolean>(() =>
|
||||
application!
|
||||
application
|
||||
.getLocalPreferences()
|
||||
.getValue(PrefKey.NotesHideNotePreview, false)
|
||||
);
|
||||
const [hideEditorIcon, setHideEditorIcon] = useState<boolean>(() =>
|
||||
application!
|
||||
application
|
||||
.getLocalPreferences()
|
||||
.getValue(PrefKey.NotesHideEditorIcon, false)
|
||||
);
|
||||
@@ -92,8 +92,8 @@ export const Notes = React.memo(
|
||||
useState<boolean>(
|
||||
() =>
|
||||
!(
|
||||
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(
|
||||
<FAB
|
||||
// @ts-ignore style prop does not exist in types
|
||||
style={
|
||||
application?.getAppState().isInTabletMode
|
||||
application.getAppState().isInTabletMode
|
||||
? { bottom: keyboardHeight }
|
||||
: undefined
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
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, SCREEN_UPLOADED_FILES_LIST } from '@Screens/screens';
|
||||
import {
|
||||
FileItemContainer,
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from '@Screens/SideMenu/Files.styled';
|
||||
import { SideMenuOptionIconDescriptionType } from '@Screens/SideMenu/SideMenuSection';
|
||||
import { SNNote } from '@standardnotes/snjs';
|
||||
import React, { FC, useContext } from 'react';
|
||||
import React, { FC } from 'react';
|
||||
|
||||
type Props = {
|
||||
note: SNNote;
|
||||
@@ -22,7 +22,7 @@ type Props = {
|
||||
const MaximumVisibleFilesCount = 3;
|
||||
|
||||
export const Files: FC<Props> = ({ note }) => {
|
||||
const application = useContext(ApplicationContext);
|
||||
const application = useSafeApplicationContext();
|
||||
|
||||
const navigation =
|
||||
useNavigation<
|
||||
@@ -30,10 +30,6 @@ export const Files: FC<Props> = ({ note }) => {
|
||||
>();
|
||||
const { showActionsMenu, attachedFiles } = useFiles({ note });
|
||||
|
||||
if (!application) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const openFilesScreen = () => {
|
||||
navigation.navigate(SCREEN_UPLOADED_FILES_LIST, { note });
|
||||
};
|
||||
|
||||
@@ -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<ListedAccountInfo, 'display_name'>;
|
||||
|
||||
export const Listed: FC<TProps> = ({ 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<TProps> = ({ 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<TProps> = ({ 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<TProps> = ({ note }) => {
|
||||
}, [application, getListedAccountsDetails]);
|
||||
|
||||
const registerNewAccount = useCallback(() => {
|
||||
if (!application || isRequestingAccount) {
|
||||
if (isRequestingAccount) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -125,9 +119,6 @@ export const Listed: FC<TProps> = ({ 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<TProps> = ({ note }) => {
|
||||
);
|
||||
};
|
||||
|
||||
if (!application) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
{isLoading && <ActivityIndicator style={styles.loadingIndicator} />}
|
||||
|
||||
@@ -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<SNComponent[]>([]);
|
||||
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<typeof SCREEN_COMPOSE>['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();
|
||||
|
||||
@@ -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<typeof SCREEN_COMPOSE>['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<SNTag | SmartView> = ({ item }) => {
|
||||
if (!application) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let title = item.deleted ? 'Deleting...' : item.title;
|
||||
if (item.errorDecrypting) {
|
||||
title = 'Unable to Decrypt';
|
||||
|
||||
@@ -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<UploadedFileItemProps> = ({ 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<UploadedFileItemProps> = ({ file, note }) => {
|
||||
setFileName(file.name);
|
||||
}, [file.name]);
|
||||
|
||||
if (!application) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const iconType = application.iconsController.getIconForFileType(
|
||||
file.mimeType
|
||||
);
|
||||
|
||||
@@ -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<typeof SCREEN_UPLOADED_FILES_LIST>;
|
||||
|
||||
export const UploadedFilesList: FC<Props> = props => {
|
||||
const application = useContext(ApplicationContext);
|
||||
const styles = useUploadedFilesListStyles();
|
||||
const navigation = useNavigation();
|
||||
|
||||
@@ -54,16 +51,12 @@ export const UploadedFilesList: FC<Props> = 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> = props => {
|
||||
[scrollListToTop]
|
||||
);
|
||||
|
||||
if (!application) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { AttachedFiles, AllFiles } = Tabs;
|
||||
const {
|
||||
centeredView,
|
||||
|
||||
Reference in New Issue
Block a user