mirror of
https://github.com/jellyfin/jellyfin-expo.git
synced 2025-02-20 06:13:52 +00:00
Refactor settings screen
This commit is contained in:
parent
7d041afc1c
commit
1958194e5e
31
components/AppInfoFooter.js
Normal file
31
components/AppInfoFooter.js
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/.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import { colors, Text } from 'react-native-elements';
|
||||
import Constants from 'expo-constants';
|
||||
|
||||
import { getAppName } from '../utils/Device';
|
||||
|
||||
const AppInfoFooter = () => (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.text}>{`${getAppName()}`}</Text>
|
||||
<Text style={styles.text}>{`${Constants.nativeAppVersion} (${Constants.nativeBuildVersion})`}</Text>
|
||||
<Text style={styles.text}>{`Expo Version: ${Constants.expoVersion}`}</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
margin: 15
|
||||
},
|
||||
text: {
|
||||
color: colors.grey4,
|
||||
fontSize: 15
|
||||
}
|
||||
});
|
||||
|
||||
export default AppInfoFooter;
|
34
components/BrowserListItem.js
Normal file
34
components/BrowserListItem.js
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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 React from 'react';
|
||||
import { ListItem } from 'react-native-elements';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { openBrowser } from '../utils/WebBrowser';
|
||||
|
||||
const BrowserListItem = ({item, index}) => (
|
||||
<ListItem
|
||||
title={item.name}
|
||||
leftIcon={item.icon}
|
||||
topDivider={index === 0}
|
||||
bottomDivider
|
||||
chevron
|
||||
onPress={() => {
|
||||
openBrowser(item.url);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
BrowserListItem.propTypes = {
|
||||
item: PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
icon: PropTypes.string.isRequired,
|
||||
url: PropTypes.string.isRequired
|
||||
}).isRequired,
|
||||
index: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
export default BrowserListItem;
|
25
components/ButtonListItem.js
Normal file
25
components/ButtonListItem.js
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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 React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { Button } from 'react-native-elements';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const ButtonListItem = ({item}) => (
|
||||
<Button {...item} buttonStyle={{ ...styles.button, ...item.buttonStyle }} />
|
||||
);
|
||||
|
||||
ButtonListItem.propTypes = {
|
||||
item: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
margin: 15
|
||||
}
|
||||
});
|
||||
|
||||
export default ButtonListItem;
|
79
components/ServerListItem.js
Normal file
79
components/ServerListItem.js
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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 React from 'react';
|
||||
import { StyleSheet, View, Platform } from 'react-native';
|
||||
import { Button, Icon, ListItem, colors } from 'react-native-elements';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { getIconName } from '../utils/Icons';
|
||||
|
||||
const ServerListItem = ({item, index, activeServer, onDelete, onPress}) => {
|
||||
let title;
|
||||
let subtitle;
|
||||
if (item.info) {
|
||||
title = item.info.ServerName;
|
||||
subtitle = `Version: ${item.info.Version}\n${item.urlString}`;
|
||||
} else {
|
||||
title = item.url.host;
|
||||
subtitle = `Version: unknown\n${item.urlString}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
title={title}
|
||||
titleStyle={styles.title}
|
||||
subtitle={subtitle}
|
||||
leftElement={(
|
||||
index === activeServer ? (
|
||||
<Icon
|
||||
name={getIconName('checkmark')}
|
||||
type='ionicon'
|
||||
size={24}
|
||||
containerStyle={styles.leftElement}
|
||||
/>
|
||||
) : (
|
||||
<View style={styles.leftElement} />
|
||||
)
|
||||
)}
|
||||
rightElement={(
|
||||
<Button
|
||||
type='clear'
|
||||
icon={{
|
||||
name: getIconName('trash'),
|
||||
type: 'ionicon',
|
||||
iconStyle: styles.deleteButton
|
||||
}}
|
||||
onPress={() => onDelete(index)}
|
||||
/>
|
||||
)}
|
||||
topDivider={index === 0}
|
||||
bottomDivider
|
||||
onPress={() => onPress(index)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ServerListItem.propTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
activeServer: PropTypes.number.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
onPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
title: {
|
||||
marginBottom: 2
|
||||
},
|
||||
leftElement: {
|
||||
width: 12
|
||||
},
|
||||
deleteButton: {
|
||||
color: Platform.OS === 'ios' ? colors.platform.ios.error : colors.platform.android.error
|
||||
}
|
||||
});
|
||||
|
||||
export default ServerListItem;
|
@ -7,6 +7,7 @@ import { Platform } from 'react-native';
|
||||
|
||||
export default [
|
||||
{
|
||||
key: 'links-website',
|
||||
name: 'Jellyfin Website',
|
||||
url: 'https://jellyfin.org/',
|
||||
icon: {
|
||||
@ -15,6 +16,7 @@ export default [
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'links-documentation',
|
||||
name: 'Documentation',
|
||||
url: 'https://docs.jellyfin.org',
|
||||
icon: {
|
||||
@ -23,6 +25,7 @@ export default [
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'links-source',
|
||||
name: 'Source Code',
|
||||
url: 'https://github.com/jellyfin/jellyfin-expo',
|
||||
icon: {
|
||||
@ -31,6 +34,7 @@ export default [
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'links-feature',
|
||||
name: 'Request a Feature',
|
||||
url: 'https://features.jellyfin.org/',
|
||||
icon: {
|
||||
@ -39,6 +43,7 @@ export default [
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'links-issue',
|
||||
name: 'Report an Issue',
|
||||
url: 'https://github.com/jellyfin/jellyfin-expo/issues',
|
||||
icon: {
|
||||
|
53
models/ServerModel.js
Normal file
53
models/ServerModel.js
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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 { action, autorun, computed, observable } from 'mobx';
|
||||
import { ignore } from 'mobx-sync';
|
||||
import { task } from 'mobx-task';
|
||||
|
||||
import JellyfinValidator from '../utils/JellyfinValidator';
|
||||
|
||||
export default class ServerModel {
|
||||
@observable
|
||||
id
|
||||
|
||||
@observable
|
||||
url
|
||||
|
||||
@ignore
|
||||
@observable
|
||||
online = false
|
||||
|
||||
@observable
|
||||
info
|
||||
|
||||
constructor(id, url, info) {
|
||||
this.id = id;
|
||||
this.url = url;
|
||||
this.info = info;
|
||||
|
||||
autorun(() => {
|
||||
this.urlString = this.parseUrlString;
|
||||
});
|
||||
}
|
||||
|
||||
@computed
|
||||
get parseUrlString() {
|
||||
try {
|
||||
return JellyfinValidator.getServerUrl(this);
|
||||
} catch (ex) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@task
|
||||
async fetchInfo() {
|
||||
return await JellyfinValidator.fetchServerInfo(this)
|
||||
.then(action(info => {
|
||||
this.online = true;
|
||||
this.info = info;
|
||||
}));
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ import Colors from '../constants/Colors';
|
||||
import AddServerScreen from '../screens/AddServerScreen';
|
||||
import HomeScreen from '../screens/HomeScreen';
|
||||
import SettingsScreen from '../screens/SettingsScreen';
|
||||
import NewSettingsScreen from '../screens/NewSettingsScreen';
|
||||
|
||||
// Customize theme for navigator
|
||||
const theme = {
|
||||
@ -57,7 +58,7 @@ function Main() {
|
||||
}}
|
||||
>
|
||||
<Tab.Screen name='Home' component={HomeScreen} />
|
||||
<Tab.Screen name='Settings' component={SettingsScreen} />
|
||||
<Tab.Screen name='Settings' component={NewSettingsScreen} />
|
||||
</Tab.Navigator>
|
||||
);
|
||||
}
|
||||
@ -71,7 +72,7 @@ const AppNavigator = observer(() => {
|
||||
return (
|
||||
<NavigationContainer theme={theme}>
|
||||
<Stack.Navigator
|
||||
initialRouteName={(rootStore.serverStore.servers.length > 0) ? 'Main' : 'AddServer'}
|
||||
initialRouteName={(rootStore.serverStore.servers?.length > 0) ? 'Main' : 'AddServer'}
|
||||
headerMode='screen'
|
||||
screenOptions={{ headerShown: false }}
|
||||
>
|
||||
@ -95,7 +96,7 @@ const AppNavigator = observer(() => {
|
||||
name='AddServer'
|
||||
component={AddServerScreen}
|
||||
options={{
|
||||
headerShown: rootStore.serverStore.servers.length > 0,
|
||||
headerShown: rootStore.serverStore.servers?.length > 0,
|
||||
title: 'Add Server'
|
||||
}}
|
||||
/>
|
||||
|
@ -26,6 +26,7 @@
|
||||
"mobx": "^5.15.4",
|
||||
"mobx-react": "^6.2.2",
|
||||
"mobx-sync": "^3.0.0",
|
||||
"mobx-task": "^2.0.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "16.9.0",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
|
@ -18,7 +18,6 @@ import PropTypes from 'prop-types';
|
||||
import { useStores } from '../hooks/useStores';
|
||||
import Colors from '../constants/Colors';
|
||||
import { getAppName, getSafeDeviceName } from '../utils/Device';
|
||||
import JellyfinValidator from '../utils/JellyfinValidator';
|
||||
import NativeShell from '../utils/NativeShell';
|
||||
import { openBrowser } from '../utils/WebBrowser';
|
||||
|
||||
@ -38,8 +37,6 @@ true;
|
||||
@observer
|
||||
class HomeScreen extends React.Component {
|
||||
state = {
|
||||
server: null,
|
||||
serverUrl: null,
|
||||
isError: false,
|
||||
isFullscreen: false,
|
||||
isLoading: true,
|
||||
@ -52,29 +49,6 @@ class HomeScreen extends React.Component {
|
||||
rootStore: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
async bootstrapAsync() {
|
||||
const servers = this.props.rootStore.serverStore.servers;
|
||||
let activeServer = this.props.rootStore.settingStore.activeServer;
|
||||
|
||||
// If the activeServer is greater than the length of the server array, reset it to 0
|
||||
if (activeServer && servers.length && activeServer > servers.length - 1) {
|
||||
this.props.rootStore.settingStore.activeServer = 0;
|
||||
activeServer = 0;
|
||||
}
|
||||
|
||||
let server;
|
||||
if (servers.length > 0) {
|
||||
server = servers[activeServer];
|
||||
}
|
||||
|
||||
const serverUrl = JellyfinValidator.getServerUrl(server);
|
||||
|
||||
this.setState({
|
||||
server,
|
||||
serverUrl
|
||||
});
|
||||
}
|
||||
|
||||
getErrorView() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
@ -124,19 +98,19 @@ class HomeScreen extends React.Component {
|
||||
deactivateKeepAwake();
|
||||
break;
|
||||
case 'console.debug':
|
||||
console.debug('[Browser Console]', data);
|
||||
// console.debug('[Browser Console]', data);
|
||||
break;
|
||||
case 'console.error':
|
||||
console.error('[Browser Console]', data);
|
||||
// console.error('[Browser Console]', data);
|
||||
break;
|
||||
case 'console.info':
|
||||
console.info('[Browser Console]', data);
|
||||
// console.info('[Browser Console]', data);
|
||||
break;
|
||||
case 'console.log':
|
||||
console.log('[Browser Console]', data);
|
||||
// console.log('[Browser Console]', data);
|
||||
break;
|
||||
case 'console.warn':
|
||||
console.warn('[Browser Console]', data);
|
||||
// console.warn('[Browser Console]', data);
|
||||
break;
|
||||
default:
|
||||
console.debug('[HomeScreen.onMessage]', event, data);
|
||||
@ -183,15 +157,9 @@ class HomeScreen extends React.Component {
|
||||
this.onGoHome();
|
||||
}
|
||||
});
|
||||
// Bootstrap component state
|
||||
this.bootstrapAsync();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (typeof this.props.route.params?.activeServer != 'undefined' &&
|
||||
prevProps.route.params?.activeServer !== this.props.route.params?.activeServer) {
|
||||
this.bootstrapAsync();
|
||||
}
|
||||
if (prevState.isFullscreen !== this.state.isFullscreen) {
|
||||
// Update the screen orientation
|
||||
this.updateScreenOrientation();
|
||||
@ -210,6 +178,11 @@ class HomeScreen extends React.Component {
|
||||
// Hide webview until loaded
|
||||
const webviewStyle = (this.state.isError || this.state.isLoading) ? styles.loading : styles.container;
|
||||
|
||||
if (!this.props.rootStore.serverStore.servers || this.props.rootStore.serverStore.servers.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const server = this.props.rootStore.serverStore.servers[this.props.rootStore.settingStore.activeServer];
|
||||
|
||||
return (
|
||||
<SafeAreaView style={safeAreaStyle} >
|
||||
{!this.state.isFullscreen && (
|
||||
@ -228,10 +201,10 @@ class HomeScreen extends React.Component {
|
||||
) : null
|
||||
}
|
||||
>
|
||||
{this.state.serverUrl && (
|
||||
{server && server.urlString && (
|
||||
<WebView
|
||||
ref={ref => (this.webview = ref)}
|
||||
source={{ uri: this.state.serverUrl }}
|
||||
source={{ uri: server.urlString }}
|
||||
style={webviewStyle}
|
||||
// Inject javascript for NativeShell
|
||||
injectedJavaScriptBeforeContentLoaded={injectedJavaScript}
|
||||
|
168
screens/NewSettingsScreen.js
Normal file
168
screens/NewSettingsScreen.js
Normal file
@ -0,0 +1,168 @@
|
||||
/**
|
||||
* 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 React, { useEffect } from 'react';
|
||||
import { Alert, AsyncStorage, Platform, SectionList, StyleSheet } from 'react-native';
|
||||
import { colors, Text } from 'react-native-elements';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import AppInfoFooter from '../components/AppInfoFooter';
|
||||
import BrowserListItem from '../components/BrowserListItem';
|
||||
import ButtonListItem from '../components/ButtonListItem';
|
||||
import ServerListItem from '../components/ServerListItem';
|
||||
import Colors from '../constants/Colors';
|
||||
import Links from '../constants/Links';
|
||||
import { useStores } from '../hooks/useStores';
|
||||
|
||||
const NewSettingsScreen = observer(() => {
|
||||
const { rootStore } = useStores();
|
||||
const navigation = useNavigation();
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch server info
|
||||
rootStore.serverStore.fetchInfo();
|
||||
}, []);
|
||||
|
||||
const onAddServer = () => {
|
||||
navigation.navigate('AddServer');
|
||||
};
|
||||
|
||||
const onDeleteServer = index => {
|
||||
Alert.alert(
|
||||
'Delete Server',
|
||||
'Are you sure you want to delete this server?',
|
||||
[
|
||||
{ text: 'Cancel' },
|
||||
{
|
||||
text: 'Delete',
|
||||
onPress: () => {
|
||||
// Remove server and update active server
|
||||
rootStore.serverStore.removeServer(index);
|
||||
rootStore.settingStore.activeServer = 0;
|
||||
|
||||
if (rootStore.serverStore.servers.length > 0) {
|
||||
// More servers exist, navigate home
|
||||
navigation.navigate('Home');
|
||||
} else {
|
||||
// No servers are present, navigate to add server screen
|
||||
navigation.replace('AddServer');
|
||||
}
|
||||
},
|
||||
style: 'destructive'
|
||||
}
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
const onSelectServer = index => {
|
||||
rootStore.settingStore.activeServer = index;
|
||||
navigation.navigate('Home');
|
||||
};
|
||||
|
||||
const onResetApplication = () => {
|
||||
Alert.alert(
|
||||
'Reset Application',
|
||||
'Are you sure you want to reset all settings?',
|
||||
[
|
||||
{ text: 'Cancel' },
|
||||
{
|
||||
text: 'Reset',
|
||||
onPress: () => {
|
||||
// Reset data in stores
|
||||
rootStore.reset();
|
||||
AsyncStorage.clear();
|
||||
// Navigate to the loading screen
|
||||
navigation.replace('AddServer');
|
||||
},
|
||||
style: 'destructive'
|
||||
}
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
const AugmentedServerListItem = (props) => (
|
||||
<ServerListItem
|
||||
{...props}
|
||||
activeServer={rootStore.settingStore.activeServer}
|
||||
onDelete={onDeleteServer}
|
||||
onPress={onSelectServer}
|
||||
/>
|
||||
);
|
||||
|
||||
const getSections = () => {
|
||||
return [
|
||||
{
|
||||
title: 'Servers',
|
||||
data: rootStore.serverStore.servers.slice(),
|
||||
keyExtractor: (item, index) => `server-${index}`,
|
||||
renderItem: AugmentedServerListItem
|
||||
},
|
||||
{
|
||||
title: 'Add Server',
|
||||
hideHeader: true,
|
||||
data: [{
|
||||
key: 'add-server-button',
|
||||
title: 'Add Server',
|
||||
onPress: onAddServer
|
||||
}],
|
||||
renderItem: ButtonListItem
|
||||
},
|
||||
{
|
||||
title: 'Links',
|
||||
data: Links,
|
||||
renderItem: BrowserListItem
|
||||
},
|
||||
{
|
||||
title: 'Reset Application',
|
||||
hideHeader: true,
|
||||
data: [{
|
||||
key: 'reset-app-button',
|
||||
title: 'Reset Application',
|
||||
buttonStyle: {
|
||||
backgroundColor: Platform.OS === 'ios' ? colors.platform.ios.error : colors.platform.android.error
|
||||
},
|
||||
onPress: onResetApplication
|
||||
}],
|
||||
renderItem: ButtonListItem
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{...styles.container, paddingTop: 0}} >
|
||||
<SectionList
|
||||
sections={getSections()}
|
||||
extraData={{
|
||||
activeServer: rootStore.settingStore.activeServer,
|
||||
isFetching: rootStore.serverStore.fetchInfo.pending
|
||||
}}
|
||||
renderItem={({ item }) => <Text>{JSON.stringify(item)}</Text>}
|
||||
renderSectionHeader={({ section: { title, hideHeader } }) => hideHeader ? null : <Text style={styles.header}>{title}</Text>}
|
||||
ListFooterComponent={AppInfoFooter}
|
||||
showsVerticalScrollIndicator={false}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: Colors.backgroundColor
|
||||
},
|
||||
header: {
|
||||
backgroundColor: Colors.backgroundColor,
|
||||
color: colors.grey4,
|
||||
fontSize: 17,
|
||||
fontWeight: '600',
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 15,
|
||||
marginBottom: 1
|
||||
}
|
||||
});
|
||||
|
||||
export default NewSettingsScreen;
|
@ -11,6 +11,12 @@ import SettingStore from "./SettingStore";
|
||||
export default class RootStore {
|
||||
@ignore
|
||||
storeLoaded = false
|
||||
|
||||
serverStore = new ServerStore()
|
||||
settingStore = new SettingStore()
|
||||
|
||||
reset() {
|
||||
this.serverStore.reset();
|
||||
this.settingStore.reset();
|
||||
}
|
||||
}
|
||||
|
@ -4,18 +4,35 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
import { action, observable } from 'mobx';
|
||||
import { format } from 'mobx-sync';
|
||||
import { task } from 'mobx-task';
|
||||
|
||||
import ServerModel from '../models/ServerModel';
|
||||
|
||||
export default class ServerStore {
|
||||
@format(data => data.map(value => new ServerModel(value.id, value.url, value.info)))
|
||||
@observable
|
||||
servers = []
|
||||
|
||||
@action
|
||||
addServer(server) {
|
||||
this.servers.push(server);
|
||||
this.servers.push(new ServerModel(this.servers.length, server.url));
|
||||
}
|
||||
|
||||
@action
|
||||
removeServer(index) {
|
||||
this.servers.splice(index, 1);
|
||||
}
|
||||
|
||||
@action
|
||||
reset() {
|
||||
this.servers = [];
|
||||
}
|
||||
|
||||
@task
|
||||
async fetchInfo() {
|
||||
await Promise.all(
|
||||
this.servers.map(server => server.fetchInfo())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +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/.
|
||||
*/
|
||||
import { observable } from 'mobx';
|
||||
import { action, observable } from 'mobx';
|
||||
|
||||
/**
|
||||
* Data store for application settings
|
||||
@ -11,4 +11,9 @@ import { observable } from 'mobx';
|
||||
export default class SettingStore {
|
||||
@observable
|
||||
activeServer = 0
|
||||
|
||||
@action
|
||||
reset() {
|
||||
this.activeServer = 0;
|
||||
}
|
||||
}
|
||||
|
13
utils/Icons.js
Normal file
13
utils/Icons.js
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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 { Platform } from 'react-native';
|
||||
|
||||
export const getIconName = (name = '') => {
|
||||
if (name) {
|
||||
return Platform.OS === 'ios' ? `ios-${name}` : `md-${name}`;
|
||||
}
|
||||
return name;
|
||||
};
|
@ -35,7 +35,7 @@ export default class JellyfinValidator {
|
||||
}
|
||||
|
||||
static async fetchServerInfo(server = {}) {
|
||||
const serverUrl = this.getServerUrl(server);
|
||||
const serverUrl = server.urlString || this.getServerUrl(server);
|
||||
const infoUrl = `${serverUrl}system/info/public`;
|
||||
console.log('info url', infoUrl);
|
||||
|
||||
@ -61,7 +61,7 @@ export default class JellyfinValidator {
|
||||
|
||||
static getServerUrl(server = {}) {
|
||||
if (!server || !server.url || !server.url.href) {
|
||||
throw new Error(`Cannot get server url for invalid server ${server}`);
|
||||
throw new Error('Cannot get server url for invalid server', server);
|
||||
}
|
||||
|
||||
// Strip the query string or hash if present
|
||||
|
@ -9780,6 +9780,13 @@ mobx-sync@^3.0.0:
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
mobx-task@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mobx-task/-/mobx-task-2.0.1.tgz#bd9e335fd2f2cb6738eb6d83cae222d3b41c9d29"
|
||||
integrity sha512-CWAqDYfNi6fKvdaPCO/qbns1VHKVF/yX5MezysieOwld4l+B77XFCDrP+E/W6W46gclPnyVRWllJ0fDYwC7S/g==
|
||||
dependencies:
|
||||
tslib "^1.9.3"
|
||||
|
||||
mobx@^5.15.4:
|
||||
version "5.15.4"
|
||||
resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.15.4.tgz#9da1a84e97ba624622f4e55a0bf3300fb931c2ab"
|
||||
|
Loading…
x
Reference in New Issue
Block a user