diff --git a/app/(tabs)/message.tsx b/app/(tabs)/message.tsx
index 64abae3..8ae1399 100644
--- a/app/(tabs)/message.tsx
+++ b/app/(tabs)/message.tsx
@@ -155,12 +155,10 @@ export default function MessageScreen() {
// Render message item
const renderMessageItem = useCallback(({ item }: { item: Message }) => (
- handleDeleteMessage(item.id)}>
-
-
+
), [handleDeleteMessage, handleMessagePress])
// Render list footer
@@ -288,6 +286,7 @@ const styles = StyleSheet.create({
listContent: {
paddingHorizontal: 4,
paddingTop: 12,
+ paddingBottom: 100,
},
emptyListContent: {
flex: 1,
diff --git a/app/(tabs)/my.tsx b/app/(tabs)/my.tsx
index 24a2454..23b7c04 100644
--- a/app/(tabs)/my.tsx
+++ b/app/(tabs)/my.tsx
@@ -32,7 +32,6 @@ import { MySkeleton } from '@/components/skeleton/MySkeleton'
import { TabNavigation } from '@/components/blocks/home/TabNavigation'
import { useUserBalance } from '@/hooks/use-user-balance'
-import { KeyboardAwareScrollView } from 'react-native-keyboard-controller'
const { width: screenWidth } = Dimensions.get('window')
const GALLERY_GAP = 2
@@ -136,9 +135,13 @@ export default function My() {
// 下拉刷新状态
const [refreshing, setRefreshing] = useState(false)
+ const [favoritesRefreshing, setFavoritesRefreshing] = useState(false)
+ const [likesRefreshing, setLikesRefreshing] = useState(false)
// 防止重复触发加载更多
const isLoadingMoreRef = useRef(false)
+ const isFavoritesLoadingMoreRef = useRef(false)
+ const isLikesLoadingMoreRef = useRef(false)
// 下拉刷新处理
const onRefresh = useCallback(async () => {
@@ -150,6 +153,26 @@ export default function My() {
}
}, [refetch])
+ // 收藏Tab下拉刷新处理
+ const onFavoritesRefresh = useCallback(async () => {
+ setFavoritesRefreshing(true)
+ try {
+ await favoritesRefetch()
+ } finally {
+ setFavoritesRefreshing(false)
+ }
+ }, [favoritesRefetch])
+
+ // 点赞Tab下拉刷新处理
+ const onLikesRefresh = useCallback(async () => {
+ setLikesRefreshing(true)
+ try {
+ await likesRefetch()
+ } finally {
+ setLikesRefreshing(false)
+ }
+ }, [likesRefetch])
+
// 加载更多处理
const handleScroll = useCallback((event: NativeSyntheticEvent) => {
const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent
@@ -173,6 +196,40 @@ export default function My() {
}
}, [loadingMore, hasMore, loadMore, loading])
+ // 收藏Tab加载更多处理
+ const handleFavoritesScroll = useCallback((event: NativeSyntheticEvent) => {
+ const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent
+ const paddingToBottom = 200
+
+ const isCloseToBottom =
+ layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom
+
+ if (isCloseToBottom && !favoritesLoadingMore && favoritesHasMore && !favoritesLoading && !isFavoritesLoadingMoreRef.current) {
+ console.log('🔄 收藏Tab触发加载更多')
+ isFavoritesLoadingMoreRef.current = true
+ favoritesLoadMore().finally(() => {
+ isFavoritesLoadingMoreRef.current = false
+ })
+ }
+ }, [favoritesLoadingMore, favoritesHasMore, favoritesLoadMore, favoritesLoading])
+
+ // 点赞Tab加载更多处理
+ const handleLikesScroll = useCallback((event: NativeSyntheticEvent) => {
+ const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent
+ const paddingToBottom = 200
+
+ const isCloseToBottom =
+ layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom
+
+ if (isCloseToBottom && !likesLoadingMore && likesHasMore && !likesLoading && !isLikesLoadingMoreRef.current) {
+ console.log('🔄 点赞Tab触发加载更多')
+ isLikesLoadingMoreRef.current = true
+ likesLoadMore().finally(() => {
+ isLikesLoadingMoreRef.current = false
+ })
+ }
+ }, [likesLoadingMore, likesHasMore, likesLoadMore, likesLoading])
+
// 处理设置菜单选择
const handleSettingsSelect = async (value: string) => {
if (value === 'changePassword') {
@@ -231,81 +288,169 @@ export default function My() {
]
return (
-
-
+
+
+
-
-
-
- {/* 顶部积分与设置 */}
-
- router.push('/membership' as any)}
- >
-
- {balance}
-
- handleSettingsSelect(value)}
- renderTrigger={(selectedOption, isOpen, toggle) => (
-
-
-
- )}
- dropdownStyle={{
- minWidth: 160,
- right: 10,
- backgroundColor: '#2A2A2A80',
- }}
- />
-
-
- {/* 个人信息区 */}
-
-
-
- {profileName}
- ID {session?.user?.id?.slice(0, 8) || '--------'}
-
- {
- console.log('[my.tsx] Edit Profile button pressed')
- setEditDrawerVisible(true)
- }}
- >
- {t('my.editProfile')}
-
-
-
- {/* Tab 导航 */}
-
+ router.push('/membership' as any)}
+ >
+
+ {balance}
+
+ handleSettingsSelect(value)}
+ renderTrigger={(selectedOption, isOpen, toggle) => (
+
+
+
+ )}
+ dropdownStyle={{
+ minWidth: 160,
+ right: 10,
+ backgroundColor: '#2A2A2A80',
+ }}
/>
+
- {/* 作品九宫格 */}
- {activeTab === 'works' && loading ? (
+ {/* 个人信息区 */}
+
+
+
+ {profileName}
+ ID {session?.user?.id?.slice(0, 8) || '--------'}
+
+ {
+ console.log('[my.tsx] Edit Profile button pressed')
+ setEditDrawerVisible(true)
+ }}
+ >
+ {t('my.editProfile')}
+
+
+
+ {/* Tab 导航 */}
+
+
+ {/* 作品九宫格 */}
+ {activeTab === 'works' && loading ? (
+
+ ) : activeTab === 'works' ? (
+
+ }
+ >
+
+ {generations.map((item, index) => (
+ {
+ if (item.status === 'completed') {
+ router.push({
+ pathname: '/generationRecord' as any,
+ params: { id: item.id },
+ })
+ }
+ }}
+ disabled={item.status !== 'completed'}
+ >
+
+
+ {/* 遮罩:非完成状态 */}
+ {item.status !== 'completed' && (
+
+ )}
+
+ {/* 数量角标:已完成且有结果 */}
+ {item.status === 'completed' && (item.resultUrl?.length || 0) > 0 && (
+
+
+ {item.resultUrl?.length || 1}
+
+
+ )}
+
+ {/* 状态角标 */}
+ {item.status === 'running' && (
+
+ {t('my.generating')}
+
+ )}
+ {item.status === 'pending' && (
+
+ {t('my.queuing')}
+
+ )}
+
+ ))}
+
+ {/* 加载更多指示器 */}
+ {loadingMore && (
+
+
+
+ )}
+
+ {/* 空状态提示 */}
+ {!loading && generations.length === 0 && (
+
+
+ {t('my.noWorks')}
+
+
+ )}
+
+
+ ) : activeTab === 'favorites' && favoritesLoading ? (
- ) : activeTab === 'works' ? (
+ ) : activeTab === 'favorites' ? (
- {generations.map((item, index) => (
- {
- if (item.status === 'completed') {
- router.push({
- pathname: '/generationRecord' as any,
- params: { id: item.id },
- })
- }
- }}
- disabled={item.status !== 'completed'}
- >
-
-
- {/* 遮罩:非完成状态 */}
- {item.status !== 'completed' && (
-
- )}
-
- {/* 数量角标:已完成且有结果 */}
- {item.status === 'completed' && (item.resultUrl?.length || 0) > 0 && (
-
-
- {item.resultUrl?.length || 1}
-
-
- )}
-
- {/* 状态角标 */}
- {item.status === 'running' && (
-
- {t('my.generating')}
-
- )}
- {item.status === 'pending' && (
-
- {t('my.queuing')}
-
- )}
-
- ))}
-
- {/* 加载更多指示器 */}
- {loadingMore && (
-
-
-
- )}
-
- {/* 空状态提示 */}
- {!loading && generations.length === 0 && (
-
-
- {t('my.noWorks')}
-
-
- )}
-
-
- ) : activeTab === 'favorites' && favoritesLoading ? (
-
- ) : activeTab === 'favorites' ? (
-
-
- {favorites.length === 0 ? (
+ {favorites.length === 0 && !favoritesLoading ? (
{t('my.noFavorites')}
) : (
- favorites.map((item, index) => (
-
-
-
- ))
+ <>
+ {favorites.map((item, index) => (
+
+
+
+ ))}
+ {/* 加载更多指示器 */}
+ {favoritesLoadingMore && (
+
+
+
+ )}
+ >
)}
@@ -425,48 +500,66 @@ export default function My() {
style={styles.scrollView}
contentContainerStyle={styles.scrollContent}
showsVerticalScrollIndicator={false}
+ onScroll={handleLikesScroll}
+ scrollEventThrottle={16}
+ refreshControl={
+
+ }
>
- {likes.length === 0 ? (
+ {likes.length === 0 && !likesLoading ? (
{t('my.noLikes')}
) : (
- likes.map((item, index) => (
-
-
-
- ))
+ <>
+ {likes.map((item, index) => (
+
+
+
+ ))}
+ {/* 加载更多指示器 */}
+ {likesLoadingMore && (
+
+
+
+ )}
+ >
)}
) : null}
- {/* 编辑资料抽屉 */}
-
- setEditDrawerVisible(false)}
- initialName={profileName}
- initialAvatar={session?.user?.image}
- onSave={(data) => {
- setProfileName(data.name)
- }}
- />
-
+ {/* 编辑资料抽屉 */}
+ setEditDrawerVisible(false)}
+ initialName={profileName}
+ initialAvatar={session?.user?.image}
+ onSave={(data) => {
+ setProfileName(data.name)
+ }}
+ />
)
}
@@ -506,7 +599,7 @@ const styles = StyleSheet.create({
scrollContent: {
backgroundColor: '#090A0B',
paddingHorizontal: GALLERY_HORIZONTAL_PADDING,
- paddingBottom: 20,
+ paddingBottom: 100,
},
profileSection: {
flexDirection: 'row',
diff --git a/components/message/MessageCard.tsx b/components/message/MessageCard.tsx
index 3680b89..c456b7a 100644
--- a/components/message/MessageCard.tsx
+++ b/components/message/MessageCard.tsx
@@ -112,9 +112,6 @@ export const MessageCard: React.FC = ({
onDelete,
}) => {
const config = getMessageConfig(message.data?.subType)
- const icon = getMessageIcon(message.data?.subType)
- const showAvatar = config.showAvatar && message.data?.likerAvatar
- const showPreview = config.showPreview && message.data?.webpPreviewUrl
const showQuote = config.showQuote && message.data?.originalComment
const handlePress = () => {
@@ -148,15 +145,6 @@ export const MessageCard: React.FC = ({
{message.content}
- {/* Preview Image */}
- {showPreview && (
-
- )}
-
{/* Quote */}
{showQuote && (
diff --git a/hooks/use-messages.ts b/hooks/use-messages.ts
index ec653ae..bbf1996 100644
--- a/hooks/use-messages.ts
+++ b/hooks/use-messages.ts
@@ -25,8 +25,8 @@ export const useMessages = (initialParams?: ListMessagesParams) => {
const [refreshing, setRefreshing] = useState(false)
const [error, setError] = useState(null)
const [data, setData] = useState()
+ const [hasMore, setHasMore] = useState(true)
const currentPageRef = useRef(1)
- const hasMoreRef = useRef(true)
const execute = useCallback(async (params?: ListMessagesParams) => {
setLoading(true)
@@ -53,14 +53,15 @@ export const useMessages = (initialParams?: ListMessagesParams) => {
const currentPage = requestParams.page || 1
const totalPages = data?.totalPages || 1
- hasMoreRef.current = currentPage < totalPages
+ const hasMoreValue = currentPage < totalPages
+ setHasMore(hasMoreValue)
setData(data)
setLoading(false)
return { data, error: null }
}, [initialParams])
const loadMore = useCallback(async () => {
- if (loadingMore || loading || !hasMoreRef.current) return { data: undefined, error: null }
+ if (loadingMore || loading || !hasMore) return { data: undefined, error: null }
setLoadingMore(true)
const nextPage = currentPageRef.current + 1
@@ -83,7 +84,8 @@ export const useMessages = (initialParams?: ListMessagesParams) => {
const newMessages = newData?.messages || []
const totalPages = newData?.totalPages || 1
- hasMoreRef.current = nextPage < totalPages
+ const hasMoreValue = nextPage < totalPages
+ setHasMore(hasMoreValue)
currentPageRef.current = nextPage
setData((prev) => ({
@@ -92,10 +94,10 @@ export const useMessages = (initialParams?: ListMessagesParams) => {
}))
setLoadingMore(false)
return { data: newData, error: null }
- }, [loading, loadingMore, initialParams])
+ }, [loading, loadingMore, hasMore, initialParams])
const refetch = useCallback(async () => {
- hasMoreRef.current = true
+ setHasMore(true)
setRefreshing(true)
const result = await execute()
setRefreshing(false)
@@ -108,11 +110,11 @@ export const useMessages = (initialParams?: ListMessagesParams) => {
loading,
loadingMore,
refreshing,
+ hasMore,
error,
execute,
refetch,
loadMore,
- hasMore: hasMoreRef.current,
}
}
diff --git a/hooks/use-user-favorites.ts b/hooks/use-user-favorites.ts
index 5d971e7..9d95932 100644
--- a/hooks/use-user-favorites.ts
+++ b/hooks/use-user-favorites.ts
@@ -24,8 +24,8 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => {
const [loadingMore, setLoadingMore] = useState(false)
const [error, setError] = useState(null)
const [data, setData] = useState()
+ const [hasMore, setHasMore] = useState(true)
const currentPageRef = useRef(1)
- const hasMoreRef = useRef(true)
const execute = useCallback(async (params?: GetUserFavoritesParams) => {
setLoading(true)
@@ -55,14 +55,15 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => {
const total = data?.total || 0
const limit = requestParams.limit || 20
const totalPages = Math.ceil(total / limit)
- hasMoreRef.current = currentPage < totalPages
+ const hasMoreValue = currentPage < totalPages
+ setHasMore(hasMoreValue)
setData(data)
setLoading(false)
return { data, error: null }
}, [initialParams])
const loadMore = useCallback(async () => {
- if (loadingMore || loading || !hasMoreRef.current) return { data: undefined, error: null }
+ if (loadingMore || loading || !hasMore) return { data: undefined, error: null }
setLoadingMore(true)
const nextPage = currentPageRef.current + 1
@@ -87,7 +88,8 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => {
const total = newData?.total || 0
const limit = requestParams.limit || 20
const totalPages = Math.ceil(total / limit)
- hasMoreRef.current = nextPage < totalPages
+ const hasMoreValue = nextPage < totalPages
+ setHasMore(hasMoreValue)
currentPageRef.current = nextPage
setData((prev) => ({
@@ -98,10 +100,10 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => {
}))
setLoadingMore(false)
return { data: newData, error: null }
- }, [loading, loadingMore, initialParams])
+ }, [loading, loadingMore, hasMore, initialParams])
const refetch = useCallback(() => {
- hasMoreRef.current = true
+ setHasMore(true)
return execute()
}, [execute])
@@ -110,11 +112,11 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => {
favorites: data?.favorites || [],
loading,
loadingMore,
+ hasMore,
error,
execute,
refetch,
loadMore,
- hasMore: hasMoreRef.current,
}
}
diff --git a/hooks/use-user-likes.ts b/hooks/use-user-likes.ts
index cb41ff7..0e2a602 100644
--- a/hooks/use-user-likes.ts
+++ b/hooks/use-user-likes.ts
@@ -21,8 +21,8 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => {
const [loadingMore, setLoadingMore] = useState(false)
const [error, setError] = useState(null)
const [data, setData] = useState()
+ const [hasMore, setHasMore] = useState(true)
const currentPageRef = useRef(1)
- const hasMoreRef = useRef(true)
const execute = useCallback(async (params?: GetUserLikesParams) => {
setLoading(true)
@@ -52,14 +52,15 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => {
const total = data?.total || 0
const limit = requestParams.limit || 20
const totalPages = Math.ceil(total / limit)
- hasMoreRef.current = currentPage < totalPages
+ const hasMoreValue = currentPage < totalPages
+ setHasMore(hasMoreValue)
setData(data)
setLoading(false)
return { data, error: null }
}, [initialParams])
const loadMore = useCallback(async () => {
- if (loadingMore || loading || !hasMoreRef.current) return { data: undefined, error: null }
+ if (loadingMore || loading || !hasMore) return { data: undefined, error: null }
setLoadingMore(true)
const nextPage = currentPageRef.current + 1
@@ -84,7 +85,8 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => {
const total = newData?.total || 0
const limit = requestParams.limit || 20
const totalPages = Math.ceil(total / limit)
- hasMoreRef.current = nextPage < totalPages
+ const hasMoreValue = nextPage < totalPages
+ setHasMore(hasMoreValue)
currentPageRef.current = nextPage
setData((prev) => ({
@@ -93,10 +95,10 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => {
}))
setLoadingMore(false)
return { data: newData, error: null }
- }, [loading, loadingMore, initialParams])
+ }, [loading, loadingMore, hasMore, initialParams])
const refetch = useCallback(() => {
- hasMoreRef.current = true
+ setHasMore(true)
return execute()
}, [execute])
@@ -105,10 +107,10 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => {
likes: data?.likes || [],
loading,
loadingMore,
+ hasMore,
error,
execute,
refetch,
loadMore,
- hasMore: hasMoreRef.current,
}
}