Skip to content
This repository has been archived by the owner on Jun 15, 2022. It is now read-only.

Commit

Permalink
fix: protected note selection on tablets (#628)
Browse files Browse the repository at this point in the history
  • Loading branch information
moughxyz committed May 31, 2022
1 parent 30333f2 commit 229528c
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 192 deletions.
3 changes: 2 additions & 1 deletion .prettierrc.js
Expand Up @@ -6,5 +6,6 @@ module.exports = {
semi: false,
singleQuote: true,
tabWidth: 2,
printWidth: 120
printWidth: 120,
trailingComma: 'all',
}
6 changes: 3 additions & 3 deletions package.json
Expand Up @@ -35,14 +35,14 @@
"@react-navigation/native": "^6.0.10",
"@react-navigation/stack": "^6.2.1",
"@standardnotes/components": "^1.8.2",
"@standardnotes/filepicker": "^1.16.2",
"@standardnotes/filepicker": "^1.16.5",
"@standardnotes/icons": "^1.1.8",
"@standardnotes/react-native-aes": "^1.4.3",
"@standardnotes/react-native-textview": "1.0.2",
"@standardnotes/react-native-utils": "1.0.1",
"@standardnotes/sncrypto-common": "1.9.0",
"@standardnotes/snjs": "2.114.1",
"@standardnotes/stylekit": "5.29.2",
"@standardnotes/snjs": "2.114.6",
"@standardnotes/stylekit": "5.29.3",
"@types/styled-components-react-native": "5.1.3",
"js-base64": "^3.7.2",
"moment": "^2.29.2",
Expand Down
8 changes: 4 additions & 4 deletions src/Lib/ApplicationState.ts
Expand Up @@ -118,7 +118,7 @@ export class ApplicationState extends ApplicationService {

this.removeHandleReactNativeAppStateChangeListener = AppState.addEventListener(
'change',
this.handleReactNativeAppStateChange
this.handleReactNativeAppStateChange,
)

this.keyboardDidShowListener = Keyboard.addListener('keyboardWillShow', this.keyboardDidShow)
Expand Down Expand Up @@ -389,7 +389,7 @@ export class ApplicationState extends ApplicationService {
this.selectedTag = matchingTag as SNTag
}
}
}
},
)
}

