Merge pull request #204 from thornbill/android-back

Fix support for hardware back buttons
This commit is contained in:
Bill Thornton 2021-01-07 09:05:16 -05:00 committed by GitHub
commit 2039e77a2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 94 additions and 32 deletions

View File

@ -4,11 +4,11 @@ root = true
insert_final_newline = true
end_of_line = lf
[{*.js, *.json}]
[{*.js, *.json, *.staticjs}]
charset = utf-8
trim_trailing_whitespace = true
[*.js]
[{*.js, .staticjs}]
indent_style = tab
[*.json]

4
App.js
View File

@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
import { useStores } from './hooks/useStores';
import AppNavigator from './navigation/AppNavigator';
import DarkTheme from './themes/dark';
import NativeShellLoader from './utils/NativeShellLoader';
import StaticScriptLoader from './utils/StaticScriptlLoader';
// Import i18n configuration
import './i18n';
@ -89,7 +89,7 @@ const App = observer(({ skipLoadingScreen }) => {
...Ionicons.font
}),
...loadImagesAsync(),
NativeShellLoader.load()
StaticScriptLoader.load()
]);
};

View File

@ -0,0 +1,31 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const getWebRouter = function() {
return window.Emby && window.Emby.Page;
};
window.ExpoRouterShim = {
back: function() {
const router = getWebRouter();
if (router) {
try {
if (router.canGoBack()) {
router.back();
} else {
window.NativeShell.AppHost.exit();
}
} catch (ex) {
console.error('[ExpoRouterShim] call to back() failed', ex);
}
}
},
home: function() {
const router = getWebRouter();
if (router && typeof router.goHome === 'function') {
router.goHome();
}
}
};

View File

@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function postExpoEvent(event, data) {
window.ReactNativeWebView.postMessage(JSON.stringify({
event: event,
@ -13,6 +14,7 @@ function postExpoEvent(event, data) {
// List of supported features as reported in Safari
const ExpoSupportedFeatures = [
// 'filedownload',
'exit',
'exitmenu',
'plugins',
'externallinks',

View File

@ -11,10 +11,10 @@ import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
import { useStores } from '../hooks/useStores';
import { getAppName, getSafeDeviceName } from '../utils/Device';
import NativeShellLoader from '../utils/NativeShellLoader';
import StaticScriptLoader from '../utils/StaticScriptlLoader';
import { openBrowser } from '../utils/WebBrowser';
import RefreshWebView from './RefreshWebView';
import { Platform } from 'react-native';
import { BackHandler, Platform } from 'react-native';
const NativeShellWebView = observer(React.forwardRef(
function NativeShellWebView(props, ref) {
@ -31,7 +31,9 @@ window.ExpoAppInfo = {
deviceName: '${getSafeDeviceName().replace(/'/g, '\\\'')}'
};
${NativeShellLoader.NativeShell}
${StaticScriptLoader.scripts.NativeShell}
${StaticScriptLoader.scripts.ExpoRouterShim}
true;
`;
@ -48,6 +50,9 @@ true;
try {
const { event, data } = JSON.parse(state.data);
switch (event) {
case 'AppHost.exit':
BackHandler.exitApp();
break;
case 'enableFullscreen':
rootStore.isFullscreen = true;
break;

View File

@ -3,12 +3,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import React, { useContext, useEffect, useState, useRef } from 'react';
import React, { useCallback, useContext, useEffect, useState, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { Platform, StyleSheet, View } from 'react-native';
import { BackHandler, Platform, StyleSheet, View } from 'react-native';
import { ThemeContext } from 'react-native-elements';
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
import { useNavigation } from '@react-navigation/native';
import { useFocusEffect, useNavigation } from '@react-navigation/native';
import { observer } from 'mobx-react';
import { useStores } from '../hooks/useStores';
@ -35,11 +35,24 @@ const HomeScreen = observer(() => {
// Prevent default behavior
e.preventDefault();
// Call the web router to navigate home
webview.current?.injectJavaScript('window.Emby && window.Emby.Page && typeof window.Emby.Page.goHome === "function" && window.Emby.Page.goHome();');
webview.current?.injectJavaScript('window.ExpoRouterShim && window.ExpoRouterShim.home();');
}
});
}, []);
useFocusEffect(
useCallback(() => {
const onBackPress = () => {
webview.current?.injectJavaScript('window.ExpoRouterShim && window.ExpoRouterShim.back();');
return true;
};
BackHandler.addEventListener('hardwareBackPress', onBackPress);
return () => BackHandler.removeEventListener('hardwareBackPress', onBackPress);
}, [webview])
);
// Clear the error state when the active server changes
useEffect(() => {
setIsLoading(true);

View File

@ -1,21 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { Asset } from 'expo-asset';
import { readAsStringAsync } from 'expo-file-system';
class Loader {
NativeShell = ''
async load() {
const [{ localUri }] = await Asset.loadAsync(require('../assets/js/NativeShell.staticjs'));
this.NativeShell = await readAsStringAsync(localUri);
return this.NativeShell;
}
}
const NativeShellLoader = new Loader();
export default NativeShellLoader;

View File

@ -0,0 +1,32 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { Asset } from 'expo-asset';
import { readAsStringAsync } from 'expo-file-system';
const loadStaticFile = async (asset) => {
const [{ localUri }] = await Asset.loadAsync(asset);
return await readAsStringAsync(localUri);
};
class Loader {
scripts = {
NativeShell: '',
ExpoRouterShim: ''
}
async load() {
// Load the NativeShell
this.scripts.NativeShell = await loadStaticFile(require('../assets/js/NativeShell.staticjs'));
// Load the RouterShim
this.scripts.ExpoRouterShim = await loadStaticFile(require('../assets/js/ExpoRouterShim.staticjs'));
return this.scripts;
}
}
const StaticScriptLoader = new Loader();
export default StaticScriptLoader;