Three parallel adversarial code-review passes surfaced real defects across the app. This commit covers the data/logic layer: - CRITICAL: file upload/download used the wrong auth header entirely. Built from docs/IM-前后端对接文档.md as `X-MeetingIM-Auth: token <token>`, but the old app's own upload code carries an explicit comment that the real header is `Authorization: Token <token>` (capitalized scheme, standard header name), "verified live against the real server, not just read from source" -- and separately warns the SDK's own built-in LargeFileHelper gets this wrong too (sends X-Tinode-APIKey/X-Tinode-Auth, which this backend doesn't recognize). This means every external (non-inline) image/file/voice attachment -- anything too large to send as base64 -- was silently broken; only the earlier live tests happened to use small inline attachments, which never exercise this code path. Confirmed fixed live: a real >256KB image now uploads (200, real file_id) and downloads (blob URL, correct 800x600 dimensions) correctly. - CRITICAL: TopicMe.onContactUpdate was never wired. Marking a conversation read (topic.noteRead()) updates the contact's unread count through ONLY this single-slot callback (confirmed against the SDK's own Topic.note()/TopicMe._refreshContact -- it does not also fire onData/ onInfo/onPres, unlike every other _refreshContact call site, which do). Without it the chat list's unread badge/ordering went stale after reading a conversation until an unrelated topic event happened to invalidate the shared snapshot cache. - HIGH: chat-list message preview didn't check isServerDeleted(msg) (the `hi` soft-delete flag), only `content == null` -- a hi-flagged message with non-null content leaked its real text/attachment label into the preview instead of showing "[消息已删除]". - MEDIUM: upload failures showed raw untranslated SDK ctrl.text (e.g. "too large" instead of "文件大小超出限制") -- ported the old app's UPLOAD_CTRL_TEXT_CN table, which it built specifically because this native-protocol endpoint's errors never pass through the REST layer's own reason-code translation. - Ambient SDK type corrections (tinode-sdk.d.ts): AccessMode.mode/given/want are numeric bitmasks at runtime, not the "JRWPS"-string type they were declared as (dormant today, nothing reads them yet, but wrong ahead of Phase 3's group-role logic); Drafty.sanitizeEntities's doc comment claimed a deep copy it doesn't do (verified it mutates entity .data in place); onAutoreconnectIteration's first param was misnamed "seconds" when the SDK always passes milliseconds. - sendVoice() now passes `filename` to Drafty.insertAudio (was the only one of sendImage/sendFile/sendVoice omitting it). - friends.ts's accept/reject-friend-request `version` param used a falsy check (`version ? ... : ...`) that would silently drop a legitimate `0`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
React + TypeScript + Vite
This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules.
Currently, two official plugins are available:
- @vitejs/plugin-react uses Oxc
- @vitejs/plugin-react-swc uses SWC
React Compiler
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.
Expanding the Oxlint configuration
If you are developing a production application, we recommend enabling type-aware lint rules by installing oxlint-tsgolint and editing .oxlintrc.json:
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["react", "typescript", "oxc"],
"options": {
"typeAware": true
},
"rules": {
"react/rules-of-hooks": "error",
"react/only-export-components": ["warn", { "allowConstantExport": true }]
}
}
See the Oxlint rules documentation for the full list of rules and categories.