Merge branch 'main' of ssh://gitea.bowongai.com:222/bowong/expo-duooomi-app

This commit is contained in:
imeepos 2026-01-15 17:04:53 +08:00
commit 05adac1a2c
12 changed files with 79 additions and 43 deletions

View File

@ -77,7 +77,7 @@ const Img = forwardRef<ExpoImage, ImgProps>((props, ref) => {
ref,
// placeholder: blurhash,
source: imageSource,
cachePolicy: 'memory-disk' as const,
cachePolicy: 'disk' as const,
errorSource,
...reset,
}

View File

@ -46,7 +46,7 @@ const VideoBox = ({ url, needWeb = true, width = 256, style, ...videoProps }: Pr
try {
// 先尝试从缓存获取
const cachedUrl = await videoUrlCache.get(url!, width)
// console.log('getRedirectUrl cachedUrl-----------', url, cachedUrl)
// console.log('getRedirectUrl cachedUrl-----------', url, cachedUrl, width)
if (cachedUrl) {
setUrlFinal(cachedUrl)
return

View File

@ -12,7 +12,7 @@ export const IOS_UNIVERSAL_LINK = 'duooomi.bowong.cn'
// 原生版本,原生代码变更时需要更新此版本号
export const VERSION = '1.1.0'
// JavaScript版本JS代码变更时需要更新此版本号
export const APP_VERSION = 'dev202601151820'
export const APP_VERSION = 'dev202601151552'
const ALIPAY_SCHEMA = 'alipay2021006119657394'
const ALIPAY_SCHEMA_SANDBOX = 'alipay9021000158673972'

View File

@ -7,7 +7,6 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { Colors } from '@/constants/theme'
import { userStore } from '@/stores'
import { configureWebBrowser } from '@/utils'
interface BottomNavProps {
currentRoute: string
@ -78,14 +77,14 @@ const CustomTabBar = observer(function CustomTabBar(props: any) {
export default function Layout() {
useEffect(() => {
// 配置WebBrowser
const setupWebBrowser = async () => {
try {
await configureWebBrowser()
} catch (error) {
console.warn('Failed to configure WebBrowser:', error)
}
}
setupWebBrowser()
// const setupWebBrowser = async () => {
// try {
// await configureWebBrowser()
// } catch (error) {
// console.warn('Failed to configure WebBrowser:', error)
// }
// }
// setupWebBrowser()
}, [])
return <Tabs screenOptions={{ headerShown: false }} tabBar={(props: any) => <CustomTabBar {...props} />}></Tabs>

View File

@ -251,6 +251,7 @@ const Generate = observer(function Generate() {
<TemplateItem
isSelected={isSelected}
item={item}
key={item?.id}
itemWidth={itemWidth}
onSelect={() => handleSelectTemplate(item)}
/>
@ -460,6 +461,7 @@ type TemplateItemProps = {
const TemplateItem = memo<TemplateItemProps>(function TemplateItem({ item, itemWidth, isSelected, onSelect }) {
return (
<Block
key={item?.id}
className={`relative overflow-hidden border-2 ${isSelected ? 'border-accent' : 'border-black'}`}
style={{
transform: [{ skewX: '-6deg' }],

View File

@ -17,13 +17,18 @@ import { cn } from '@/utils/cn'
const CATEGORY_ID = process.env.EXPO_PUBLIC_INDEX_GROUP_ID
const ITEM_WIDTH = Math.floor((screenWidth - 24 - 12 * 2) / 3)
const PAGE_SIZE = 21
console.log('Item----------', ITEM_WIDTH)
const PAGE_SIZE = 12
type MediaItem = {
id: string
type: 'image' | 'video'
url: string
url: string | ''
poster?: string
webpPreviewUrl?: string
webpHighPreviewUrl?: string
mp4Url?: string
likeCount?: number
price: number
title?: string
@ -83,9 +88,10 @@ const Index = observer(function Index() {
return {
id: template.id,
type: isVideo ? 'video' : 'image',
url: isVideo
? (template?.webpPreviewUrl ?? template?.previewUrl)
: template.coverImageUrl || template.previewUrl || '',
url: isVideo ? template?.previewUrl || '' : template.coverImageUrl || template.previewUrl || '',
webpPreviewUrl: template?.webpPreviewUrl,
webpHighPreviewUrl: template?.webpHighPreviewUrl,
mp4Url: template?.previewUrl,
poster: isVideo ? template.coverImageUrl : undefined,
likeCount: template.likeCount || 0,
price: template.price || 0,
@ -365,6 +371,7 @@ const Index = observer(function Index() {
isSelected={selectedItem?.id === item.id}
item={item}
itemWidth={ITEM_WIDTH}
key={item?.id}
onSelect={() => setSelectedItem(item)}
/>
),
@ -399,7 +406,8 @@ const Index = observer(function Index() {
}
numColumns={3}
onEndReached={handleLoadMore}
drawDistance={600}
removeClippedSubviews={true}
drawDistance={300}
onEndReachedThreshold={0.3}
refreshControl={<RefreshControl colors={['#FFE500']} refreshing={refreshing} onRefresh={handleRefresh} />}
renderItem={renderItem}
@ -526,7 +534,12 @@ type HeroCircleProps = {
const HeroCircle = observer<HeroCircleProps>(function HeroCircle({ selectedItem, onQuickGen, onOpenSearch }) {
const isAuthenticated = userStore.isAuthenticated
const { balance } = userBalanceStore
const Width = 216
const previewUrl = selectedItem?.webpHighPreviewUrl || selectedItem?.url || ''
const existItem = !!selectedItem?.url
return (
<Block className="relative z-10 items-center">
<Block className="relative mx-[12px] flex-row justify-between">
@ -534,7 +547,7 @@ const HeroCircle = observer<HeroCircleProps>(function HeroCircle({ selectedItem,
<Block className="relative z-10 mt-[20px] flex size-[224px] rounded-full border-4 border-black shadow-deep-black">
{existItem && (
<Block className="relative size-full overflow-hidden rounded-full">
<VideoBox style={{ height: 216, width: 216, borderRadius: 108 }} url={selectedItem.url} />
<VideoBox style={{ height: Width, width: Width, borderRadius: Width }} width={256} url={previewUrl} />
</Block>
)}
@ -626,8 +639,10 @@ const GridItem = memo<GridItemProps>(
function GridItem({ item, isSelected, itemWidth, onSelect }) {
// console.log('item-------------', item);
const previewUrl = item?.webpPreviewUrl || item?.url || ''
return (
<Block className="relative mb-[12px]" onClick={onSelect}>
<Block className="relative mb-[12px]" onClick={onSelect} key={item?.id}>
<Block
className={`relative overflow-hidden border-2 ${isSelected ? 'border-accent' : 'border-black'}`}
style={{
@ -636,7 +651,7 @@ const GridItem = memo<GridItemProps>(
width: itemWidth,
}}
>
<VideoBox style={{ height: itemWidth, width: itemWidth }} url={item.url} />
<VideoBox style={{ height: itemWidth, width: itemWidth }} width={128} url={previewUrl} />
{isSelected && <Block className="absolute inset-0 border-[3px] border-accent" />}

View File

@ -172,7 +172,7 @@ const Sync = observer(() => {
})
.catch((e) => {
Toast.hideLoading()
console.log('e--------', e)
console.log('transferMediaSingle e--------', e)
Toast.show({ title: e || '同步失败' })
})
@ -382,6 +382,7 @@ const Sync = observer(() => {
itemWidth={itemWidth}
post={post}
onSelect={handleItemSelect}
key={post?.id}
/>
)
},
@ -396,7 +397,8 @@ const Sync = observer(() => {
<FlashList
contentContainerStyle={{ paddingHorizontal: 12, paddingBottom: 200 }}
data={posts}
drawDistance={1200}
drawDistance={300}
removeClippedSubviews={true}
// @ts-ignore
estimatedItemSize={itemWidth}
getItemType={() => 'row'}
@ -702,7 +704,7 @@ const GridItem = memo(
}
return (
<Block className="relative" onClick={() => onSelect(post)}>
<Block className="relative" key={post?.id} onClick={() => onSelect(post)}>
<Block
className={`relative overflow-hidden border-2 ${isSelected ? 'shadow-[0px_0px_0px_4px_#FFE500]' : 'shadow-hard-black'} ${isSelected ? 'border-accent' : 'border-black'}`}
style={{ transform: [{ skewX: '-6deg' }], height: itemWidth, width: itemWidth }}
@ -951,7 +953,7 @@ const TopCircleSection = memo(
const GalleryRenderer = memo(({ selectedItem }: { selectedItem: any }) => {
const url = selectedItem?.url || selectedItem?.imageUrl
// console.log('GalleryRenderer--------------', selectedItem)
console.log('GalleryRenderer--------------', selectedItem)
if (!url) return null
@ -961,7 +963,7 @@ const GalleryRenderer = memo(({ selectedItem }: { selectedItem: any }) => {
className="relative z-10 border-4 border-black"
style={{ width: Width, height: Width, borderRadius: Width, overflow: 'hidden' }}
>
<VideoBox style={{ width: Width, height: Width }} url={url} />
<VideoBox style={{ width: Width, height: Width }} width={Width} url={url} />
</View>
)
})

View File

@ -93,7 +93,7 @@ function RootLayout() {
<Stack.Screen name="auth" options={{ headerShown: false }} />
<Stack.Screen name="forgotPassword" options={{ headerShown: false }} />
<Stack.Screen name="pointList" options={{ headerShown: false }} />
<Stack.Screen name="webView" options={{ headerShown: false }} />
<Stack.Screen name="webview" options={{ headerShown: false }} />
</Stack>
</Providers>
)

View File

@ -6,7 +6,7 @@
"build": {
"production": {
"channel": "production",
"distribution": "store",
"distribution": "internal",
"bun": "1.3.3",
"ios": {
"image": "latest"
@ -17,6 +17,10 @@
},
"env": {
"EXPO_PUBLIC_ENV": "production",
"EXPO_PUBLIC_OWNER_ID": "x3xbTCWf7dbtWu4gGU2TeI054L77xtkt",
"EXPO_PUBLIC_INDEX_GROUP_ID": "cmjto2jdq02egeqecpfehyggs",
"EXPO_PUBLIC_GENERATE_GROUP_ID": "cmk3qbw9p0008j2eb84etgxcb",
"FLIPPER_DISABLE": "1",
"GRADLE_OPTS": "-Dorg.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m",
"ORG_GRADLE_PROJECT_reactNativeArchitectures": "arm64-v8a,x86_64"
@ -37,6 +41,10 @@
},
"env": {
"EXPO_PUBLIC_ENV": "development",
"EXPO_PUBLIC_OWNER_ID": "x3xbTCWf7dbtWu4gGU2TeI054L77xtkt",
"EXPO_PUBLIC_INDEX_GROUP_ID": "cmjto2jdq02egeqecpfehyggs",
"EXPO_PUBLIC_GENERATE_GROUP_ID": "cmk3qbw9p0008j2eb84etgxcb",
"GRADLE_OPTS": "-Dorg.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m",
"ORG_GRADLE_PROJECT_reactNativeArchitectures": "arm64-v8a,x86_64"
},
@ -55,6 +63,10 @@
},
"env": {
"EXPO_PUBLIC_ENV": "test",
"EXPO_PUBLIC_OWNER_ID": "x3xbTCWf7dbtWu4gGU2TeI054L77xtkt",
"EXPO_PUBLIC_INDEX_GROUP_ID": "cmjto2jdq02egeqecpfehyggs",
"EXPO_PUBLIC_GENERATE_GROUP_ID": "cmk3qbw9p0008j2eb84etgxcb",
"FLIPPER_DISABLE": "1",
"GRADLE_OPTS": "-Dorg.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m",
"ORG_GRADLE_PROJECT_reactNativeArchitectures": "arm64-v8a,x86_64"

View File

@ -18,6 +18,8 @@ export const useTemplateGenerations = () => {
const currentPageRef = useRef(1)
const hasMoreRef = useRef(true)
const pageSize = 10
const load = useCallback(async (params?: ListTemplateGenerationsInput) => {
setLoading(true)
setError(null)
@ -29,7 +31,7 @@ export const useTemplateGenerations = () => {
async () =>
await templateGeneration.list({
page: params?.page || 1,
limit: params?.limit || 20,
limit: params?.limit || pageSize,
...params,
}),
)
@ -60,7 +62,7 @@ export const useTemplateGenerations = () => {
async () =>
await templateGeneration.list({
page: nextPage,
limit: params?.limit || 20,
limit: params?.limit || pageSize,
...params,
}),
)

View File

@ -10,7 +10,7 @@ interface UseUpdateCheckerOptions {
}
export const useUpdateChecker = ({
interval = 5 * 60 * 1000, // 5分钟
interval = 1 * 60 * 1000, // 5分钟
// 关闭轮询
enablePeriodicCheck = false,
}: UseUpdateCheckerOptions = {}) => {

View File

@ -1,11 +1,13 @@
import AsyncStorage from '@react-native-async-storage/async-storage'
import { APP_VERSION } from '@/app.config'
interface StorageData {
[key: string]: string
}
class Storage {
private readonly STORAGE_KEY = 'app_storage'
private readonly STORAGE_KEY = `app_storage_${APP_VERSION}`
private cache: StorageData = {}
private isInitialized = false
@ -28,23 +30,25 @@ class Storage {
// 获取存储值
async get<T>(key: string): Promise<T | null> {
await this.init()
try {
await this.init()
const value = this.cache[key]
// console.log('get-----------', value)
return value ? (value as unknown as T) : null
const value = this.cache[key]
return value as unknown as T
// console.log('get-----------', value)
} catch (error) {
return null
}
}
// 设置存储
async set(key: string, value: any): Promise<void> {
await this.init()
this.cache[key] = value
// 保存到本地存储
try {
await this.init()
this.cache[key] = value
// 保存到本地存储
await AsyncStorage.setItem(this.STORAGE_KEY, JSON.stringify(this.cache))
// console.log('💾 已存储:', key, '->', value)
} catch (error) {