Commit Graph

652 Commits

Author SHA1 Message Date
admin 50ae420871 chore(config): add /ws path suffix to WebSocket URLs
Update WebSocket base URLs across environment examples and default config to include the required `/ws` path suffix that the backend WebSocket endpoint expects. Applies to development, test/local, and production environments.
2026-06-16 12:35:45 +08:00
admin cba52884a3 chore: clean up migration comments and unused params
Remove obsolete Dart migration notes and route handling comments from splash-button.tsx and auth-machine.ts, and drop the unused `self` parameter from `chatWebSocketActor` callback signature.
2026-06-16 12:01:42 +08:00
admin 29776272ad fix(auth): handle null backend values and surface login errors on splash
Two related fixes for OAuth login failures:

- `UserSchema`: backend (Facebook/Apple) returns `null` for fields like
  `email`; Zod's `.default("")` rejects `null`, causing silent login
  failures. Introduce `stringOrEmpty` / `numberOrZero` / `booleanOrFalse`
  helpers (`nullable().transform(v => v ?? x).default(x)`) and apply
  across the schema so input accepts `string | null | undefined` while
  output stays the typed primitive.

- `SplashScreen`: render `state.errorMessage` (set by auth state machine
  `onError`, e.g. Facebook sync / schema mismatch) so users no longer
  get stuck on splash without feedback.
2026-06-16 11:10:21 +08:00
admin 00651861ce chore(env): update stripe publishable key placeholders in env examples 2026-06-16 11:09:20 +08:00
admin e44cc7e2f3 feat(sidebar): redesign sidebar UI with three user states (light theme)
Replace the dark sidebar theme with a light-themed three-state UI
matching the design references:

- guest  : pink "login" pill in user row, no status pill on VIP card,
           "Activate VIP Membership" button shown
- member : "VIP membership not activated" subtitle, no status pill,
           "Activate VIP Membership" button shown
- vip    : pink "VIP Member" pill with diamond icon, "Activated" pill
           in VIP card header, no Activate button

Decompose into BackBar, UserHeader, VipBenefitsCard, and VoicePackageCard
under src/app/sidebar/components/. Delete obsolete GuestPanel,
UserInfoCard, and VipCta.

Lift VIP_BENEFITS to a shared src/data/constants/vip-benefits.ts so the
sidebar and subscription page render identical benefit copy.

Add five sidebar tokens (--color-card-surface, --color-voice-gradient-*
--border-card, --shadow-card, --color-pill-bg) to src/tokens/colors.css.

Includes barrelsby regeneration for src/app/sidebar/components and
side-effect barrel updates under src/stores/{auth,chat,sidebar,user},
plus package-lock.json from npm install (required for lint/typecheck).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 10:30:21 +08:00
admin 0548a08cbb feat: integrate Stripe payment with subscription plans
Add Stripe payment integration across the project:

