Improvements to the UriBar implementation and some navigation tweaks.

This commit is contained in:
Akinwale Ariwodola 2018-05-26 00:20:44 +01:00
parent 7c8f9a6662
commit 6a60ce07e9
20 changed files with 206 additions and 43 deletions

View file

@ -38,7 +38,6 @@ const discoverStack = StackNavigator({
navigationOptions: ({ navigation }) => ({
title: 'Discover',
headerLeft: <Feather name="menu" size={24} style={discoverStyle.drawerHamburger} onPress={() => navigation.navigate('DrawerOpen')} />,
headerRight: <Feather name="search" size={24} style={discoverStyle.rightHeaderIcon} onPress={() => navigation.navigate('Search')} />
})
},
File: {
@ -51,9 +50,7 @@ const discoverStack = StackNavigator({
Search: {
screen: SearchPage,
navigationOptions: ({ navigation }) => ({
drawerLockMode: 'locked-closed',
headerTitle: <SearchInput style={searchStyle.searchInput} />,
headerRight: <SearchRightHeaderIcon style={discoverStyle.rightHeaderIcon} size={24} navigation={navigation} />
drawerLockMode: 'locked-closed'
})
}
}, {
@ -66,7 +63,6 @@ const walletStack = StackNavigator({
navigationOptions: ({ navigation }) => ({
title: 'Wallet',
headerLeft: <Feather name="menu" size={24} style={discoverStyle.drawerHamburger} onPress={() => navigation.navigate('DrawerOpen')} />,
headerRight: <Feather name="search" size={24} style={discoverStyle.rightHeaderIcon} onPress={() => navigation.navigate('Search')} />
})
},
TransactionHistory: {
@ -185,6 +181,7 @@ class AppWithNavigationState extends React.Component {
if (evt.url) {
const navigateAction = NavigationActions.navigate({
routeName: 'File',
key: 'filePage',
params: { uri: evt.url }
});
dispatch(navigateAction);

View file

@ -61,7 +61,7 @@ class FileItem extends React.PureComponent {
if (NativeModules.Mixpanel) {
NativeModules.Mixpanel.track('Discover Tap', { Uri: uri });
}
navigation.navigate('File', { uri: uri });
navigation.navigate({ routeName: 'File', key: 'filePage', params: { uri } });
}
}>
<FileItemMedia title={title} thumbnail={thumbnail} blurRadius={obscureNsfw ? 15 : 0} resizeMode="cover" />

View file

@ -23,7 +23,11 @@ class TransactionListItem extends React.PureComponent {
{name && claimId && (
<Link
style={transactionListStyle.link}
onPress={() => navigation && navigation.navigate('File', { uri: buildURI({ claimName: name, claimId }) })}
onPress={() => navigation && navigation.navigate({
routeName: 'File',
key: 'filePage',
params: { uri: buildURI({ claimName: name, claimId }) }})
}
text={name} />
)}
</View>

View file

@ -1,12 +1,17 @@
import { connect } from 'react-redux';
import { doUpdateSearchQuery, selectSearchState as selectSearch } from 'lbry-redux';
import UriBar from './view';
const select = state => ({
const select = state => {
const { ...searchState } = selectSearch(state);
});
return {
...searchState
};
};
const perform = dispatch => ({
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)),
});
export default connect(select, perform)(UriBar);

View file

@ -0,0 +1,38 @@
// @flow
import React from 'react';
import { SEARCH_TYPES, normalizeURI } from 'lbry-redux';
import { Text, TouchableOpacity, View } from 'react-native';
import Feather from 'react-native-vector-icons/Feather';
import uriBarStyle from '../../../styles/uriBar';
class UriBarItem extends React.PureComponent {
render() {
const { item, onPress } = this.props;
const { type, value } = item;
let icon;
switch (type) {
case SEARCH_TYPES.CHANNEL:
icon = <Feather name="at-sign" size={18} />
break;
case SEARCH_TYPES.SEARCH:
icon = <Feather name="search" size={18} />
break;
case SEARCH_TYPES.FILE:
default:
icon = <Feather name="compass" size={18} />
break;
}
return (
<TouchableOpacity style={uriBarStyle.item} onPress={onPress}>
{icon}
<Text style={uriBarStyle.itemText} numberOfLines={1}>{value}</Text>
</TouchableOpacity>
)
}
}
export default UriBarItem;

View file

@ -1,42 +1,97 @@
// @flow
import React from 'react';
import { normalizeURI } from 'lbry-redux';
import { TextInput, View } from 'react-native';
import { SEARCH_TYPES, isNameValid, normalizeURI } from 'lbry-redux';
import { FlatList, Keyboard, TextInput, View } from 'react-native';
import UriBarItem from './internal/uri-bar-item';
import uriBarStyle from '../../styles/uriBar';
class UriBar extends React.PureComponent {
static INPUT_TIMEOUT = 500;
constructor(props) {
super(props);
this.state = {
uri: null,
currentValue: null
changeTextTimeout: null,
currentValue: null,
inputText: null,
focused: false
};
}
handleChangeText = text => {
const newValue = text ? text : '';
clearTimeout(this.state.changeTextTimeout);
const { updateSearchQuery } = this.props;
let timeout = setTimeout(() => {
updateSearchQuery(text);
}, UriBar.INPUT_TIMEOUT);
this.setState({ inputText: newValue, currentValue: newValue, changeTextTimeout: timeout });
}
handleItemPress = (item) => {
const { navigation, updateSearchQuery } = this.props;
const { type, value } = item;
Keyboard.dismiss();
if (SEARCH_TYPES.SEARCH === type) {
navigation.navigate({ routeName: 'Search', key: 'searchPage', params: { searchQuery: value }});
} else {
navigation.navigate({ routeName: 'File', key: 'filePage', params: { uri: normalizeURI(value) }});
}
}
render() {
const { value, navigation } = this.props;
if (!this.state.currentValue) {
const { navigation, suggestions, updateSearchQuery, value } = this.props;
if (this.state.currentValue === null) {
this.setState({ currentValue: value });
}
// TODO: Search and URI suggestions overlay
let style = [uriBarStyle.overlay];
if (this.state.focused) {
style.push(uriBarStyle.inFocus);
}
return (
<View style={style}>
{this.state.focused && (
<View style={uriBarStyle.suggestions}>
<FlatList style={uriBarStyle.suggestionList}
data={suggestions}
keyboardShouldPersistTaps={'handled'}
keyExtractor={(item, value) => item.value}
renderItem={({item}) => <UriBarItem item={item}
navigation={navigation}
onPress={() => this.handleItemPress(item)} />} />
</View>)}
<View style={uriBarStyle.uriContainer}>
<TextInput style={uriBarStyle.uriText}
placeholder={'Enter a LBRY URI or some text'}
selectTextOnFocus={true}
placeholder={'Search for videos, music, games and more'}
underlineColorAndroid={'transparent'}
numberOfLines={1}
clearButtonMode={'while-editing'}
value={this.state.currentValue}
returnKeyType={'go'}
onChangeText={(text) => this.setState({uri: text, currentValue: text})}
inlineImageLeft={'baseline_search_black_24'}
inlineImagePadding={16}
onFocus={() => this.setState({ focused: true })}
onBlur={() => this.setState({ focused: false })}
onChangeText={this.handleChangeText}
onSubmitEditing={() => {
if (this.state.uri) {
let uri = this.state.uri;
uri = uri.replace(/ /g, '-');
navigation.navigate('File', { uri: normalizeURI(uri) });
if (this.state.inputText) {
let inputText = this.state.inputText;
if (isNameValid(inputText)) {
navigation.navigate({ routeName: 'File', key: 'filePage', params: { uri: normalizeURI(inputText) }});
} else {
// Open the search page with the query populated
navigation.navigate({ routeName: 'Search', key: 'searchPage', params: { searchQuery: inputText }});
}
}
}}/>
</View>
</View>
);
}
}

View file

@ -220,7 +220,7 @@ class FilePage extends React.PureComponent {
renderIndicator={() => null} />}
{!this.state.showWebView && (
<View style={filePageStyle.pageContainer}>
<View style={filePageStyle.innerPageContainer}>
<View style={filePageStyle.mediaContainer}>
{(canOpen || (!fileInfo || (isPlayable && !canLoadMedia))) &&
<FileItemMedia style={filePageStyle.thumbnail} title={title} thumbnail={metadata.thumbnail} />}

View file

@ -8,13 +8,28 @@ import {
View,
ScrollView
} from 'react-native';
import SearchResultItem from '../../component/searchResultItem';
import Colors from '../../styles/colors';
import PageHeader from '../../component/pageHeader';
import SearchResultItem from '../../component/searchResultItem';
import UriBar from '../../component/uriBar';
import searchStyle from '../../styles/search';
class SearchPage extends React.PureComponent {
static navigationOptions = {
title: 'Search Results'
};
componentDidMount() {
const { navigation, search } = this.props;
const { searchQuery } = navigation.state.params;
if (searchQuery && searchQuery.trim().length > 0) {
search(searchQuery);
}
}
render() {
const { isSearching, navigation, uris } = this.props;
const { isSearching, navigation, uris, query } = this.props;
const { searchQuery } = navigation.state.params;
return (
<View style={searchStyle.container}>
@ -26,10 +41,15 @@ class SearchPage extends React.PureComponent {
uri={uri}
style={searchStyle.resultItem}
navigation={navigation}
onPress={() => {navigation.navigate('File', { uri: uri }); }}/>)
onPress={() => navigation.navigate({
routeName: 'File',
key: 'filePage',
params: { uri }})
}/>)
) : null }
</ScrollView>
{isSearching && <ActivityIndicator size="large" color={Colors.LbryGreen} style={searchStyle.loading} /> }
<UriBar value={searchQuery} navigation={navigation} />
</View>
);
}

View file

@ -54,7 +54,7 @@ class SplashScreen extends React.PureComponent {
navigation.dispatch(resetAction);
if (this.state.launchUrl) {
navigation.navigate('File', { uri: this.state.launchUrl });
navigation.navigate({ routeName: 'File', key: 'filePage', params: { uri: this.state.launchUrl } });
}
});
return;

View file

@ -11,7 +11,8 @@ const channelPageStyle = StyleSheet.create({
},
fileList: {
paddingTop: 30,
flex: 1
flex: 1,
marginBottom: 60
},
title: {
color: Colors.LbryGreen,

View file

@ -5,7 +5,8 @@ const discoverStyle = StyleSheet.create({
flex: 1
},
scrollContainer: {
flex: 1
flex: 1,
marginBottom: 60
},
busyContainer: {
flex: 1,

View file

@ -12,6 +12,10 @@ const filePageStyle = StyleSheet.create({
pageContainer: {
flex: 1
},
innerPageContainer: {
flex: 1,
marginBottom: 60
},
mediaContainer: {
alignItems: 'center',
width: screenWidth,
@ -150,7 +154,7 @@ const filePageStyle = StyleSheet.create({
left: 0,
right: 0,
top: 0,
bottom: 0,
bottom: 60,
zIndex: 100
}
});

View file

@ -10,7 +10,8 @@ const searchStyle = StyleSheet.create({
flex: 1,
width: '100%',
height: '100%',
padding: 16
padding: 16,
marginBottom: 60
},
scrollPadding: {
paddingBottom: 16

View file

@ -6,6 +6,7 @@ const uriBarStyle = StyleSheet.create({
backgroundColor: Colors.White,
padding: 8,
alignSelf: 'flex-end',
height: 60,
width: '100%',
shadowColor: Colors.Black,
shadowOpacity: 0.1,
@ -24,6 +25,32 @@ const uriBarStyle = StyleSheet.create({
fontFamily: 'Metropolis-Regular',
fontSize: 16,
width: '100%'
},
overlay: {
position: 'absolute',
backgroundColor: 'transparent',
bottom: 0,
width: '100%',
zIndex: 200,
elevation: 16
},
inFocus: {
height: '100%'
},
suggestions: {
backgroundColor: 'white',
flex: 1
},
item: {
flexDirection: 'row',
justifyContent: 'flex-start',
padding: 12
},
itemText: {
fontFamily: 'Metropolis-Regular',
fontSize: 16,
marginLeft: 12,
marginRight: 12
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>