Channel page redesign (#528)

* channel page redesign changes
* add constants. change publisher thumbnail resize mode.
This commit is contained in:
Akinwale Ariwodola 2019-05-02 07:07:26 +01:00 committed by GitHub
parent 7a7e96388b
commit 07f23ba927
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 234 additions and 39 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

View file

@ -4,6 +4,9 @@ const Constants = {
FIRST_RUN_PAGE_WALLET: "wallet", FIRST_RUN_PAGE_WALLET: "wallet",
FIRST_RUN_PAGE_SKIP_ACCOUNT: "skip-account", FIRST_RUN_PAGE_SKIP_ACCOUNT: "skip-account",
CONTENT_TAB: "content",
ABOUT_TAB: "about",
KEY_FIRST_RUN_EMAIL: "firstRunEmail", KEY_FIRST_RUN_EMAIL: "firstRunEmail",
KEY_FIRST_RUN_PASSWORD: "firstRunPassword", KEY_FIRST_RUN_PASSWORD: "firstRunPassword",
KEY_SHOULD_VERIFY_EMAIL: "shouldVerifyEmail", KEY_SHOULD_VERIFY_EMAIL: "shouldVerifyEmail",

View file

@ -1,7 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
doFetchClaimsByChannel, doFetchClaimsByChannel,
doFetchClaimCountByChannel,
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectClaimsInChannelForCurrentPageState, makeSelectClaimsInChannelForCurrentPageState,
makeSelectFetchingChannelClaims, makeSelectFetchingChannelClaims,
@ -21,7 +20,6 @@ const select = (state, props) => ({
const perform = dispatch => ({ const perform = dispatch => ({
fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)), fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)),
fetchClaimCount: uri => dispatch(doFetchClaimCountByChannel(uri)),
popDrawerStack: () => dispatch(doPopDrawerStack()) popDrawerStack: () => dispatch(doPopDrawerStack())
}); });

View file

