From 0357fbcaffc7396baffaf514b292e7e9b2881f8a Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 23 Jul 2026 10:53:41 +0800 Subject: [PATCH] refactor(private-zone): use canonical product name --- barrelsby.json | 6 +- docs/backend/FRONTEND_MULTI_ROLE_CHAT_API.md | 10 +- docs/backend/FRONTEND_PAYMENT_API.md | 4 +- ...OM_API.md => FRONTEND_PRIVATE_ZONE_API.md} | 52 +++++----- docs/external-entry/README.md | 6 +- docs/external-entry/debug-links.md | 6 +- docs/external-entry/links.md | 12 +-- ...e.md => 2026-07-22-private-zone-rename.md} | 90 +++++++++--------- .../mock/chat/chat-avatar-navigation.spec.ts | 6 +- .../mock/favorite-menu-navigation.spec.ts | 10 +- e2e/specs/mock/multi-role-commercial.spec.ts | 10 +- .../banner/elio.png | Bin .../banner/maya.png | Bin .../banner/nayeli.png | Bin .../__tests__/openapi-contract.test.mjs | 4 +- .../__tests__/tailwind-components.test.tsx | 8 +- .../__tests__/tailwind-components.test.tsx | 22 ++--- src/app/_components/core/app-bottom-nav.tsx | 22 ++--- .../{private-zoom => private-zone}/layout.tsx | 10 +- .../[characterSlug]/private-zone/page.tsx | 5 + .../[characterSlug]/private-zoom/page.tsx | 5 - src/app/chat/chat-screen.tsx | 6 +- .../__tests__/tailwind-components.test.tsx | 4 +- src/app/chat/components/message-avatar.tsx | 4 +- .../private-album-gallery-motion.test.ts | 0 .../private-album-gallery-url.test.ts | 8 +- .../__tests__/private-album-images.test.ts | 2 +- ...use-private-zone-flow-navigation.test.tsx} | 30 +++--- .../__tests__/use-private-zone-flow.test.ts} | 8 +- .../private-album-card.interaction.test.tsx | 10 +- .../__tests__/private-album-card.test.tsx | 6 +- .../__tests__/private-album-gallery.test.tsx | 10 +- .../components/index.ts | 0 .../components/private-album-card.tsx | 6 +- .../components/private-album-gallery.tsx | 4 +- .../components/status-card.tsx | 2 +- .../components/unlock-confirm-dialog.tsx | 4 +- .../{private-zoom => private-zone}/page.tsx | 4 +- .../private-album-gallery-motion.ts | 0 .../private-album-gallery-url.ts | 6 +- .../private-album-images.ts | 2 +- .../private-zone-screen.module.css} | 0 .../private-zone-screen.tsx} | 82 ++++++++-------- .../use-private-zone-flow.ts} | 40 ++++---- src/app/profile/profile-screen.tsx | 8 +- src/app/splash/splash-screen.tsx | 8 +- .../constants/__tests__/character.test.ts | 4 +- src/data/constants/character.ts | 36 +++---- src/data/repositories/index.ts | 4 +- src/data/repositories/interfaces/index.ts | 2 +- ...ository.ts => iprivate_zone_repository.ts} | 4 +- ...pository.ts => private_zone_repository.ts} | 20 ++-- .../__tests__/immutable_schema.test.ts | 4 +- .../__tests__/private_album.test.ts | 6 +- .../{private-zoom => private-zone}/index.ts | 0 .../private_album.ts | 0 .../request/index.ts | 0 .../request/unlock_private_album_request.ts | 0 .../response/index.ts | 0 .../response/private_album_unlock_response.ts | 0 .../response/private_albums_response.ts | 0 .../services/api/__tests__/api_path.test.ts | 6 +- .../api/__tests__/multi_character_api.test.ts | 8 +- src/data/services/api/api_contract.json | 4 +- src/data/services/api/api_path.ts | 6 +- src/data/services/api/index.ts | 2 +- ...rivate_zoom_api.ts => private_zone_api.ts} | 10 +- .../payment/pending_payment_order_storage.ts | 2 +- .../analytics/payment_analytics_context.ts | 4 +- .../__tests__/external_entry.test.ts | 10 +- .../__tests__/subscription_exit.test.ts | 16 ++-- src/lib/navigation/external_entry.ts | 6 +- src/lib/navigation/subscription_exit.ts | 10 +- .../__tests__/payment_search_params.test.ts | 6 +- .../__tests__/pending_payment_order.test.ts | 16 ++-- src/lib/payment/payment_search_params.ts | 2 +- .../private_album.ts | 2 +- .../character-actor-scope-providers.test.tsx | 34 +++---- src/providers/private-zone-route-provider.tsx | 21 ++++ src/providers/private-zoom-route-provider.tsx | 21 ---- src/providers/root-providers.tsx | 2 +- .../__tests__/global-route-context.test.ts | 2 +- .../__tests__/navigation-resolver.test.ts | 6 +- src/router/__tests__/route-meta.test.ts | 10 +- src/router/navigation-types.ts | 2 +- src/router/route-meta.ts | 4 +- src/router/routes.ts | 8 +- .../private-zone-album-flow.test.ts} | 22 ++--- .../private-zone-machine.test-utils.ts} | 26 ++--- .../private-zone-unlock-flow.test.ts} | 18 ++-- .../helper/albums.ts | 10 +- .../helper/index.ts | 0 .../helper/unlock.ts | 10 +- src/stores/private-zone/index.ts | 7 ++ .../machine/actors/albums.ts | 12 +-- .../machine/album-flow.ts | 24 ++--- .../machine/setup.ts | 28 +++--- .../machine/unlock-flow.ts | 36 +++---- .../private-zone-context.tsx} | 48 +++++----- .../private-zone/private-zone-events.ts | 8 ++ .../private-zone/private-zone-machine.ts | 18 ++++ .../private-zone-state.ts} | 14 +-- src/stores/private-zoom/index.ts | 7 -- .../private-zoom/private-zoom-events.ts | 8 -- .../private-zoom/private-zoom-machine.ts | 18 ---- 105 files changed, 578 insertions(+), 578 deletions(-) rename docs/backend/{FRONTEND_PRIVATE_ZOOM_API.md => FRONTEND_PRIVATE_ZONE_API.md} (83%) rename docs/frontend-integration/{2026-07-22-private-zoom-rename.md => 2026-07-22-private-zone-rename.md} (69%) rename public/images/{private-zoom => private-zone}/banner/elio.png (100%) rename public/images/{private-zoom => private-zone}/banner/maya.png (100%) rename public/images/{private-zoom => private-zone}/banner/nayeli.png (100%) rename src/app/characters/[characterSlug]/{private-zoom => private-zone}/layout.tsx (57%) create mode 100644 src/app/characters/[characterSlug]/private-zone/page.tsx delete mode 100644 src/app/characters/[characterSlug]/private-zoom/page.tsx rename src/app/{private-zoom => private-zone}/__tests__/private-album-gallery-motion.test.ts (100%) rename src/app/{private-zoom => private-zone}/__tests__/private-album-gallery-url.test.ts (83%) rename src/app/{private-zoom => private-zone}/__tests__/private-album-images.test.ts (95%) rename src/app/{private-zoom/__tests__/use-private-zoom-flow-navigation.test.tsx => private-zone/__tests__/use-private-zone-flow-navigation.test.tsx} (74%) rename src/app/{private-zoom/__tests__/use-private-zoom-flow.test.ts => private-zone/__tests__/use-private-zone-flow.test.ts} (56%) rename src/app/{private-zoom => private-zone}/components/__tests__/private-album-card.interaction.test.tsx (91%) rename src/app/{private-zoom => private-zone}/components/__tests__/private-album-card.test.tsx (96%) rename src/app/{private-zoom => private-zone}/components/__tests__/private-album-gallery.test.tsx (92%) rename src/app/{private-zoom => private-zone}/components/index.ts (100%) rename src/app/{private-zoom => private-zone}/components/private-album-card.tsx (97%) rename src/app/{private-zoom => private-zone}/components/private-album-gallery.tsx (98%) rename src/app/{private-zoom => private-zone}/components/status-card.tsx (88%) rename src/app/{private-zoom => private-zone}/components/unlock-confirm-dialog.tsx (92%) rename src/app/{private-zoom => private-zone}/page.tsx (77%) rename src/app/{private-zoom => private-zone}/private-album-gallery-motion.ts (100%) rename src/app/{private-zoom => private-zone}/private-album-gallery-url.ts (89%) rename src/app/{private-zoom => private-zone}/private-album-images.ts (94%) rename src/app/{private-zoom/private-zoom-screen.module.css => private-zone/private-zone-screen.module.css} (100%) rename src/app/{private-zoom/private-zoom-screen.tsx => private-zone/private-zone-screen.tsx} (81%) rename src/app/{private-zoom/use-private-zoom-flow.ts => private-zone/use-private-zone-flow.ts} (70%) rename src/data/repositories/interfaces/{iprivate_zoom_repository.ts => iprivate_zone_repository.ts} (83%) rename src/data/repositories/{private_zoom_repository.ts => private_zone_repository.ts} (64%) rename src/data/schemas/{private-zoom => private-zone}/__tests__/private_album.test.ts (95%) rename src/data/schemas/{private-zoom => private-zone}/index.ts (100%) rename src/data/schemas/{private-zoom => private-zone}/private_album.ts (100%) rename src/data/schemas/{private-zoom => private-zone}/request/index.ts (100%) rename src/data/schemas/{private-zoom => private-zone}/request/unlock_private_album_request.ts (100%) rename src/data/schemas/{private-zoom => private-zone}/response/index.ts (100%) rename src/data/schemas/{private-zoom => private-zone}/response/private_album_unlock_response.ts (100%) rename src/data/schemas/{private-zoom => private-zone}/response/private_albums_response.ts (100%) rename src/data/services/api/{private_zoom_api.ts => private_zone_api.ts} (83%) rename src/lib/{private-zoom => private-zone}/private_album.ts (68%) create mode 100644 src/providers/private-zone-route-provider.tsx delete mode 100644 src/providers/private-zoom-route-provider.tsx rename src/stores/{private-zoom/__tests__/private-zoom-album-flow.test.ts => private-zone/__tests__/private-zone-album-flow.test.ts} (78%) rename src/stores/{private-zoom/__tests__/private-zoom-machine.test-utils.ts => private-zone/__tests__/private-zone-machine.test-utils.ts} (81%) rename src/stores/{private-zoom/__tests__/private-zoom-unlock-flow.test.ts => private-zone/__tests__/private-zone-unlock-flow.test.ts} (88%) rename src/stores/{private-zoom => private-zone}/helper/albums.ts (87%) rename src/stores/{private-zoom => private-zone}/helper/index.ts (100%) rename src/stores/{private-zoom => private-zone}/helper/unlock.ts (82%) create mode 100644 src/stores/private-zone/index.ts rename src/stores/{private-zoom => private-zone}/machine/actors/albums.ts (65%) rename src/stores/{private-zoom => private-zone}/machine/album-flow.ts (69%) rename src/stores/{private-zoom => private-zone}/machine/setup.ts (56%) rename src/stores/{private-zoom => private-zone}/machine/unlock-flow.ts (83%) rename src/stores/{private-zoom/private-zoom-context.tsx => private-zone/private-zone-context.tsx} (55%) create mode 100644 src/stores/private-zone/private-zone-events.ts create mode 100644 src/stores/private-zone/private-zone-machine.ts rename src/stores/{private-zoom/private-zoom-state.ts => private-zone/private-zone-state.ts} (67%) delete mode 100644 src/stores/private-zoom/index.ts delete mode 100644 src/stores/private-zoom/private-zoom-events.ts delete mode 100644 src/stores/private-zoom/private-zoom-machine.ts diff --git a/barrelsby.json b/barrelsby.json index 7063f371..55ed10c9 100644 --- a/barrelsby.json +++ b/barrelsby.json @@ -25,9 +25,9 @@ "./src/data/schemas/payment", "./src/data/schemas/payment/request", "./src/data/schemas/payment/response", - "./src/data/schemas/private-zoom", - "./src/data/schemas/private-zoom/request", - "./src/data/schemas/private-zoom/response", + "./src/data/schemas/private-zone", + "./src/data/schemas/private-zone/request", + "./src/data/schemas/private-zone/response", "./src/data/schemas/user", "./src/data/storage/app", "./src/data/storage/auth", diff --git a/docs/backend/FRONTEND_MULTI_ROLE_CHAT_API.md b/docs/backend/FRONTEND_MULTI_ROLE_CHAT_API.md index 2a853293..7848e5b6 100644 --- a/docs/backend/FRONTEND_MULTI_ROLE_CHAT_API.md +++ b/docs/backend/FRONTEND_MULTI_ROLE_CHAT_API.md @@ -63,7 +63,7 @@ Authorization: Bearer 2. `isActive=true`; 3. `capabilities.chat=true`。 -服务端目录决定角色是否可聊天及排序;本地目录继续提供 slug、图片、文案和 Tip 能力。`privateZoom` 只有在本地能力和服务端 `privateContent` 同时开启时可用。 +服务端目录决定角色是否可聊天及排序;本地目录继续提供 slug、图片、文案和 Tip 能力。`privateZone` 只有在本地能力和服务端 `privateContent` 同时开启时可用。 远端目录返回前,生产环境只使用 Elio 作为临时目录;非生产环境可使用完整本地目录。远端目录加载成功后,以合并结果为准。 @@ -72,7 +72,7 @@ Authorization: Bearer ```text /characters/{slug}/splash /characters/{slug}/chat -/characters/{slug}/private-zoom +/characters/{slug}/private-zone /characters/{slug}/tip ``` @@ -81,11 +81,11 @@ Authorization: Bearer ```text /splash -> /characters/elio/splash /chat -> /characters/elio/chat -/private-zoom -> /characters/elio/private-zoom +/private-zone -> /characters/elio/private-zone /tip -> /characters/elio/tip ``` -Chat Provider 以 `characterId` 为边界,路由角色变化时创建新的 Actor。Private Zoom 的角色边界由 [Private Zoom 权威协议](./FRONTEND_PRIVATE_ZOOM_API.md) 定义。 +Chat Provider 以 `characterId` 为边界,路由角色变化时创建新的 Actor。Private Zone 的角色边界由 [Private Zone 权威协议](./FRONTEND_PRIVATE_ZONE_API.md) 定义。 ## 3. Chat HTTP 协议 @@ -308,7 +308,7 @@ conversationKey = {ownerKey}::character:{encodeURIComponent(characterId)} ## 7. 关联业务边界 -- Private Zoom 的相册、解锁、Gallery 和支付回跳由 [Private Zoom 权威协议](./FRONTEND_PRIVATE_ZOOM_API.md) 定义。 +- Private Zone 的相册、解锁、Gallery 和支付回跳由 [Private Zone 权威协议](./FRONTEND_PRIVATE_ZONE_API.md) 定义。 - Tip 的角色归属、订单轮询和支付回跳由 [Payment 权威协议](./FRONTEND_PAYMENT_API.md) 定义;Chat 只保存解锁所需的原角色回跳地址。 - 登录、支付和解锁回跳保存原角色动态 URL,不能降级为通用 `/chat`。 - Analytics 可以使用 `characterId`,聊天正文不属于路由或身份协议的一部分。 diff --git a/docs/backend/FRONTEND_PAYMENT_API.md b/docs/backend/FRONTEND_PAYMENT_API.md index 0b7805a7..e972e1f2 100644 --- a/docs/backend/FRONTEND_PAYMENT_API.md +++ b/docs/backend/FRONTEND_PAYMENT_API.md @@ -224,7 +224,7 @@ payChannel = ezpay subscriptionType = vip | topup | tip giftCategory(仅 Tip,可空) giftPlanId(仅 Tip,可空) -returnTo = chat | private-zoom | profile(可选) +returnTo = chat | private-zone | profile(可选) characterSlug(可选) createdAt ``` @@ -238,7 +238,7 @@ Tip -> /characters/{slug}/tip?category=...&planId=...&payChannel=ezpay& 恢复页面只接受与当前 `paymentType` 相同的待处理订单。带有 `paymentReturn=1` 时派发 `PaymentReturned` 并继续轮询;普通进入支付页时会清理同类型的旧待处理订单。订单进入 paid、failed 或 expired 后清理持久化记录。缺少 Gift 字段的旧记录由最新目录默认选择第一件商品,不再读取 `coffee_type`。 -无效或未知 `characterSlug` 回退到默认角色 slug。有效角色回跳必须保留原角色,不能统一返回 Elio。`returnTo=private-zoom` 的最终页面行为由 [Private Zoom 权威协议](./FRONTEND_PRIVATE_ZOOM_API.md) 定义。 +无效或未知 `characterSlug` 回退到默认角色 slug。有效角色回跳必须保留原角色,不能统一返回 Elio。`returnTo=private-zone` 的最终页面行为由 [Private Zone 权威协议](./FRONTEND_PRIVATE_ZONE_API.md) 定义。 ## 8. 成功后的跨域同步 diff --git a/docs/backend/FRONTEND_PRIVATE_ZOOM_API.md b/docs/backend/FRONTEND_PRIVATE_ZONE_API.md similarity index 83% rename from docs/backend/FRONTEND_PRIVATE_ZOOM_API.md rename to docs/backend/FRONTEND_PRIVATE_ZONE_API.md index b6148d3c..14108767 100644 --- a/docs/backend/FRONTEND_PRIVATE_ZOOM_API.md +++ b/docs/backend/FRONTEND_PRIVATE_ZONE_API.md @@ -1,4 +1,4 @@ -# CozSweet Private Zoom 权威协议 +# CozSweet Private Zone 权威协议 ## 1. 状态与范围 @@ -9,11 +9,11 @@ | 边界 | 实现位置 | | --- | --- | | API 路径与方法 | `src/data/services/api/api_contract.json` | -| 请求与响应字段 | `src/data/schemas/private-zoom` | -| API 与 Repository | `src/data/services/api/private_zoom_api.ts`、`src/data/repositories/private_zoom_repository.ts` | -| Private Zoom 状态机 | `src/stores/private-zoom` | -| 页面、Gallery 与导航 | `src/app/private-zoom` | -| 角色 Provider | `src/providers/private-zoom-route-provider.tsx` | +| 请求与响应字段 | `src/data/schemas/private-zone` | +| API 与 Repository | `src/data/services/api/private_zone_api.ts`、`src/data/repositories/private_zone_repository.ts` | +| Private Zone 状态机 | `src/stores/private-zone` | +| 页面、Gallery 与导航 | `src/app/private-zone` | +| 角色 Provider | `src/providers/private-zone-route-provider.tsx` | 修改上述实现时必须在同一变更中更新本文,不能再新增按相册列表、解锁或 Gallery 拆分的并行协议。 @@ -22,13 +22,13 @@ 标准路由: ```text -/characters/{characterSlug}/private-zoom +/characters/{characterSlug}/private-zone ``` 旧地址保留为默认角色重定向,并保留查询参数: ```text -/private-zoom -> /characters/elio/private-zoom +/private-zone -> /characters/elio/private-zone ``` URL 使用角色 `slug`,API 和 Actor 使用角色业务 `id`: @@ -39,14 +39,14 @@ URL 使用角色 `slug`,API 和 Actor 使用角色业务 `id`: | `maya-tan` | `maya` | | `nayeli-cervantes` | `nayeli` | -角色必须同时存在于本地目录且 `capabilities.privateZoom=true`。该能力由本地配置和角色目录响应的 `privateContent` 共同决定;能力关闭或 slug 未知时路由返回 Not Found。 +角色必须同时存在于本地目录且 `capabilities.privateZone=true`。该能力由本地配置和角色目录响应的 `privateContent` 共同决定;能力关闭或 slug 未知时路由返回 Not Found。 -`PrivateZoomProvider` 以 `characterId` 为输入和 React key。切换角色会销毁旧 Actor 并创建空状态,不能复用上一角色的相册、余额或解锁请求。 +`PrivateZoneProvider` 以 `characterId` 为输入和 React key。切换角色会销毁旧 Actor 并创建空状态,不能复用上一角色的相册、余额或解锁请求。 ## 3. 相册列表 ```http -GET /api/private-zoom/albums?characterId=maya-tan&limit=20 +GET /api/private-zone/albums?characterId=maya-tan&limit=20 Authorization: Bearer ``` @@ -55,7 +55,7 @@ Authorization: Bearer | `characterId` | 是 | 当前角色业务 ID | | `limit` | 否 | 当前固定为 20 | -前端当前只加载第一页,不实现 Private Zoom 分页,也不把相册列表写入本地缓存。初始化、手动刷新或登录身份变化时重新请求网络。 +前端当前只加载第一页,不实现 Private Zone 分页,也不把相册列表写入本地缓存。初始化、手动刷新或登录身份变化时重新请求网络。 标准响应数据: @@ -105,7 +105,7 @@ album.locked || !album.unlocked || album.lockDetail.locked 用户点击锁定相册后,前端先展示确认 Dialog。只有待确认 `albumId` 仍存在于当前 Actor 的 `items` 中,才会发起请求。 ```http -POST /api/private-zoom/albums/{albumId}/unlock +POST /api/private-zone/albums/{albumId}/unlock Content-Type: application/json Authorization: Bearer ``` @@ -177,25 +177,25 @@ Schema 同时允许未知字符串,未知失败原因使用通用错误文案 ## 5. 身份与支付导航 -Private Zoom 初始化会复用 Guest 登录引导。Auth 尚未初始化或正在加载时不请求列表;`notLoggedIn` 完成 Guest bootstrap 后再进入列表加载。Guest 和正式用户都可以读取后端允许的相册列表。 +Private Zone 初始化会复用 Guest 登录引导。Auth 尚未初始化或正在加载时不请求列表;`notLoggedIn` 完成 Guest bootstrap 后再进入列表加载。Guest 和正式用户都可以读取后端允许的相册列表。 积分不足生成 Paywall 请求后: | 当前身份 | 导航 | | --- | --- | -| Guest 或 Not Logged In | 打开 Auth,redirect 为当前角色 Private Zoom | -| 已认证用户 | 打开 Top-up,`returnTo=private-zoom`,保留当前角色来源 | +| Guest 或 Not Logged In | 打开 Auth,redirect 为当前角色 Private Zone | +| 已认证用户 | 打开 Top-up,`returnTo=private-zone`,保留当前角色来源 | Paywall 导航发起后立即消费当前请求,避免 React 重渲染重复导航。支付回跳和订单恢复遵循 [Payment 权威协议](./FRONTEND_PAYMENT_API.md)。 -解锁成功后 `unlockSuccessNonce` 递增,页面桥接到 `UserFetch`,刷新当前积分和权益。Private Zoom 不自行修改 User Store 余额。 +解锁成功后 `unlockSuccessNonce` 递增,页面桥接到 `UserFetch`,刷新当前积分和权益。Private Zone 不自行修改 User Store 余额。 ## 6. Gallery URL 协议 解锁相册使用查询参数打开页内 Gallery: ```text -/characters/{slug}/private-zoom?album={albumId}&image={zeroBasedIndex} +/characters/{slug}/private-zone?album={albumId}&image={zeroBasedIndex} ``` 解析规则: @@ -208,7 +208,7 @@ Paywall 导航发起后立即消费当前请求,避免 React 重渲染重复 任一条件不满足时,页面通过 replace 删除 `album` 和 `image`,并保留其他查询参数。 -页面内点击九宫格缩略图时,Gallery 从该图片的后端数组原始索引打开。关闭操作优先使用浏览器 back;直接刷新或外部分享 Gallery URL 时,关闭操作使用 replace 返回当前角色 Private Zoom。 +页面内点击九宫格缩略图时,Gallery 从该图片的后端数组原始索引打开。关闭操作优先使用浏览器 back;直接刷新或外部分享 Gallery URL 时,关闭操作使用 replace 返回当前角色 Private Zone。 Gallery 只浏览 `locked=false` 且 URL 非空的图片,但 URL 中的 `image` 仍使用原始数组索引。横向拖动时图片跟随指针,达到视口宽度 18%(最低 56px),或达到 0.45px/ms 且至少移动 24px 时切换;首尾越界拖动使用 0.28 阻尼且不循环。松手后使用 240ms 横向吸附动画,键盘方向键和左右按钮复用相同切换逻辑。Escape 关闭;`prefers-reduced-motion` 下取消吸附过渡。 @@ -222,17 +222,17 @@ Gallery 只浏览 `locked=false` 且 URL 非空的图片,但 URL 中的 `image - 超过 9 张时卡片显示前九张,末格显示 `+N`,Gallery 仍可浏览全部有效图片; - Gallery 只挂载当前图片和相邻图片,避免多图相册同时解码全部原图; - `creditBalance` 是当前列表/解锁响应快照,不替代 User Store 权益; -- Private Zoom 不使用 Chat 的 `conversationKey`、消息缓存或媒体缓存; -- Private Zoom 不持有 Payment Actor,Top-up 通过路由级导航进入独立 Payment Provider。 +- Private Zone 不使用 Chat 的 `conversationKey`、消息缓存或媒体缓存; +- Private Zone 不持有 Payment Actor,Top-up 通过路由级导航进入独立 Payment Provider。 ## 8. 变更验收 -Private Zoom 协议相关变更至少验证: +Private Zone 协议相关变更至少验证: -1. `src/data/schemas/private-zoom/__tests__`; -2. `src/data/services/api/__tests__/multi_character_api.test.ts` 中的 Private Zoom 请求; -3. `src/stores/private-zoom/__tests__`; -4. `src/app/private-zoom/__tests__` 与组件测试; +1. `src/data/schemas/private-zone/__tests__`; +2. `src/data/services/api/__tests__/multi_character_api.test.ts` 中的 Private Zone 请求; +3. `src/stores/private-zone/__tests__`; +4. `src/app/private-zone/__tests__` 与组件测试; 5. Elio、Maya、Nayeli 列表互不串联; 6. 登录身份变化会刷新当前角色列表; 7. 成功、余额不足、价格变化、重复解锁、退款失败和 not found 分支; diff --git a/docs/external-entry/README.md b/docs/external-entry/README.md index 290cbbdc..40b092ad 100644 --- a/docs/external-entry/README.md +++ b/docs/external-entry/README.md @@ -19,7 +19,7 @@ https:///external-entry?<参数> | 参数 | 可选值或格式 | 用途 | | --- | --- | --- | -| `target` | `chat`、`tip`、`private-zoom` | 指定进入的页面;不传或值无效时进入聊天页。 | +| `target` | `chat`、`tip`、`private-zone` | 指定进入的页面;不传或值无效时进入聊天页。 | | `character` | `elio`、`maya`、`nayeli` | 指定角色;不传或值无效时使用 Elio。 | | `psid` | string | 传入 Facebook Page-scoped User ID。 | | `mode` | `promotion` | 开启聊天促销模式。 | @@ -78,13 +78,13 @@ https:///external-entry?target=tip 私密空间: ```text -https:///external-entry?target=private-zoom +https:///external-entry?target=private-zone ``` 进入 Nayeli 私密空间: ```text -https:///external-entry?target=private-zoom&character=nayeli +https:///external-entry?target=private-zone&character=nayeli ``` `psid` 可以与任意 `target` 或聊天促销参数组合使用。参数值需要进行 URL 编码,不要在入口中传递登录 Token、Page Access Token 或 App Secret。 diff --git a/docs/external-entry/debug-links.md b/docs/external-entry/debug-links.md index 0fcd6779..52c50d55 100644 --- a/docs/external-entry/debug-links.md +++ b/docs/external-entry/debug-links.md @@ -40,8 +40,8 @@ | 角色 | 链接 | | --- | --- | -| Elio | [打开 Elio 私密空间](http://localhost:3000/external-entry?target=private-zoom&character=elio) | -| Maya | [打开 Maya 私密空间](http://localhost:3000/external-entry?target=private-zoom&character=maya) | -| Nayeli | [打开 Nayeli 私密空间](http://localhost:3000/external-entry?target=private-zoom&character=nayeli) | +| Elio | [打开 Elio 私密空间](http://localhost:3000/external-entry?target=private-zone&character=elio) | +| Maya | [打开 Maya 私密空间](http://localhost:3000/external-entry?target=private-zone&character=maya) | +| Nayeli | [打开 Nayeli 私密空间](http://localhost:3000/external-entry?target=private-zone&character=nayeli) | 如需为其他入口携带 PSID,在链接末尾追加 `&psid=27511427698460020`。对于不带查询参数的默认入口,请改为追加 `?psid=27511427698460020`。 diff --git a/docs/external-entry/links.md b/docs/external-entry/links.md index 7164e81f..af002af6 100644 --- a/docs/external-entry/links.md +++ b/docs/external-entry/links.md @@ -18,9 +18,9 @@ | 咖啡打赏 | [打开咖啡打赏](https://frontend-test.banlv-ai.com/external-entry?target=tip) | | Maya 咖啡打赏 | [打开 Maya 咖啡打赏](https://frontend-test.banlv-ai.com/external-entry?target=tip&character=maya) | | Nayeli 咖啡打赏 | [打开 Nayeli 咖啡打赏](https://frontend-test.banlv-ai.com/external-entry?target=tip&character=nayeli) | -| 私密空间 | [打开私密空间](https://frontend-test.banlv-ai.com/external-entry?target=private-zoom) | -| Maya 私密空间 | [打开 Maya 私密空间](https://frontend-test.banlv-ai.com/external-entry?target=private-zoom&character=maya) | -| Nayeli 私密空间 | [打开 Nayeli 私密空间](https://frontend-test.banlv-ai.com/external-entry?target=private-zoom&character=nayeli) | +| 私密空间 | [打开私密空间](https://frontend-test.banlv-ai.com/external-entry?target=private-zone) | +| Maya 私密空间 | [打开 Maya 私密空间](https://frontend-test.banlv-ai.com/external-entry?target=private-zone&character=maya) | +| Nayeli 私密空间 | [打开 Nayeli 私密空间](https://frontend-test.banlv-ai.com/external-entry?target=private-zone&character=nayeli) | ## 正式环境 @@ -36,8 +36,8 @@ | 咖啡打赏 | [打开咖啡打赏](https://cozsweet.com/external-entry?target=tip) | | Maya 咖啡打赏 | [打开 Maya 咖啡打赏](https://cozsweet.com/external-entry?target=tip&character=maya) | | Nayeli 咖啡打赏 | [打开 Nayeli 咖啡打赏](https://cozsweet.com/external-entry?target=tip&character=nayeli) | -| 私密空间 | [打开私密空间](https://cozsweet.com/external-entry?target=private-zoom) | -| Maya 私密空间 | [打开 Maya 私密空间](https://cozsweet.com/external-entry?target=private-zoom&character=maya) | -| Nayeli 私密空间 | [打开 Nayeli 私密空间](https://cozsweet.com/external-entry?target=private-zoom&character=nayeli) | +| 私密空间 | [打开私密空间](https://cozsweet.com/external-entry?target=private-zone) | +| Maya 私密空间 | [打开 Maya 私密空间](https://cozsweet.com/external-entry?target=private-zone&character=maya) | +| Nayeli 私密空间 | [打开 Nayeli 私密空间](https://cozsweet.com/external-entry?target=private-zone&character=nayeli) | 如需在其他入口携带 PSID,在链接末尾追加 `&psid=27511427698460020`。 diff --git a/docs/frontend-integration/2026-07-22-private-zoom-rename.md b/docs/frontend-integration/2026-07-22-private-zone-rename.md similarity index 69% rename from docs/frontend-integration/2026-07-22-private-zoom-rename.md rename to docs/frontend-integration/2026-07-22-private-zone-rename.md index af19d0d2..a612018f 100644 --- a/docs/frontend-integration/2026-07-22-private-zoom-rename.md +++ b/docs/frontend-integration/2026-07-22-private-zone-rename.md @@ -1,4 +1,4 @@ -# Private Zoom 全链路改名联调说明 +# Private Zone 全链路改名联调说明 - 日期:2026-07-22 - 目标环境:本地、`pre`、生产 @@ -6,7 +6,7 @@ ## 1. 目标 -原功能名称存在拼写错误。本次将前端、unified 后端、Manager、数据库、埋点和文档中的正式命名统一为 `Private Zoom`,并同步切换页面路由、API 路径和公开枚举值。 +原功能名称存在拼写错误。本次将前端、unified 后端、Manager、数据库、埋点和文档中的正式命名统一为 `Private Zone`,并同步切换页面路由、API 路径和公开枚举值。 ## 2. 环境地址 @@ -19,12 +19,12 @@ 前端已完成以下修改: -- 页面路由统一为 `/private-zoom` 和 `/characters/{characterSlug}/private-zoom`。 -- 外部入口参数统一为 `target=private-zoom`。 -- 支付回跳参数统一为 `returnTo=private-zoom`。 -- 类型、Repository、API client、XState actor、Provider 和资源目录统一使用 `privateZoom`、`PrivateZoom`、`private-zoom` 或 `private_zoom`。 -- 埋点键统一为 `navigation.private_zoom`、`chat.open_private_zoom_from_avatar` 等新名称。 -- 角色能力字段统一为 `capabilities.privateZoom`。 +- 页面路由统一为 `/private-zone` 和 `/characters/{characterSlug}/private-zone`。 +- 外部入口参数统一为 `target=private-zone`。 +- 支付回跳参数统一为 `returnTo=private-zone`。 +- 类型、Repository、API client、XState actor、Provider 和资源目录统一使用 `privateZone`、`PrivateZone`、`private-zone` 或 `private_zone`。 +- 埋点键统一为 `navigation.private_zone`、`chat.open_private_zone_from_avatar` 等新名称。 +- 角色能力字段统一为 `capabilities.privateZone`。 旧页面和旧查询参数不再作为正式入口保留。发布时必须让前后端属于同一个发布批次。 @@ -34,19 +34,19 @@ | 方法 | 新路径 | 用途 | | --- | --- | --- | -| `GET` | `/api/private-zoom/albums` | 查询付费图片包 | -| `POST` | `/api/private-zoom/albums/{albumId}/unlock` | 解锁图片包 | -| `GET` | `/api/private-zoom/moments` | 查询朋友圈式内容 | -| `POST` | `/api/private-zoom/moments/{momentId}/unlock` | 解锁单条内容 | -| `GET` | `/api/private-zoom/config` | 查询当前角色和用户解锁配置 | -| `GET` | `/api/private-zoom/diaries` | 查询关系日记 | -| `POST` | `/api/private-zoom/diaries/{diaryId}/seen` | 标记关系日记已读 | -| `POST` | `/api/private-zoom/diaries/{diaryId}/unlock` | 解锁关系日记 | +| `GET` | `/api/private-zone/albums` | 查询付费图片包 | +| `POST` | `/api/private-zone/albums/{albumId}/unlock` | 解锁图片包 | +| `GET` | `/api/private-zone/moments` | 查询朋友圈式内容 | +| `POST` | `/api/private-zone/moments/{momentId}/unlock` | 解锁单条内容 | +| `GET` | `/api/private-zone/config` | 查询当前角色和用户解锁配置 | +| `GET` | `/api/private-zone/diaries` | 查询关系日记 | +| `POST` | `/api/private-zone/diaries/{diaryId}/seen` | 标记关系日记已读 | +| `POST` | `/api/private-zone/diaries/{diaryId}/unlock` | 解锁关系日记 | ### 4.1 图片包列表 ```http -GET /api/private-zoom/albums?characterId=elio&limit=20 +GET /api/private-zone/albums?characterId=elio&limit=20 Authorization: Bearer ``` @@ -59,14 +59,14 @@ Authorization: Bearer 调用示例: ```bash -curl 'https://proapi.banlv-ai.com/api/private-zoom/albums?characterId=elio&limit=20' \ +curl 'https://proapi.banlv-ai.com/api/private-zone/albums?characterId=elio&limit=20' \ -H 'Authorization: Bearer ' ``` ### 4.2 解锁图片包 ```http -POST /api/private-zoom/albums/{albumId}/unlock +POST /api/private-zone/albums/{albumId}/unlock Authorization: Bearer Content-Type: application/json ``` @@ -77,7 +77,7 @@ Content-Type: application/json | `expectedCost` | body | integer | 否 | 是 | 前端确认价格;与后端价格不一致时拒绝解锁 | ```bash -curl -X POST 'https://proapi.banlv-ai.com/api/private-zoom/albums//unlock' \ +curl -X POST 'https://proapi.banlv-ai.com/api/private-zone/albums//unlock' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ -d '{"expectedCost":320}' @@ -86,8 +86,8 @@ curl -X POST 'https://proapi.banlv-ai.com/api/private-zoom/albums//unl ### 4.3 Moments 内容与解锁 ```http -GET /api/private-zoom/moments?characterId=elio&limit=20 -POST /api/private-zoom/moments/{momentId}/unlock +GET /api/private-zone/moments?characterId=elio&limit=20 +POST /api/private-zone/moments/{momentId}/unlock ``` 解锁请求体与图片包一致,`expectedCost` 为可选整数。响应中的正式分类值同步改为: @@ -95,8 +95,8 @@ POST /api/private-zoom/moments/{momentId}/unlock ```json { "lockDetail": { - "type": "private_zoom_moment", - "reason": "private_zoom_moment" + "type": "private_zone_moment", + "reason": "private_zone_moment" } } ``` @@ -105,24 +105,24 @@ POST /api/private-zoom/moments/{momentId}/unlock | 使用位置 | 新值 | 类型 | | --- | --- | --- | -| `/api/chat/unlock-private` 的 `lockType` 别名 | `private_zoom` | string enum | -| 日程导入 `contentType` 别名 | `private_zoom` | string enum,归一化为 `paid_content` | -| 外部入口 `target` | `private-zoom` | string enum | -| 支付回跳 `returnTo` | `private-zoom` | string enum | -| 锁定详情分类 | `private_zoom_moment` | string enum | +| `/api/chat/unlock-private` 的 `lockType` 别名 | `private_zone` | string enum | +| 日程导入 `contentType` 别名 | `private_zone` | string enum,归一化为 `paid_content` | +| 外部入口 `target` | `private-zone` | string enum | +| 支付回跳 `returnTo` | `private-zone` | string enum | +| 锁定详情分类 | `private_zone_moment` | string enum | ## 6. 数据库迁移 因为 `pre` 与生产当前共用 `https://dbapi.banlv-ai.com`,预发部署前先执行 unified 仓库中的临时桥接脚本: ```text -database/private-zoom-bridge.sql +database/private-zone-bridge.sql ``` 桥接脚本会创建新表并在切换窗口内保持新旧解锁写入双向同步。生产前后端全部切换完成后,再执行最终迁移: ```text -database/private-zoom-migration.sql +database/private-zone-migration.sql ``` 迁移会在同一事务中完成: @@ -130,7 +130,7 @@ database/private-zoom-migration.sql - 将历史解锁表无损重命名;新旧表同时存在时先合并再删除旧表。 - 重命名关联约束、索引、策略和触发器。 - 合并 `users.preferences` 中历史解锁键,防止已解锁内容重新锁定。 -- 把 `credit_ledger` 历史分类迁移到 `private_zoom` 和 `private_zoom_moment`。 +- 把 `credit_ledger` 历史分类迁移到 `private_zone` 和 `private_zone_moment`。 - 定向迁移历史埋点键、页面 URL 和系统媒体路径,不改写用户聊天正文。 - 删除切换窗口使用的双写触发器和函数。 - 支持重复执行。 @@ -140,13 +140,13 @@ database/private-zoom-migration.sql 这是破坏性命名修正,不保留旧 API、旧页面路由或旧公开枚举作为正式兼容层。必须按以下顺序发布: 1. 备份数据库并记录当前 unified、前端和 Manager 版本。 -2. 执行 `database/private-zoom-bridge.sql`,确认新旧表双向写入一致。 -3. 部署 unified `pre`,验证所有 `/api/private-zoom/*` 接口。 +2. 执行 `database/private-zone-bridge.sql`,确认新旧表双向写入一致。 +3. 部署 unified `pre`,验证所有 `/api/private-zone/*` 接口。 4. 部署前端 `pre`,验证页面、外部入口、解锁和支付回跳。 5. Manager 更新后验证积分用途显示为新分类。 6. `pre` 验证通过后,先启动新生产后端并临时配置旧 API 到新 API 的 Nginx 转发。 -7. 切换生产后端,再部署同批次生产前端;确认新前端只调用 `/api/private-zoom/*`。 -8. 删除临时 Nginx 转发,执行 `database/private-zoom-migration.sql` 清理旧数据库对象。 +7. 切换生产后端,再部署同批次生产前端;确认新前端只调用 `/api/private-zone/*`。 +8. 删除临时 Nginx 转发,执行 `database/private-zone-migration.sql` 清理旧数据库对象。 ## 8. 错误与界面状态 @@ -154,34 +154,34 @@ database/private-zoom-migration.sql - `403`:游客访问仅注册用户可用的关系日记操作,展示现有注册引导。 - `404`:角色、图片包、内容或日记不存在,展示现有空状态或失效提示。 - `409`:`expectedCost` 与后端价格不同,刷新列表后重新确认。 -- `402` 或业务余额不足错误:进入现有充值流程,并使用 `returnTo=private-zoom` 返回原角色页面。 +- `402` 或业务余额不足错误:进入现有充值流程,并使用 `returnTo=private-zone` 返回原角色页面。 - 网络失败:不修改本地解锁状态,保留重试入口。 ## 9. 验收用例 -1. `/characters/elio/private-zoom`、Maya 和 Nayeli 对应页面均可打开。 -2. `GET /api/private-zoom/albums` 返回当前角色内容,角色之间不混用。 +1. `/characters/elio/private-zone`、Maya 和 Nayeli 对应页面均可打开。 +2. `GET /api/private-zone/albums` 返回当前角色内容,角色之间不混用。 3. 已解锁历史记录在迁移后保持解锁状态,不重复扣积分。 4. 新解锁成功后刷新页面仍为已解锁状态。 -5. 积分不足进入充值页后,回跳到原角色 `/private-zoom` 页面。 -6. `target=private-zoom&character=nayeli` 进入 Nayeli 对应页面。 +5. 积分不足进入充值页后,回跳到原角色 `/private-zone` 页面。 +6. `target=private-zone&character=nayeli` 进入 Nayeli 对应页面。 7. Manager 的积分用途不再出现旧分类。 8. 三个仓库执行旧命名残留扫描,结果为 `0`。 ## 10. 当前测试证据 - unified:`316 passed`。 -- 前端:TypeScript 类型检查通过;Vitest `639 passed`;ESLint 通过;契约测试 `4 passed`;生产构建通过并生成三个角色的 `/private-zoom` 页面。 +- 前端:TypeScript 类型检查通过;Vitest `639 passed`;ESLint 通过;契约测试 `4 passed`;生产构建通过并生成三个角色的 `/private-zone` 页面。 - Manager:`75 passed`。 - PostgreSQL 16 临时库:升级、重复升级、回滚和再次升级全部通过;历史解锁、偏好键、积分账本、埋点、媒体路径和数据库对象名均通过断言,临时容器已删除。 -- `pre`:unified `71da49b` 和前端 `35939e7` 已验证;新 API 已注册 `8` 条 `/api/private-zoom/*` 路径,旧 API 路径数量为 `0`;新页面返回 `200`,旧页面返回 `404`。 +- `pre`:unified `71da49b` 和前端 `35939e7` 已验证;新 API 已注册 `8` 条 `/api/private-zone/*` 路径,旧 API 路径数量为 `0`;新页面返回 `200`,旧页面返回 `404`。 - 生产:unified 镜像 `ai-boyfriend-unified:prod-20260722-71da49b`(镜像 ID `sha256:755ef5741856d83d7d808e7df8ee259b6fa5fb94fe333b523ee280ed1d5f674b`)和前端镜像 `prod-35939e7` 已健康运行;Manager 当前版本为 `6eea005`。 -- 生产接口:测试账号调用 `GET https://api.banlv-ai.com/api/private-zoom/config?characterId=elio` 返回 `200`,`success=true`;旧版 API 路径在所有公开 API 入口均返回 `404`。 +- 生产接口:测试账号调用 `GET https://api.banlv-ai.com/api/private-zone/config?characterId=elio` 返回 `200`,`success=true`;旧版 API 路径在所有公开 API 入口均返回 `404`。 - 生产数据库:最终迁移已执行,旧表、桥接函数、桥接触发器、旧偏好键、旧积分分类和旧埋点值的残留数量均为 `0`。 ## 11. 回滚影响 -最终迁移执行前可直接恢复旧应用,桥接表会保留双向一致的数据。最终迁移执行后,回滚必须同时执行 unified 仓库中的 `database/private-zoom-rollback.sql`。回滚前应停止写入,先保存切换后的新增解锁记录,再执行逆向迁移并恢复旧应用版本。不得只恢复前端或只恢复 unified。 +最终迁移执行前可直接恢复旧应用,桥接表会保留双向一致的数据。最终迁移执行后,回滚必须同时执行 unified 仓库中的 `database/private-zone-rollback.sql`。回滚前应停止写入,先保存切换后的新增解锁记录,再执行逆向迁移并恢复旧应用版本。不得只恢复前端或只恢复 unified。 ## 12. 待确认事项 diff --git a/e2e/specs/mock/chat/chat-avatar-navigation.spec.ts b/e2e/specs/mock/chat/chat-avatar-navigation.spec.ts index 44a1bb71..24d8677d 100644 --- a/e2e/specs/mock/chat/chat-avatar-navigation.spec.ts +++ b/e2e/specs/mock/chat/chat-avatar-navigation.spec.ts @@ -42,7 +42,7 @@ test("guest user avatar returns to Profile after sign-in", async ({ }); for (const character of characters) { - test(`${character.displayName} avatar opens the matching Private Zoom`, async ({ + test(`${character.displayName} avatar opens the matching Private Zone`, async ({ page, }) => { await enterCharacterChat(page, character.slug); @@ -50,13 +50,13 @@ for (const character of characters) { await page .getByRole("button", { - name: `Open ${character.displayName}'s private zoom`, + name: `Open ${character.displayName}'s private zone`, }) .last() .click(); await expect(page).toHaveURL( - new RegExp(`/characters/${character.slug}/private-zoom(?:\\?.*)?$`), + new RegExp(`/characters/${character.slug}/private-zone(?:\\?.*)?$`), ); }); } diff --git a/e2e/specs/mock/favorite-menu-navigation.spec.ts b/e2e/specs/mock/favorite-menu-navigation.spec.ts index aa6a1708..aad4963a 100644 --- a/e2e/specs/mock/favorite-menu-navigation.spec.ts +++ b/e2e/specs/mock/favorite-menu-navigation.spec.ts @@ -57,16 +57,16 @@ test("favorite entry and three-tab Menu navigation render on the real pages", as name: "Primary navigation", }); await expect(navigation).toContainText("Chat"); - await expect(navigation).toContainText("Elio Private Zoom"); + await expect(navigation).toContainText("Elio Private Zone"); await expect(navigation).toContainText("Menu"); await savePreview(page, `${mobile ? "mobile" : "desktop"}-splash.png`); - await page.goto("/characters/elio/private-zoom"); + await page.goto("/characters/elio/private-zone"); await expect(page.getByRole("button", { name: "Save CozSweet" })).toBeVisible(); await expect(page.getByRole("button", { name: "Menu" })).toBeVisible(); await savePreview( page, - `${mobile ? "mobile" : "desktop"}-private-zoom.png`, + `${mobile ? "mobile" : "desktop"}-private-zone.png`, ); await page.getByRole("button", { name: "Menu" }).click(); @@ -111,7 +111,7 @@ async function registerFavoriteMenuMocks(page: Page): Promise { }), }); }); - await page.route("**/api/private-zoom/albums**", async (route) => { + await page.route("**/api/private-zone/albums**", async (route) => { await route.fulfill({ json: apiEnvelope({ items: [], creditBalance: 80 }), }); @@ -162,7 +162,7 @@ async function registerFavoriteMenuMocks(page: Page): Promise { }); return; } - if (pathname === "/api/private-zoom/albums") { + if (pathname === "/api/private-zone/albums") { await route.fulfill({ json: apiEnvelope({ items: [], creditBalance: 80 }), }); diff --git a/e2e/specs/mock/multi-role-commercial.spec.ts b/e2e/specs/mock/multi-role-commercial.spec.ts index 2c269d2c..8f1b95de 100644 --- a/e2e/specs/mock/multi-role-commercial.spec.ts +++ b/e2e/specs/mock/multi-role-commercial.spec.ts @@ -81,18 +81,18 @@ for (const character of characters) { } }); - test(`${character.displayName} can open a character-scoped Private Zoom`, async ({ + test(`${character.displayName} can open a character-scoped Private Zone`, async ({ page, }) => { const albumRequest = page.waitForRequest((request) => { const url = new URL(request.url()); return ( - url.pathname === "/api/private-zoom/albums" && + url.pathname === "/api/private-zone/albums" && url.searchParams.get("characterId") === character.id ); }); - await page.goto(`/characters/${character.slug}/private-zoom`); + await page.goto(`/characters/${character.slug}/private-zone`); await albumRequest; await expect( @@ -134,7 +134,7 @@ for (const character of characters) { } async function registerMultiRoleCommercialMocks(page: Page): Promise { - await page.route("**/api/private-zoom/albums**", async (route) => { + await page.route("**/api/private-zone/albums**", async (route) => { const url = new URL(route.request().url()); const characterId = url.searchParams.get("characterId") ?? "elio"; const character = @@ -152,7 +152,7 @@ async function registerMultiRoleCommercialMocks(page: Page): Promise { imageCount: 8, images: [ { - url: `/images/private-zoom/banner/${character.slug}.png`, + url: `/images/private-zone/banner/${character.slug}.png`, locked: true, index: 0, }, diff --git a/public/images/private-zoom/banner/elio.png b/public/images/private-zone/banner/elio.png similarity index 100% rename from public/images/private-zoom/banner/elio.png rename to public/images/private-zone/banner/elio.png diff --git a/public/images/private-zoom/banner/maya.png b/public/images/private-zone/banner/maya.png similarity index 100% rename from public/images/private-zoom/banner/maya.png rename to public/images/private-zone/banner/maya.png diff --git a/public/images/private-zoom/banner/nayeli.png b/public/images/private-zone/banner/nayeli.png similarity index 100% rename from public/images/private-zoom/banner/nayeli.png rename to public/images/private-zone/banner/nayeli.png diff --git a/scripts/contracts/__tests__/openapi-contract.test.mjs b/scripts/contracts/__tests__/openapi-contract.test.mjs index 9216acb1..80f279c8 100644 --- a/scripts/contracts/__tests__/openapi-contract.test.mjs +++ b/scripts/contracts/__tests__/openapi-contract.test.mjs @@ -13,13 +13,13 @@ describe("OpenAPI contract comparison", () => { chatHistory: { method: "get", path: "/api/chat/history" }, unlockAlbum: { method: "post", - path: "/api/private-zoom/albums/{albumId}/unlock", + path: "/api/private-zone/albums/{albumId}/unlock", }, }, { paths: { "/api/chat/history": { get: {} }, - "/api/private-zoom/albums/{album_id}/unlock/": { post: {} }, + "/api/private-zone/albums/{album_id}/unlock/": { post: {} }, }, }, ); diff --git a/src/app/_components/__tests__/tailwind-components.test.tsx b/src/app/_components/__tests__/tailwind-components.test.tsx index 43487509..613d179c 100644 --- a/src/app/_components/__tests__/tailwind-components.test.tsx +++ b/src/app/_components/__tests__/tailwind-components.test.tsx @@ -85,8 +85,8 @@ describe("shared Tailwind components", () => { undefined} />, ); @@ -100,10 +100,10 @@ describe("shared Tailwind components", () => { expect(characterHtml).toContain('