diff --git a/app.json b/app.json
index 6accc99..8c0a32a 100644
--- a/app.json
+++ b/app.json
@@ -20,7 +20,8 @@
},
"edgeToEdgeEnabled": true,
"predictiveBackGestureEnabled": false,
- "package": "com.anonymous.bwexpoappv3"
+ "package": "com.anonymous.bwexpoappv3",
+ "versionCode": 3
},
"web": {
"output": "static",
@@ -42,7 +43,8 @@
],
"expo-video",
"expo-audio",
- "expo-web-browser"
+ "expo-web-browser",
+ "expo-asset"
],
"experiments": {
"typedRoutes": true,
@@ -53,6 +55,6 @@
"projectId": "191f0396-3e0c-40ec-bd06-b15f58278b8f"
}
},
- "owner": "imeepos"
+ "owner": "bowong"
}
}
diff --git a/app/result.tsx b/app/result.tsx
index 447321c..2a0f686 100644
--- a/app/result.tsx
+++ b/app/result.tsx
@@ -1,10 +1,29 @@
import { ThemedView } from '@/components/themed-view';
-import { VideoView, useVideoPlayer } from 'expo-video';
-import * as MediaLibrary from 'expo-media-library';
-import * as FileSystem from 'expo-file-system';
-import { Platform } from 'react-native';
-import { ThemedText } from '@/components/themed-text';
import { getTemplateGeneration } from '@/lib/api/template-runs';
+import * as Clipboard from 'expo-clipboard';
+import * as FileSystem from 'expo-file-system';
+import * as MediaLibrary from 'expo-media-library';
+import { router, useLocalSearchParams } from 'expo-router';
+import { VideoView, useVideoPlayer } from 'expo-video';
+import {
+ ArrowLeft,
+ Copy,
+ Download,
+ Maximize2,
+ Plus,
+ X,
+} from 'lucide-react';
+import React, { useEffect, useState } from 'react';
+import {
+ ActivityIndicator,
+ Alert,
+ Dimensions,
+ Image, Modal, Platform, ScrollView,
+ StyleSheet, Text,
+ TouchableOpacity,
+ View
+} from 'react-native';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
// ResizeMode 兼容映射 - 移除 'stretch',expo-video 不支持
const ResizeMode = {
@@ -12,43 +31,33 @@ const ResizeMode = {
COVER: 'cover' as const,
STRETCH: 'fill' as const, // 使用 'fill' 替代 'stretch'
};
-import { router, useLocalSearchParams } from 'expo-router';
-import { useSafeAreaInsets } from 'react-native-safe-area-context';
-import {
- Copy,
- Download,
- Maximize2,
- Plus,
- X,
- ArrowLeft,
-} from 'lucide-react';
-import React, { useEffect, useState } from 'react';
-import {
- ActivityIndicator,
- Alert,
- Dimensions,
- Image,
- ImageStyle,
- Modal,
- ScrollView,
- StyleSheet,
- StyleProp,
- Text,
- TouchableOpacity,
- View,
- ViewStyle,
- FlatList,
-} from 'react-native';
const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
const HERO_HEIGHT = screenWidth * 0.58;
const VIDEO_HEIGHT = screenHeight * 0.6;
+// 原生视频播放组件
+const NativeVideoPlayer: React.FC<{ url: string; style?: any }> = ({ url, style }) => {
+ const player = useVideoPlayer(url, player => {
+ player.loop = false;
+ });
+
+ return (
+
+ );
+};
+
interface ResultWithTemplate {
id: string;
userId: string;
templateId: string;
- type: 'TEXT' | 'IMAGE' | 'VIDEO';
+ type: 'UNKNOWN' | 'TEXT' | 'IMAGE' | 'VIDEO';
resultUrl: string[];
status: 'pending' | 'running' | 'completed' | 'failed';
creditsCost?: number;
@@ -233,7 +242,7 @@ export default function ResultPage() {
if (!result || result.type !== 'TEXT') return;
try {
- await navigator.clipboard?.writeText?.(result.resultUrl[0]);
+ await Clipboard.setStringAsync(result.resultUrl[0]);
Alert.alert('复制成功', '文本已复制到剪贴板');
} catch (error) {
Alert.alert('复制失败', '无法复制文本');
@@ -306,9 +315,10 @@ export default function ResultPage() {
playsInline
/>
) : (
-
- Video: {url}
-
+
)
) : (
) : (
-
- Video Player
-
+
)}
>
)}
diff --git a/app/templates/[id].tsx b/app/templates/[id].tsx
index 5905267..972c818 100644
--- a/app/templates/[id].tsx
+++ b/app/templates/[id].tsx
@@ -87,6 +87,7 @@ export default function TemplateDetailScreen() {
const [menuVisible, setMenuVisible] = useState(false);
const [loadingLooks, setLoadingLooks] = useState(true);
const [errorMessage, setErrorMessage] = useState(null);
+ const [retryTrigger, setRetryTrigger] = useState(0);
const abortControllerRef = useRef(null);
const imageCache = useRef(new Set());
@@ -242,22 +243,15 @@ export default function TemplateDetailScreen() {
cache.delete(`tag:${current?.title}`);
setErrorMessage(null);
setLoadingLooks(true);
-
- const event = new Event('retry');
- window.dispatchEvent(event);
+ setRetryTrigger(prev => prev + 1);
}, [id, current?.title]);
useEffect(() => {
- const handleRetryEvent = () => {
+ if (retryTrigger > 0) {
const newController = new AbortController();
abortControllerRef.current = newController;
- };
-
- window.addEventListener('retry', handleRetryEvent);
- return () => {
- window.removeEventListener('retry', handleRetryEvent);
- };
- }, []);
+ }
+ }, [retryTrigger]);
const handleGenerate = () => {
if (!resolvedTemplateId) {
diff --git a/bun.lock b/bun.lock
index 196c7c4..57f64c9 100644
--- a/bun.lock
+++ b/bun.lock
@@ -16,8 +16,11 @@
"better-auth": "1.3.27",
"eas-cli": "^16.22.0",
"expo": "54.0.23",
+ "expo-asset": "~12.0.9",
"expo-audio": "~1.0.14",
+ "expo-clipboard": "~8.0.7",
"expo-constants": "~18.0.10",
+ "expo-crypto": "~15.0.7",
"expo-dev-client": "~6.0.17",
"expo-file-system": "~19.0.17",
"expo-font": "~14.0.9",
@@ -312,7 +315,7 @@
"@expo/fingerprint": ["@expo/fingerprint@0.15.3", "", { "dependencies": { "@expo/spawn-async": "^1.7.2", "arg": "^5.0.2", "chalk": "^4.1.2", "debug": "^4.3.4", "getenv": "^2.0.0", "glob": "^10.4.2", "ignore": "^5.3.1", "minimatch": "^9.0.0", "p-limit": "^3.1.0", "resolve-from": "^5.0.0", "semver": "^7.6.0" }, "bin": { "fingerprint": "bin/cli.js" } }, "sha512-8YPJpEYlmV171fi+t+cSLMX1nC5ngY9j2FiN70dHldLpd6Ct6ouGhk96svJ4BQZwsqwII2pokwzrDAwqo4Z0FQ=="],
- "@expo/image-utils": ["@expo/image-utils@0.6.5", "https://registry.npmmirror.com/@expo/image-utils/-/image-utils-0.6.5.tgz", { "dependencies": { "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "fs-extra": "9.0.0", "getenv": "^1.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", "semver": "^7.6.0", "temp-dir": "~2.0.0", "unique-string": "~2.0.0" } }, "sha512-RsS/1CwJYzccvlprYktD42KjyfWZECH6PPIEowvoSmXfGLfdViwcUEI4RvBfKX5Jli6P67H+6YmHvPTbGOboew=="],
+ "@expo/image-utils": ["@expo/image-utils@0.8.7", "https://registry.npmmirror.com/@expo/image-utils/-/image-utils-0.8.7.tgz", { "dependencies": { "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", "resolve-global": "^1.0.0", "semver": "^7.6.0", "temp-dir": "~2.0.0", "unique-string": "~2.0.0" } }, "sha512-SXOww4Wq3RVXLyOaXiCCuQFguCDh8mmaHBv54h/R29wGl4jRY8GEyQEx8SypV/iHt1FbzsU/X3Qbcd9afm2W2w=="],
"@expo/json-file": ["@expo/json-file@8.3.3", "https://registry.npmmirror.com/@expo/json-file/-/json-file-8.3.3.tgz", { "dependencies": { "@babel/code-frame": "~7.10.4", "json5": "^2.2.2", "write-file-atomic": "^2.3.0" } }, "sha512-eZ5dld9AD0PrVRiIWpRkm5aIoWBw3kAyd8VkuWEy92sEthBKDDDHAnK2a0dw0Eil6j7rK7lS/Qaq/Zzngv2h5A=="],
@@ -1072,6 +1075,8 @@
"expo-audio": ["expo-audio@1.0.14", "", { "peerDependencies": { "expo": "*", "expo-asset": "*", "react": "*", "react-native": "*" } }, "sha512-UU8n1mIDPfO9zFQbPnIpnzhHeqC8c8WQUoOOFvlgI5CeOJMUrQ6UXDpX+LBcHxw/amSBhF5HP6VMr58foPKwbA=="],
+ "expo-clipboard": ["expo-clipboard@8.0.7", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-zvlfFV+wB2QQrQnHWlo0EKHAkdi2tycLtE+EXFUWTPZYkgu1XcH+aiKfd4ul7Z0SDF+1IuwoiW9AA9eO35aj3Q=="],
+
"expo-constants": ["expo-constants@18.0.10", "", { "dependencies": { "@expo/config": "~12.0.10", "@expo/env": "~2.0.7" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Rhtv+X974k0Cahmvx6p7ER5+pNhBC0XbP1lRviL2J1Xl4sT2FBaIuIxF/0I0CbhOsySf0ksqc5caFweAy9Ewiw=="],
"expo-crypto": ["expo-crypto@15.0.7", "https://registry.npmmirror.com/expo-crypto/-/expo-crypto-15.0.7.tgz", { "dependencies": { "base64-js": "^1.3.0" }, "peerDependencies": { "expo": "*" } }, "sha512-FUo41TwwGT2e5rA45PsjezI868Ch3M6wbCZsmqTWdF/hr+HyPcrp1L//dsh/hsrsyrQdpY/U96Lu71/wXePJeg=="],
@@ -2216,8 +2221,6 @@
"@expo/cli/@expo/env": ["@expo/env@2.0.7", "https://registry.npmmirror.com/@expo/env/-/env-2.0.7.tgz", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "dotenv": "~16.4.5", "dotenv-expand": "~11.0.6", "getenv": "^2.0.0" } }, "sha512-BNETbLEohk3HQ2LxwwezpG8pq+h7Fs7/vAMP3eAtFT1BCpprLYoBBFZH7gW4aqGfqOcVP4Lc91j014verrYNGg=="],
- "@expo/cli/@expo/image-utils": ["@expo/image-utils@0.8.7", "https://registry.npmmirror.com/@expo/image-utils/-/image-utils-0.8.7.tgz", { "dependencies": { "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", "resolve-global": "^1.0.0", "semver": "^7.6.0", "temp-dir": "~2.0.0", "unique-string": "~2.0.0" } }, "sha512-SXOww4Wq3RVXLyOaXiCCuQFguCDh8mmaHBv54h/R29wGl4jRY8GEyQEx8SypV/iHt1FbzsU/X3Qbcd9afm2W2w=="],
-
"@expo/cli/@expo/json-file": ["@expo/json-file@10.0.7", "https://registry.npmmirror.com/@expo/json-file/-/json-file-10.0.7.tgz", { "dependencies": { "@babel/code-frame": "~7.10.4", "json5": "^2.2.3" } }, "sha512-z2OTC0XNO6riZu98EjdNHC05l51ySeTto6GP7oSQrCvQgG9ARBwD1YvMQaVZ9wU7p/4LzSf1O7tckL3B45fPpw=="],
"@expo/cli/@expo/osascript": ["@expo/osascript@2.3.7", "https://registry.npmmirror.com/@expo/osascript/-/osascript-2.3.7.tgz", { "dependencies": { "@expo/spawn-async": "^1.7.2", "exec-async": "^2.2.0" } }, "sha512-IClSOXxR0YUFxIriUJVqyYki7lLMIHrrzOaP01yxAL1G8pj2DWV5eW1y5jSzIcIfSCNhtGsshGd1tU/AYup5iQ=="],
@@ -2288,7 +2291,7 @@
"@expo/fingerprint/semver": ["semver@7.7.3", "https://registry.npmmirror.com/semver/-/semver-7.7.3.tgz", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
- "@expo/image-utils/fs-extra": ["fs-extra@9.0.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.0.0.tgz", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^1.0.0" } }, "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g=="],
+ "@expo/image-utils/getenv": ["getenv@2.0.0", "https://registry.npmmirror.com/getenv/-/getenv-2.0.0.tgz", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="],
"@expo/image-utils/semver": ["semver@7.7.3", "https://registry.npmmirror.com/semver/-/semver-7.7.3.tgz", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
@@ -2332,6 +2335,8 @@
"@expo/plugin-warn-if-update-available/tslib": ["tslib@2.8.1", "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+ "@expo/prebuild-config/@expo/image-utils": ["@expo/image-utils@0.6.5", "https://registry.npmmirror.com/@expo/image-utils/-/image-utils-0.6.5.tgz", { "dependencies": { "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "fs-extra": "9.0.0", "getenv": "^1.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", "semver": "^7.6.0", "temp-dir": "~2.0.0", "unique-string": "~2.0.0" } }, "sha512-RsS/1CwJYzccvlprYktD42KjyfWZECH6PPIEowvoSmXfGLfdViwcUEI4RvBfKX5Jli6P67H+6YmHvPTbGOboew=="],
+
"@expo/prebuild-config/@expo/json-file": ["@expo/json-file@9.1.5", "https://registry.npmmirror.com/@expo/json-file/-/json-file-9.1.5.tgz", { "dependencies": { "@babel/code-frame": "~7.10.4", "json5": "^2.2.3" } }, "sha512-prWBhLUlmcQtvN6Y7BpW2k9zXGd3ySa3R6rAguMJkp1z22nunLN64KYTUWfijFlprFoxm9r2VNnGkcbndAlgKA=="],
"@expo/prebuild-config/@react-native/normalize-colors": ["@react-native/normalize-colors@0.76.2", "https://registry.npmmirror.com/@react-native/normalize-colors/-/normalize-colors-0.76.2.tgz", {}, "sha512-ICoOpaTLPsFQjNLSM00NgQr6wal300cZZonHVSDXKntX+BfkLeuCHRtr/Mn+klTtW+/1v2/2FRm9dXjvyGf9Dw=="],
@@ -2480,8 +2485,6 @@
"expo/@expo/config-plugins": ["@expo/config-plugins@54.0.2", "https://registry.npmmirror.com/@expo/config-plugins/-/config-plugins-54.0.2.tgz", { "dependencies": { "@expo/config-types": "^54.0.8", "@expo/json-file": "~10.0.7", "@expo/plist": "^0.4.7", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^10.4.2", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slash": "^3.0.0", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-jD4qxFcURQUVsUFGMcbo63a/AnviK8WUGard+yrdQE3ZrB/aurn68SlApjirQQLEizhjI5Ar2ufqflOBlNpyPg=="],
- "expo-asset/@expo/image-utils": ["@expo/image-utils@0.8.7", "https://registry.npmmirror.com/@expo/image-utils/-/image-utils-0.8.7.tgz", { "dependencies": { "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", "resolve-global": "^1.0.0", "semver": "^7.6.0", "temp-dir": "~2.0.0", "unique-string": "~2.0.0" } }, "sha512-SXOww4Wq3RVXLyOaXiCCuQFguCDh8mmaHBv54h/R29wGl4jRY8GEyQEx8SypV/iHt1FbzsU/X3Qbcd9afm2W2w=="],
-
"expo-asset/expo-constants": ["expo-constants@18.0.9", "https://registry.npmmirror.com/expo-constants/-/expo-constants-18.0.9.tgz", { "dependencies": { "@expo/config": "~12.0.9", "@expo/env": "~2.0.7" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-sqoXHAOGDcr+M9NlXzj1tGoZyd3zxYDy215W6E0Z0n8fgBaqce9FAYQE2bu5X4G629AYig5go7U6sQz7Pjcm8A=="],
"expo-constants/@expo/config": ["@expo/config@12.0.10", "https://registry.npmmirror.com/@expo/config/-/config-12.0.10.tgz", { "dependencies": { "@babel/code-frame": "~7.10.4", "@expo/config-plugins": "~54.0.2", "@expo/config-types": "^54.0.8", "@expo/json-file": "^10.0.7", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^10.4.2", "require-from-string": "^2.0.2", "resolve-from": "^5.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4", "sucrase": "3.35.0" } }, "sha512-lJMof5Nqakq1DxGYlghYB/ogSBjmv4Fxn1ovyDmcjlRsQdFCXgu06gEUogkhPtc9wBt9WlTTfqENln5HHyLW6w=="],
@@ -2704,8 +2707,6 @@
"@expo/fingerprint/minimatch/brace-expansion": ["brace-expansion@2.0.2", "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
- "@expo/image-utils/fs-extra/universalify": ["universalify@1.0.0", "https://registry.npmmirror.com/universalify/-/universalify-1.0.0.tgz", {}, "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="],
-
"@expo/metro-config/@expo/config/@babel/code-frame": ["@babel/code-frame@7.10.4", "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.10.4.tgz", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
"@expo/metro-config/@expo/config/@expo/config-plugins": ["@expo/config-plugins@54.0.2", "https://registry.npmmirror.com/@expo/config-plugins/-/config-plugins-54.0.2.tgz", { "dependencies": { "@expo/config-types": "^54.0.8", "@expo/json-file": "~10.0.7", "@expo/plist": "^0.4.7", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^10.4.2", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slash": "^3.0.0", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-jD4qxFcURQUVsUFGMcbo63a/AnviK8WUGard+yrdQE3ZrB/aurn68SlApjirQQLEizhjI5Ar2ufqflOBlNpyPg=="],
@@ -2742,6 +2743,8 @@
"@expo/plugin-warn-if-update-available/@oclif/core/supports-color": ["supports-color@8.1.1", "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
+ "@expo/prebuild-config/@expo/image-utils/fs-extra": ["fs-extra@9.0.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.0.0.tgz", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^1.0.0" } }, "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g=="],
+
"@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
"@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
@@ -2804,10 +2807,6 @@
"eas-cli/minimatch/brace-expansion": ["brace-expansion@2.0.2", "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
- "expo-asset/@expo/image-utils/getenv": ["getenv@2.0.0", "https://registry.npmmirror.com/getenv/-/getenv-2.0.0.tgz", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="],
-
- "expo-asset/@expo/image-utils/semver": ["semver@7.7.3", "https://registry.npmmirror.com/semver/-/semver-7.7.3.tgz", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
"expo-asset/expo-constants/@expo/config": ["@expo/config@12.0.10", "https://registry.npmmirror.com/@expo/config/-/config-12.0.10.tgz", { "dependencies": { "@babel/code-frame": "~7.10.4", "@expo/config-plugins": "~54.0.2", "@expo/config-types": "^54.0.8", "@expo/json-file": "^10.0.7", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^10.4.2", "require-from-string": "^2.0.2", "resolve-from": "^5.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4", "sucrase": "3.35.0" } }, "sha512-lJMof5Nqakq1DxGYlghYB/ogSBjmv4Fxn1ovyDmcjlRsQdFCXgu06gEUogkhPtc9wBt9WlTTfqENln5HHyLW6w=="],
"expo-asset/expo-constants/@expo/env": ["@expo/env@2.0.7", "https://registry.npmmirror.com/@expo/env/-/env-2.0.7.tgz", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "dotenv": "~16.4.5", "dotenv-expand": "~11.0.6", "getenv": "^2.0.0" } }, "sha512-BNETbLEohk3HQ2LxwwezpG8pq+h7Fs7/vAMP3eAtFT1BCpprLYoBBFZH7gW4aqGfqOcVP4Lc91j014verrYNGg=="],
@@ -2850,8 +2849,6 @@
"expo-splash-screen/@expo/prebuild-config/@expo/config-types": ["@expo/config-types@54.0.8", "https://registry.npmmirror.com/@expo/config-types/-/config-types-54.0.8.tgz", {}, "sha512-lyIn/x/Yz0SgHL7IGWtgTLg6TJWC9vL7489++0hzCHZ4iGjVcfZmPTUfiragZ3HycFFj899qN0jlhl49IHa94A=="],
- "expo-splash-screen/@expo/prebuild-config/@expo/image-utils": ["@expo/image-utils@0.8.7", "https://registry.npmmirror.com/@expo/image-utils/-/image-utils-0.8.7.tgz", { "dependencies": { "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", "resolve-global": "^1.0.0", "semver": "^7.6.0", "temp-dir": "~2.0.0", "unique-string": "~2.0.0" } }, "sha512-SXOww4Wq3RVXLyOaXiCCuQFguCDh8mmaHBv54h/R29wGl4jRY8GEyQEx8SypV/iHt1FbzsU/X3Qbcd9afm2W2w=="],
-
"expo-splash-screen/@expo/prebuild-config/@expo/json-file": ["@expo/json-file@10.0.7", "https://registry.npmmirror.com/@expo/json-file/-/json-file-10.0.7.tgz", { "dependencies": { "@babel/code-frame": "~7.10.4", "json5": "^2.2.3" } }, "sha512-z2OTC0XNO6riZu98EjdNHC05l51ySeTto6GP7oSQrCvQgG9ARBwD1YvMQaVZ9wU7p/4LzSf1O7tckL3B45fPpw=="],
"expo-splash-screen/@expo/prebuild-config/@react-native/normalize-colors": ["@react-native/normalize-colors@0.81.4", "https://registry.npmmirror.com/@react-native/normalize-colors/-/normalize-colors-0.81.4.tgz", {}, "sha512-9nRRHO1H+tcFqjb9gAM105Urtgcanbta2tuqCVY0NATHeFPDEAB7gPyiLxCHKMi1NbhP6TH0kxgSWXKZl1cyRg=="],
@@ -2954,6 +2951,8 @@
"@expo/plugin-warn-if-update-available/@oclif/core/js-yaml/argparse": ["argparse@1.0.10", "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
+ "@expo/prebuild-config/@expo/image-utils/fs-extra/universalify": ["universalify@1.0.0", "https://registry.npmmirror.com/universalify/-/universalify-1.0.0.tgz", {}, "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="],
+
"@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
"@oclif/plugin-autocomplete/@oclif/core/js-yaml/argparse": ["argparse@1.0.10", "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
@@ -3016,8 +3015,6 @@
"expo-splash-screen/@expo/prebuild-config/@expo/config-plugins/glob": ["glob@10.4.5", "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
- "expo-splash-screen/@expo/prebuild-config/@expo/image-utils/getenv": ["getenv@2.0.0", "https://registry.npmmirror.com/getenv/-/getenv-2.0.0.tgz", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="],
-
"expo/@expo/config-plugins/@expo/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="],
"expo/@expo/config-plugins/@expo/plist/xmlbuilder": ["xmlbuilder@15.1.1", "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
diff --git a/components/CommonHeader.tsx b/components/CommonHeader.tsx
index 5294a19..d80130c 100644
--- a/components/CommonHeader.tsx
+++ b/components/CommonHeader.tsx
@@ -1,6 +1,7 @@
import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { ArrowLeft } from 'lucide-react';
+import { router } from 'expo-router';
import { Colors, Spacing, FontSize, Layout } from '@/constants/theme';
interface CommonHeaderProps {
@@ -23,9 +24,7 @@ export const CommonHeader: React.FC = ({
onBack();
return;
}
- if (typeof window !== 'undefined' && window.history) {
- window.history.back();
- }
+ router.back();
};
return (
diff --git a/components/templates/template-card.tsx b/components/templates/template-card.tsx
index 1dd9938..5f38ed2 100644
--- a/components/templates/template-card.tsx
+++ b/components/templates/template-card.tsx
@@ -122,7 +122,7 @@ export function TemplateCard({
)}
{template.category && (
-
+
{template.category.name}
@@ -132,7 +132,7 @@ export function TemplateCard({
)}
{template.tags.length > 0 && (
-
+
{template.tags.slice(0, 2).map((tag) => (
diff --git a/components/ui/user-count-badge.tsx b/components/ui/user-count-badge.tsx
index a768bc7..e2ca8a5 100644
--- a/components/ui/user-count-badge.tsx
+++ b/components/ui/user-count-badge.tsx
@@ -41,7 +41,7 @@ export function UserCountBadge({
const displayText = formatCount(count);
return (
-
+
{showIcon && (
;
+ setItem(key: string, value: string): Promise;
+ removeItem(key: string): Promise;
}
class WebStorage implements Storage {
- getItem(key: string): string | null {
+ async getItem(key: string): Promise {
if (typeof window === "undefined") return null;
return window.localStorage.getItem(key);
}
- setItem(key: string, value: string) {
+ async setItem(key: string, value: string): Promise {
if (typeof window === "undefined") return;
window.localStorage.setItem(key, value);
}
- removeItem(key: string) {
+ async removeItem(key: string): Promise {
if (typeof window === "undefined") return;
console.log(`[WebStorage] Removing key: ${key}`);
window.localStorage.removeItem(key);
@@ -27,18 +27,18 @@ class WebStorage implements Storage {
}
class NativeStorage implements Storage {
- getItem(key: string): string | null {
- return SecureStore.getItem(key);
+ async getItem(key: string): Promise {
+ return await SecureStore.getItemAsync(key);
}
- setItem(key: string, value: string) {
- SecureStore.setItem(key, value);
+ async setItem(key: string, value: string): Promise {
+ await SecureStore.setItemAsync(key, value);
}
- removeItem(key: string) {
+ async removeItem(key: string): Promise {
console.log(`[NativeStorage] Removing key: ${key}`);
- SecureStore.setItem(key, "");
- console.log(`[NativeStorage] Key set to empty string`);
+ await SecureStore.deleteItemAsync(key);
+ console.log(`[NativeStorage] Key removed`);
}
}
diff --git a/package.json b/package.json
index 669153a..2ea9c2f 100644
--- a/package.json
+++ b/package.json
@@ -25,8 +25,11 @@
"better-auth": "1.3.27",
"eas-cli": "^16.22.0",
"expo": "54.0.23",
+ "expo-asset": "~12.0.9",
"expo-audio": "~1.0.14",
+ "expo-clipboard": "~8.0.7",
"expo-constants": "~18.0.10",
+ "expo-crypto": "~15.0.7",
"expo-dev-client": "~6.0.17",
"expo-file-system": "~19.0.17",
"expo-font": "~14.0.9",
diff --git a/todo.md b/todo.md
new file mode 100644
index 0000000..6de77c8
--- /dev/null
+++ b/todo.md
@@ -0,0 +1,6 @@
+/plan 检查代码中不符合expo/react-native最佳实践规范的代码,如div/video/img等只有h5中才有的标签没有适配多平台等问题
+
+我的目标是三个端正常运行:
+1. h5 web 端
+2. android 端
+3. ios 端
\ No newline at end of file