- Introduce PermissionControlPanel in UserCenter for managing notification permissions.
- Update Service Worker (sw.ts) to handle background push notifications via Firebase Cloud Messaging.
- Implement EventSubscribeService logic to fetch active events, filter expired ones, and clean up subscriptions.
- Refactor KaiqiuService and parsing utilities to include eventId in event details.
- Remove deprecated ScheduleService and inline sendNotification logic.
- Update utility functions to support new types and notification checks.
- Add VAPI public key configuration and update Firebase exports.
Refactor the application to implement native browser push notifications and remove unnecessary Redis caching for performance optimization.
Key changes:
- Introduce a dedicated server topic 'SERVER_PUSH' to handle push notification messages via WebSocket.
- Implement a Service Worker (sw.ts) to capture push events and display system-level notifications, replacing the previous Ant Design toast usage for server messages.
- Add a "Notification Permission" button in the User Center to allow users to request push notification rights.
- Remove Redis caching logic from KaiqiuService (event lists, match details, and member details) to ensure real-time data accuracy, as the cache was causing latency in updates.
- Clean up WebSocket service subscription logic to focus on user-specific events.
This shift from UI-only notifications to system push notifications improves visibility for critical server events (like match updates) even when the user is not on the active tab. Additionally, removing the cache simplifies the codebase and ensures the latest match data is always fetched.
- Add `.catch(() => null)` in `ClubSummary.tsx` to gracefully handle failed API requests and prevent UI crashes.
- Return `null` from `ClubSummary` when the club data is `null` to skip rendering during errors.
- Extract `getMatchInfo` logic into a new static method `getMatchDetail` within `KaiqiuService` for better separation of concerns.
- Update `getClubLocation` and `getEventInfo` to accept an optional `force` parameter, allowing cache bypass when network errors (like '连接超时') occur.
- Remove the old `getMatchInfo` utility function from `server.ts` and update the `/api/match` route to use `KaiqiuService.getMatchDetail`.
- Add `UserBind` model to Prisma schema for linking Logto and Kaiqiu user IDs.
- Implement `/api/account/bind` endpoint (GET/PUT) to handle Kaiqiu account binding and retrieval.
- Refactor `KaiqiuService` to include a `login` method that performs browser automation-like login on kaiqiuwang.cc using `cheerio` and `fetch`.
- Update `UserCenter` page to include a new `BindKaiqiuAccount` component.
- Restructure `WebSocketService`:
- Change from a simple global connection map to a per-user client tracking system (`#userClients`).
- Update topic naming conventions (e.g., `ONLINE_MEMBER_CHANGE` -> `MEMBER_CHANGE`).
- Add client-side broadcast capabilities for user-specific events like `MY_CLIENT_ONLINE`.
- Add support for dynamic subscription handling (SUB/UNSUB) via WebSocket messages.
- Update `verifyLogtoToken` to accept either `Headers` or a raw token string for flexibility in WebSocket auth.
- Minor fixes: typo corrections in `WSTopic` enum and commented out debug logs.
BREAKING CHANGE: WebSocket payload structure has changed.
The `ws.data` property now contains a `WsPaylaod` object with a `user` field (previously it was a JSON string of the JWT payload).
The `WSTopic` names have been updated (e.g., `ONLINE_MEMBER_CHANGE` is now `MEMBER_CHANGE`), requiring updates to any client code subscribing to these topics.
- Remove `getGitHash` function from `src/utils/server.ts` as it relied on `.git` directory presence which is not available in production builds.
- Remove the `/api/app-version` endpoint from `src/index.tsx` since fetching version via API is no longer needed.
- Update `src/hooks/useAppVersion.ts` to derive the version directly from the `src` attribute of a script tag in the HTML head.
- This change improves performance by avoiding an extra API request and ensures version accuracy across all deployment environments without requiring Git metadata.
- Add `getGitHash` utility to extract the git commit hash from the `.git/HEAD` file.
- Expose a new `/api/app-version` endpoint on the server to return the current version.
- Implement a `useAppVersion` hook to fetch the version asynchronously.
- Display the app version (e.g., `app version: a1b2c3d`) in the User Center UI for both authenticated and unauthenticated users.
- This helps in tracking which version of the application is currently running in production.
- Centralized Logto domain and API base URLs in `common.ts` to avoid duplication.
- Replaced deprecated `Modal.useModal` with `App.useApp().modal` for consistent Ant Design usage.
- Refactored `useAutoLogin` hook to handle token expiration checks and trigger re-authentication.
- Updated `UserCenter` and `FavPlayersPage` to use the new `autoSignIn` flow.
- Removed the `useAuthHeaders` hook as logic was consolidated into `useAutoLogin`.
- Added `AUTH_CALLBACK_URL` and `USER_CENTER_URL` constants for cleaner routing.
- Update database schema to rename `UserFav` to `LogtoUserFav` with clearer field names (`logto_uid`, `kaiqiu_uid`).
- Bump `jose` dependency to v6.2.1 for improved JWT verification.
- Configure `@logto/react` to request the correct resource token for API access.
- Implement token verification on the server side using `jose` and `jwtVerify`.
- Update API routes (`/api/fav`) to extract the user ID from the verified JWT `sub` claim instead of the URL `aud` parameter.
- Refactor frontend components (`FavButton`, `FavePlayersPage`) to use `useAuthHeaders` for fetching auth headers instead of manual token claims extraction.
- Clean up unused migration and DAO functions related to the old `aud`-based logic.
- **Frontend Refactoring**: Extracted EventCard logic and finished game filtering from GameSelector into a new ClubEventsList component. Removed direct routing logic (handleGameClick, navigate) from App.tsx in favor of router loaders.
- **New Feature - Club Detail Page**: Implemented /club/:id route with ClubEventsPage. Added server-side loader to fetch club info and events in parallel via new API endpoints (/api/club/find, /api/club/:id). Created KaiqiuService for direct data fetching.
- **API & Types**: Extended IEventInfo with isFinished flag; updated server-side parsing in utils/server.ts. Added ClubInfo type definition. Migrated club search and filtering logic to the server side.
- **Dependencies**: Updated antd from 6.2.1 to 6.3.2.
- Corrected the default value assignment for REDIS_CACHE_HOUR using logical OR instead of nullish coalescing.
- Added a debug log to output the cache hour value.
- Added error handling for redis.get calls to ensure they return a string or an empty string in case of failure.
- Added REDIS_CACHE_HOUR to .env.example and src/utils/server.ts.
- Updated TIMEOUT usage in src/services/uidScoreStore.ts and src/utils/server.ts to use REDIS_CACHE_HOUR.
- Increased the cache expiration time for event lists from 30 minutes to 72 hours.
- Increased the cache expiration time for match info from 3 minutes to 72 hours.
- Added REDIS environment variable to .env.example
- Updated src/index.tsx to check for multiple required environment variables
- Updated src/utils/server.ts to use REDIS environment variable for RedisClient
- export shared redis client from utils/server
- reuse shared redis in uidScoreStore
- cache listEvent HTML for 30 minutes
- cache getMatchInfo HTML for 3 minutes
- move event scraping/parsing and match lookup logic into src/utils/server.ts
- extract BASE_URL and grouping/round-table helpers into src/utils/common.ts
- update component/service entry imports to new module locations
- remove deprecated src/utils/utils.ts monolith
- clean up unused XCXFindUser type import
- update tests to new utils import path
- move shared parsing/grouping helpers into serverUtils and update imports
- add xcxApi singleton in serverUtils
- add Redis-backed uid score store and /api/user/nowScores endpoint
- preload uid scores in event loader and tags in profile loader
- allow grouping prediction to switch sort mode between current/yearly score
- update tags component to consume loader-provided tags
- remove unused zustand game store
- add redis test scaffold and scoreboard component scaffold