72b7b79cafb048e4705e29f96f501d35cd893def
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
72b7b79caf |
fix(web): code review round 3 -- UI bugs and remaining design fidelity
- FileAttachment never surfaced a failed authenticated download -- the card looked identically clickable whether it worked or not, and clicking while broken silently no-op'd. Added an error state/retry (useAuthedBlobUrl gained a retry() escape hatch for this). ImageAttachment/AudioAttachment already handled this; only the file card didn't. - --shadow-btn was one token serving two different specs: round 2's fix (0 6px 16px, from the 50px auth CTAs) actually regressed the 36px messaging send button (ConversationView/VoiceRecorder), which needs 0 4px 12px per 02-messages.dc.html. Split into --shadow-btn / --shadow-btn-sm. - loadOlder's scroll-restore guard compared topicId by value, which false-positives on an A->B->A round trip within one request's lifetime (same string, but the DOM was torn down and rebuilt by the intervening open/close). Switched to a generation counter, same pattern as topics.ts's leave-race fix. - errorToast wasn't included in ConversationView/DetailColumn's topicId-reset effects -- a failed action's toast could keep showing over a conversation/contact switched to afterward. Also switched those effects (and MessagesLayout's) from useEffect to useLayoutEffect -- since none of these components remount on topicId change, a post-paint effect could let one frame render with the previous topicId's stale UI still showing. - VoiceRecorder never listened for MediaRecorder's own onerror -- a mid-recording failure left the "录音中" timer ticking forever with no indication the recording had already died. - VerificationCodeButton's phone-change countdown reset (round 2) only cleared the button's own state; RegisterPage/ResetPasswordPage's challengeId was still tied to whatever phone the code was actually issued for, with nothing cross-checking it against a since-edited phone number. - Agreement's checkbox used bare accent-color on a native input, which only tints the checked fill and leaves size/radius/border to the browser/OS; replaced with the spec's exact 16x16 border-radius:4px box + check glyph. - Added a catch-all route (App.tsx), TenantFeedbackPage image-picker validation feedback + corrected remove-button style, and a handful of smaller token/spacing corrections against screens/*.dc.html (NavRail font-weight, LoginPage/TenantEntryPage logo size+shadow+color, ChatListColumn row padding/icon size, --shadow-modal alpha). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
569f266390 |
fix(web): code review round 1 -- auth pages design fidelity + missing screens
- CRITICAL correctness bug: resetTinode() was defined but never called anywhere. Switching tenants (TenantEntryPage) only updated the session store; the Tinode singleton it drives is created once and permanently cached (getTinode() lazily creates it, reusing it forever afterward), so every subsequent login kept talking to the FIRST tenant's host regardless of which tenant was actually selected -- multi-tenant switching was silently broken. Also moved LoginPage's getTinode() call to after its "no tenant yet" redirect guard, so it can't get created against a not-yet-resolved tenant in the first place. - Error strips across all four auth pages were missing the error_outline icon README §10.1 specifies. - Fixed a token mix-up affecting every error-state input border across Register/PasswordInput: README's exact spec is border #d94b4b (this app's --color-danger-text) with #cf3f3f text below (--color-danger-border) -- the code had them backwards, borders were using danger-border. - TenantEntryPage: added the missing 企业注册/遇到问题 links (now real, working pages -- see below), fixed the business icon's color token (was accent #1677ff, spec calls for focus-border #4091ff). - LoginPage/ResetPasswordPage: the "切换企业"/"返回登录" back link was nested inside the vertically-centered form container, so it got pulled to the page's middle instead of staying pinned to the top like every reference screenshot shows it. Also gave LoginPage's brand panel the spec's 56/44 split (was an even 50/50), 40px headline (was Tailwind's 36px text-4xl), and the missing footer links row; added a mobile-only large-logo facade (matches 1e-mobile-login.png) since the desktop split-panel brand block is hidden below 900px and mobile had no tenant-identifying visual at all. - RegisterPage: removed an extra 56px-logo+tenant-name block that appears in neither the desktop nor mobile reference screenshots; added the mobile-only 48px back-chevron+title header bar the design calls for (RegisterPage previously had zero back-navigation on any breakpoint). - ResetPasswordPage: the password error text said "需要包含字母和数字" while the actual check only enforces a minimum length (>=8, no character-class requirement, matching Register's own rule) -- the message was promising a validation this page doesn't perform. - VerificationCodeButton: the resend countdown's setInterval was never cleared on unmount -- a real leak if the user navigates away mid-countdown. - New: EnterpriseRegisterPage (企业注册, README §10.5) and TenantFeedbackPage (问题反馈, README §10.6 / `01/1j`), both previously linked-to-but-nonexistent. lib/api/tenant.ts gained the REST calls they need (submitTenantApplication, submitTenantEntryFeedback, uploadPublicFile against the pre-login /v1/im/public/uploads surface, distinct from the chat-file upload endpoint). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
f549248c08 |
feat(web): real chat list + P2P conversation view against live Tinode data
Phase 2 core loop: chat list and single-chat conversation now read/write real
Tinode topic data end to end, replacing the earlier hardcoded placeholders.
- lib/tinode/topics.ts: per-topic pub-sub layered on connection.ts's pattern
(Topic.onData/onInfo/etc are single-slot callbacks, claimed once and fanned
out). Implements the old app's subscribe lifecycle: `me` subscribed once
per session (metadata only), each contact gets a one-shot preview
subscription (withLaterData(1), never left), opening a conversation
leaves-then-resubscribes with a full history page (withData, not
withLaterData -- a preview prefetch already nudging _maxSeq would make
withLaterData return empty).
- lib/tinode/hooks.ts: useChatList()/useTopicMessages() via
useSyncExternalStore, snapshots cached and only invalidated on real
topic-change notifications (not recomputed every render).
- lib/tinode/send.ts: sendText/retryMessage via createMessage+publishDraft
(optimistic local echo), not the simpler publish() -- matches the old
app's approach. retryMessage flushes the failed local entry and rebuilds
before republishing, per the old app's context-menu retry handler.
- lib/messages/{time,avatar,attachments,status,preview,dispatch,drafty}:
formatting utilities. Avatar color hash ports the old app's Java-style
string hash but with modulus 11 (this design's palette) not the old app's
16. @mention renders flat accent blue per the new design, not the old
app's per-user hash color -- a deliberate simplification. File-type icons
(PDF/Word/Excel/PPT) are new-design-only; the old app buckets all
documents identically. Date/time formatting is written fresh against the
design spec (today+time combined, weekday tier) since the old app never
combines a relative-date word with a time in one string.
- ChatListColumn, MessageBubble, ConversationView: real components replacing
the placeholder chat list and "占位" conversation view.
- tinode-sdk.d.ts: expanded with the real Topic/MetaGetBuilder/Drafty
surface needed above, verified against the installed SDK source
(createMessage/publishDraft/messages/msgStatus/noteRead/flushMessage/
Drafty.format's exact treeBottomUp contract, MESSAGE_STATUS_* statics).
Verified end to end against the real backend: used the still-functional old
app (a second account, ixp355087) to create a real friendship and exchange
messages with the new app's test account, confirming the new chat list and
conversation view correctly render pre-existing real data, sending a new
message shows the right optimistic-then-delivered status transition, and
the old app receives it live in return.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
aa1c46ff22 |
feat(web): full auth screens rework to match design + old-app business rules
Rebuilt tenant/login/register/reset-password to match the design handoff's 01-account screens precisely (previously only loosely approximated), and ported the old app's real business rules instead of guessing: - LoginPage: desktop split branding panel (>=900px), terms-agreement checkbox gating submit, forgot-password link, password visibility toggle, full ctrl-error translation table (lib/tinode/errors.ts, ported from the old app's CTRL_ERROR_TEXT_CN/translateCtrlError -- registration/login go over native WS, not REST, so client.ts's REASON_MESSAGES never applied). - RegisterPage: rebuilt as the real unified username-OR-phone form (not phone-only) -- username optional unless phone is blank, invite code required+validated only on the username-only path, matching the server's actual resolveRegistrationAccount rules. connection.ts's registerAccountByPhone generalized into registerAccount() supporting both paths, including the Tinode.credential(null) crash the old app had to work around on the username-only path. - New ResetPasswordPage wired to /auth/password-reset/* (a different endpoint family than registration's /auth/verification-codes/*). - Shared components: PasswordInput, VerificationCodeButton, Agreement, Toast. - Fixed tinode-sdk.d.ts: the real method is getCurrentUserID(), not the invented getAuthenticatedUserID() -- caught live, login crashed past a successful auth. - Fixed a responsive bug present on all four auth pages: fixed w-[380px] forms overflowed past the viewport edge below ~430px wide. Verified end-to-end against the real backend (api.118im.com, tenant "default"): fresh phone registration, password reset, re-login with the new password, and the username-only path's invite-code rejection all round-tripped correctly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
63c1b84b41 |
feat(web): phone registration + fix login/register response handling
- Add RegisterPage (phone + SMS code) and lib/api/auth.ts verification-code
endpoints, wired into App.tsx routing.
- Fix registerAccountByPhone(): the injected acc.phone extra field must be
bare 11-digit, not E.164 -- server checks digit length before normalizing.
- Fix LoginCtrl shape: SDK's login/loginBasic/createAccountBasic promises
resolve with the ctrl fields flat, not wrapped in {ctrl: {...}}.
- Fix tinode-sdk.d.ts: the real method is getCurrentUserID(), there is no
getAuthenticatedUserID().
All three bugs found and fixed via live testing against the real backend
(api.118im.com, tenant "default"), confirming registration and login both
work end-to-end.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|