Skip to content

Commit

Permalink
Merge pull request #2921 from ecency/nt/feed-filters
Browse files Browse the repository at this point in the history
Nt/feed filters
  • Loading branch information
feruzm authored Sep 20, 2024
2 parents 3416eb6 + 9fdc414 commit 89a3451
Show file tree
Hide file tree
Showing 13 changed files with 211 additions and 144 deletions.
8 changes: 8 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,10 @@ PODS:
- React-Core
- react-native-orientation-locker (1.6.0):
- React-Core
- react-native-pager-view (6.4.1):
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
- react-native-randombytes (3.6.1):
- React-Core
- react-native-receive-sharing-intent (2.0.0):
Expand Down Expand Up @@ -1510,6 +1514,7 @@ DEPENDENCIES:
- react-native-heic-converter (from `../node_modules/react-native-heic-converter`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
- react-native-pager-view (from `../node_modules/react-native-pager-view`)
- react-native-randombytes (from `../node_modules/react-native-randombytes`)
- react-native-receive-sharing-intent (from `../node_modules/react-native-receive-sharing-intent`)
- react-native-render-html (from `../node_modules/react-native-render-html`)
Expand Down Expand Up @@ -1711,6 +1716,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/@react-native-community/netinfo"
react-native-orientation-locker:
:path: "../node_modules/react-native-orientation-locker"
react-native-pager-view:
:path: "../node_modules/react-native-pager-view"
react-native-randombytes:
:path: "../node_modules/react-native-randombytes"
react-native-receive-sharing-intent:
Expand Down Expand Up @@ -1905,6 +1912,7 @@ SPEC CHECKSUMS:
react-native-heic-converter: 8f7cd7a143ef013a54540ef7ebbc232cecb4fa87
react-native-netinfo: 8a7fd3f7130ef4ad2fb4276d5c9f8d3f28d2df3d
react-native-orientation-locker: 4409c5b12b65f942e75449872b4f078b6f27af81
react-native-pager-view: 4e062b5bf27b7070d470c60fd2e091ee641ba852
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
react-native-receive-sharing-intent: 62ab28c50e6ae56d32b9e841d7452091312a0bc7
react-native-render-html: 984dfe2294163d04bf5fe25d7c9f122e60e05ebe
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@tanstack/react-query": "^4.3.9",
"@tanstack/react-query-persist-client": "^4.3.9",
"@tradle/react-native-http": "^2.0.0",
"add": "^2.0.6",
"appcenter": "5.0.0",
"appcenter-analytics": "5.0.0",
"appcenter-crashes": "5.0.0",
Expand Down Expand Up @@ -137,6 +138,7 @@
"react-native-navigation-bar-color": "^2.0.2",
"react-native-orientation-locker": "^1.6.0",
"react-native-os": "^1.2.6",
"react-native-pager-view": "^6.4.1",
"react-native-permissions": "^3.3.0",
"react-native-portalize": "^1.0.7",
"react-native-progress": "^5.0.0",
Expand All @@ -154,6 +156,7 @@
"react-native-snap-carousel": "^3.8.0",
"react-native-svg": "^12.1.1",
"react-native-swiper": "^1.6.0-rc.3",
"react-native-tab-view": "^3.5.2",
"react-native-tcp": "^4.0.0",
"react-native-tus-client": "^1.1.0",
"react-native-udp": "^4.1.4",
Expand Down Expand Up @@ -187,7 +190,8 @@
"tty-browserify": "0.0.0",
"url": "~0.10.1",
"util": "~0.10.3",
"vm-browserify": "0.0.4"
"vm-browserify": "0.0.4",
"yarn": "^1.22.22"
},
"devDependencies": {
"@babel/core": "^7.20.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const CustomiseFiltersModal = ({ pageType }: Props, ref: Ref<CustomiseFiltersMod

// save snippet based on editor pageType
const _onApply = () => {
if (selectedFilters.size !== 3) {
if (selectedFilters.size < 3) {
alert(intl.formatMessage({ id: 'alert.wrong_filter_count' }));
return;
}
Expand Down
65 changes: 32 additions & 33 deletions src/components/tabbedPosts/container/tabbedPosts.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useState } from 'react';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import { TabView, TabBarProps } from 'react-native-tab-view';
import { useWindowDimensions, View } from 'react-native';
import { TabbedPostsProps } from '../types/tabbedPosts.types';
import { StackedTabBar, TabItem } from '../view/stackedTabBar';
import { FeedTabBar, TabItem } from '../view/feedTabBar';
import PostsTabContent from '../view/postsTabContent';

export const TabbedPosts = ({
Expand All @@ -14,15 +15,16 @@ export const TabbedPosts = ({
feedUsername,
pageType,
tabContentOverrides,
imagesToggleEnabled,
stackedTabs,
onTabChange,
...props
}: TabbedPostsProps) => {
const layout = useWindowDimensions();

// initialize state
const [initialTabIndex] = useState(
selectedOptionIndex == 0 && stackedTabs ? filterOptions.length : selectedOptionIndex,
);
const [index, setIndex] = useState(initialTabIndex);

const mainFilters = filterOptions.map(
(label, index) =>
Expand All @@ -43,6 +45,9 @@ export const TabbedPosts = ({
: [];

const combinedFilters = [...mainFilters, ...subFilters];
const [routes] = useState(
combinedFilters.map((filter) => ({ key: filter.filterKey, title: filter.label })),
);

const [selectedFilter, setSelectedFilter] = useState(combinedFilters[initialTabIndex].filterKey);
const [filterScrollRequest, createFilterScrollRequest] = useState<string | null>(null);
Expand All @@ -60,16 +65,22 @@ export const TabbedPosts = ({
createFilterScrollRequest(null);
};

// initialize first set of pages
const pages = combinedFilters.map((filter, index) => {
// render tab bar
const _renderTabBar = (props: TabBarProps<any>) => {
return (
<FeedTabBar {...props} routes={routes} onFilterSelect={_onFilterSelect} pageType={pageType} />
);
};

// Dynamically create scenes for each tab
const renderScene = ({ route }) => {
if (tabContentOverrides && tabContentOverrides.has(index)) {
return tabContentOverrides.get(index);
}

return (
<PostsTabContent
key={filter.filterKey}
filterKey={filter.filterKey}
key={route.key}
filterKey={route.key}
isFeedScreen={isFeedScreen}
isInitialTab={initialTabIndex == index}
feedUsername={feedUsername}
Expand All @@ -79,32 +90,20 @@ export const TabbedPosts = ({
{...props}
/>
);
});

// render tab bar
const _renderTabBar = (props) => {
return (
<StackedTabBar
{...props}
firstStack={mainFilters}
secondStack={subFilters}
initialFirstStackIndex={selectedOptionIndex}
onFilterSelect={_onFilterSelect}
toggleHideImagesFlag={imagesToggleEnabled}
pageType={pageType}
/>
);
};

return (
<ScrollableTabView
scrollWithoutAnimation={true}
locked={true}
initialPage={initialTabIndex}
renderTabBar={_renderTabBar}
onTabChange={onTabChange}
>
{pages}
</ScrollableTabView>
<View style={{ flex: 1, width: layout.width }}>
<TabView
animationEnabled={false}
lazy={true}
swipeEnabled={false}
renderTabBar={_renderTabBar}
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={setIndex}
initialLayout={{ width: layout.width }}
/>
</View>
);
};
59 changes: 59 additions & 0 deletions src/components/tabbedPosts/styles/feedTabBar.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import EStyleSheet from 'react-native-extended-stylesheet';
import getWindowDimensions from '../../../utils/getWindowDimensions';

const deviceWidth = getWindowDimensions().width;

export default EStyleSheet.create({
container: {
justifyContent: 'center',
backgroundColor: '$primaryLightBackground',
shadowOpacity: 0.3,
shadowColor: '$shadowColor',
elevation: 0.1,
shadowOffset: {
height: 1,
},
zIndex: 99,
},

indicatorStyle: {
backgroundColor: 'transparent',
},
tabStyle: {
width: 'auto',
minWidth: deviceWidth / 3 - 12,
height: 38,
paddingTop: 0,
},
tabBarStyle: {
flex: 1,
backgroundColor: EStyleSheet.value('$primaryLightBackground'), // Background color for the TabBar
},

dropdownWrapper: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
marginRight: 8,
flex: 1,
},
filterBarWrapper: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
rightIconWrapper: {
paddingRight: 12,
paddingLeft: 4,
width: 40,
alignSelf: 'center',
},
rightIcon: {
color: '$darkIconColor',
textAlign: 'center',
},
rightIconPlaceholder: {
marginRight: 8,
},
});
2 changes: 0 additions & 2 deletions src/components/tabbedPosts/types/tabbedPosts.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ export interface TabbedPostsProps {
tag: string;
forceLoadPosts: boolean;
tabContentOverrides: Map<number, any>;
imagesToggleEnabled?: boolean;
stackedTabs: boolean;
pinnedPermlink?: string;
onTabChange: (index: number) => void;
handleOnScroll: () => void;
}

Expand Down
77 changes: 77 additions & 0 deletions src/components/tabbedPosts/view/feedTabBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React, { useRef } from 'react';
import { useIntl } from 'react-intl';
import { TabBar, TabBarProps } from 'react-native-tab-view';
import EStyleSheet from 'react-native-extended-stylesheet';
import { useWindowDimensions, View } from 'react-native';
import { CustomiseFiltersModal, IconButton, Tag } from '../..';
import { CustomiseFiltersModalRef } from '../../customiseFiltersModal/customiseFiltersModal';
import styles from '../styles/feedTabBar.styles';

export interface TabItem {
filterKey: string;
label: string;
}

interface FeedTabBarProps extends TabBarProps<any> {
pageType?: 'main' | 'community' | 'profile' | 'ownProfile';
routes: {
key: string;
title: string;
}[];
onFilterSelect: (filterKey: string) => void;
}

export const FeedTabBar = ({ routes, onFilterSelect, pageType, ...props }: FeedTabBarProps) => {
const intl = useIntl();
const layout = useWindowDimensions();

const customiseModalRef = useRef<CustomiseFiltersModalRef>();

const enableCustomTabs = pageType !== undefined;

const _onCustomisePress = () => {
if (customiseModalRef.current) {
customiseModalRef.current.show();
}
};

return (
<View
style={{
flexDirection: 'row',
alignItems: 'center',
backgroundColor: EStyleSheet.value('$primaryLightBackground'),
}}
>
<TabBar
renderLabel={({ route, focused }) => (
<Tag
key={route.key}
value={intl.formatMessage({ id: route.title.toLowerCase() }).toUpperCase()}
isFilter
isPin={focused}
/>
)}
style={styles.tabBarStyle}
indicatorStyle={styles.indicatorStyle}
tabStyle={{ ...styles.tabStyle, minWidth: layout.width / 3 - (enableCustomTabs ? 14 : 0) }}
scrollEnabled={routes.length > 3}
onTabPress={({ route }) => {
onFilterSelect(route.key);
}}
{...props}
/>
{enableCustomTabs && (
<IconButton
iconStyle={styles.rightIcon}
style={styles.rightIconWrapper}
iconType="MaterialIcon"
size={28}
name="add"
onPress={_onCustomisePress}
/>
)}
{enableCustomTabs && <CustomiseFiltersModal pageType={pageType} ref={customiseModalRef} />}
</View>
);
};
2 changes: 1 addition & 1 deletion src/components/tabbedPosts/view/listEmptyView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useNavigation } from '@react-navigation/native';
import { NoPost, PostCardPlaceHolder, UserListItem } from '../..';
import globalStyles from '../../../globalStyles';
import { CommunityListItem, EmptyScreen } from '../../basicUIElements';
import styles from './tabbedPostsStyles';
import styles from '../styles/tabbedPosts.styles';
import { default as ROUTES } from '../../../constants/routeNames';
import {
fetchCommunities,
Expand Down
2 changes: 1 addition & 1 deletion src/components/tabbedPosts/view/scrollTopPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Image as ExpoImage } from 'expo-image';
import Animated, { ZoomIn, ZoomOut } from 'react-native-reanimated';
import EStyleSheet from 'react-native-extended-stylesheet';
import { IconButton } from '../..';
import styles from './tabbedPostsStyles';
import styles from '../styles/tabbedPosts.styles';

interface ScrollTopPopupProps {
onPress: () => void;
Expand Down
Loading

0 comments on commit 89a3451

Please sign in to comment.