Remove old settings screen

This commit is contained in:
Bill Thornton 2020-07-01 17:15:38 -04:00
parent 1958194e5e
commit d3d4036296
3 changed files with 126 additions and 412 deletions

View File

@ -16,7 +16,6 @@ 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 = {
@ -58,7 +57,7 @@ function Main() {
}}
>
<Tab.Screen name='Home' component={HomeScreen} />
<Tab.Screen name='Settings' component={NewSettingsScreen} />
<Tab.Screen name='Settings' component={SettingsScreen} />
</Tab.Navigator>
);
}

View File

@ -1,168 +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 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;

View File

@ -3,283 +3,166 @@
* 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 {
ActivityIndicator,
Alert,
FlatList,
Platform,
ScrollView,
StyleSheet,
View
} from 'react-native';
import { Button, colors, ListItem, Text, Icon } from 'react-native-elements';
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 Constants from 'expo-constants';
import Url from 'url';
import PropTypes from 'prop-types';
import { useStores } from '../hooks/useStores';
import SettingsSection from '../components/SettingsSection';
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 JellyfinValidator from '../utils/JellyfinValidator';
import { getAppName } from '../utils/Device';
import { openBrowser } from '../utils/WebBrowser';
import { useStores } from '../hooks/useStores';
@observer
class SettingsScreen extends React.Component {
static propTypes = {
navigation: PropTypes.object.isRequired,
rootStore: PropTypes.object.isRequired
}
const SettingsScreen = observer(() => {
const { rootStore } = useStores();
const navigation = useNavigation();
state = {
servers: null
useEffect(() => {
// Fetch server info
rootStore.serverStore.fetchInfo();
}, []);
const onAddServer = () => {
navigation.navigate('AddServer');
};
_keyExtractor = (item, index) => `${item.name}-${index}`;
_renderLink = ({ item, index }) => {
console.log('renderLink', item);
return (
<ListItem
title={item.name}
leftIcon={item.icon}
topDivider={index === 0}
bottomDivider
chevron
onPress={() => {
openBrowser(item.url);
}}
/>
);
};
_renderServer = ({ item, index }) => {
const { info, serverUrl, online = false } = item;
console.log('renderServer', info, serverUrl, online);
let title;
let subtitle;
if (info) {
title = info.ServerName;
subtitle = `Version: ${info.Version}\n${serverUrl}`;
} else {
title = Url.parse(serverUrl).host;
subtitle = `Version: unknown\n${serverUrl}`;
}
return (<ListItem
title={title}
titleStyle={{
marginBottom: 2
}}
subtitle={subtitle}
leftElement={(
index === this.props.rootStore.settingStore.activeServer ? (
<Icon
name={(Platform.OS === 'ios' ? 'ios-checkmark' : 'md-checkmark')}
type='ionicon'
size={24}
containerStyle={{ width: 12 }}
/>
) : (
<View style={{ width: 12 }} />
)
)}
rightElement={(
<Button
type='clear'
icon={{
name: Platform.OS === 'ios' ? 'ios-trash' : 'md-trash',
type: 'ionicon',
iconStyle: {
color: Platform.OS === 'ios' ? colors.platform.ios.error : colors.platform.android.error
}
}}
onPress={() => this.onDeleteServer(index)}
/>
)}
topDivider={index === 0}
bottomDivider
onPress={async () => {
this.props.rootStore.settingStore.activeServer = index;
this.props.navigation.navigate('Home', { activeServer: index });
}}
/>);
};
async bootstrapAsync() {
let { servers } = this.props.rootStore.serverStore;
servers = servers.map(async (server) => {
let serverUrl;
try {
serverUrl = JellyfinValidator.getServerUrl(server);
} catch (err) {
serverUrl = '';
}
// Try to fetch the server's public info
try {
const serverInfo = await JellyfinValidator.fetchServerInfo(server);
return Object.assign(
{},
server,
{
info: serverInfo,
serverUrl,
online: true
}
);
} catch (err) {
return Object.assign(
{},
server,
{
serverUrl,
online: false
}
);
}
});
servers = await Promise.all(servers);
console.log('bootstrapAsync', servers);
this.setState({
servers
});
}
async deleteServer(index) {
// Remove server and update active server
this.props.rootStore.serverStore.removeServer(index);
this.props.rootStore.settingStore.activeServer = 0;
if (this.props.rootStore.serverStore.servers.length > 0) {
// More servers exist, update state and navigate home
this.bootstrapAsync();
this.props.navigation.navigate('Home', { activeServer: 0 });
} else {
// No servers are present, navigate to add server screen
this.props.navigation.replace('AddServer');
}
}
async resetApplication() {
// Reset data in stores
this.props.rootStore.serverStore.servers = [];
this.props.rootStore.settingStore.activeServer = 0;
// Navigate to the loading screen
this.props.navigation.replace('AddServer');
}
onDeleteServer(index) {
const onDeleteServer = index => {
Alert.alert(
'Delete Server',
'Are you sure you want to delete this server?',
[
{ text: 'Cancel' },
{ text: 'Delete', onPress: () => this.deleteServer(index), style: 'destructive' }
{
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'
}
]
);
}
};
onResetApplication() {
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: () => this.resetApplication(), style: 'destructive' }
{
text: 'Reset',
onPress: () => {
// Reset data in stores
rootStore.reset();
AsyncStorage.clear();
// Navigate to the loading screen
navigation.replace('AddServer');
},
style: 'destructive'
}
]
);
}
};
componentDidMount() {
this.bootstrapAsync();
}
const AugmentedServerListItem = (props) => (
<ServerListItem
{...props}
activeServer={rootStore.settingStore.activeServer}
onDelete={onDeleteServer}
onPress={onSelectServer}
/>
);
render() {
return (
<SafeAreaView style={{...styles.container, paddingTop: 0}} >
<ScrollView
style={styles.container}
showsVerticalScrollIndicator={false}
>
<SettingsSection heading='Servers'>
{
this.state.servers ? (
<FlatList
keyExtractor={this._keyExtractor}
data={this.state.servers}
renderItem={this._renderServer}
scrollEnabled={false}
extraData={this.props.rootStore.settingStore.activeServer}
/>
) : (
<ActivityIndicator />
)
}
</SettingsSection>
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
}
];
};
<Button
buttonStyle={{ margin: 15 }}
title='Add Server'
onPress={() => this.props.navigation.navigate('AddServer')}
/>
<SettingsSection heading='Links'>
<FlatList
keyExtractor={this._keyExtractor}
data={Links}
renderItem={this._renderLink}
scrollEnabled={false}
/>
</SettingsSection>
<Button
buttonStyle={{
backgroundColor: Platform.OS === 'ios' ? colors.platform.ios.error : colors.platform.android.error,
margin: 15
}}
title='Reset Application'
onPress={() => this.onResetApplication()}
/>
<View style={styles.infoContainer}>
<Text style={styles.infoText}>{`${getAppName()}`}</Text>
<Text style={styles.infoText}>{`${Constants.nativeAppVersion} (${Constants.nativeBuildVersion})`}</Text>
<Text style={styles.infoText}>{`Expo Version: ${Constants.expoVersion}`}</Text>
</View>
</ScrollView>
</SafeAreaView>
);
}
}
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
},
infoContainer: {
margin: 15
},
infoText: {
header: {
backgroundColor: Colors.backgroundColor,
color: colors.grey4,
fontSize: 15
fontSize: 17,
fontWeight: '600',
paddingVertical: 8,
paddingHorizontal: 15,
marginBottom: 1
}
});
// Inject the Navigation Hook as a prop to mimic the legacy behavior
const SettingsScreenWithNavigation = observer((props) => {
const stores = useStores();
return <SettingsScreen {...props} navigation={useNavigation()} {...stores} />;
});
export default SettingsScreenWithNavigation;
export default SettingsScreen;