diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-11-02 12:09:57 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-02 12:09:57 -0700 |
commit | 0f4bfcb05d4d902209126cca216eac31d49c8f80 (patch) | |
tree | 51de199207ed0d029f76aaf1125058bda1fc40d7 | |
parent | 0e8723c3bb9566542f009994484b30c3da72ede7 (diff) | |
download | voidsky-0f4bfcb05d4d902209126cca216eac31d49c8f80.tar.zst |
Replace draglist due to upstream errors (#1795)
* Replace draggable flatlist with simple sort buttons * Remove react-native-draggable-flatlist dep * Fix hitslops * Update lockfile * Remove bad flex:1
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/state/models/ui/saved-feeds.ts | 10 | ||||
-rw-r--r-- | src/view/screens/SavedFeeds.tsx | 285 | ||||
-rw-r--r-- | yarn.lock | 9 |
4 files changed, 133 insertions, 172 deletions
diff --git a/package.json b/package.json index 01528bf08..24ddbeb18 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,6 @@ "react-dom": "^18.2.0", "react-native": "0.72.5", "react-native-appstate-hook": "^1.0.6", - "react-native-draggable-flatlist": "^4.0.1", "react-native-drawer-layout": "^3.2.0", "react-native-fs": "^2.20.0", "react-native-gesture-handler": "^2.12.1", diff --git a/src/state/models/ui/saved-feeds.ts b/src/state/models/ui/saved-feeds.ts index 881684ee6..667bc03a3 100644 --- a/src/state/models/ui/saved-feeds.ts +++ b/src/state/models/ui/saved-feeds.ts @@ -95,19 +95,15 @@ export class SavedFeedsModel { return } if (direction === 'up' && index !== 0) { - const temp = pinned[index] - pinned[index] = pinned[index - 1] - pinned[index - 1] = temp + ;[pinned[index], pinned[index - 1]] = [pinned[index - 1], pinned[index]] } else if (direction === 'down' && index < pinned.length - 1) { - const temp = pinned[index] - pinned[index] = pinned[index + 1] - pinned[index + 1] = temp + ;[pinned[index], pinned[index + 1]] = [pinned[index + 1], pinned[index]] } + this._updatePinSortOrder(pinned.concat(this.unpinned.map(f => f.uri))) await this.rootStore.preferences.setSavedFeeds( this.rootStore.preferences.savedFeeds, pinned, ) - this._updatePinSortOrder() track('CustomFeed:Reorder', { name: item.displayName, uri: item.uri, diff --git a/src/view/screens/SavedFeeds.tsx b/src/view/screens/SavedFeeds.tsx index 8f8cdc6c9..0f6278288 100644 --- a/src/view/screens/SavedFeeds.tsx +++ b/src/view/screens/SavedFeeds.tsx @@ -1,6 +1,5 @@ import React, {useCallback, useMemo} from 'react' import { - RefreshControl, StyleSheet, View, ActivityIndicator, @@ -18,23 +17,30 @@ import {SavedFeedsModel} from 'state/models/ui/saved-feeds' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {withAuthRequired} from 'view/com/auth/withAuthRequired' import {ViewHeader} from 'view/com/util/ViewHeader' -import {CenteredView} from 'view/com/util/Views' +import {ScrollView, CenteredView} from 'view/com/util/Views' import {Text} from 'view/com/util/text/Text' -import {isWeb} from 'platform/detection' import {s, colors} from 'lib/styles' -import DraggableFlatList, { - ShadowDecorator, - ScaleDecorator, -} from 'react-native-draggable-flatlist' import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard' import {FeedSourceModel} from 'state/models/content/feed-source' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import * as Toast from 'view/com/util/Toast' import {Haptics} from 'lib/haptics' -import {Link, TextLink} from 'view/com/util/Link' +import {TextLink} from 'view/com/util/Link' -type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'> +const HITSLOP_TOP = { + top: 20, + left: 20, + bottom: 5, + right: 20, +} +const HITSLOP_BOTTOM = { + top: 5, + left: 20, + bottom: 20, + right: 20, +} +type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'> export const SavedFeeds = withAuthRequired( observer(function SavedFeedsImpl({}: Props) { const pal = usePalette('default') @@ -55,37 +61,76 @@ export const SavedFeeds = withAuthRequired( }, [screen, store, savedFeeds]), ) - const renderListEmptyComponent = useCallback(() => { - return ( - <View - style={[ - pal.border, - isMobile && s.flex1, - pal.viewLight, - styles.empty, - ]}> - <Text type="lg" style={[pal.text]}> - You don't have any saved feeds. - </Text> - </View> - ) - }, [pal, isMobile]) - - const renderListFooterComponent = useCallback(() => { - return ( - <> - <View style={[styles.footerLinks, pal.border]}> - <Link style={styles.footerLink} href="/feeds"> - <FontAwesomeIcon - icon="search" - size={18} - color={pal.colors.icon} - /> - <Text type="lg-medium" style={pal.textLight}> - Discover new feeds - </Text> - </Link> + return ( + <CenteredView + style={[ + s.hContentRegion, + pal.border, + isTabletOrDesktop && styles.desktopContainer, + ]}> + <ViewHeader title="Edit My Feeds" showOnDesktop showBorder /> + <ScrollView style={s.flex1}> + <View style={[pal.text, pal.border, styles.title]}> + <Text type="title" style={pal.text}> + Pinned Feeds + </Text> </View> + {savedFeeds.hasLoaded ? ( + !savedFeeds.pinned.length ? ( + <View + style={[ + pal.border, + isMobile && s.flex1, + pal.viewLight, + styles.empty, + ]}> + <Text type="lg" style={[pal.text]}> + You don't have any pinned feeds. + </Text> + </View> + ) : ( + savedFeeds.pinned.map(feed => ( + <ListItem + key={feed._reactKey} + savedFeeds={savedFeeds} + item={feed} + /> + )) + ) + ) : ( + <ActivityIndicator style={{marginTop: 20}} /> + )} + <View style={[pal.text, pal.border, styles.title]}> + <Text type="title" style={pal.text}> + Saved Feeds + </Text> + </View> + {savedFeeds.hasLoaded ? ( + !savedFeeds.unpinned.length ? ( + <View + style={[ + pal.border, + isMobile && s.flex1, + pal.viewLight, + styles.empty, + ]}> + <Text type="lg" style={[pal.text]}> + You don't have any saved feeds. + </Text> + </View> + ) : ( + savedFeeds.unpinned.map(feed => ( + <ListItem + key={feed._reactKey} + savedFeeds={savedFeeds} + item={feed} + /> + )) + ) + ) : ( + <ActivityIndicator style={{marginTop: 20}} /> + )} + <View style={styles.footerText}> <Text type="sm" style={pal.textLight}> Feeds are custom algorithms that users build with a little coding @@ -99,60 +144,8 @@ export const SavedFeeds = withAuthRequired( for more information. </Text> </View> - {savedFeeds.isLoading && <ActivityIndicator />} - </> - ) - }, [pal, savedFeeds.isLoading]) - - const onRefresh = useCallback(() => savedFeeds.refresh(), [savedFeeds]) - - const onDragEnd = useCallback( - async ({data}: {data: FeedSourceModel[]}) => { - try { - await savedFeeds.reorderPinnedFeeds(data) - } catch (e) { - Toast.show('There was an issue contacting the server') - store.log.error('Failed to save pinned feed order', {e}) - } - }, - [savedFeeds, store], - ) - - return ( - <CenteredView - style={[ - s.hContentRegion, - pal.border, - isTabletOrDesktop && styles.desktopContainer, - ]}> - <ViewHeader title="Edit My Feeds" showOnDesktop showBorder /> - <DraggableFlatList - containerStyle={[isTabletOrDesktop ? s.hContentRegion : s.flex1]} - data={savedFeeds.pinned.concat(savedFeeds.unpinned)} - keyExtractor={item => item.uri} - refreshing={savedFeeds.isRefreshing} - refreshControl={ - <RefreshControl - refreshing={savedFeeds.isRefreshing} - onRefresh={onRefresh} - tintColor={pal.colors.text} - titleColor={pal.colors.text} - /> - } - renderItem={({item, drag}) => ( - <ListItem savedFeeds={savedFeeds} item={item} drag={drag} /> - )} - getItemLayout={(data, index) => ({ - length: 77, - offset: 77 * index, - index, - })} - initialNumToRender={10} - ListFooterComponent={renderListFooterComponent} - ListEmptyComponent={renderListEmptyComponent} - extraData={savedFeeds.isLoading} - onDragEnd={onDragEnd} - /> + <View style={{height: 100}} /> + </ScrollView> </CenteredView> ) }), @@ -161,11 +154,9 @@ export const SavedFeeds = withAuthRequired( const ListItem = observer(function ListItemImpl({ savedFeeds, item, - drag, }: { savedFeeds: SavedFeedsModel item: FeedSourceModel - drag: () => void }) { const pal = usePalette('default') const store = useStores() @@ -196,59 +187,46 @@ const ListItem = observer(function ListItemImpl({ ) return ( - <ScaleDecorator> - <ShadowDecorator> - <Pressable - accessibilityRole="button" - onLongPress={isPinned ? drag : undefined} - delayLongPress={200} - style={[styles.itemContainer, pal.border]}> - {isPinned && isWeb ? ( - <View style={styles.webArrowButtonsContainer}> - <TouchableOpacity accessibilityRole="button" onPress={onPressUp}> - <FontAwesomeIcon - icon="arrow-up" - size={12} - style={[pal.text, styles.webArrowUpButton]} - /> - </TouchableOpacity> - <TouchableOpacity - accessibilityRole="button" - onPress={onPressDown}> - <FontAwesomeIcon - icon="arrow-down" - size={12} - style={[pal.text]} - /> - </TouchableOpacity> - </View> - ) : isPinned ? ( - <FontAwesomeIcon - icon="bars" - size={20} - color={pal.colors.text} - style={s.ml20} - /> - ) : null} - <FeedSourceCard - key={item.uri} - item={item} - showSaveBtn - style={styles.noBorder} - /> + <Pressable + accessibilityRole="button" + style={[styles.itemContainer, pal.border]}> + {isPinned ? ( + <View style={styles.webArrowButtonsContainer}> <TouchableOpacity accessibilityRole="button" - hitSlop={10} - onPress={onTogglePinned}> + onPress={onPressUp} + hitSlop={HITSLOP_TOP}> <FontAwesomeIcon - icon="thumb-tack" - size={20} - color={isPinned ? colors.blue3 : pal.colors.icon} + icon="arrow-up" + size={12} + style={[pal.text, styles.webArrowUpButton]} /> </TouchableOpacity> - </Pressable> - </ShadowDecorator> - </ScaleDecorator> + <TouchableOpacity + accessibilityRole="button" + onPress={onPressDown} + hitSlop={HITSLOP_BOTTOM}> + <FontAwesomeIcon icon="arrow-down" size={12} style={[pal.text]} /> + </TouchableOpacity> + </View> + ) : null} + <FeedSourceCard + key={item.uri} + item={item} + showSaveBtn + style={styles.noBorder} + /> + <TouchableOpacity + accessibilityRole="button" + hitSlop={10} + onPress={onTogglePinned}> + <FontAwesomeIcon + icon="thumb-tack" + size={20} + color={isPinned ? colors.blue3 : pal.colors.icon} + /> + </TouchableOpacity> + </Pressable> ) }) @@ -262,12 +240,17 @@ const styles = StyleSheet.create({ empty: { paddingHorizontal: 20, paddingVertical: 20, - borderRadius: 16, - marginHorizontal: 24, + borderRadius: 8, + marginHorizontal: 10, marginTop: 10, }, + title: { + paddingHorizontal: 14, + paddingTop: 20, + paddingBottom: 10, + borderBottomWidth: 1, + }, itemContainer: { - flex: 1, flexDirection: 'row', alignItems: 'center', borderBottomWidth: 1, @@ -289,14 +272,4 @@ const styles = StyleSheet.create({ paddingTop: 22, paddingBottom: 100, }, - footerLinks: { - borderBottomWidth: 1, - borderTopWidth: 0, - }, - footerLink: { - flexDirection: 'row', - paddingHorizontal: 26, - paddingVertical: 18, - gap: 18, - }, }) diff --git a/yarn.lock b/yarn.lock index 1611786f5..b42475ac0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1483,7 +1483,7 @@ "@babel/plugin-transform-react-jsx-development" "^7.22.5" "@babel/plugin-transform-react-pure-annotations" "^7.22.5" -"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.0", "@babel/preset-typescript@^7.16.7", "@babel/preset-typescript@^7.17.12": +"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.0", "@babel/preset-typescript@^7.16.7": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz#16367d8b01d640e9a507577ed4ee54e0101e51c8" integrity sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ== @@ -15801,13 +15801,6 @@ react-native-dotenv@^3.3.1: dependencies: dotenv "^16.3.1" -react-native-draggable-flatlist@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/react-native-draggable-flatlist/-/react-native-draggable-flatlist-4.0.1.tgz#2f027d387ba4b8f3eb0907340e32cb85e6460df2" - integrity sha512-ZO1QUTNx64KZfXGXeXcBfql67l38X7kBcJ3rxUVZzPHt5r035GnGzIC0F8rqSXp6zgnwgUYMfB6zQc5PKmPL9Q== - dependencies: - "@babel/preset-typescript" "^7.17.12" - react-native-drawer-layout@^3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/react-native-drawer-layout/-/react-native-drawer-layout-3.2.1.tgz#eb626216181965e72de6d9377ca619fab40226f2" |