@coze-arch/cli 0.0.1-alpha.351659 → 0.0.1-alpha.45a0c2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/__templates__/expo/.coze +7 -2
- package/lib/__templates__/expo/.cozeproj/scripts/{deploy_build.sh → dev_build.sh} +0 -7
- package/lib/__templates__/expo/.cozeproj/scripts/{deploy_run.sh → dev_run.sh} +22 -22
- package/lib/__templates__/expo/.cozeproj/scripts/prod_build.sh +47 -0
- package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +34 -0
- package/lib/__templates__/expo/README.md +59 -8
- package/lib/__templates__/expo/_gitignore +1 -1
- package/lib/__templates__/expo/_npmrc +2 -4
- package/lib/__templates__/expo/client/app/_layout.tsx +1 -1
- package/lib/__templates__/expo/client/app/index.ts +1 -0
- package/lib/__templates__/expo/client/app.config.ts +71 -0
- package/lib/__templates__/expo/client/components/ThemedText.tsx +33 -0
- package/lib/__templates__/expo/client/components/ThemedView.tsx +38 -0
- package/lib/__templates__/expo/client/constants/theme.ts +779 -47
- package/lib/__templates__/expo/client/hooks/useTheme.ts +1 -1
- package/lib/__templates__/expo/client/metro.config.js +121 -0
- package/lib/__templates__/expo/client/package.json +92 -0
- package/lib/__templates__/expo/client/screens/home/index.tsx +0 -1
- package/lib/__templates__/expo/client/tsconfig.json +24 -0
- package/lib/__templates__/expo/package.json +13 -103
- package/lib/__templates__/expo/pnpm-lock.yaml +399 -867
- package/lib/__templates__/expo/pnpm-workspace.yaml +3 -0
- package/lib/__templates__/expo/server/package.json +30 -0
- package/lib/__templates__/expo/server/tsconfig.json +24 -0
- package/lib/__templates__/expo/tsconfig.json +1 -24
- package/lib/__templates__/nextjs/next.config.ts +1 -0
- package/lib/__templates__/nextjs/scripts/dev.sh +7 -26
- package/lib/__templates__/nextjs/src/app/globals.css +99 -87
- package/lib/__templates__/templates.json +27 -0
- package/lib/__templates__/vite/package.json +1 -1
- package/lib/__templates__/vite/pnpm-lock.yaml +120 -120
- package/lib/__templates__/vite/scripts/dev.sh +7 -26
- package/lib/__templates__/vite/vite.config.ts +3 -3
- package/lib/cli.js +144 -31
- package/package.json +8 -3
- package/lib/__templates__/expo/app.json +0 -63
- package/lib/__templates__/expo/babel.config.js +0 -9
- package/lib/__templates__/expo/client/app/(tabs)/_layout.tsx +0 -43
- package/lib/__templates__/expo/client/app/(tabs)/home.tsx +0 -1
- package/lib/__templates__/expo/client/app/(tabs)/index.tsx +0 -7
- package/lib/__templates__/expo/client/app/+not-found.tsx +0 -79
- package/lib/__templates__/expo/client/index.js +0 -12
- package/lib/__templates__/expo/metro.config.js +0 -53
- /package/lib/__templates__/expo/{eslint-formatter-simple.mjs → client/eslint-formatter-simple.mjs} +0 -0
- /package/lib/__templates__/expo/{eslint.config.mjs → client/eslint.config.mjs} +0 -0
- /package/lib/__templates__/expo/{src → server/src}/index.ts +0 -0
|
@@ -3,5 +3,10 @@ entrypoint = "server.js"
|
|
|
3
3
|
requires = ["nodejs-24"]
|
|
4
4
|
|
|
5
5
|
[dev]
|
|
6
|
-
build = ["bash", ".cozeproj/scripts/
|
|
7
|
-
run = ["bash", ".cozeproj/scripts/
|
|
6
|
+
build = ["bash", ".cozeproj/scripts/dev_build.sh"]
|
|
7
|
+
run = ["bash", ".cozeproj/scripts/dev_run.sh"]
|
|
8
|
+
|
|
9
|
+
[deploy]
|
|
10
|
+
build = ["bash", ".cozeproj/scripts/prod_build.sh"]
|
|
11
|
+
run = ["bash", ".cozeproj/scripts/prod_run.sh"]
|
|
12
|
+
build_app_dir = "."
|
|
@@ -49,13 +49,6 @@ fs.writeSync(fd, record+"\n", null, "utf8");
|
|
|
49
49
|
fs.fsyncSync(fd);
|
|
50
50
|
fs.closeSync(fd);
|
|
51
51
|
' "$LOG_FILE" "$level" "$msg"
|
|
52
|
-
|
|
53
|
-
case "$level" in
|
|
54
|
-
INFO) info "$msg" ;;
|
|
55
|
-
WARN) warn "$msg" ;;
|
|
56
|
-
ERROR) echo -e "\033[31m[ERROR] $msg\033[0m" ;;
|
|
57
|
-
*) info "$msg" ;;
|
|
58
|
-
esac
|
|
59
52
|
}
|
|
60
53
|
|
|
61
54
|
# ==================== 前置检查 ====================
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
2
|
+
PREVIEW_DIR="${COZE_PREVIEW_DIR:-$ROOT_DIR}"
|
|
2
3
|
LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
|
|
3
4
|
LOG_FILE="$LOG_DIR/app.log"
|
|
4
5
|
mkdir -p "$LOG_DIR"
|
|
@@ -10,7 +11,7 @@ SERVER_PORT="9091"
|
|
|
10
11
|
# Expo 项目配置
|
|
11
12
|
EXPO_HOST="0.0.0.0"
|
|
12
13
|
EXPO_DIR="expo"
|
|
13
|
-
EXPO_PORT="
|
|
14
|
+
EXPO_PORT="5000"
|
|
14
15
|
WEB_URL="${COZE_PROJECT_DOMAIN_DEFAULT:-http://127.0.0.1:${SERVER_PORT}}"
|
|
15
16
|
ASSUME_YES="1"
|
|
16
17
|
EXPO_PUBLIC_BACKEND_BASE_URL="${EXPO_PUBLIC_BACKEND_BASE_URL:-$WEB_URL}"
|
|
@@ -116,18 +117,12 @@ fs.writeSync(fd, record+"\n", null, "utf8");
|
|
|
116
117
|
fs.fsyncSync(fd);
|
|
117
118
|
fs.closeSync(fd);
|
|
118
119
|
' "$LOG_FILE" "$level" "$msg"
|
|
119
|
-
case "$level" in
|
|
120
|
-
INFO) echo -e "\033[32m[INFO] $msg\033[0m" ;;
|
|
121
|
-
WARN) echo -e "\033[33m[WARN] $msg\033[0m" ;;
|
|
122
|
-
ERROR) echo -e "\033[31m[ERROR] $msg\033[0m" ;;
|
|
123
|
-
*) echo -e "\033[32m[INFO] $msg\033[0m" ;;
|
|
124
|
-
esac
|
|
125
120
|
}
|
|
126
121
|
|
|
127
122
|
wait_port_connectable() {
|
|
128
123
|
local host=$1 port=$2 retries=${3:-10}
|
|
129
124
|
for _ in $(seq 1 "$retries"); do
|
|
130
|
-
nc -z "$host" "$port" && return 0
|
|
125
|
+
nc -z -w 1 "$host" "$port" >/dev/null 2>&1 && return 0
|
|
131
126
|
sleep 1
|
|
132
127
|
done
|
|
133
128
|
return 1
|
|
@@ -135,13 +130,18 @@ wait_port_connectable() {
|
|
|
135
130
|
|
|
136
131
|
start_expo() {
|
|
137
132
|
local offline="${1:-0}"
|
|
133
|
+
|
|
134
|
+
pushd ./client
|
|
135
|
+
|
|
138
136
|
if [ "$offline" = "1" ]; then
|
|
139
|
-
EXPO_OFFLINE=1 EXPO_NO_DOCTOR=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" nohup npx expo start --port "$EXPO_PORT" > logs/expo.log 2>&1 &
|
|
137
|
+
EXPO_OFFLINE=1 EXPO_NO_DOCTOR=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" nohup npx expo start --clear --port "$EXPO_PORT" > ../logs/expo.log 2>&1 &
|
|
140
138
|
else
|
|
141
|
-
EXPO_NO_DOCTOR=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" nohup npx expo start --port "$EXPO_PORT" > logs/expo.log 2>&1 &
|
|
139
|
+
EXPO_NO_DOCTOR=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" nohup npx expo start --clear --port "$EXPO_PORT" > ../logs/expo.log 2>&1 &
|
|
142
140
|
fi
|
|
143
141
|
EXPO_PID=$!
|
|
144
142
|
echo "$EXPO_PID"
|
|
143
|
+
|
|
144
|
+
popd
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
detect_expo_fetch_failed() {
|
|
@@ -159,6 +159,15 @@ detect_expo_fetch_failed() {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
# ==================== 前置检查 ====================
|
|
162
|
+
# 关掉nginx进程
|
|
163
|
+
ps -ef | grep nginx | grep -v grep | awk '{print $2}' | xargs -r kill -9
|
|
164
|
+
|
|
165
|
+
write_log "INFO" "检查根目录 pre_install.py"
|
|
166
|
+
if [ -f "$PREVIEW_DIR/pre_install.py" ]; then
|
|
167
|
+
write_log "INFO" "执行:python $PREVIEW_DIR/pre_install.py"
|
|
168
|
+
python "$PREVIEW_DIR/pre_install.py" || write_log "ERROR" "pre_install.py 执行失败"
|
|
169
|
+
fi
|
|
170
|
+
|
|
162
171
|
write_log "INFO" "==================== 开始启动 ===================="
|
|
163
172
|
write_log "INFO" "开始执行服务启动脚本(start_dev.sh)..."
|
|
164
173
|
write_log "INFO" "正在检查依赖命令和目录是否存在..."
|
|
@@ -176,17 +185,9 @@ ensure_port SERVER_PORT "$SERVER_PORT"
|
|
|
176
185
|
ensure_port EXPO_PORT "$EXPO_PORT"
|
|
177
186
|
|
|
178
187
|
# ==================== 启动 Server 服务 ====================
|
|
179
|
-
write_log "INFO" "检查 Nginx 端口 (5000)..."
|
|
180
|
-
if is_port_free 5000; then
|
|
181
|
-
write_log "INFO" "端口 5000 未被占用,正在启动 Nginx..."
|
|
182
|
-
service nginx start
|
|
183
|
-
else
|
|
184
|
-
write_log "INFO" "端口 5000 已被占用,跳过 Nginx 启动"
|
|
185
|
-
fi
|
|
186
|
-
|
|
187
188
|
write_log "INFO" "==================== 启动 server 服务 ===================="
|
|
188
|
-
write_log "INFO" "正在执行:npm run
|
|
189
|
-
PORT="$SERVER_PORT" nohup npm run server > logs/app.log 2>&1 &
|
|
189
|
+
write_log "INFO" "正在执行:npm run dev"
|
|
190
|
+
PORT="$SERVER_PORT" nohup npm run dev --prefix ./server > logs/app.log 2>&1 &
|
|
190
191
|
SERVER_PID=$!
|
|
191
192
|
if [ -z "${SERVER_PID}" ]; then
|
|
192
193
|
write_log "ERROR" "无法获取 server 后台进程 PID"
|
|
@@ -194,8 +195,7 @@ fi
|
|
|
194
195
|
write_log "INFO" "server 服务已启动,进程 ID:${SERVER_PID:-unknown}"
|
|
195
196
|
|
|
196
197
|
write_log "INFO" "==================== 启动 Expo 项目 ===================="
|
|
197
|
-
write_log "INFO" "
|
|
198
|
-
write_log "INFO" "开始启动 Expo 服务"
|
|
198
|
+
write_log "INFO" "开始启动 Expo 服务,端口 ${EXPO_PORT}"
|
|
199
199
|
EXPO_PID=$(start_expo 0)
|
|
200
200
|
if detect_expo_fetch_failed 8; then
|
|
201
201
|
write_log "WARN" "Expo 启动检测到网络错误:TypeError: fetch failed,启用离线模式重试"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
if [ -z "${BASH_VERSION:-}" ]; then exec /usr/bin/env bash "$0" "$@"; fi
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
ROOT_DIR="$(pwd)"
|
|
5
|
+
|
|
6
|
+
# ==================== 工具函数 ====================
|
|
7
|
+
info() {
|
|
8
|
+
echo "[INFO] $1"
|
|
9
|
+
}
|
|
10
|
+
warn() {
|
|
11
|
+
echo "[WARN] $1"
|
|
12
|
+
}
|
|
13
|
+
error() {
|
|
14
|
+
echo "[ERROR] $1"
|
|
15
|
+
exit 1
|
|
16
|
+
}
|
|
17
|
+
check_command() {
|
|
18
|
+
if ! command -v "$1" &> /dev/null; then
|
|
19
|
+
error "命令 $1 未找到,请先安装"
|
|
20
|
+
fi
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
info "==================== 开始构建 ===================="
|
|
24
|
+
info "开始执行构建脚本(build_prod.sh)..."
|
|
25
|
+
info "正在检查依赖命令是否存在..."
|
|
26
|
+
# 检查核心命令
|
|
27
|
+
check_command "pnpm"
|
|
28
|
+
check_command "npm"
|
|
29
|
+
|
|
30
|
+
# ==================== 安装 Node 依赖 ====================
|
|
31
|
+
info "==================== 安装 Node 依赖 ===================="
|
|
32
|
+
info "开始安装 Node 依赖"
|
|
33
|
+
if [ -f "$ROOT_DIR/package.json" ]; then
|
|
34
|
+
info "进入目录:$ROOT_DIR"
|
|
35
|
+
info "正在执行:pnpm install"
|
|
36
|
+
(cd "$ROOT_DIR" && pnpm install --registry=https://registry.npmmirror.com) || error "Node 依赖安装失败"
|
|
37
|
+
else
|
|
38
|
+
warn "未找到 $ROOT_DIR/package.json 文件,请检查路径是否正确"
|
|
39
|
+
fi
|
|
40
|
+
info "==================== 依赖安装完成!====================\n"
|
|
41
|
+
|
|
42
|
+
info "==================== dist打包 ===================="
|
|
43
|
+
info "开始执行:npm run build --prefix server"
|
|
44
|
+
(cd "$ROOT_DIR" && npm run build --prefix ./server) || error "dist打包失败"
|
|
45
|
+
info "==================== dist打包完成!====================\n"
|
|
46
|
+
|
|
47
|
+
info "下一步:执行 ./prod_run.sh 启动服务"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# 产物部署使用
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
ROOT_DIR="$(pwd)"
|
|
6
|
+
|
|
7
|
+
HOST="${HOST:-0.0.0.0}"
|
|
8
|
+
PORT="${PORT:-5000}"
|
|
9
|
+
|
|
10
|
+
# ==================== 工具函数 ====================
|
|
11
|
+
info() {
|
|
12
|
+
echo "[INFO] $1"
|
|
13
|
+
}
|
|
14
|
+
warn() {
|
|
15
|
+
echo "[WARN] $1"
|
|
16
|
+
}
|
|
17
|
+
error() {
|
|
18
|
+
echo "[ERROR] $1"
|
|
19
|
+
exit 1
|
|
20
|
+
}
|
|
21
|
+
check_command() {
|
|
22
|
+
if ! command -v "$1" &> /dev/null; then
|
|
23
|
+
error "命令 $1 未找到,请先安装"
|
|
24
|
+
fi
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# ============== 启动服务 ======================
|
|
28
|
+
# 检查核心命令
|
|
29
|
+
check_command "pnpm"
|
|
30
|
+
check_command "npm"
|
|
31
|
+
|
|
32
|
+
info "开始执行:npm run start"
|
|
33
|
+
(cd "$ROOT_DIR" && PORT="$PORT" npm run start --prefix ./server) || error "服务启动失败"
|
|
34
|
+
info "服务启动完成!\n"
|
|
@@ -1,13 +1,64 @@
|
|
|
1
|
-
# Expo App
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
# Expo App + Express.js
|
|
2
|
+
|
|
3
|
+
## 目录结构规范(严格遵循)
|
|
4
|
+
|
|
5
|
+
当前仓库是一个 monorepo(基于 pnpm 的 workspace)
|
|
6
|
+
其中 Expo 代码在 client 目录,Express.js 代码在 server 目录
|
|
7
|
+
|
|
8
|
+
目录结构说明
|
|
9
|
+
|
|
10
|
+
├── server/ # 服务端代码根目录 (Express.js)
|
|
11
|
+
| ├── src/
|
|
12
|
+
│ │ └── index.ts # Express 入口文件
|
|
13
|
+
| └── package.json # 服务端 package.json
|
|
14
|
+
├── client/ # React Native 前端代码
|
|
15
|
+
│ ├── app/ # Expo Router 路由目录(仅路由配置)
|
|
16
|
+
│ │ ├── _layout.tsx # 根布局文件(必需)
|
|
17
|
+
│ │ └── index.ts # 首页
|
|
18
|
+
│ ├── screens/ # 页面实现目录(与 app/ 路由对应)
|
|
19
|
+
│ │ └── home/
|
|
20
|
+
│ │ ├── index.tsx # 页面组件实现
|
|
21
|
+
│ │ └── styles.ts # 页面样式
|
|
22
|
+
│ ├── components/ # 可复用组件
|
|
23
|
+
│ │ └── Screen.tsx # 页面容器组件(必用)
|
|
24
|
+
│ ├── hooks/ # 自定义 Hooks
|
|
25
|
+
│ ├── contexts/ # React Context 代码
|
|
26
|
+
│ ├── assets/ # 静态资源
|
|
27
|
+
| └── package.json # Expo 应用 package.json
|
|
28
|
+
├── package.json
|
|
29
|
+
├── .cozeproj # 预置脚手架脚本(禁止修改)
|
|
30
|
+
└── .coze # 配置文件(禁止修改)
|
|
31
|
+
|
|
32
|
+
## Expo 路径别名
|
|
33
|
+
Expo 配置了 `@/` 路径别名指向 `client/` 目录:
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
// 正确
|
|
37
|
+
import { Screen } from '@/components/Screen';
|
|
38
|
+
|
|
39
|
+
// 避免相对路径
|
|
40
|
+
import { Screen } from '../../../components/Screen';
|
|
5
41
|
```
|
|
6
|
-
|
|
42
|
+
|
|
43
|
+
## 安装依赖
|
|
44
|
+
|
|
45
|
+
### 命令
|
|
46
|
+
|
|
7
47
|
```bash
|
|
8
|
-
|
|
48
|
+
pnpm i
|
|
9
49
|
```
|
|
10
|
-
|
|
50
|
+
|
|
51
|
+
### 新增依赖约束
|
|
52
|
+
|
|
53
|
+
如果需要新增依赖,需在 client 和 server 各自的目录添加(原因:隔离前后端的依赖),禁止在根目录直接安装依赖
|
|
54
|
+
|
|
55
|
+
### 新增依赖标准流程
|
|
56
|
+
|
|
57
|
+
- 编辑 `client/package.json` 或 `server/package.json`
|
|
58
|
+
- 在根目录执行 `pnpm i`
|
|
59
|
+
|
|
60
|
+
## 启动前后端服务(开发环境)
|
|
61
|
+
|
|
11
62
|
```bash
|
|
12
|
-
|
|
63
|
+
coze dev
|
|
13
64
|
```
|
|
@@ -8,15 +8,13 @@ network-concurrency=16
|
|
|
8
8
|
fetch-retries=3
|
|
9
9
|
fetch-timeout=60000
|
|
10
10
|
|
|
11
|
-
#
|
|
11
|
+
# peerDependencies
|
|
12
12
|
strict-peer-dependencies=false
|
|
13
|
-
|
|
14
|
-
# 自动生成 lockfile
|
|
15
13
|
auto-install-peers=true
|
|
16
14
|
|
|
17
15
|
# lockfile 配置
|
|
18
16
|
lockfile=true
|
|
19
17
|
prefer-frozen-lockfile=true
|
|
20
18
|
|
|
21
|
-
#
|
|
19
|
+
# semver 选择最高版本
|
|
22
20
|
resolution-mode=highest
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@/screens/home'
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ExpoConfig, ConfigContext } from 'expo/config';
|
|
2
|
+
|
|
3
|
+
export default ({ config }: ConfigContext): ExpoConfig => {
|
|
4
|
+
return {
|
|
5
|
+
...config,
|
|
6
|
+
"name": "${app_name}",
|
|
7
|
+
"slug": "${slug}",
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"orientation": "portrait",
|
|
10
|
+
"icon": "./assets/images/icon.png",
|
|
11
|
+
"scheme": "myapp",
|
|
12
|
+
"userInterfaceStyle": "automatic",
|
|
13
|
+
"newArchEnabled": true,
|
|
14
|
+
"ios": {
|
|
15
|
+
"supportsTablet": true
|
|
16
|
+
},
|
|
17
|
+
"android": {
|
|
18
|
+
"adaptiveIcon": {
|
|
19
|
+
"foregroundImage": "./assets/images/adaptive-icon.png",
|
|
20
|
+
"backgroundColor": "#ffffff"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"web": {
|
|
24
|
+
"bundler": "metro",
|
|
25
|
+
"output": "single",
|
|
26
|
+
"favicon": "./assets/images/favicon.png"
|
|
27
|
+
},
|
|
28
|
+
"plugins": [
|
|
29
|
+
process.env.EXPO_PUBLIC_BACKEND_BASE_URL ? [
|
|
30
|
+
"expo-router",
|
|
31
|
+
{
|
|
32
|
+
"origin": process.env.EXPO_PUBLIC_BACKEND_BASE_URL
|
|
33
|
+
}
|
|
34
|
+
] : 'expo-router',
|
|
35
|
+
[
|
|
36
|
+
"expo-splash-screen",
|
|
37
|
+
{
|
|
38
|
+
"image": "./assets/images/splash-icon.png",
|
|
39
|
+
"imageWidth": 200,
|
|
40
|
+
"resizeMode": "contain",
|
|
41
|
+
"backgroundColor": "#ffffff"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
[
|
|
45
|
+
"expo-image-picker",
|
|
46
|
+
{
|
|
47
|
+
"photosPermission": "允许${app_name}访问您的相册,以便您上传或保存图片。",
|
|
48
|
+
"cameraPermission": "允许${app_name}使用您的相机,以便您直接拍摄照片上传。",
|
|
49
|
+
"microphonePermission": "允许${app_name}访问您的麦克风,以便您拍摄带有声音的视频。"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
"expo-location",
|
|
54
|
+
{
|
|
55
|
+
"locationWhenInUsePermission": "${app_name}需要访问您的位置以提供周边服务及导航功能。"
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
"expo-camera",
|
|
60
|
+
{
|
|
61
|
+
"cameraPermission": "${app_name}需要访问相机以拍摄照片和视频。",
|
|
62
|
+
"microphonePermission": "${app_name}需要访问麦克风以录制视频声音。",
|
|
63
|
+
"recordAudioAndroid": true
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
],
|
|
67
|
+
"experiments": {
|
|
68
|
+
"typedRoutes": true
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text, TextProps, TextStyle } from 'react-native';
|
|
3
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
4
|
+
import { Typography } from '@/constants/theme';
|
|
5
|
+
|
|
6
|
+
type TypographyVariant = keyof typeof Typography;
|
|
7
|
+
|
|
8
|
+
interface ThemedTextProps extends TextProps {
|
|
9
|
+
variant?: TypographyVariant;
|
|
10
|
+
color?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function ThemedText({
|
|
14
|
+
variant = 'body',
|
|
15
|
+
color,
|
|
16
|
+
style,
|
|
17
|
+
children,
|
|
18
|
+
...props
|
|
19
|
+
}: ThemedTextProps) {
|
|
20
|
+
const { theme } = useTheme();
|
|
21
|
+
const typographyStyle = Typography[variant];
|
|
22
|
+
|
|
23
|
+
const textStyle: TextStyle = {
|
|
24
|
+
...typographyStyle,
|
|
25
|
+
color: color ?? theme.textPrimary,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Text style={[textStyle, style]} {...props}>
|
|
30
|
+
{children}
|
|
31
|
+
</Text>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, ViewProps, ViewStyle } from 'react-native';
|
|
3
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
4
|
+
|
|
5
|
+
type BackgroundLevel = 'root' | 'default' | 'secondary' | 'tertiary';
|
|
6
|
+
|
|
7
|
+
interface ThemedViewProps extends ViewProps {
|
|
8
|
+
level?: BackgroundLevel;
|
|
9
|
+
backgroundColor?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const backgroundMap: Record<BackgroundLevel, string> = {
|
|
13
|
+
root: 'backgroundRoot',
|
|
14
|
+
default: 'backgroundDefault',
|
|
15
|
+
secondary: 'backgroundSecondary',
|
|
16
|
+
tertiary: 'backgroundTertiary',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function ThemedView({
|
|
20
|
+
level = 'root',
|
|
21
|
+
backgroundColor,
|
|
22
|
+
style,
|
|
23
|
+
children,
|
|
24
|
+
...props
|
|
25
|
+
}: ThemedViewProps) {
|
|
26
|
+
const { theme } = useTheme();
|
|
27
|
+
const bgColor = backgroundColor ?? (theme as any)[backgroundMap[level]];
|
|
28
|
+
|
|
29
|
+
const viewStyle: ViewStyle = {
|
|
30
|
+
backgroundColor: bgColor,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<View style={[viewStyle, style]} {...props}>
|
|
35
|
+
{children}
|
|
36
|
+
</View>
|
|
37
|
+
);
|
|
38
|
+
}
|