using stacked tabs in profile screen with content overrides

This commit is contained in:
Nouman Tahir 2021-04-13 13:13:42 +05:00
parent de487eb0a6
commit 44bec50e7d
9 changed files with 226 additions and 205 deletions

View File

@ -6,7 +6,9 @@ import { useSelector } from 'react-redux';
import { ThemeContainer } from '../../../containers'; import { ThemeContainer } from '../../../containers';
import styles from '../view/postsListStyles'; import styles from '../view/postsListStyles';
export interface PostsListRef {
scrollToTop:()=>void
}
interface postsListContainerProps extends FlatListProps<any> { interface postsListContainerProps extends FlatListProps<any> {
promotedPosts:Array<any>; promotedPosts:Array<any>;

View File

@ -9,13 +9,18 @@ import { CollapsibleCard } from '../collapsibleCard';
import { Comments } from '../comments'; import { Comments } from '../comments';
import { Header } from '../header'; import { Header } from '../header';
import { NoPost, ProfileSummaryPlaceHolder, WalletDetailsPlaceHolder } from '../basicUIElements'; import { NoPost, ProfileSummaryPlaceHolder, WalletDetailsPlaceHolder } from '../basicUIElements';
import { Posts } from '../posts';
import { ProfileSummary } from '../profileSummary'; import { ProfileSummary } from '../profileSummary';
import { TabBar } from '../tabBar'; import { TabBar } from '../tabBar';
import { Wallet } from '../wallet'; import { Wallet } from '../wallet';
// Constants // Constants
import { PROFILE_FILTERS, PROFILE_FILTERS_VALUE } from '../../constants/options/filters'; import {
PROFILE_FILTERS,
PROFILE_FILTERS_OWN,
PROFILE_FILTERS_VALUE,
PROFILE_SUBFILTERS,
PROFILE_SUBFILTERS_VALUE,
} from '../../constants/options/filters';
// Utils // Utils
import { getFormatedCreatedDate } from '../../utils/time'; import { getFormatedCreatedDate } from '../../utils/time';
@ -74,24 +79,25 @@ class ProfileView extends PureComponent {
return value; return value;
}; };
_isCloseToBottom({ layoutMeasurement, contentOffset, contentSize }) { _onTabChange = ({ i }) => {
return layoutMeasurement.height + contentOffset.y >= contentSize.height - 20; const { estimatedWalletValue, oldEstimatedWalletValue } = this.state;
}
render() { if (i !== 2) {
this.setState({
estimatedWalletValue: 0,
oldEstimatedWalletValue: estimatedWalletValue,
});
} else {
this.setState({ estimatedWalletValue: oldEstimatedWalletValue });
}
};
_renderProfileContent = () => {
const { const {
about, about,
activePage,
changeForceLoadPostState,
comments,
currencyRate,
currencySymbol,
follows, follows,
forceLoadPost,
getReplies,
handleFollowUnfollowUser, handleFollowUnfollowUser,
handleMuteUnmuteUser, handleMuteUnmuteUser,
handleOnBackPress,
handleOnFavoritePress, handleOnFavoritePress,
handleOnFollowsPress, handleOnFollowsPress,
handleOnPressProfileEdit, handleOnPressProfileEdit,
@ -104,20 +110,164 @@ class ProfileView extends PureComponent {
isOwnProfile, isOwnProfile,
isProfileLoading, isProfileLoading,
isReady, isReady,
quickProfile,
resourceCredits, resourceCredits,
selectedUser, selectedUser,
username,
votingPower, votingPower,
isHideImage,
} = this.props; } = this.props;
const { const { isSummaryOpen, collapsibleMoreHeight } = this.state;
isSummaryOpen,
collapsibleMoreHeight, return !isReady ? (
estimatedWalletValue, <ProfileSummaryPlaceHolder />
oldEstimatedWalletValue, ) : (
} = this.state; <CollapsibleCard
title={get(about, 'about')}
isTitleCenter
defaultTitle={intl.formatMessage({
id: 'profile.details',
})}
expanded={!isOwnProfile}
isExpanded={isSummaryOpen}
handleOnExpanded={this._handleOnSummaryExpanded}
moreHeight={collapsibleMoreHeight}
>
<ProfileSummary
date={getFormatedCreatedDate(get(selectedUser, 'created'))}
about={about}
followerCount={follows.follower_count}
followingCount={follows.following_count}
handleFollowUnfollowUser={handleFollowUnfollowUser}
handleMuteUnmuteUser={handleMuteUnmuteUser}
handleOnFavoritePress={handleOnFavoritePress}
handleOnFollowsPress={handleOnFollowsPress}
handleUIChange={this._handleUIChange}
hoursRC={Math.ceil((100 - resourceCredits) * 0.833333) || null}
hoursVP={Math.ceil((100 - votingPower) * 0.833333) || null}
intl={intl}
isDarkTheme={isDarkTheme}
isFavorite={isFavorite}
isFollowing={isFollowing}
isLoggedIn={isLoggedIn}
isMuted={isMuted}
isOwnProfile={isOwnProfile}
isProfileLoading={isProfileLoading}
percentRC={resourceCredits}
percentVP={votingPower}
handleOnPressProfileEdit={handleOnPressProfileEdit}
/>
</CollapsibleCard>
);
};
_contentComentsTab = () => {
const { comments, getReplies, intl, isOwnProfile, username, isHideImage } = this.props;
return (
<View key="profile.comments" style={styles.commentsTabBar}>
{comments && comments.length > 0 ? (
<ScrollView
onScroll={({ nativeEvent }) => {
this._handleOnScroll();
if (this._isCloseToBottom(nativeEvent)) {
this._loadMoreComments();
}
}}
contentContainerStyle={styles.scrollContentContainer}
//scrollEventThrottle={16}
>
<Comments
isProfilePreview
comments={comments}
fetchPost={getReplies}
isOwnProfile={isOwnProfile}
isHideImage={isHideImage}
/>
</ScrollView>
) : (
<NoPost
name={username}
text={intl.formatMessage({
id: 'profile.havent_commented',
})}
defaultText={intl.formatMessage({
id: 'profile.login_to_see',
})}
/>
)}
</View>
);
};
_contentWalletTab = () => {
const { currencyRate, currencySymbol, selectedUser } = this.props;
const { isSummaryOpen, estimatedWalletValue } = this.state;
return (
<View
key="profile.wallet"
tabLabel={
estimatedWalletValue
? `${currencySymbol} ${(estimatedWalletValue * currencyRate).toFixed()}`
: null
}
>
{selectedUser ? (
<Wallet
setEstimatedWalletValue={(value) => this.setState({ estimatedWalletValue: value })}
selectedUser={selectedUser}
handleOnScroll={isSummaryOpen ? this._handleOnScroll : null}
/>
) : (
<WalletDetailsPlaceHolder />
)}
</View>
);
};
_renderTabs = () => {
const { changeForceLoadPostState, forceLoadPost, username, isOwnProfile } = this.props;
const { isSummaryOpen } = this.state;
const filterOptions = isOwnProfile ? PROFILE_FILTERS_OWN : PROFILE_FILTERS;
//compile content overrides
const tabContentOverrides = new Map();
tabContentOverrides.set(1, this._contentComentsTab());
if (!isOwnProfile) {
tabContentOverrides.set(2, this._contentWalletTab());
}
return (
<View style={styles.postTabBar}>
<TabbedPosts
filterOptions={filterOptions}
filterOptionsValue={PROFILE_FILTERS_VALUE}
feedSubfilterOptions={PROFILE_SUBFILTERS}
feedSubfilterOptionsValue={PROFILE_SUBFILTERS_VALUE}
selectedOptionIndex={0}
pageType="profiles"
getFor="blog"
feedUsername={username}
key={username}
handleOnScroll={isSummaryOpen ? this._handleOnScroll : null}
forceLoadPost={forceLoadPost}
changeForceLoadPostState={changeForceLoadPostState}
isFeedScreen={false}
tabContentOverrides={tabContentOverrides}
onChangeTab={this._onTabChange}
stackedTabs={true}
/>
</View>
);
};
_isCloseToBottom({ layoutMeasurement, contentOffset, contentSize }) {
return layoutMeasurement.height + contentOffset.y >= contentSize.height - 20;
}
render() {
const { handleOnBackPress, isOwnProfile, quickProfile } = this.props;
return ( return (
<View style={styles.container}> <View style={styles.container}>
@ -128,148 +278,8 @@ class ProfileView extends PureComponent {
handleOnBackPress={handleOnBackPress} handleOnBackPress={handleOnBackPress}
/> />
<View style={styles.container}> <View style={styles.container}>
{!isReady ? ( {this._renderProfileContent()}
<ProfileSummaryPlaceHolder /> {this._renderTabs()}
) : (
<CollapsibleCard
title={get(about, 'about')}
isTitleCenter
defaultTitle={intl.formatMessage({
id: 'profile.details',
})}
expanded={!isOwnProfile}
isExpanded={isSummaryOpen}
handleOnExpanded={this._handleOnSummaryExpanded}
moreHeight={collapsibleMoreHeight}
// expanded={isLoggedIn}
// locked={!isLoggedIn}
>
<ProfileSummary
date={getFormatedCreatedDate(get(selectedUser, 'created'))}
about={about}
followerCount={follows.follower_count}
followingCount={follows.following_count}
handleFollowUnfollowUser={handleFollowUnfollowUser}
handleMuteUnmuteUser={handleMuteUnmuteUser}
handleOnFavoritePress={handleOnFavoritePress}
handleOnFollowsPress={handleOnFollowsPress}
handleUIChange={this._handleUIChange}
hoursRC={Math.ceil((100 - resourceCredits) * 0.833333) || null}
hoursVP={Math.ceil((100 - votingPower) * 0.833333) || null}
intl={intl}
isDarkTheme={isDarkTheme}
isFavorite={isFavorite}
isFollowing={isFollowing}
isLoggedIn={isLoggedIn}
isMuted={isMuted}
isOwnProfile={isOwnProfile}
isProfileLoading={isProfileLoading}
percentRC={resourceCredits}
percentVP={votingPower}
handleOnPressProfileEdit={handleOnPressProfileEdit}
/>
</CollapsibleCard>
)}
<ScrollableTabView
style={[globalStyles.tabView, styles.tabView]}
initialPage={activePage}
renderTabBar={() => (
<TabBar style={styles.tabbar} tabUnderlineDefaultWidth={80} tabUnderlineScaleX={2} />
)}
onChangeTab={({ i }) => {
if (i !== 2) {
this.setState({
estimatedWalletValue: 0,
oldEstimatedWalletValue: estimatedWalletValue,
});
} else {
this.setState({ estimatedWalletValue: oldEstimatedWalletValue });
}
}}
>
<View
tabLabel={this._getTabLabel(intl.formatMessage({ id: 'profile.post' }))}
style={styles.postTabBar}
>
<TabbedPosts
filterOptions={PROFILE_FILTERS}
filterOptionsValue={PROFILE_FILTERS_VALUE}
selectedOptionIndex={0}
pageType="profiles"
getFor="blog"
feedUsername={username}
key={username}
handleOnScroll={isSummaryOpen ? this._handleOnScroll : null}
forceLoadPost={forceLoadPost}
changeForceLoadPostState={changeForceLoadPostState}
isFeedScreen={false}
/>
</View>
<View
tabLabel={
!isOwnProfile
? this._getTabLabel(intl.formatMessage({ id: 'profile.comments' }))
: this._getTabLabel(intl.formatMessage({ id: 'profile.replies' }))
}
style={styles.commentsTabBar}
>
{comments && comments.length > 0 ? (
<ScrollView
onScroll={({ nativeEvent }) => {
this._handleOnScroll();
if (this._isCloseToBottom(nativeEvent)) {
this._loadMoreComments();
}
}}
contentContainerStyle={styles.scrollContentContainer}
//scrollEventThrottle={16}
>
<Comments
isProfilePreview
comments={comments}
fetchPost={getReplies}
isOwnProfile={isOwnProfile}
isHideImage={isHideImage}
/>
</ScrollView>
) : (
<NoPost
name={username}
text={intl.formatMessage({
id: 'profile.havent_commented',
})}
defaultText={intl.formatMessage({
id: 'profile.login_to_see',
})}
/>
)}
</View>
{!isOwnProfile && (
<View
tabLabel={
estimatedWalletValue
? `${currencySymbol} ${(estimatedWalletValue * currencyRate).toFixed()}`
: intl.formatMessage({
id: 'profile.wallet',
})
}
>
{selectedUser ? (
<Wallet
setEstimatedWalletValue={(value) =>
this.setState({ estimatedWalletValue: value })
}
selectedUser={selectedUser}
handleOnScroll={isSummaryOpen ? this._handleOnScroll : null}
/>
) : (
<WalletDetailsPlaceHolder />
)}
</View>
)}
</ScrollableTabView>
</View> </View>
</View> </View>
); );

View File

@ -16,6 +16,9 @@ export const TabbedPosts = ({
isFeedScreen, isFeedScreen,
feedUsername, feedUsername,
pageType, pageType,
tabContentOverrides,
stackedTabs,
onTabChange,
...props ...props
}:TabbedPostsProps) => { }:TabbedPostsProps) => {
@ -25,7 +28,7 @@ export const TabbedPosts = ({
const isHideImages = useSelector((state) => state.ui.hidePostsThumbnails); const isHideImages = useSelector((state) => state.ui.hidePostsThumbnails);
//initialize state //initialize state
const [initialTabIndex] = useState(selectedOptionIndex == 0 && isFeedScreen ? filterOptions.length : selectedOptionIndex) const [initialTabIndex] = useState(selectedOptionIndex == 0 && stackedTabs ? filterOptions.length : selectedOptionIndex)
const [mainFilters] = useState<TabItem[]>( const [mainFilters] = useState<TabItem[]>(
filterOptions.map((label, index)=>({ filterOptions.map((label, index)=>({
@ -56,7 +59,6 @@ export const TabbedPosts = ({
}else{ }else{
setSelectedFilter(filter) setSelectedFilter(filter)
} }
} }
const _toggleHideImagesFlag = () => { const _toggleHideImagesFlag = () => {
@ -70,19 +72,23 @@ export const TabbedPosts = ({
//initialize first set of pages //initialize first set of pages
const pages = combinedFilters.map((filter)=>( const pages = combinedFilters.map((filter, index)=>{
<TabContent if(tabContentOverrides && tabContentOverrides.has(index)){
key={filter.filterKey} return tabContentOverrides.get(index);
filterKey={filter.filterKey} }
tabLabel={filter.label} return (
isFeedScreen={isFeedScreen} <TabContent
feedUsername={feedUsername} key={filter.filterKey}
pageType={pageType} filterKey={filter.filterKey}
filterScrollRequest={filterScrollRequest} isFeedScreen={isFeedScreen}
onScrollRequestProcessed={_onScrollRequestProcessed} feedUsername={feedUsername}
{...props} pageType={pageType}
/> filterScrollRequest={filterScrollRequest}
)) onScrollRequestProcessed={_onScrollRequestProcessed}
{...props}
/>
)
});
//render tab bar //render tab bar
@ -90,7 +96,7 @@ export const TabbedPosts = ({
return ( return (
<StackedTabBar <StackedTabBar
{...props} {...props}
shouldStack={isFeedScreen && feedUsername} shouldStack={stackedTabs}
firstStack={mainFilters} firstStack={mainFilters}
secondStack={subFilters} secondStack={subFilters}
initialFirstStackIndex={selectedOptionIndex} initialFirstStackIndex={selectedOptionIndex}
@ -106,7 +112,9 @@ export const TabbedPosts = ({
scrollWithoutAnimation={true} scrollWithoutAnimation={true}
locked={true} locked={true}
initialPage={initialTabIndex} initialPage={initialTabIndex}
renderTabBar={_renderTabBar}> renderTabBar={_renderTabBar}
onTabChange={onTabChange}
>
{pages} {pages}
</ScrollableTabView> </ScrollableTabView>
); );

View File

@ -11,6 +11,9 @@ export interface TabbedPostsProps {
pageType:string, pageType:string,
tag:string, tag:string,
forceLoadPosts:boolean, forceLoadPosts:boolean,
tabContentOverrides:Map<number, any>,
stackedTabs:boolean,
onTabChange:(index:number)=>void
handleOnScroll:()=>void, handleOnScroll:()=>void,
} }
@ -44,7 +47,6 @@ export interface TabMeta {
export interface TabContentProps { export interface TabContentProps {
filterKey:string, filterKey:string,
tabLabel:string,
isFeedScreen:boolean, isFeedScreen:boolean,
getFor:string, getFor:string,
pageType:string, pageType:string,

View File

@ -20,7 +20,6 @@ interface StackedTabBarProps {
} }
export const StackedTabBar = ({ export const StackedTabBar = ({
activeTab,
goToPage, goToPage,
tabs, tabs,
shouldStack, shouldStack,
@ -39,9 +38,13 @@ export const StackedTabBar = ({
return ( return (
<> <>
<FilterBar <FilterBar
options={firstStack.map((item) => options={firstStack.map((item, index) => {
intl.formatMessage({ id: `home.${item.label.toLowerCase()}` }).toUpperCase(), return tabs[index]
)} ? tabs[index]
: intl.formatMessage({ id: item.label.toLowerCase() }).toUpperCase()
})
}
selectedOptionIndex={selectedFilterIndex} selectedOptionIndex={selectedFilterIndex}
rightIconName="view-module" rightIconName="view-module"
rightIconType="MaterialIcons" rightIconType="MaterialIcons"
@ -65,7 +68,7 @@ export const StackedTabBar = ({
selectedFilterIndex == 0 && shouldStack && ( selectedFilterIndex == 0 && shouldStack && (
<FilterBar <FilterBar
options={secondStack.map((item) => options={secondStack.map((item) =>
intl.formatMessage({ id: `home.${item.label.toLowerCase()}` }).toUpperCase(), intl.formatMessage({ id: item.label.toLowerCase() }).toUpperCase(),
)} )}
selectedOptionIndex={selectedSecondStackIndex} selectedOptionIndex={selectedSecondStackIndex}
onDropdownSelect={(index)=>{ onDropdownSelect={(index)=>{

View File

@ -8,6 +8,7 @@ import { setInitPosts } from '../../../redux/actions/postsAction';
import NewPostsPopup from './newPostsPopup'; import NewPostsPopup from './newPostsPopup';
import { calculateTimeLeftForPostCheck } from '../services/tabbedPostsReducer'; import { calculateTimeLeftForPostCheck } from '../services/tabbedPostsReducer';
import { AppState } from 'react-native'; import { AppState } from 'react-native';
import { PostsListRef } from '../../postsList/container/postsListContainer';
const TabContent = ({ const TabContent = ({

View File

@ -243,7 +243,7 @@
"posts": "Posts", "posts": "Posts",
"friends": "Friends", "friends": "Friends",
"communities": "Communities", "communities": "Communities",
"popup_postfix":"Posted" "popup_postfix":"Posted",
}, },
"side_menu": { "side_menu": {
"profile": "Profile", "profile": "Profile",

View File

@ -1,14 +1,18 @@
export const POPULAR_FILTERS = ['FEED', 'TOP', 'HOT', 'NEW']; export const POPULAR_FILTERS = ['home.FEED', 'home.TOP', 'home.HOT', 'home.NEW'];
export const POPULAR_FILTERS_VALUE = ['feed', 'trending', 'hot', 'created']; export const POPULAR_FILTERS_VALUE = ['feed', 'trending', 'hot', 'created'];
export const FEED_SUBFILTERS = ['friends', 'communities']; export const FEED_SUBFILTERS = ['home.friends', 'home.communities'];
export const FEED_SUBFILTERS_VALUE = ['friends', 'communities']; export const FEED_SUBFILTERS_VALUE = ['friends', 'communities'];
export const GLOBAL_POST_FILTERS = ['TOP', 'HOT', 'NEW']; export const GLOBAL_POST_FILTERS = ['home.TOP', 'home.HOT', 'home.NEW'];
export const GLOBAL_POST_FILTERS_VALUE = ['trending', 'hot', 'created']; export const GLOBAL_POST_FILTERS_VALUE = ['trending', 'hot', 'created'];
export const PROFILE_FILTERS = ['BLOG', 'POSTS']; export const PROFILE_FILTERS_OWN = ['profile.post', 'profile.replies'];
export const PROFILE_FILTERS_VALUE = ['blog', 'posts']; export const PROFILE_FILTERS = ['profile.post', 'profile.comments', 'profile.wallet'];
export const PROFILE_FILTERS_VALUE = ['feed', 'comments', 'wallet'];
export const PROFILE_SUBFILTERS = ['home.BLOG', 'home.POSTS'];
export const PROFILE_SUBFILTERS_VALUE = ['blog', 'posts'];
// 'TRENDING', // 'TRENDING',
// 'HOT', // 'HOT',

View File

@ -34,17 +34,8 @@ const FeedScreen = () => {
selectedOptionIndex={get(currentAccount, 'name', null) ? 0 : 2} selectedOptionIndex={get(currentAccount, 'name', null) ? 0 : 2}
feedUsername={get(currentAccount, 'name', null)} feedUsername={get(currentAccount, 'name', null)}
isFeedScreen={true} isFeedScreen={true}
stackedTabs={get(currentAccount, 'name', null)}
/> />
{/* <Posts
filterOptions={[...POPULAR_FILTERS]}
filterOptionsValue={[...POPULAR_FILTERS_VALUE]}
feedSubfilterOptions={[...FEED_SUBFILTERS]}
feedSubfilterOptionsValue={[...FEED_SUBFILTERS_VALUE]}
getFor={get(currentAccount, 'name', null) ? 'feed' : 'hot'}
selectedOptionIndex={get(currentAccount, 'name', null) ? 0 : 2}
feedUsername={get(currentAccount, 'name', null)}
isFeedScreen={true}
/> */}
</SafeAreaView> </SafeAreaView>
</Fragment> </Fragment>
)} )}