various fixes
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
EXPO_PUBLIC_API_URL=http://192.168.10.178:8000
|
||||
EXPO_PUBLIC_WS_URL=ws://192.168.10.178:8000
|
||||
@@ -1,2 +1,9 @@
|
||||
EXPO_PUBLIC_API_URL=http://192.168.10.178:8000
|
||||
EXPO_PUBLIC_WS_URL=ws://192.168.10.178:8000
|
||||
# 复制为 .env.development / .env.staging / .env.production 后填写(勿提交含密钥的副本)。
|
||||
# 本地:npm start 会通过 prestart 执行 `use-env development` 生成 .env;
|
||||
# 或手动 `npm run use-env -- staging` / `npm run use-env -- production`。
|
||||
# CI:GitHub Actions 在构建 APK 前会按分支调用 use-env(main → staging,tag → production)。
|
||||
#
|
||||
# 变量在构建时注入;修改后需重新 prebuild/打包客户端。
|
||||
|
||||
EXPO_PUBLIC_API_URL=https://your-api.example.com
|
||||
EXPO_PUBLIC_WS_URL=wss://your-api.example.com
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* 将 app-expo/.env.<name> 复制为 .env,供 Metro/Expo 读取 EXPO_PUBLIC_*。
|
||||
*
|
||||
* 参数 name → 源文件:
|
||||
* development → .env.development(本地默认:npm start / prestart)
|
||||
* staging → .env.staging
|
||||
* production → .env.production
|
||||
*
|
||||
* CI:.github/workflows/app-expo-deploy.yml 按分支/tag 调用本脚本,与后端 env 策略对齐。
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const env = process.argv[2] || 'development';
|
||||
|
||||
@@ -24,7 +24,10 @@ import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Text } from '@/components/ui/text';
|
||||
import { ScreenGutter } from '@/constants/layout';
|
||||
import { useCreateConversation } from '@/features/conversation/hooks';
|
||||
import { buildFrameworkChapterPlaceholders } from '@/features/memoir/framework-chapter-keys';
|
||||
import {
|
||||
buildFrameworkChapterPlaceholders,
|
||||
mergeFrameworkChaptersWithFetched,
|
||||
} from '@/features/memoir/framework-chapter-keys';
|
||||
import { useChapters, useCheckCoverGeneration } from '@/features/memoir/hooks';
|
||||
import type { ChapterViewModel } from '@/features/memoir/types';
|
||||
|
||||
@@ -263,6 +266,11 @@ export default function MemoirScreen() {
|
||||
[t],
|
||||
);
|
||||
|
||||
const displayChapters = useMemo(
|
||||
() => mergeFrameworkChaptersWithFetched(frameworkPlaceholders, chapters),
|
||||
[frameworkPlaceholders, chapters],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (didRunInitialCoverCheckRef.current) return;
|
||||
didRunInitialCoverCheckRef.current = true;
|
||||
@@ -318,19 +326,8 @@ export default function MemoirScreen() {
|
||||
</>
|
||||
) : isError ? (
|
||||
<MemoirLoadError onRetry={() => void refetch()} />
|
||||
) : chapters.length === 0 ? (
|
||||
frameworkPlaceholders.map((item) => (
|
||||
<ChapterCard
|
||||
key={item.id}
|
||||
item={item}
|
||||
variant="drafting"
|
||||
t={t as (key: string) => string}
|
||||
onReadPress={() => handleReadChapter(item.id)}
|
||||
onContinuePress={handleStartChapter}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
chapters.map((item) => (
|
||||
displayChapters.map((item) => (
|
||||
<ChapterCard
|
||||
key={item.id}
|
||||
item={item}
|
||||
|
||||
@@ -35,3 +35,17 @@ export function buildFrameworkChapterPlaceholders(
|
||||
wordCount: 0,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表页始终展示 8 个框架槽位:已有章节用接口数据,其余槽位仍用框架占位(与「零章节」时一致)。
|
||||
*/
|
||||
export function mergeFrameworkChaptersWithFetched(
|
||||
placeholders: ChapterViewModel[],
|
||||
fetched: ChapterViewModel[],
|
||||
): ChapterViewModel[] {
|
||||
const byOrder = new Map<number, ChapterViewModel>();
|
||||
for (const vm of fetched) {
|
||||
byOrder.set(vm.orderIndex, vm);
|
||||
}
|
||||
return placeholders.map((p) => byOrder.get(p.orderIndex) ?? p);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user