Commit Graph

212 Commits

Author SHA1 Message Date
admin d5ddb3f97f fix(githooks): cd to worktree root before running build
When git invokes post-receive, cwd is GIT_DIR (not worktree root).
`git rev-parse --show-toplevel` refuses to run from a bare context,
so the script would silently cd into .git/. Use `--absolute-git-dir`
and its parent to find the worktree reliably.

Also: receive.denyCurrentBranch=false means push does NOT auto-update
the worktree, so the hook must do `git reset --hard HEAD` to sync
the source the build will use.
2026-06-16 14:18:25 +08:00
admin fa5678ffdf ci: debug post-receive cwd 2026-06-16 14:15:51 +08:00
admin 704e2292fc ci: post-receive hook live test from plan-mode-exec 2026-06-16 14:12:28 +08:00
admin 9ffa30cc03 style: remove markdown bold syntax from code comments
Remove `**...**` emphasis markers from inline comments and JSDoc blocks across
auth and chat components, machine mappers, and quota helpers. These are
plain code comments, not rendered markdown, so the bold syntax was noise.

Files touched:
- src/app/auth/components/auth-screen.tsx
- src/app/chat/components/chat-header.tsx
- src/app/chat/components/chat-screen.tsx
- chat machine mapper / quota helpers

No functional or behavioral changes.
2026-06-16 14:06:31 +08:00
admin 8553f91e5d ci: trigger post-receive hook smoke test #2 (absolute hooksPath) 2026-06-16 14:02:59 +08:00
admin a370518d5f ci: trigger post-receive hook smoke test 2026-06-16 13:27:47 +08:00
admin c24a7751b7 Merge branch 'dev' into test 2026-06-16 13:24:48 +08:00
admin 7506dcae3a chore(githooks): sync worktree to new HEAD in post-receive hook
The post-receive hook now performs a `git reset --hard HEAD` after each push
to ensure the working tree reflects the newly received commits. This is needed
when the server's `receive.denyCurrentBranch` is set to `false`, in which case
Git no longer auto-updates the working tree and downstream build steps would
otherwise run against stale code.
2026-06-16 13:24:37 +08:00
admin c878959dd7 chore: add use client directive and remove outdated dart reference
- Add "use client" directive to device_identifier.ts to enable client-side usage
- Remove outdated Dart source reference comment in pwa-install-overlay.tsx
2026-06-16 13:23:46 +08:00
deploy-bot d4dab061a8 fix(deploy): sync worktree to HEAD inside post-receive
The server-side .git/config sets receive.denyCurrentBranch=updateInstead,
which auto-updates the worktree but bypasses the post-receive hook entirely.
Changing it to false restores hook execution; adding git reset --hard HEAD
inside the hook compensates for the lost auto-update so the build uses the
just-pushed source code.
2026-06-16 13:17:40 +08:00
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