Expand Down Expand Up @@ -527,7 +527,7 @@ export class ApplicationState extends ApplicationService {
const challenge = new Challenge(
[new ChallengePrompt(ChallengeValidation.Biometric)],
ChallengeReason.ApplicationUnlock,
false
false,
)
void this.application.promptForCustomChallenge(challenge)

Expand Down Expand Up @@ -640,7 +640,7 @@ export class ApplicationState extends ApplicationService {
public async getPasscodeKeyboardType(): Promise<PasscodeKeyboardType> {
return this.application.getValue(
MobileStorageKey.PasscodeKeyboardTypeKey,
StorageValueModes.Nonwrapped
StorageValueModes.Nonwrapped,
) as Promise<PasscodeKeyboardType>
}

Expand Down
173 changes: 89 additions & 84 deletions src/Screens/Notes/Notes.tsx
Expand Up @@ -31,46 +31,35 @@ type SearchOptions = {
}[]

export const Notes = React.memo(
({
shouldSplitLayout,
keyboardHeight,
}: {
shouldSplitLayout: boolean | undefined
keyboardHeight: number | undefined
}) => {
// Context
({ isInTabletMode, keyboardHeight }: { isInTabletMode: boolean | undefined; keyboardHeight: number | undefined }) => {
const application = useSafeApplicationContext()
const theme = useContext(ThemeContext)
const navigation = useNavigation<AppStackNavigationProp<typeof SCREEN_NOTES>['navigation']>()

/**
* Update sync status
*/
const [loading, decrypting, refreshing, startRefreshing] = useSyncStatus()
const [signedIn] = useSignedIn()

// State
const [sortBy, setSortBy] = useState<CollectionSortProperty>(() =>
application.getLocalPreferences().getValue(PrefKey.MobileSortNotesBy, CollectionSort.CreatedAt)
application.getLocalPreferences().getValue(PrefKey.MobileSortNotesBy, CollectionSort.CreatedAt),
)
const [sortReverse, setSortReverse] = useState<boolean>(() =>
application.getLocalPreferences().getValue(PrefKey.MobileSortNotesReverse, false)
application.getLocalPreferences().getValue(PrefKey.MobileSortNotesReverse, false),
)
const [hideDates, setHideDates] = useState<boolean>(() =>
application.getLocalPreferences().getValue(PrefKey.MobileNotesHideDate, false)
application.getLocalPreferences().getValue(PrefKey.MobileNotesHideDate, false),
)
const [hidePreviews, setHidePreviews] = useState<boolean>(() =>
application.getLocalPreferences().getValue(PrefKey.MobileNotesHideNotePreview, false)
application.getLocalPreferences().getValue(PrefKey.MobileNotesHideNotePreview, false),
)
const [hideEditorIcon, setHideEditorIcon] = useState<boolean>(() =>
application.getLocalPreferences().getValue(PrefKey.MobileNotesHideEditorIcon, false)
application.getLocalPreferences().getValue(PrefKey.MobileNotesHideEditorIcon, false),
)
const [notes, setNotes] = useState<SNNote[]>([])
const [selectedNoteId, setSelectedNoteId] = useState<SNNote['uuid']>()
const [searchText, setSearchText] = useState('')
const [searchOptions, setSearchOptions] = useState<SearchOptions>([])
const [includeProtectedNoteText, setIncludeProtectedNoteText] = useState<boolean>(
() => !(application.hasProtectionSources() && !application.hasUnprotectedAccessSession())
() => !(application.hasProtectionSources() && !application.hasUnprotectedAccessSession()),
)
const [includeArchivedNotes, setIncludeArchivedNotes] = useState<boolean>(false)
const [includeTrashedNotes, setIncludeTrashedNotes] = useState<boolean>(false)
Expand Down Expand Up @@ -104,12 +93,12 @@ export const Notes = React.memo(
subTitle,
})
},
[application, navigation, searchText]
[application, navigation, searchText],
)

const openCompose = useCallback(
(newNote: boolean, noteUuid: UuidString, replaceScreen = false) => {
if (!shouldSplitLayout) {
if (!isInTabletMode) {
if (replaceScreen) {
navigation.replace(SCREEN_COMPOSE, {
title: newNote ? 'Compose' : 'Note',
Expand All @@ -123,15 +112,15 @@ export const Notes = React.memo(
}
}
},
[navigation, shouldSplitLayout]
[navigation, isInTabletMode],
)

const openNote = useCallback(
async (noteUuid: SNNote['uuid'], replaceScreen = false) => {
await application.getAppState().openEditor(noteUuid)
openCompose(false, noteUuid, replaceScreen)
},
[application, openCompose]
[application, openCompose],
)

const onNoteSelect = useCallback(
Expand All @@ -144,11 +133,21 @@ export const Notes = React.memo(
})
}
if (await application.authorizeNoteAccess(note)) {
void openNote(noteUuid)
if (!isInTabletMode) {
await openNote(noteUuid)
} else {
/**
* @TODO: remove setTimeout after SNJS navigation feature
* https://app.asana.com/0/1201653402817596/1202360754617865
*/
setTimeout(async () => {
await openNote(noteUuid)
})
}
}
}
},
[application, navigation, openNote]
[application, isInTabletMode, navigation, openNote],
)

useEffect(() => {
Expand Down Expand Up @@ -192,7 +191,7 @@ export const Notes = React.memo(
},
includeProtected?: boolean,
includeArchived?: boolean,
includeTrashed?: boolean
includeTrashed?: boolean,
) => {
const tag = application.getAppState().selectedTag
const searchQuery =
Expand Down Expand Up @@ -228,7 +227,7 @@ export const Notes = React.memo(
sortBy,
sortReverse,
searchText,
]
],
)

const toggleIncludeProtected = useCallback(async () => {
Expand Down Expand Up @@ -315,7 +314,7 @@ export const Notes = React.memo(
void onNoteSelect(note.uuid)
}
},
[decrypting, getFirstSelectableNote, loading, onNoteSelect]
[decrypting, getFirstSelectableNote, loading, onNoteSelect],
)

const selectNextOrCreateNew = useCallback(
Expand All @@ -327,19 +326,19 @@ export const Notes = React.memo(
application.getAppState().closeActiveEditor()
}
},
[application, getFirstSelectableNote, onNoteSelect]
[application, getFirstSelectableNote, onNoteSelect],
)

const reloadNotes = useCallback(
(reselectNote?: boolean, tagChanged?: boolean, searchFilter?: string) => {
const tag = application.getAppState().selectedTag

if (!tag) {
return
}

reloadSearchOptions()

/** If no display options we set them initially */
if (!haveDisplayOptions.current) {
haveDisplayOptions.current = true
reloadNotesDisplayOptions()
Expand All @@ -351,30 +350,40 @@ export const Notes = React.memo(
setNotes(renderedNotes)
reloadTitle(renderedNotes, searchFilter)

if (reselectNote && application.getAppState().isTabletDevice) {
if (tagChanged) {
if (renderedNotes.length > 0) {
selectFirstNote(renderedNotes)
} else {
application.getAppState().closeActiveEditor()
}
if (!application.getAppState().isTabletDevice || !reselectNote) {
return
}

if (tagChanged) {
if (renderedNotes.length > 0) {
selectFirstNote(renderedNotes)
} else {
const activeNote = application.getAppState().getActiveNoteController()?.note

if (activeNote) {
const isTrashView =
application.getAppState().selectedTag instanceof SmartView &&
application.getAppState().selectedTag.uuid === SystemViewId.TrashedNotes
if (activeNote.trashed && !isTrashView) {
selectNextOrCreateNew(renderedNotes)
}
} else {
selectFirstNote(renderedNotes)
application.getAppState().closeActiveEditor()
}
} else {
const activeNote = application.getAppState().getActiveNoteController()?.note

if (activeNote) {
const isTrashView =
application.getAppState().selectedTag instanceof SmartView &&
application.getAppState().selectedTag.uuid === SystemViewId.TrashedNotes

if (activeNote.trashed && !isTrashView) {
selectNextOrCreateNew(renderedNotes)
}
} else {
selectFirstNote(renderedNotes)
}
}
},
[application, reloadNotesDisplayOptions, reloadSearchOptions, reloadTitle, selectFirstNote, selectNextOrCreateNew]
[
application,
reloadNotesDisplayOptions,
reloadSearchOptions,
reloadTitle,
selectFirstNote,
selectNextOrCreateNew,
],
)

const onNoteCreate = useCallback(async () => {
Expand All @@ -384,25 +393,6 @@ export const Notes = React.memo(
reloadNotes(true)
}, [application, notes.length, openCompose, reloadNotes])

const streamNotesAndTags = useCallback(() => {
const removeStreamNotes = application.streamItems([ContentType.Note], async () => {
/** If a note changes, it will be queried against the existing filter;
* we dont need to reload display options */
reloadNotes(true)
})

const removeStreamTags = application.streamItems([ContentType.Tag], async () => {
/** A tag could have changed its relationships, so we need to reload the filter */
reloadNotesDisplayOptions()
reloadNotes()
})

return () => {
removeStreamNotes()
removeStreamTags()
}
}, [application, reloadNotes, reloadNotesDisplayOptions])

const reloadPreferences = useCallback(async () => {
let newSortBy = application.getLocalPreferences().getValue(PrefKey.MobileSortNotesBy, CollectionSort.CreatedAt)

Expand Down Expand Up @@ -465,7 +455,7 @@ export const Notes = React.memo(
setSearchText(filter)
reloadNotes(undefined, undefined, filter)
},
[reloadNotes, reloadNotesDisplayOptions]
[reloadNotes, reloadNotesDisplayOptions],
)

useEffect(() => {
Expand All @@ -481,23 +471,38 @@ export const Notes = React.memo(
useFocusEffect(
useCallback(() => {
void reloadPreferences()
const removeAppStateChangeHandler = application.getAppState().addStateChangeObserver(state => {
if (state === AppStateType.TagChanged) {
reloadNotesDisplayOptions()
reloadNotes(true, true)
}
if (state === AppStateType.PreferencesChanged) {
void reloadPreferences()
}
})
const removeStreams = streamNotesAndTags()
}, [reloadPreferences]),
)

return () => {
removeAppStateChangeHandler()
removeStreams()
useEffect(() => {
const removeAppStateChangeHandler = application.getAppState().addStateChangeObserver(state => {
if (state === AppStateType.TagChanged) {
reloadNotesDisplayOptions()
reloadNotes(true, true)
}
}, [application, reloadNotes, reloadNotesDisplayOptions, reloadPreferences, streamNotesAndTags])
)
if (state === AppStateType.PreferencesChanged) {
void reloadPreferences()
}
})

const removeStreamNotes = application.streamItems([ContentType.Note], async () => {
/** If a note changes, it will be queried against the existing filter;
* we dont need to reload display options */
reloadNotes(true)
})

const removeStreamTags = application.streamItems([ContentType.Tag], async () => {
/** A tag could have changed its relationships, so we need to reload the filter */
reloadNotesDisplayOptions()
reloadNotes()
})

return () => {
removeStreamNotes()
removeStreamTags()
removeAppStateChangeHandler()
}
}, [application, reloadNotes, reloadNotesDisplayOptions, reloadPreferences])

return (
<>
Expand Down Expand Up @@ -534,5 +539,5 @@ export const Notes = React.memo(
/>
</>
)
}
},
)
6 changes: 3 additions & 3 deletions src/Screens/Root.styled.ts
Expand Up @@ -5,11 +5,11 @@ export const Container = styled.View`
flex-direction: row;
`
export const NotesContainer = styled.View<{
shouldSplitLayout?: boolean
isInTabletMode?: boolean
notesListCollapsed?: boolean
}>`
${({ shouldSplitLayout, notesListCollapsed, theme }) => {
return shouldSplitLayout
${({ isInTabletMode, notesListCollapsed, theme }) => {
return isInTabletMode
? css`
border-right-color: ${theme.stylekitBorderColor};
border-right-width: ${notesListCollapsed ? 0 : 1}px;
Expand Down

0 comments on commit 229528c

Please sign in to comment.