- Add @stripe/stripe-js dependency
- Configure Stripe environment variables (secret key, publishable key, webhook secret) for dev, local, and production environments
- Add Product/Price IDs for monthly, quarterly, and annual subscription tiers
- Extend subscription plan data with voiceMinutesPerDay quotas (30/45/60 minutes per tier)
- Update .gitignore to exclude implementation_plan.md
2026-06-16 10:21:02 +08:00
admin 17741320ff Implement code changes to enhance functionality and improve performance 2026-06-15 19:13:47 +08:00
admin 6614e788fe chore(gitignore): ignore pictures directory
Add `pictures/` to .gitignore to prevent tracking of local image files that should not be committed to the repository.
2026-06-15 19:03:35 +08:00
admin 7ec76e592f Add new image assets for voice message feature
- Added ic_voicemessage_lock.png for locking voice messages.
- Added pic_bg_vip.png as a background for VIP sections.
- Added pic_popup_voicemessage.png for the voice message popup interface.
2026-06-15 18:53:47 +08:00
admin 7b347a5c30 style(sidebar): retune user area to dark theme with pink accent
Rebase the sidebar's user information area onto the project's
dark sidebar surface (--color-sidebar-background #0d0b14) and
pink accent (--color-accent #f84d96), replacing the previous
white-card / purple-gradient look that did not align with the
design.

- Shell, back link, profile card, guest panel: switch to dark
  surfaces (#1a1625) with white text.
- VIP badge: use --color-accent pink (was purple fallback).
- VIP CTA + Sign up primary link: use --color-button-gradient
  pink gradient (was purple fallback).
- Sign in secondary link: use dialog border on transparent.
- Override nested SettingsSection elements (list/row/button/svg)
  inside the sidebar's settingsArea so the dark theme carries
  through without modifying the shared core component.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 18:50:04 +08:00
admin 664ff67ee9 chore(githooks): simplify post-receive hook and overwrite server log
Simplify the repo toplevel detection logic and remove verbose comments from the post-receive hook. Switch next-server.log from append mode to overwrite mode so each deploy starts with a fresh log file.
2026-06-15 18:44:35 +08:00
admin fd5dfe2715 feat(sidebar): show user info with three-state UI (guest/member/vip)
Sidebar screen now primarily displays user-related information
and derives three render states from loginStatus + currentUser.isVip:

- guest (notLoggedIn): welcome panel + Sign in / Sign up entries
- member (logged in, no VIP): user info card + Get VIP CTA + Log out
- vip (logged in, VIP): user info card with VIP badge + Manage VIP CTA
  + Log out

Adds UserView.isVip (default false), patches user-machine.toView()
to populate it, and introduces three presentational components
(GuestPanel, UserInfoCard, VipCta) co-located under src/app/sidebar.

Preserves existing UserInit + logout-redirect behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 18:11:39 +08:00
admin 1449acd6c9 chore(barrels): regenerate barrel files via barrelsby
- Fix chat components barrel to properly export all component modules
- Remove interceptor exports from API services barrel
- Regenerate store barrel files (auth, chat, sidebar, user) using barrelsby
2026-06-15 17:53:15 +08:00
Claude e88a99626d feat(subscription): add VIP subscription page
Add a new /subscription route showing three VIP membership plans (Monthly,
Quarterly, Annual) with a pink→peach banner, per-plan gradient price bars,
a benefits card, a mock activate CTA, and an agreement checkbox.

- New reusable <Checkbox /> in src/app/_components/core for the legal
  agreement toggle
- Hardcoded SUBSCRIPTION_PLANS constant in src/data/constants
- New SubscriptionScreen composed of 7 colocated components (back link,
  user row, banner, plan card, benefits card, CTA button) with CSS
  Modules matching the existing design-token system
- Route registered as protected and reached from /sidebar "Membership"
- Mock CTA: window.alert + router.push(/chat) — no payment calls

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 17:49:15 +08:00
admin b9315c9f8b refactor(chat): synchronize guest chat quota updates for messages and images 2026-06-15 17:47:35 +08:00
admin 31f2433c4b refactor: auto-init guest chat quota on first read, clean up logs
- Remove unused `quotaWarningThreshold` and `warningThreshold` getter from `GuestChatQuota` DTO
- Apply get-or-init pattern in `ChatStorage.getGuestDailyChatQuota` and `getGuestTotalQuota`: when no existing value, initialize with DTO defaults (`threshold` = max per day, `totalQuotaDefault`) and return the seeded data
- Fall back to original `null` result if initialization write fails
- Consolidate logging strategy: drop per-actor trace logs in `chat-machine.ts`, keep business-decision logs in 3 assign actions, move all actor ENTRY/API/DONE chains to `chat-machine.actors.ts` and helper load logs to `chat-machine.helpers.ts`
2026-06-15 17:39:50 +08:00
admin fa694af723 docs(plan): add chat state machine refactor design
Update implementation_plan.md with a detailed refactor plan that splits
`chatInitActor` into two independent actors (`loadQuotaActor` +
`loadHistoryActor`) and redesigns the history loading flow to follow
local → network → save semantics so the UI sees local data first,
then network data.

Key changes outlined in the plan:
- Add new events: `ChatQuotaLoaded`, `ChatHistoryLocalLoaded`,
  `ChatHistoryNetworkLoaded`, `ChatHistorySyncDone`
- Remove dead-code `ChatInit` event
- Extend `ChatState` with `quotaLoaded` and `historyLoaded` flags
- Use an `always` barrier in `guestSession.initializing` and
  `userSession.initializing` so both tasks must complete before
  transitioning to `ready`
- Guest init runs `loadQuota` + `loadHistory` in parallel; non-guest
  init runs `chatWebSocket` + `loadHistory` as independent tasks

Also adds `implementation_plan` to .gitignore.
2026-06-15 17:05:32 +08:00
admin 9b28404673 refactor(chat): remove QuotaDialog and related state/effects
Drop the QuotaDialog component invocation in chat-screen along with
its useState/useEffect wiring, and delete the component files. Update
JSDoc in chat-screen and routes to reflect the removed consumer.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 16:24:50 +08:00
admin 1f3980d461 chore(chat): refactor chat init into separate quota and history actors
Split `chatInitActor` into `loadQuotaActor` (guest quota fetch) and `loadHistoryActor` (local → network → save sync), and add `quotaLoaded` / `historyLoaded` state flags so the UI can display loading status during the new local-first history hydration flow. Also drop the now-unused `ChatInit` event and pipe Next.js stdout/stderr to a persistent log file in the post-receive hook for easier troubleshooting.
2026-06-15 16:21:40 +08:00
admin cfc6de5a8c style(pwa-install-dialog): tune content text color and margins
Set content color to #393939 and apply 36px horizontal margin to align
with the dialog's visual rhythm.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 15:57:46 +08:00
admin 41dfc6094b chore: update favicon and app icons
Replace favicon.ico and PWA app icons (Icon-192.png, Icon-512.png) with updated versions.
2026-06-15 14:47:27 +08:00
admin 87edc682b4 Merge branch 'dev' into test 2026-06-15 14:26:35 +08:00
admin a1b595ca14 chore: add dev:proxy script and change start port
- Add dev:proxy script using HTTPS_PROXY for proxied local development
- Update start script to run on port 9135
2026-06-15 14:25:26 +08:00
admin 7b143ee1d2 test: trigger debug hook 2026-06-15 14:23:31 +08:00
admin 4a86e95ecf fix(githooks): restore cd-to-repo-top before NVM load
Without cd, git rev-parse --show-toplevel fails inside .git/
with 'must be run in a work tree', causing init_log_file to
write to /logs/post-receive.log (root path), and copy_env_by_branch
to fail with 'cannot stat env-example/...'.
2026-06-15 14:18:58 +08:00
admin cc75bed133 chore(githooks): simplify post-receive hook
Remove the repo top-level navigation logic and its accompanying
explanatory comments from the post-receive hook. The previous code
used `git rev-parse --absolute-git-dir` and `dirname` to determine
and `cd` into the repository's top-level directory, which is no
longer needed. The hook now starts directly with the nvm setup,
making the script leaner and easier to maintain.
2026-06-15 14:10:26 +08:00
admin 3b1ab0fc1b fix(githooks): use git rev-parse --absolute-git-dir for repo root
The $0-based dirname trick didn't work because git invokes
hooks with just the basename (e.g., 'post-receive'), not the
absolute path. Use 'git rev-parse --absolute-git-dir' instead,
which works even when CWD is inside .git/.
2026-06-15 13:07:16 +08:00
admin d3e134d247 fix(githooks): use simple NVM loading (same as .bashrc)
Replace complex pnpm-finding fallback with the same NVM loading
syntax used in ~/.bashrc. Removes the multiple candidate-path
fallback loop in favor of a clean shell snippet.
2026-06-15 13:02:46 +08:00
admin b7e048ed87 fix(githooks): derive repo top from $0 path (not --show-toplevel)
git-receive-pack may invoke hook with CWD inside .git/,
where 'git rev-parse --show-toplevel' errors with
'must be run in a work tree'. Use $(dirname $0) instead.
2026-06-15 11:51:49 +08:00
admin ca3adb0f5b chore(router): disable router proxy and re-exports by commenting out
Comment out `src/router/index.ts` and `src/router/proxy.ts` to temporarily
disable the Next.js 16 proxy (auth-driven redirects) and router re-exports.
This effectively turns off the centralized route guard logic and stops the
proxy from intercepting requests until further iteration.
2026-06-15 11:50:09 +08:00
admin 558b3a32af fix(githooks): cd to repo top + load pnpm into PATH
- cd to repo toplevel first (defensive: git-receive-pack CWD may differ)
- source nvm or directly find pnpm binary if not in PATH
- prepend pnpm's dir to PATH so build/start work

Root cause: post-receive hook was not being triggered on push.
With core.hooksPath=.githooks (relative), git-receive-pack
resolved the path incorrectly. Also pnpm wasn't in PATH during
non-interactive shell invocation.
2026-06-15 11:48:49 +08:00
admin b2170f789b abs path test 2026-06-15 11:39:20 +08:00
admin f0a5f9f7cd trace test from clone 2026-06-15 11:37:48 +08:00
admin caacc5cb83 test from local clone 2026-06-15 11:37:29 +08:00
admin 67bd1b13a2 test: after old hook delete 2026-06-15 11:37:00 +08:00
admin a18fb0f07d test: trace push 2026-06-15 11:35:41 +08:00
admin 5d1aebdfad refactor(auth): extract helpers and actors out of auth-machine
Move the file-local Helpers block (readGuestId) to auth-helpers.ts and the
Actors block (authRepo + 7 fromPromise actors) to auth-actors.ts. Public API
(authMachine, AuthEvent, AuthState, initialState, AuthMachine) is unchanged;
auth-context.tsx and the barrel index.ts need no edits.
2026-06-15 11:33:05 +08:00
admin 9c1622c6bd test: add marker to hook 2026-06-15 11:32:24 +08:00
admin 46cb0a9b9d test: marker push 4 1781494272 2026-06-15 11:31:12 +08:00
admin f5be8d558e test: marker push 3 1781494210 2026-06-15 11:30:10 +08:00
admin fe70c3748a test: marker push 1781494100 2026-06-15 11:28:20 +08:00
admin c26ba02c42 test: trigger post-receive hook 1781493924 2026-06-15 11:25:24 +08:00
admin 65891b3a8a chore(deploy): comment out version bump in deployment script 2026-06-15 10:58:22 +08:00
admin 83fdd73923 refactor(githooks): restructure post-receive hook into modular functions
Refactor the post-receive deployment hook from a linear script into
discrete functions (init_log_file, write_metadata_header,
copy_env_by_branch, run_build, stop_existing_next, launch_next) for
better readability, maintainability, and error isolation.

Key changes:
- Remove `set -e` so deploy errors don't block git push; each step
  handles its own failures (missing env, build failure
2026-06-12 19:08:25 +08:00
admin f72d1ce94f ci(deploy): branch-aware env copy and restore start output silencing
- Select env template per branch: main → .env.production, test/dev → .env.local
- Skip env copy on unknown branches with warning log
- Revert pnpm run start output to /dev/null (debugging complete)
- Reorder LOG_FILE definition before env-copy block so case branches can log
2026-06-12 18:53:30 +08:00
admin c90d2a5139 chore(env): add AUTH_SECRET for next-auth across environments
- Add per-environment AUTH_SECRET (dev/test/prod) for next-auth v4 JWT signing
- Temporarily redirect next start stdout/stderr to LOG_FILE in post-receive hook for server error debugging
2026-06-12 18:42:43 +08:00
admin 546e5f4b3d chore(githooks): rename hooks dir to .githooks and stop old next processes
Move repository-managed git hooks from `git_hooks/` to `.githooks/` to follow the conventional hidden-directory naming, and add a graceful shutdown step in `post-receive` that terminates any running `next start` / `next-server` processes (SIGTERM → wait 2s → SIGKILL → wait 1s) before relaunching, avoiding EADDRINUSE port conflicts so the freshly built code actually takes effect. README updated to reference the new path.
2026-06-12 18:24:08 +08:00
admin 8afcc40b9c fix:社交登录重定向网址错误问题 2026-06-12 18:15:58 +08:00
admin c7b02ecfb6 refactor(auth): extract NextAuth config to shared lib module
Move the NextAuth v4 configuration from the route handler
(src/app/api/auth/[...nextauth]/route.ts) into a dedicated module
(src/lib/auth/auth.ts) to establish a single source of truth. The
route file now simply re-exports the handler from the shared
module, keeping provider setup, JWT/session callbacks, and
environment variable references in one reusable location.
2026-06-12 17:56:01 +08:00
admin dbc9a0cd13 refactor(auth): inline NextAuth v4 config and simplify AuthPlatform API
- Inline NextAuth v4 handler directly in `[...nextauth]/route.ts`, removing
  the `@/lib/auth/nextauth` abstraction layer
- Add Google/Facebook providers with JWT/session callbacks that expose
  `idToken` and `accessToken` on the session for backend exchange
- Refactor `AuthPlatform` from constructor-based to static methods
  (`googleSignIn()` / `facebookSignIn()`)
- Update `auth-machine.ts` and layout comment reference to match new structure
- Align with original Dart `nextauth-helpers.{googleLogin, facebookLogin}()`
  naming and keep persistence concerns (unstorage, backend, custom cookies)
  out of scope for this iteration
2026-06-12 17:20:56 +08:00