@ -1,9 +1,20 @@
// @flow // @flow
import React from 'react'; import React from 'react';
import { ActivityIndicator, Text, View } from 'react-native'; import {
ActivityIndicator,
Dimensions,
Image,
ScrollView,
Text,
TouchableOpacity,
View
} from 'react-native';
import { TabView, SceneMap } from 'react-native-tab-view';
import { navigateBack } from 'utils/helper'; import { navigateBack } from 'utils/helper';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants';
import Button from 'component/button'; import Button from 'component/button';
import Link from 'component/link';
import FileList from 'component/fileList'; import FileList from 'component/fileList';
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
import SubscribeButton from 'component/subscribeButton'; import SubscribeButton from 'component/subscribeButton';
@ -13,7 +24,8 @@ import channelPageStyle from 'styles/channelPage';
class ChannelPage extends React.PureComponent { class ChannelPage extends React.PureComponent {
state = { state = {
page: 1, page: 1,
showPageButtons: false showPageButtons: false,
activeTab: Constants.CONTENT_TAB
}; };
componentDidMount() { componentDidMount() {
@ -21,7 +33,6 @@ class ChannelPage extends React.PureComponent {
if (!claimsInChannel || !claimsInChannel.length) { if (!claimsInChannel || !claimsInChannel.length) {
fetchClaims(uri, page || this.state.page); fetchClaims(uri, page || this.state.page);
fetchClaimCount(uri);
} }
} }
@ -43,18 +54,8 @@ class ChannelPage extends React.PureComponent {
} }
} }
render() { renderContent = () => {
const { const { fetching, claimsInChannel, totalPages, navigation } = this.props;
fetching,
claimsInChannel,
claim,
navigation,
totalPages,
uri,
drawerStack,
popDrawerStack
} = this.props;
const { name, permanent_url: permanentUrl } = claim;
let contentList; let contentList;
if (fetching) { if (fetching) {
@ -81,15 +82,9 @@ class ChannelPage extends React.PureComponent {
); );
} }
return ( let pageButtons;
<View style={channelPageStyle.container}> if (totalPages > 1 && this.state.showPageButtons) {
<UriBar value={uri} navigation={navigation} /> pageButtons = (
<View style={channelPageStyle.channelHeader}>
<Text style={channelPageStyle.channelName}>{name}</Text>
<SubscribeButton style={channelPageStyle.subscribeButton} uri={uri} name={name} />
</View>
{contentList}
{(totalPages > 1) && this.state.showPageButtons &&
<View style={channelPageStyle.pageButtons}> <View style={channelPageStyle.pageButtons}>
<View> <View>
{(this.state.page > 1) && <Button {(this.state.page > 1) && <Button
@ -103,7 +98,127 @@ class ChannelPage extends React.PureComponent {
text={"Next"} text={"Next"}
disabled={!!fetching} disabled={!!fetching}
onPress={this.handleNextPage} />} onPress={this.handleNextPage} />}
</View>
);
}
return (
<View style={channelPageStyle.contentTab}>
{contentList}
{pageButtons}
</View>
);
}
renderAbout = () => {
const { claim } = this.props;
if (!claim) {
return (
<View style={channelPageStyle.aboutTab}>
<View style={channelPageStyle.busyContainer}>
<Text style={channelPageStyle.infoText}>No information to display.</Text>
</View>
</View>
);
}
const { cover, description, thumbnail, email, website_url, title } = claim.value;
return (
<View style={channelPageStyle.aboutTab}>
{(!website_url && !email && !description) &&
<View style={channelPageStyle.busyContainer}>
<Text style={channelPageStyle.infoText}>Nothing here yet. Please check back later.</Text>
</View>} </View>}
{(website_url || email || description) &&
<ScrollView style={channelPageStyle.aboutScroll} contentContainerStyle={channelPageStyle.aboutScrollContent}>
{(website_url && website_url.trim().length > 0) &&
<View style={channelPageStyle.aboutItem}>
<Text style={channelPageStyle.aboutTitle}>Website</Text>
<Link style={channelPageStyle.aboutText} text={website_url} href={website_url} />
</View>}
{(email && email.trim().length > 0) &&
<View style={channelPageStyle.aboutItem}>
<Text style={channelPageStyle.aboutTitle}>Email</Text>
<Link style={channelPageStyle.aboutText} text={email} href={`mailto:${email}`} />
</View>}
{(description && description.trim().length > 0) &&
<View style={channelPageStyle.aboutItem}>
<Text style={channelPageStyle.aboutText}>{description}</Text>
</View>}
</ScrollView>}
</View>
);
}
render() {
const {
fetching,
claimsInChannel,
claim,
navigation,
totalPages,
uri,
drawerStack,
popDrawerStack
} = this.props;
const { name, permanent_url: permanentUrl } = claim;
let thumbnailUrl, coverUrl, title;
if (claim && claim.value) {
title = claim.value.title;
if (claim.value.cover) {
coverUrl = claim.value.cover.url;
}
if (claim.value.thumbnail) {
thumbnailUrl = claim.value.thumbnail.url;
}
}
return (
<View style={channelPageStyle.container}>
<UriBar value={uri} navigation={navigation} />
<View style={channelPageStyle.viewContainer}>
<View style={channelPageStyle.cover}>
<Image
style={channelPageStyle.coverImage}
resizeMode={'cover'}
source={(coverUrl && coverUrl.trim().length > 0) ? { uri: coverUrl } : require('../../assets/default_channel_cover.png')} />
<View style={channelPageStyle.channelHeader}>
<Text style={channelPageStyle.channelName}>{(title && title.trim().length > 0) ? title : name}</Text>
</View>
<View style={channelPageStyle.avatarImageContainer}>
<Image
style={channelPageStyle.avatarImage}
resizeMode={'cover'}
source={(thumbnailUrl && thumbnailUrl.trim().length > 0) ? { uri: thumbnailUrl } : require('../../assets/default_avatar.jpg')} />
</View>
<SubscribeButton style={channelPageStyle.subscribeButton} uri={uri} name={name} />
</View>
<View style={channelPageStyle.tabBar}>
<TouchableOpacity style={channelPageStyle.tab} onPress={() => this.setState({ activeTab: Constants.CONTENT_TAB })}>
<Text style={channelPageStyle.tabTitle}>CONTENT</Text>
{Constants.CONTENT_TAB === this.state.activeTab && <View style={channelPageStyle.activeTabHint} />}
</TouchableOpacity>
<TouchableOpacity style={channelPageStyle.tab} onPress={() => this.setState({ activeTab: Constants.ABOUT_TAB })}>
<Text style={channelPageStyle.tabTitle}>ABOUT</Text>
{Constants.ABOUT_TAB === this.state.activeTab && <View style={channelPageStyle.activeTabHint} />}
</TouchableOpacity>
</View>
{Constants.CONTENT_TAB === this.state.activeTab && this.renderContent()}
{Constants.ABOUT_TAB === this.state.activeTab && this.renderAbout()}
</View>
</View> </View>
) )
} }

View file

