mirror of
https://github.com/jellyfin/jellyfin-expo.git
synced 2025-02-18 21:37:50 +00:00
Merge pull request #204 from thornbill/android-back
Fix support for hardware back buttons
This commit is contained in:
commit
2039e77a2a
@ -4,11 +4,11 @@ root = true
|
|||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
|
|
||||||
[{*.js, *.json}]
|
[{*.js, *.json, *.staticjs}]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.js]
|
[{*.js, .staticjs}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
||||||
[*.json]
|
[*.json]
|
||||||
|
4
App.js
4
App.js
@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
|
|||||||
import { useStores } from './hooks/useStores';
|
import { useStores } from './hooks/useStores';
|
||||||
import AppNavigator from './navigation/AppNavigator';
|
import AppNavigator from './navigation/AppNavigator';
|
||||||
import DarkTheme from './themes/dark';
|
import DarkTheme from './themes/dark';
|
||||||
import NativeShellLoader from './utils/NativeShellLoader';
|
import StaticScriptLoader from './utils/StaticScriptlLoader';
|
||||||
|
|
||||||
// Import i18n configuration
|
// Import i18n configuration
|
||||||
import './i18n';
|
import './i18n';
|
||||||
@ -89,7 +89,7 @@ const App = observer(({ skipLoadingScreen }) => {
|
|||||||
...Ionicons.font
|
...Ionicons.font
|
||||||
}),
|
}),
|
||||||
...loadImagesAsync(),
|
...loadImagesAsync(),
|
||||||
NativeShellLoader.load()
|
StaticScriptLoader.load()
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
31
assets/js/ExpoRouterShim.staticjs
Normal file
31
assets/js/ExpoRouterShim.staticjs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -3,6 +3,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function postExpoEvent(event, data) {
|
function postExpoEvent(event, data) {
|
||||||
window.ReactNativeWebView.postMessage(JSON.stringify({
|
window.ReactNativeWebView.postMessage(JSON.stringify({
|
||||||
event: event,
|
event: event,
|
||||||
@ -13,6 +14,7 @@ function postExpoEvent(event, data) {
|
|||||||
// List of supported features as reported in Safari
|
// List of supported features as reported in Safari
|
||||||
const ExpoSupportedFeatures = [
|
const ExpoSupportedFeatures = [
|
||||||
// 'filedownload',
|
// 'filedownload',
|
||||||
|
'exit',
|
||||||
'exitmenu',
|
'exitmenu',
|
||||||
'plugins',
|
'plugins',
|
||||||
'externallinks',
|
'externallinks',
|
||||||
|
@ -11,10 +11,10 @@ import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
|
|||||||
|
|
||||||
import { useStores } from '../hooks/useStores';
|
import { useStores } from '../hooks/useStores';
|
||||||
import { getAppName, getSafeDeviceName } from '../utils/Device';
|
import { getAppName, getSafeDeviceName } from '../utils/Device';
|
||||||
import NativeShellLoader from '../utils/NativeShellLoader';
|
import StaticScriptLoader from '../utils/StaticScriptlLoader';
|
||||||
import { openBrowser } from '../utils/WebBrowser';
|
import { openBrowser } from '../utils/WebBrowser';
|
||||||
import RefreshWebView from './RefreshWebView';
|
import RefreshWebView from './RefreshWebView';
|
||||||
import { Platform } from 'react-native';
|
import { BackHandler, Platform } from 'react-native';
|
||||||
|
|
||||||
const NativeShellWebView = observer(React.forwardRef(
|
const NativeShellWebView = observer(React.forwardRef(
|
||||||
function NativeShellWebView(props, ref) {
|
function NativeShellWebView(props, ref) {
|
||||||
@ -31,7 +31,9 @@ window.ExpoAppInfo = {
|
|||||||
deviceName: '${getSafeDeviceName().replace(/'/g, '\\\'')}'
|
deviceName: '${getSafeDeviceName().replace(/'/g, '\\\'')}'
|
||||||
};
|
};
|
||||||
|
|
||||||
${NativeShellLoader.NativeShell}
|
${StaticScriptLoader.scripts.NativeShell}
|
||||||
|
|
||||||
|
${StaticScriptLoader.scripts.ExpoRouterShim}
|
||||||
|
|
||||||
true;
|
true;
|
||||||
`;
|
`;
|
||||||
@ -48,6 +50,9 @@ true;
|
|||||||
try {
|
try {
|
||||||
const { event, data } = JSON.parse(state.data);
|
const { event, data } = JSON.parse(state.data);
|
||||||
switch (event) {
|
switch (event) {
|
||||||
|
case 'AppHost.exit':
|
||||||
|
BackHandler.exitApp();
|
||||||
|
break;
|
||||||
case 'enableFullscreen':
|
case 'enableFullscreen':
|
||||||
rootStore.isFullscreen = true;
|
rootStore.isFullscreen = true;
|
||||||
break;
|
break;
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/.
|
* 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 { 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 { ThemeContext } from 'react-native-elements';
|
||||||
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
|
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 { observer } from 'mobx-react';
|
||||||
|
|
||||||
import { useStores } from '../hooks/useStores';
|
import { useStores } from '../hooks/useStores';
|
||||||
@ -35,11 +35,24 @@ const HomeScreen = observer(() => {
|
|||||||
// Prevent default behavior
|
// Prevent default behavior
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// Call the web router to navigate home
|
// 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
|
// Clear the error state when the active server changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
@ -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;
|
|
32
utils/StaticScriptlLoader.js
Normal file
32
utils/StaticScriptlLoader.js
Normal 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;
|
Loading…
x
Reference in New Issue
Block a user