mirror of
https://github.com/jellyfin/jellyfin-expo.git
synced 2024-11-27 00:00:26 +00:00
Move NativeShell to asset file to read as a string
This commit is contained in:
parent
505b501706
commit
2e2c671a6b
@ -12,10 +12,6 @@
|
||||
"plugin:import/typescript",
|
||||
"plugin:eslint-comments/recommended"
|
||||
],
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
@ -55,5 +51,21 @@
|
||||
"semi": ["error"],
|
||||
"space-before-blocks": ["error"],
|
||||
"space-infix-ops": ["error"]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [ "./**/*.js" ],
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [ "./assets/**/*.staticjs" ],
|
||||
"env": {
|
||||
"node": false,
|
||||
"browser": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
4
App.js
4
App.js
@ -21,6 +21,7 @@ import { useStores } from './hooks/useStores';
|
||||
import Colors from './constants/Colors';
|
||||
import AppNavigator from './navigation/AppNavigator';
|
||||
import Theme from './utils/Theme';
|
||||
import NativeShellLoader from './utils/NativeShellLoader';
|
||||
|
||||
// Import i18n configuration
|
||||
import './i18n';
|
||||
@ -87,7 +88,8 @@ const App = observer(({ skipLoadingScreen }) => {
|
||||
// This is the font that we are using for our tab bar
|
||||
...Ionicons.font
|
||||
}),
|
||||
...loadImagesAsync()
|
||||
...loadImagesAsync(),
|
||||
NativeShellLoader.load()
|
||||
]);
|
||||
};
|
||||
|
||||
|
140
assets/js/NativeShell.staticjs
Normal file
140
assets/js/NativeShell.staticjs
Normal file
@ -0,0 +1,140 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
function postExpoEvent(event, data) {
|
||||
window.ReactNativeWebView.postMessage(JSON.stringify({
|
||||
event: event,
|
||||
data: data
|
||||
}));
|
||||
}
|
||||
|
||||
// List of supported features as reported in Safari
|
||||
const ExpoSupportedFeatures = [
|
||||
// 'filedownload',
|
||||
'exitmenu',
|
||||
'plugins',
|
||||
'externallinks',
|
||||
'externalpremium',
|
||||
'externallinkdisplay',
|
||||
'fullscreenchange',
|
||||
'physicalvolumecontrol',
|
||||
'remotecontrol',
|
||||
'remotevideo',
|
||||
'displaylanguage',
|
||||
'otherapppromotions',
|
||||
'displaymode',
|
||||
'subtitleappearancesettings',
|
||||
'subtitleburnsettings',
|
||||
'fileinput'
|
||||
];
|
||||
|
||||
window.console = Object.assign(window.console, {
|
||||
debug: text => postExpoEvent('console.debug', text),
|
||||
error: text => postExpoEvent('console.error', text),
|
||||
info: text => postExpoEvent('console.info', text),
|
||||
log: text => postExpoEvent('console.log', text),
|
||||
warn: text => postExpoEvent('console.warn', text)
|
||||
});
|
||||
|
||||
window.NativeShell = {
|
||||
AppHost: {
|
||||
init: function() {
|
||||
postExpoEvent('AppHost.init', window.ExpoAppInfo);
|
||||
return Promise.resolve(window.ExpoAppInfo);
|
||||
},
|
||||
|
||||
appName: function() {
|
||||
postExpoEvent('AppHost.appName', window.ExpoAppInfo.appName);
|
||||
return window.ExpoAppInfo.appName;
|
||||
},
|
||||
|
||||
appVersion: function() {
|
||||
postExpoEvent('AppHost.appVersion', window.ExpoAppInfo.appVersion);
|
||||
return window.ExpoAppInfo.appVersion;
|
||||
},
|
||||
|
||||
deviceId: function() {
|
||||
postExpoEvent('AppHost.deviceId', window.ExpoAppInfo.deviceId);
|
||||
return window.ExpoAppInfo.deviceId;
|
||||
},
|
||||
|
||||
deviceName: function() {
|
||||
postExpoEvent('AppHost.deviceName', window.ExpoAppInfo.deviceName);
|
||||
return window.ExpoAppInfo.deviceName;
|
||||
},
|
||||
|
||||
exit: function() {
|
||||
postExpoEvent('AppHost.exit');
|
||||
},
|
||||
|
||||
getDefaultLayout: function() {
|
||||
postExpoEvent('AppHost.getDefaultLayout', 'mobile');
|
||||
return 'mobile';
|
||||
},
|
||||
|
||||
getDeviceProfile: function(profileBuilder, profileBuilderVersion) {
|
||||
const audioCodecs = ['opus'];
|
||||
const versionNumber = profileBuilderVersion !== undefined && profileBuilderVersion.split('.').map(num => Number.parseInt(num, 10));
|
||||
const isAc3Eac3Disabled = profileBuilderVersion === undefined || (versionNumber.length === 3 && versionNumber[0] === 10 && versionNumber[1] < 7);
|
||||
if (isAc3Eac3Disabled) {
|
||||
audioCodecs.push('ac3');
|
||||
audioCodecs.push('eac3');
|
||||
}
|
||||
|
||||
postExpoEvent('AppHost.getDeviceProfile');
|
||||
return profileBuilder({
|
||||
enableMkvProgressive: false,
|
||||
disableHlsVideoAudioCodecs: audioCodecs
|
||||
});
|
||||
},
|
||||
|
||||
// Keep for support server versions < 10.7
|
||||
getSyncProfile: function() {
|
||||
postExpoEvent('AppHost.getSyncProfile');
|
||||
return Promise.resolve({});
|
||||
},
|
||||
|
||||
supports: function(command) {
|
||||
const isSupported = command && ExpoSupportedFeatures.indexOf(command.toLowerCase()) != -1;
|
||||
postExpoEvent('AppHost.supports', {
|
||||
command: command,
|
||||
isSupported: isSupported
|
||||
});
|
||||
return isSupported;
|
||||
}
|
||||
},
|
||||
|
||||
downloadFile: function(url) {
|
||||
postExpoEvent('downloadFile', { url: url });
|
||||
},
|
||||
|
||||
enableFullscreen: function() {
|
||||
postExpoEvent('enableFullscreen');
|
||||
},
|
||||
|
||||
disableFullscreen: function() {
|
||||
postExpoEvent('disableFullscreen');
|
||||
},
|
||||
|
||||
getPlugins: function() {
|
||||
postExpoEvent('getPlugins');
|
||||
return [];
|
||||
},
|
||||
|
||||
openUrl: function(url, target) {
|
||||
postExpoEvent('openUrl', {
|
||||
url: url,
|
||||
target: target
|
||||
});
|
||||
},
|
||||
|
||||
updateMediaSession: function(mediaInfo) {
|
||||
postExpoEvent('updateMediaSession', { mediaInfo: mediaInfo });
|
||||
},
|
||||
|
||||
hideMediaSession: function() {
|
||||
postExpoEvent('hideMediaSession');
|
||||
}
|
||||
};
|
@ -11,24 +11,11 @@ import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
|
||||
|
||||
import { useStores } from '../hooks/useStores';
|
||||
import { getAppName, getSafeDeviceName } from '../utils/Device';
|
||||
import NativeShell from '../utils/NativeShell';
|
||||
import NativeShellLoader from '../utils/NativeShellLoader';
|
||||
import { openBrowser } from '../utils/WebBrowser';
|
||||
import RefreshWebView from './RefreshWebView';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
const injectedJavaScript = `
|
||||
window.ExpoAppInfo = {
|
||||
appName: '${getAppName()}',
|
||||
appVersion: '${Constants.nativeAppVersion}',
|
||||
deviceId: '${Constants.deviceId}',
|
||||
deviceName: '${getSafeDeviceName().replace(/'/g, '\\\'')}'
|
||||
};
|
||||
|
||||
${NativeShell}
|
||||
|
||||
true;
|
||||
`;
|
||||
|
||||
const NativeShellWebView = observer(React.forwardRef(
|
||||
function NativeShellWebView(props, ref) {
|
||||
const { rootStore } = useStores();
|
||||
@ -36,6 +23,19 @@ const NativeShellWebView = observer(React.forwardRef(
|
||||
|
||||
const server = rootStore.serverStore.servers[rootStore.settingStore.activeServer];
|
||||
|
||||
const injectedJavaScript = `
|
||||
window.ExpoAppInfo = {
|
||||
appName: '${getAppName()}',
|
||||
appVersion: '${Constants.nativeAppVersion}',
|
||||
deviceId: '${Constants.deviceId}',
|
||||
deviceName: '${getSafeDeviceName().replace(/'/g, '\\\'')}'
|
||||
};
|
||||
|
||||
${NativeShellLoader.NativeShell}
|
||||
|
||||
true;
|
||||
`;
|
||||
|
||||
const onRefresh = () => {
|
||||
// Disable pull to refresh when in fullscreen
|
||||
if (rootStore.isFullscreen) return;
|
||||
|
17
metro.config.js
Normal file
17
metro.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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 { getDefaultConfig } = require('@expo/metro-config');
|
||||
|
||||
const defaultConfig = getDefaultConfig(__dirname);
|
||||
|
||||
module.exports = {
|
||||
resolver: {
|
||||
assetExts: [
|
||||
...defaultConfig.resolver.assetExts,
|
||||
'staticjs'
|
||||
]
|
||||
}
|
||||
};
|
@ -20,6 +20,7 @@
|
||||
"expo-asset": "~8.2.0",
|
||||
"expo-constants": "~9.2.0",
|
||||
"expo-device": "~2.3.0",
|
||||
"expo-file-system": "~9.2.0",
|
||||
"expo-font": "~8.3.0",
|
||||
"expo-keep-awake": "~8.3.0",
|
||||
"expo-localization": "~9.0.0",
|
||||
|
@ -1,146 +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/.
|
||||
*/
|
||||
/* eslint-env browser */
|
||||
|
||||
const NativeShell = `
|
||||
function postExpoEvent(event, data) {
|
||||
window.ReactNativeWebView.postMessage(JSON.stringify({
|
||||
event: event,
|
||||
data: data
|
||||
}));
|
||||
}
|
||||
|
||||
// List of supported features as reported in Safari
|
||||
const ExpoSupportedFeatures = [
|
||||
// 'filedownload',
|
||||
'exitmenu',
|
||||
'plugins',
|
||||
'externallinks',
|
||||
'externalpremium',
|
||||
'externallinkdisplay',
|
||||
'fullscreenchange',
|
||||
'physicalvolumecontrol',
|
||||
'remotecontrol',
|
||||
'remotevideo',
|
||||
'displaylanguage',
|
||||
'otherapppromotions',
|
||||
'displaymode',
|
||||
'subtitleappearancesettings',
|
||||
'subtitleburnsettings',
|
||||
'fileinput',
|
||||
];
|
||||
|
||||
window.console = Object.assign(window.console, {
|
||||
debug: text => postExpoEvent('console.debug', text),
|
||||
error: text => postExpoEvent('console.error', text),
|
||||
info: text => postExpoEvent('console.info', text),
|
||||
log: text => postExpoEvent('console.log', text),
|
||||
warn: text => postExpoEvent('console.warn', text)
|
||||
});
|
||||
|
||||
window.NativeShell = {
|
||||
AppHost: {
|
||||
init: function() {
|
||||
postExpoEvent('AppHost.init', window.ExpoAppInfo);
|
||||
return Promise.resolve(window.ExpoAppInfo);
|
||||
},
|
||||
|
||||
appName: function() {
|
||||
postExpoEvent('AppHost.appName', window.ExpoAppInfo.appName);
|
||||
return window.ExpoAppInfo.appName;
|
||||
},
|
||||
|
||||
appVersion: function() {
|
||||
postExpoEvent('AppHost.appVersion', window.ExpoAppInfo.appVersion);
|
||||
return window.ExpoAppInfo.appVersion;
|
||||
},
|
||||
|
||||
deviceId: function() {
|
||||
postExpoEvent('AppHost.deviceId', window.ExpoAppInfo.deviceId);
|
||||
return window.ExpoAppInfo.deviceId;
|
||||
},
|
||||
|
||||
deviceName: function() {
|
||||
postExpoEvent('AppHost.deviceName', window.ExpoAppInfo.deviceName);
|
||||
return window.ExpoAppInfo.deviceName;
|
||||
},
|
||||
|
||||
exit: function() {
|
||||
postExpoEvent('AppHost.exit');
|
||||
},
|
||||
|
||||
getDefaultLayout: function() {
|
||||
postExpoEvent('AppHost.getDefaultLayout', 'mobile');
|
||||
return 'mobile';
|
||||
},
|
||||
|
||||
getDeviceProfile: function(profileBuilder, profileBuilderVersion) {
|
||||
const audioCodecs = ['opus'];
|
||||
const versionNumber = profileBuilderVersion !== undefined && profileBuilderVersion.split('.').map(num => Number.parseInt(num, 10));
|
||||
const isAc3Eac3Disabled = profileBuilderVersion === undefined || (versionNumber.length === 3 && versionNumber[0] === 10 && versionNumber[1] < 7);
|
||||
if (isAc3Eac3Disabled) {
|
||||
audioCodecs.push('ac3');
|
||||
audioCodecs.push('eac3');
|
||||
}
|
||||
|
||||
postExpoEvent('AppHost.getDeviceProfile');
|
||||
return profileBuilder({
|
||||
enableMkvProgressive: false,
|
||||
disableHlsVideoAudioCodecs: audioCodecs
|
||||
});
|
||||
},
|
||||
|
||||
// Keep for support server versions < 10.7
|
||||
getSyncProfile: function() {
|
||||
postExpoEvent('AppHost.getSyncProfile');
|
||||
return Promise.resolve({});
|
||||
},
|
||||
|
||||
supports: function(command) {
|
||||
const isSupported = command && ExpoSupportedFeatures.indexOf(command.toLowerCase()) != -1;
|
||||
postExpoEvent('AppHost.supports', {
|
||||
command: command,
|
||||
isSupported: isSupported
|
||||
});
|
||||
return isSupported;
|
||||
}
|
||||
},
|
||||
|
||||
downloadFile: function(url) {
|
||||
postExpoEvent('downloadFile', { url: url });
|
||||
},
|
||||
|
||||
enableFullscreen: function() {
|
||||
postExpoEvent('enableFullscreen');
|
||||
},
|
||||
|
||||
disableFullscreen: function() {
|
||||
postExpoEvent('disableFullscreen');
|
||||
},
|
||||
|
||||
getPlugins: function() {
|
||||
postExpoEvent('getPlugins');
|
||||
return [];
|
||||
},
|
||||
|
||||
openUrl: function(url, target) {
|
||||
postExpoEvent('openUrl', {
|
||||
url: url,
|
||||
target: target
|
||||
});
|
||||
},
|
||||
|
||||
updateMediaSession: function(mediaInfo) {
|
||||
postExpoEvent('updateMediaSession', { mediaInfo: mediaInfo });
|
||||
},
|
||||
|
||||
hideMediaSession: function() {
|
||||
postExpoEvent('hideMediaSession');
|
||||
}
|
||||
};
|
||||
`;
|
||||
|
||||
export default NativeShell;
|
21
utils/NativeShellLoader.js
Normal file
21
utils/NativeShellLoader.js
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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;
|
Loading…
Reference in New Issue
Block a user