refactor(HomeScreen): simplify capsule visibility logic and improve list rendering
- Removed unnecessary state and logic related to capsule visibility based on scroll position, streamlining the component's functionality. - Adjusted FlatList properties to enhance rendering performance and layout consistency. - Updated styles for the list header to ensure full-width display, improving the overall UI experience.
This commit is contained in:
@@ -9,9 +9,7 @@ import {
|
|||||||
View,
|
View,
|
||||||
FlatList,
|
FlatList,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
LayoutAnimation,
|
|
||||||
Platform,
|
Platform,
|
||||||
UIManager,
|
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
RefreshControl,
|
RefreshControl,
|
||||||
StatusBar,
|
StatusBar,
|
||||||
@@ -48,7 +46,6 @@ const SWIPE_COOLDOWN_MS = 300;
|
|||||||
const MOBILE_TAB_BAR_HEIGHT = 64;
|
const MOBILE_TAB_BAR_HEIGHT = 64;
|
||||||
const MOBILE_TAB_FLOATING_MARGIN = 12;
|
const MOBILE_TAB_FLOATING_MARGIN = 12;
|
||||||
const MOBILE_FAB_GAP = 12;
|
const MOBILE_FAB_GAP = 12;
|
||||||
const CAPSULE_HIDE_THRESHOLD = 24;
|
|
||||||
|
|
||||||
type ViewMode = 'list' | 'grid';
|
type ViewMode = 'list' | 'grid';
|
||||||
type PostType = 'follow' | 'hot' | 'latest';
|
type PostType = 'follow' | 'hot' | 'latest';
|
||||||
@@ -77,7 +74,6 @@ export const HomeScreen: React.FC = () => {
|
|||||||
const [viewMode, setViewMode] = useState<ViewMode>('list');
|
const [viewMode, setViewMode] = useState<ViewMode>('list');
|
||||||
const [latestCapsules, setLatestCapsules] = useState<LatestCapsule[]>([{ id: '', name: '全部' }]);
|
const [latestCapsules, setLatestCapsules] = useState<LatestCapsule[]>([{ id: '', name: '全部' }]);
|
||||||
const [activeCapsuleId, setActiveCapsuleId] = useState('');
|
const [activeCapsuleId, setActiveCapsuleId] = useState('');
|
||||||
const [showLatestCapsules, setShowLatestCapsules] = useState(true);
|
|
||||||
|
|
||||||
// 图片查看器状态
|
// 图片查看器状态
|
||||||
const [showImageViewer, setShowImageViewer] = useState(false);
|
const [showImageViewer, setShowImageViewer] = useState(false);
|
||||||
@@ -94,15 +90,8 @@ export const HomeScreen: React.FC = () => {
|
|||||||
const postIdsRef = useRef<Set<string>>(new Set());
|
const postIdsRef = useRef<Set<string>>(new Set());
|
||||||
const lastSwipeAtRef = useRef(0);
|
const lastSwipeAtRef = useRef(0);
|
||||||
|
|
||||||
// 网格模式滚动位置检测
|
|
||||||
const gridScrollYRef = useRef(0);
|
|
||||||
const listScrollYRef = useRef(0);
|
|
||||||
const isLoadingMoreRef = useRef(false);
|
const isLoadingMoreRef = useRef(false);
|
||||||
|
|
||||||
if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
|
|
||||||
UIManager.setLayoutAnimationEnabledExperimental(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建一个以 postId 为 key 的 map,用于快速查找
|
// 构建一个以 postId 为 key 的 map,用于快速查找
|
||||||
const postsMap = useMemo(() => {
|
const postsMap = useMemo(() => {
|
||||||
const map = new Map<string, Post>();
|
const map = new Map<string, Post>();
|
||||||
@@ -125,21 +114,6 @@ export const HomeScreen: React.FC = () => {
|
|||||||
const isLatestTab = activeIndex === 1;
|
const isLatestTab = activeIndex === 1;
|
||||||
const currentChannelId = isLatestTab && activeCapsuleId ? activeCapsuleId : undefined;
|
const currentChannelId = isLatestTab && activeCapsuleId ? activeCapsuleId : undefined;
|
||||||
|
|
||||||
const updateCapsuleVisibilityByScroll = useCallback((nextY: number, previousY: number) => {
|
|
||||||
if (!isLatestTab) return;
|
|
||||||
const delta = nextY - previousY;
|
|
||||||
const isScrollingDown = delta > CAPSULE_HIDE_THRESHOLD;
|
|
||||||
const isScrollingUp = delta < -CAPSULE_HIDE_THRESHOLD;
|
|
||||||
|
|
||||||
if (isScrollingDown && showLatestCapsules) {
|
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
|
||||||
setShowLatestCapsules(false);
|
|
||||||
} else if (isScrollingUp && !showLatestCapsules) {
|
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
|
||||||
setShowLatestCapsules(true);
|
|
||||||
}
|
|
||||||
}, [isLatestTab, showLatestCapsules]);
|
|
||||||
|
|
||||||
// 使用差异更新 Hook 获取帖子列表
|
// 使用差异更新 Hook 获取帖子列表
|
||||||
const listKey = useMemo(
|
const listKey = useMemo(
|
||||||
() => `home_${getPostType()}_${currentChannelId || 'all'}`,
|
() => `home_${getPostType()}_${currentChannelId || 'all'}`,
|
||||||
@@ -196,9 +170,7 @@ export const HomeScreen: React.FC = () => {
|
|||||||
if (scrollY + visibleHeight >= contentHeight - 200) {
|
if (scrollY + visibleHeight >= contentHeight - 200) {
|
||||||
loadMore();
|
loadMore();
|
||||||
}
|
}
|
||||||
updateCapsuleVisibilityByScroll(scrollY, gridScrollYRef.current);
|
}, [loadMore]);
|
||||||
gridScrollYRef.current = scrollY;
|
|
||||||
}, [loadMore, updateCapsuleVisibilityByScroll]);
|
|
||||||
|
|
||||||
// 刷新方法 - 先获取正确类型的帖子,再刷新
|
// 刷新方法 - 先获取正确类型的帖子,再刷新
|
||||||
const refresh = useCallback(async () => {
|
const refresh = useCallback(async () => {
|
||||||
@@ -303,12 +275,6 @@ export const HomeScreen: React.FC = () => {
|
|||||||
setActiveIndex(nextIndex);
|
setActiveIndex(nextIndex);
|
||||||
}, [activeIndex]);
|
}, [activeIndex]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setShowLatestCapsules(true);
|
|
||||||
listScrollYRef.current = 0;
|
|
||||||
gridScrollYRef.current = 0;
|
|
||||||
}, [activeIndex]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadChannels = async () => {
|
const loadChannels = async () => {
|
||||||
const list = await channelService.list();
|
const list = await channelService.list();
|
||||||
@@ -481,7 +447,7 @@ export const HomeScreen: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderLatestCapsules = () => {
|
const renderLatestCapsules = () => {
|
||||||
if (!isLatestTab || !showLatestCapsules) {
|
if (!isLatestTab) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,6 +682,7 @@ export const HomeScreen: React.FC = () => {
|
|||||||
renderItem={renderPostList}
|
renderItem={renderPostList}
|
||||||
keyExtractor={keyExtractor}
|
keyExtractor={keyExtractor}
|
||||||
ListHeaderComponent={renderLatestCapsules()}
|
ListHeaderComponent={renderLatestCapsules()}
|
||||||
|
ListHeaderComponentStyle={styles.listHeader}
|
||||||
contentContainerStyle={[
|
contentContainerStyle={[
|
||||||
styles.listContent,
|
styles.listContent,
|
||||||
{
|
{
|
||||||
@@ -735,11 +702,6 @@ export const HomeScreen: React.FC = () => {
|
|||||||
}
|
}
|
||||||
onEndReached={loadMore}
|
onEndReached={loadMore}
|
||||||
onEndReachedThreshold={0.3}
|
onEndReachedThreshold={0.3}
|
||||||
onScroll={(event) => {
|
|
||||||
const nextY = event.nativeEvent.contentOffset.y;
|
|
||||||
updateCapsuleVisibilityByScroll(nextY, listScrollYRef.current);
|
|
||||||
listScrollYRef.current = nextY;
|
|
||||||
}}
|
|
||||||
scrollEventThrottle={16}
|
scrollEventThrottle={16}
|
||||||
ListEmptyComponent={renderEmpty}
|
ListEmptyComponent={renderEmpty}
|
||||||
ListFooterComponent={isLoadingMore ? <Loading size="sm" /> : null}
|
ListFooterComponent={isLoadingMore ? <Loading size="sm" /> : null}
|
||||||
@@ -747,7 +709,7 @@ export const HomeScreen: React.FC = () => {
|
|||||||
maxToRenderPerBatch={8}
|
maxToRenderPerBatch={8}
|
||||||
updateCellsBatchingPeriod={60}
|
updateCellsBatchingPeriod={60}
|
||||||
windowSize={7}
|
windowSize={7}
|
||||||
removeClippedSubviews
|
removeClippedSubviews={false}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -918,6 +880,9 @@ const styles = StyleSheet.create({
|
|||||||
listContent: {
|
listContent: {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
},
|
},
|
||||||
|
listHeader: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
contentContainer: {
|
contentContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user