diff --git a/app/(tabs)/generate.tsx b/app/(tabs)/generate.tsx
index 4ace44e..eae8e9f 100644
--- a/app/(tabs)/generate.tsx
+++ b/app/(tabs)/generate.tsx
@@ -1,19 +1,20 @@
-import React, { memo, useCallback, useMemo, useState, useEffect } from 'react'
-import { Block, Text, Img, Input, VideoBox } from '@/@share/components'
-import { imgPicker } from '@/@share/apis/imgPicker'
-import Svg, { Defs, Pattern, Rect, Circle } from 'react-native-svg'
+import { FontAwesome, Fontisto, Ionicons } from '@expo/vector-icons'
+import { useRouter } from 'expo-router'
+import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { ActivityIndicator } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import { useAnimatedStyle } from 'react-native-reanimated'
-import { FontAwesome, Fontisto, Ionicons } from '@expo/vector-icons'
-import { screenHeight, screenWidth } from '@/utils'
-import { useRouter } from 'expo-router'
-import { useRecommendedTemplates } from '@/hooks/data/use-recommended-templates'
-import { useCategories } from '@/hooks/data/use-categories'
-import { useTemplates } from '@/hooks/data/use-templates'
-import { ActivityIndicator } from 'react-native'
-import { ApiError } from '@/lib/types'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
+import Svg, { Circle, Defs, Pattern, Rect } from 'react-native-svg'
+
+import { imgPicker } from '@/@share/apis/imgPicker'
+import { Block, Img, Input, Text, VideoBox } from '@/@share/components'
import BannerSection from '@/components/BannerSection'
+import { useCategories } from '@/hooks/data/use-categories'
+import { useRecommendedTemplates } from '@/hooks/data/use-recommended-templates'
+import { useTemplates } from '@/hooks/data/use-templates'
+import { type ApiError } from '@/lib/types'
+import { screenHeight, screenWidth } from '@/utils'
export default function Index() {
const router = useRouter()
@@ -43,7 +44,9 @@ export default function Index() {
const recommended = recommendedTemplates.data?.templates || []
const regular = templates.data?.templates || []
- const all = selectedCategoryId ? regular : [...recommended.map((r: RecommendedTemplate) => r.template).filter(Boolean), ...regular]
+ const all = selectedCategoryId
+ ? regular
+ : [...recommended.map((r: RecommendedTemplate) => r.template).filter(Boolean), ...regular]
return all.map(
(t: any): Template => ({
@@ -128,17 +131,23 @@ export default function Index() {
-
+
- {categoryList.length > 0 && }
+ {categoryList.length > 0 && (
+
+ )}
@@ -158,17 +167,17 @@ export default function Index() {
type BannerProps = { bgVideo: string }
const Banner = memo(function Banner({ bgVideo }) {
return (
-
-
+
+
-
@@ -183,17 +192,17 @@ type HeaderProps = { onSearch: () => void }
const Header = memo(function Header({ onSearch }) {
return (
-
-
- 创造终端
+
+
+ 创造终端
GEN_STUDIO
-
-
+
+
)
@@ -210,26 +219,26 @@ const UploadCard = memo(function UploadCard({ variant, img, onP
return (
{isMe ? (
-
+
我
) : (
-
+
朋友
)}
-
+
{img ? (
-
+
) : (
{isMe ? (
-
+
+
) : (
-
+
+
)}
@@ -251,8 +260,8 @@ type UploadSectionProps = {
const UploadSection = memo(function UploadSection({ meImg, friendImg, onPickMe, onPickFriend }) {
return (
-
-
+
+
)
})
@@ -263,21 +272,21 @@ type PromptSectionProps = {
}
const PromptSection = memo(function PromptSection({ prompt, onChangePrompt }) {
return (
-
+
-
- 提示词
+
+ 提示词
@@ -301,7 +310,7 @@ type TemplateItemProps = {
const TemplateItem = memo(function TemplateItem({ item, itemWidth, isSelected, onSelect }) {
return (
(function TemplateItem({ item, itemW
}}
onClick={onSelect}
>
-
+
{isSelected && }
{isSelected && }
-
+
{item.name}
{item.type === 'video' && (
-
-
+
+
)}
@@ -337,7 +346,7 @@ type CategoryChipProps = {
const CategoryChip = memo(function CategoryChip({ name, isSelected, onSelect }) {
return (
{name}
@@ -346,17 +355,22 @@ const CategoryChip = memo(function CategoryChip({ name, isSel
})
type CategoryFilterProps = {
- categories: Array<{ id: string; name: string }>
+ categories: { id: string; name: string }[]
selectedId: string
onSelect: (id: string) => void
}
const CategoryFilter = memo(function CategoryFilter({ categories, selectedId, onSelect }) {
return (
-
- onSelect('')} />
+
+ onSelect('')} />
{categories.map((cat) => (
- onSelect(cat.id)} />
+ onSelect(cat.id)}
+ />
))}
@@ -393,25 +407,32 @@ const TemplateSection = memo(function TemplateSection({
return (
-
-
+
+
视频模版
-
+
换一波
{loading ? (
-
+
) : error ? (
加载失败
{onRetry && (
-
+
重试
)}
@@ -424,7 +445,15 @@ const TemplateSection = memo(function TemplateSection({
{templates.map((item) => {
const isSelected = selectedTemplateId === item.id
- return onSelectTemplate(item)} />
+ return (
+ onSelectTemplate(item)}
+ />
+ )
})}
)}
@@ -436,12 +465,12 @@ type GenerateSectionProps = { onGenerate: () => void }
const GenerateSection = memo(function GenerateSection({ onGenerate }) {
const insets = useSafeAreaInsets()
return (
-
+
{/* 左侧文字 */}
@@ -450,9 +479,9 @@ const GenerateSection = memo(function GenerateSection({ on
{/* 右侧 Goo 标签 */}
-
-
- 3 Goo
+
+
+ 3 Goo
diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx
index c73d392..4e3615e 100644
--- a/app/(tabs)/index.tsx
+++ b/app/(tabs)/index.tsx
@@ -9,15 +9,21 @@ import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from '
import { ActivityIndicator, RefreshControl, TextInput } from 'react-native'
import BannerSection from '@/components/BannerSection'
-import { useAigcTask } from '@/hooks/actions/use-aigc-task'
+import { useTemplateActions } from '@/hooks/actions/use-template-actions'
import { useAuth } from '@/hooks/core/use-auth'
import { useUserBalance } from '@/hooks/core/use-user-balance'
+import { useTemplates } from '@/hooks/data'
import { useFavoriteTemplates } from '@/hooks/data/use-favorite-templates'
import { usePublicTemplates } from '@/hooks/data/use-public-templates'
-import { useTemplates } from '@/hooks/data/use-templates'
import { screenWidth } from '@/utils'
import { cn } from '@/utils/cn'
+const BACKGROUND_VIDEOS = [
+ 'https://cdn.roasmax.cn/material/b46f380532e14cf58dd350dbacc7c34a.mp4',
+ 'https://cdn.roasmax.cn/material/992e6c5d940c42feb71c27e556b754c0.mp4',
+ 'https://cdn.roasmax.cn/material/e4947477843f4067be7c37569a33d17b.mp4',
+]
+
type MediaItem = {
id: string
type: 'image' | 'video'
@@ -324,7 +330,7 @@ export default function Sync() {
execute: loadPublicTemplates,
} = usePublicTemplates()
const { data: favoritesData, loading: favoritesLoading, execute: loadFavorites } = useFavoriteTemplates()
- const { submitTask, startPolling } = useAigcTask()
+ const { runTemplate } = useTemplateActions()
const [searchText, setSearchText] = useState('')
@@ -365,7 +371,7 @@ export default function Sync() {
useEffect(() => {
if (isAuthenticated && user?.id) {
- loadBalance(user.id)
+ loadBalance()
}
}, [isAuthenticated, user?.id])
@@ -604,39 +610,25 @@ export default function Sync() {
onCancel={() => Toast.hideModal()}
onConfirm={async () => {
Toast.hideModal()
-
- const { taskId, error } = await submitTask({
- model_name: 'default',
- prompt: `生成与 ${selectedItem.id} 相似的内容`,
- img_url: selectedItem.url,
+ // 要传 扣费返回的凭证
+ const { generationId, error } = await runTemplate({
+ templateId: selectedItem.id,
+ data: {},
+ originalUrl: selectedItem.url,
})
- if (error) {
- Toast.show({ title: `提交失败: ${error.message}` })
+ if (error || !generationId) {
+ Toast.show({ title: error?.message || '生成失败' })
return
}
- if (taskId) {
- Toast.show({
- title: '任务提交成功,正在生成中...',
- duration: 30e3,
- })
- startPolling(
- taskId,
- (result) => {
- Toast.show({ title: '生成成功!' })
- if (user?.id) loadBalance(user.id)
- },
- (error) => {
- Toast.show({ title: `生成失败: ${error.message}` })
- },
- )
- }
+ Toast.show({ title: '生成成功!' })
+ if (user?.id) loadBalance()
}}
/>,
{},
)
- }, [isAuthenticated, balance, selectedItem, submitTask, startPolling, user?.id, loadBalance])
+ }, [isAuthenticated, balance, selectedItem, runTemplate, user?.id, loadBalance])
const openSearch = useCallback(() => setIsSearchOpen(true), [])
const closeSearch = useCallback(() => {
diff --git a/app/generateVideo.tsx b/app/generateVideo.tsx
index 0fc9a02..e404113 100644
--- a/app/generateVideo.tsx
+++ b/app/generateVideo.tsx
@@ -176,7 +176,7 @@ export default function GenerateVideoScreen() {
])
if (user?.id) {
- loadBalance(user.id)
+ loadBalance()
}
}
diff --git a/app/generationRecord.tsx b/app/generationRecord.tsx
index 2bd2e8e..a63b167 100644
--- a/app/generationRecord.tsx
+++ b/app/generationRecord.tsx
@@ -49,7 +49,7 @@ export default function GenerationRecordScreen() {
useEffect(() => {
if (user?.id) {
- loadBalance(user.id)
+ loadBalance()
}
}, [user?.id])
@@ -110,7 +110,7 @@ export default function GenerationRecordScreen() {
} else {
Alert.alert('生成成功', '视频已生成完成')
if (user?.id) {
- loadBalance(user.id)
+ loadBalance()
}
if (newGeneration?.id) {
router.replace({
@@ -315,7 +315,7 @@ const styles = StyleSheet.create({
alignItems: 'center',
paddingHorizontal: 16,
marginBottom: 8,
- gap:4,
+ gap: 4,
},
categoryIcon: {
width: 16,