feat: handle android back button on android (#1656)
This commit is contained in:
21
packages/mobile/src/AndroidBackHandlerService.ts
Normal file
21
packages/mobile/src/AndroidBackHandlerService.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { AbstractService, InternalEventBus, ReactNativeToWebEvent } from '@standardnotes/snjs'
|
||||
import { BackHandler, NativeEventSubscription } from 'react-native'
|
||||
|
||||
export class AndroidBackHandlerService extends AbstractService<ReactNativeToWebEvent> {
|
||||
private removeListener: NativeEventSubscription
|
||||
|
||||
constructor() {
|
||||
const internalEventBus = new InternalEventBus()
|
||||
super(internalEventBus)
|
||||
|
||||
this.removeListener = BackHandler.addEventListener('hardwareBackPress', () => {
|
||||
void this.notifyEvent(ReactNativeToWebEvent.AndroidBackButtonPressed)
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
deinit() {
|
||||
this.removeListener.remove()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import AsyncStorage from '@react-native-community/async-storage'
|
||||
import { AndroidBackHandlerService } from '@Root/AndroidBackHandlerService'
|
||||
import SNReactNative from '@standardnotes/react-native-utils'
|
||||
import {
|
||||
ApplicationIdentifier,
|
||||
@@ -80,13 +81,18 @@ export class MobileDevice implements MobileDeviceInterface {
|
||||
public isDarkMode = false
|
||||
private crypto: SNReactNativeCrypto
|
||||
|
||||
constructor(private stateObserverService?: AppStateObserverService) {
|
||||
constructor(
|
||||
private stateObserverService?: AppStateObserverService,
|
||||
private androidBackHandlerService?: AndroidBackHandlerService,
|
||||
) {
|
||||
this.crypto = new SNReactNativeCrypto()
|
||||
}
|
||||
|
||||
deinit() {
|
||||
this.stateObserverService?.deinit()
|
||||
;(this.stateObserverService as unknown) = undefined
|
||||
this.androidBackHandlerService?.deinit()
|
||||
;(this.androidBackHandlerService as unknown) = undefined
|
||||
}
|
||||
|
||||
consoleLog(...args: any[]): void {
|
||||
@@ -542,4 +548,29 @@ export class MobileDevice implements MobileDeviceInterface {
|
||||
this.consoleLog(`${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
confirmAndExit() {
|
||||
Alert.alert(
|
||||
'Close app',
|
||||
'Do you want to close the app?',
|
||||
[
|
||||
{
|
||||
text: 'Cancel',
|
||||
style: 'cancel',
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
onPress: async () => {},
|
||||
},
|
||||
{
|
||||
text: 'Close',
|
||||
style: 'destructive',
|
||||
onPress: async () => {
|
||||
SNReactNative.exitApp()
|
||||
},
|
||||
},
|
||||
],
|
||||
{
|
||||
cancelable: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Keyboard, Platform } from 'react-native'
|
||||
import VersionInfo from 'react-native-version-info'
|
||||
import { WebView, WebViewMessageEvent } from 'react-native-webview'
|
||||
import pjson from '../package.json'
|
||||
import { AndroidBackHandlerService } from './AndroidBackHandlerService'
|
||||
import { AppStateObserverService } from './AppStateObserverService'
|
||||
|
||||
const LoggingEnabled = IsDev
|
||||
@@ -24,13 +25,23 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
|
||||
const webViewRef = useRef<WebView>(null)
|
||||
const sourceUri = (Platform.OS === 'android' ? 'file:///android_asset/' : '') + 'Web.bundle/src/index.html'
|
||||
const stateService = useMemo(() => new AppStateObserverService(), [])
|
||||
const device = useMemo(() => new MobileDevice(stateService), [stateService])
|
||||
const androidBackHandlerService = useMemo(() => new AndroidBackHandlerService(), [])
|
||||
const device = useMemo(
|
||||
() => new MobileDevice(stateService, androidBackHandlerService),
|
||||
[androidBackHandlerService, stateService],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const removeListener = stateService.addEventObserver((event: ReactNativeToWebEvent) => {
|
||||
const removeStateServiceListener = stateService.addEventObserver((event: ReactNativeToWebEvent) => {
|
||||
webViewRef.current?.postMessage(JSON.stringify({ reactNativeEvent: event, messageType: 'event' }))
|
||||
})
|
||||
|
||||
const removeBackHandlerServiceListener = androidBackHandlerService.addEventObserver(
|
||||
(event: ReactNativeToWebEvent) => {
|
||||
webViewRef.current?.postMessage(JSON.stringify({ reactNativeEvent: event, messageType: 'event' }))
|
||||
},
|
||||
)
|
||||
|
||||
const keyboardShowListener = Keyboard.addListener('keyboardWillShow', () => {
|
||||
device.reloadStatusBarStyle(false)
|
||||
})
|
||||
@@ -40,11 +51,12 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
|
||||
})
|
||||
|
||||
return () => {
|
||||
removeListener()
|
||||
removeStateServiceListener()
|
||||
removeBackHandlerServiceListener()
|
||||
keyboardShowListener.remove()
|
||||
keyboardHideListener.remove()
|
||||
}
|
||||
}, [webViewRef, stateService])
|
||||
}, [webViewRef, stateService, device, androidBackHandlerService])
|
||||
|
||||
useEffect(() => {
|
||||
const observer = device.addMobileWebEventReceiver((event) => {
|
||||
|
||||
Reference in New Issue
Block a user