@ -11,7 +11,7 @@ import {
StyleSheet, StyleSheet,
Text, Text,
TextInput, TextInput,
TouchableOpacity, TouchableWithoutFeedback,
View, View,
WebView WebView
} from 'react-native'; } from 'react-native';
@ -444,7 +444,7 @@ class FilePage extends React.PureComponent {
const { height, channel_name: channelName, value } = claim; const { height, channel_name: channelName, value } = claim;
const showActions = !this.state.fullscreenMode && !this.state.showImageViewer && !this.state.showWebView; const showActions = !this.state.fullscreenMode && !this.state.showImageViewer && !this.state.showWebView;
const showFileActions = (completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes)); const showFileActions = (completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
const channelClaimId = value && value.publisherSignature && value.publisherSignature.certificateId; const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
const canSendTip = this.state.tipAmount > 0; const canSendTip = this.state.tipAmount > 0;
const fullChannelUri = channelClaimId && channelClaimId.trim().length > 0 ? `${channelName}#${channelClaimId}` : channelName; const fullChannelUri = channelClaimId && channelClaimId.trim().length > 0 ? `${channelName}#${channelClaimId}` : channelName;
@ -582,10 +582,10 @@ class FilePage extends React.PureComponent {
ref={(ref) => { this.scrollView = ref; }}> ref={(ref) => { this.scrollView = ref; }}>
<View style={filePageStyle.titleRow}> <View style={filePageStyle.titleRow}>
<Text style={filePageStyle.title} selectable={true}>{title}</Text> <Text style={filePageStyle.title} selectable={true}>{title}</Text>
<TouchableOpacity style={filePageStyle.descriptionToggle} <TouchableWithoutFeedback style={filePageStyle.descriptionToggle}
onPress={() => this.setState({ showDescription: !this.state.showDescription })}> onPress={() => this.setState({ showDescription: !this.state.showDescription })}>
<Icon name={this.state.showDescription ? "caret-up" : "caret-down"} size={24} /> <Icon name={this.state.showDescription ? "caret-up" : "caret-down"} size={24} />
</TouchableOpacity> </TouchableWithoutFeedback>
</View> </View>
{channelName && {channelName &&
<View style={filePageStyle.channelRow}> <View style={filePageStyle.channelRow}>

View file

@ -10,6 +10,10 @@ const channelPageStyle = StyleSheet.create({
content: { content: {
flex: 1 flex: 1
}, },
viewContainer: {
flex: 1,
marginTop: 60
},
fileList: { fileList: {
flex: 1, flex: 1,
paddingTop: 30 paddingTop: 30
@ -53,22 +57,95 @@ const channelPageStyle = StyleSheet.create({
alignSelf: 'flex-end' alignSelf: 'flex-end'
}, },
channelHeader: { channelHeader: {
marginTop: 60, position: 'absolute',
marginLeft: 16, left: 120,
marginRight: 16 bottom: 4
}, },
channelName: { channelName: {
fontFamily: 'Inter-UI-SemiBold', color: Colors.White,
fontSize: 24, fontFamily: 'Inter-UI-Regular',
marginTop: 16, fontSize: 18
marginBottom: 8
}, },
subscribeButton: { subscribeButton: {
alignSelf: 'flex-start', alignSelf: 'flex-start',
backgroundColor: Colors.White, backgroundColor: Colors.White,
paddingLeft: 16, paddingLeft: 16,
paddingRight: 16 paddingRight: 16,
position: 'absolute',
right: 8,
bottom: -88,
zIndex: 100
}, },
cover: {
width: '100%',
height: '20%',
},
coverImage: {
width: '100%',
height: '100%'
},
tabBar: {
height: 45,
backgroundColor: Colors.LbryGreen,
flexDirection: 'row',
justifyContent: 'flex-end'
},
tabTitle: {
fontFamily: 'Inter-UI-SemiBold',
fontSize: 14,
color: Colors.White,
},
tab: {
width: '30%',
alignItems: 'center',
justifyContent: 'center'
},
activeTabHint: {
position: 'absolute',
bottom: 0,
backgroundColor: Colors.White,
height: 3,
width: '100%'
},
contentTab: {
flex: 1
},
aboutTab: {
flex: 1
},
aboutScroll: {
flex: 1,
},
aboutItem: {
marginBottom: 24
},
aboutScrollContent: {
padding: 24
},
aboutTitle: {
fontFamily: 'Inter-UI-SemiBold',
fontSize: 16,
lineHeight: 24
},
aboutText: {
fontFamily: 'Inter-UI-Regular',
fontSize: 16,
lineHeight: 24
},
avatarImageContainer: {
width: 80,
height: 80,
borderRadius: 160,
position: 'absolute',
overflow: 'hidden',
left: 24,
bottom: -40,
zIndex: 100
},
avatarImage: {
width: '100%',
height: '100%',
}
}); });
export default channelPageStyle; export default channelPageStyle;

View file

@ -306,6 +306,7 @@ const filePageStyle = StyleSheet.create({
tagContainer: { tagContainer: {
marginLeft: 12, marginLeft: 12,
marginRight: 12, marginRight: 12,
marginBottom: 16,
flexDirection: 'row' flexDirection: 'row'
}, },
tagTitle: { tagTitle: {

View file

@ -84,6 +84,7 @@ ext {
buildToolsVersion = '{{ build_tools_version }}' buildToolsVersion = '{{ build_tools_version }}'
minSdkVersion = {{ args.min_sdk_version }} minSdkVersion = {{ args.min_sdk_version }}
targetSdkVersion = {{ android_api }} targetSdkVersion = {{ android_api }}
supportLibVersion = '27.1.1'
} }
subprojects { subprojects {

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB