Merge branch 'main' of ssh://gitea.bowongai.com:222/bowong/expo-duooomi-app
This commit is contained in:
commit
05adac1a2c
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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' }],
|
||||
|
|
|
|||
|
|
@ -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" />}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)
|
||||
|
|
|
|||
14
eas.json
14
eas.json
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ interface UseUpdateCheckerOptions {
|
|||
}
|
||||
|
||||
export const useUpdateChecker = ({
|
||||
interval = 5 * 60 * 1000, // 5分钟
|
||||
interval = 1 * 60 * 1000, // 5分钟
|
||||
// 关闭轮询
|
||||
enablePeriodicCheck = false,
|
||||
}: UseUpdateCheckerOptions = {}) => {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue