@ermis-network/ermis-chat-react 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +144 -0
  2. package/dist/index.cjs +5087 -11279
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +632 -152
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.mts +273 -9
  7. package/dist/index.d.ts +273 -9
  8. package/dist/index.mjs +5085 -11295
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +2 -2
  11. package/src/components/Channel.tsx +0 -3
  12. package/src/components/ChannelActions.tsx +6 -1
  13. package/src/components/ChannelHeader.tsx +8 -32
  14. package/src/components/ChannelInfo/AddMemberModal.tsx +7 -1
  15. package/src/components/ChannelInfo/ChannelInfo.tsx +82 -2
  16. package/src/components/ChannelInfo/EditChannelModal.tsx +2 -2
  17. package/src/components/ChannelInfo/MediaGridItem.tsx +215 -78
  18. package/src/components/ChannelInfo/useChannelInfoTabs.tsx +170 -129
  19. package/src/components/ChannelList.tsx +72 -13
  20. package/src/components/CreateChannelModal.tsx +131 -12
  21. package/src/components/FilesPreview.tsx +8 -12
  22. package/src/components/FlatTopicGroupItem.tsx +27 -16
  23. package/src/components/ForwardMessageModal.tsx +11 -3
  24. package/src/components/MediaLightbox.tsx +444 -304
  25. package/src/components/MessageActionsBox.tsx +2 -0
  26. package/src/components/MessageInput.tsx +41 -12
  27. package/src/components/MessageItem.tsx +70 -25
  28. package/src/components/MessageQuickReactions.tsx +131 -128
  29. package/src/components/MessageReactions.tsx +47 -2
  30. package/src/components/MessageRenderers.tsx +1030 -433
  31. package/src/components/PinnedMessages.tsx +40 -12
  32. package/src/components/QuotedMessagePreview.tsx +99 -8
  33. package/src/components/RecoveryPin/RecoveryPin.tsx +279 -0
  34. package/src/components/RecoveryPin/index.ts +19 -0
  35. package/src/components/TopicList.tsx +20 -5
  36. package/src/components/TypingIndicator.tsx +3 -3
  37. package/src/components/UserPicker.tsx +26 -25
  38. package/src/components/VirtualMessageList.tsx +345 -125
  39. package/src/context/ChatProvider.tsx +27 -1
  40. package/src/hooks/useChannelListUpdates.ts +22 -1
  41. package/src/hooks/useChannelMessages.ts +338 -51
  42. package/src/hooks/useChannelRowUpdates.ts +18 -6
  43. package/src/hooks/useChatUser.ts +9 -1
  44. package/src/hooks/useE2eeAttachmentRenderer.ts +204 -0
  45. package/src/hooks/useE2eeFileUpload.ts +38 -0
  46. package/src/hooks/useFileUpload.ts +25 -5
  47. package/src/hooks/useForwardMessage.ts +210 -13
  48. package/src/hooks/useLoadMessages.ts +16 -4
  49. package/src/hooks/useMentions.ts +60 -6
  50. package/src/hooks/useMessageActions.ts +14 -8
  51. package/src/hooks/useMessageSend.ts +64 -12
  52. package/src/hooks/usePendingE2eeSends.ts +29 -0
  53. package/src/hooks/useRecoveryPin.ts +287 -0
  54. package/src/hooks/useScrollToMessage.ts +29 -4
  55. package/src/hooks/useTopicGroupUpdates.ts +49 -11
  56. package/src/index.ts +23 -0
  57. package/src/messageTypeUtils.ts +14 -0
  58. package/src/styles/_channel-info.css +9 -0
  59. package/src/styles/_channel-list.css +37 -14
  60. package/src/styles/_media-lightbox.css +36 -3
  61. package/src/styles/_message-bubble.css +381 -41
  62. package/src/styles/_message-input.css +8 -0
  63. package/src/styles/_message-list.css +67 -10
  64. package/src/styles/_message-quick-reactions.css +101 -59
  65. package/src/styles/_message-reactions.css +18 -32
  66. package/src/styles/_recovery-pin.css +97 -0
  67. package/src/styles/_tokens.css +5 -5
  68. package/src/styles/_typing-indicator.css +23 -13
  69. package/src/styles/index.css +1 -0
  70. package/src/types.ts +115 -1
  71. package/src/utils/avatarColors.ts +1 -1
  72. package/src/utils.ts +38 -18
package/README.md CHANGED
@@ -2,6 +2,150 @@
2
2
 
3
3
  The official React UI components for Ermis Chat.
4
4
 
5
+ ## E2EE UI Support
6
+
7
+ - `CreateChannelModal` supports E2EE direct/group creation when `client.encryptionManager` is initialized.
8
+ - `CreateChannelModal` accepts `e2eeRecoveryPolicy`, defaulting to `member_assisted`, and sends it with new E2EE direct/group creation payloads.
9
+ - Channel info actions can enable E2EE for an existing standard channel when the viewer is the owner and encryption is initialized; enable uses `member_assisted` recovery by default unless the caller has already set a policy in channel data.
10
+ - Channel message lists listen for `e2ee.message_decrypted` and refresh decrypted message content from the SDK encryption storage.
11
+ - Channel and topic-group previews listen for E2EE decrypted/local-cache refresh events so sidebar previews replace `Encrypted message` after plaintext is available.
12
+ - E2EE sender display names come from the richest local user metadata available, so message rows and channel previews do not fall back to raw user ids when a cache entry only contains `{ id }`.
13
+ - Quoted reply previews fall back to the active channel state when a message has `quoted_message_id` and no renderable embedded `quoted_message`; sticker quotes render as stickers before the encrypted/unavailable fallback is considered.
14
+ - Recovery PIN helpers expose vault state, unlocked PIN change, issue-bearing restore progress records, `repairEncryptedChannel()` for Channel Info repair, lower-level archive repair, selected-channel restore progress loading, and queue enqueueing for app-level PIN gates.
15
+ - `useRecoveryPin()` refreshes after encryption initialization and restore progress events, including apps that mount recovery UI before `client.encryptionManager` is attached.
16
+ - `CreateChannelModal` asks the SDK to archive the initial E2EE epoch after server channel creation succeeds, but does not fail channel creation if archive upload/stash is temporarily unavailable.
17
+ - Channel info add/remove member actions use encryption member commits for E2EE channels and never fall back to standard `removeMembers` while encryption is required. Self-leave calls `channel.leaveChannelE2ee`, sending `self_remove: true` so the remaining designated encryption member can commit the eviction.
18
+ - Consumers can customize E2EE toggle rendering through `E2eeToggleComponent` and receive E2EE status/key-rotation props in channel info cover/actions components.
19
+ - Custom Channel Info action components receive the current `channel`, allowing selected-timeline repair UI without relying on global active-channel state.
20
+
21
+ ## Progress Log
22
+
23
+ ### 2026-07-03 - E2EE File Upload Progress
24
+
25
+ - Goal: make generic E2EE file upload bubbles update progress like image/video attachments.
26
+ - Code changed: `MessageRenderers` memo comparisons for image, video, and file attachments now include `upload_status`, rounded `upload_progress`, type, and local object URL via `attachmentRenderKey`; generic file attachments no longer compare only the object URL.
27
+ - Docs/artifacts changed: this README records the React behavior fix. Bellboy E2EE docs record the matching multipart complete optimization and client-side progress guidance. SQL and Postman are unchanged because no public API/schema changed.
28
+ - Design decision: keep progress delivery event-driven in the SDK/channel state and make render memoization observe that state instead of adding polling or special file-only state.
29
+ - Verification: `./node_modules/.bin/prettier --write packages/ermis-chat-react/src/components/MessageRenderers.tsx packages/ermis-chat-react/README.md`, `npm run build:react`, `npm run build:uhm`, and monorepo `git diff --check` passed.
30
+
31
+ ### 2026-06-19 - E2EE Sender Display Name Hydration
32
+
33
+ - Goal: keep freshly sent encrypted messages from showing the current user's raw id in message rows or channel previews.
34
+ - Code changed: React consumes SDK message state whose E2EE user objects are now selected from richer local metadata instead of bare cache entries; no React component API changed.
35
+ - Docs/artifacts changed: this README records the UI behavior. SDK and UHM README files record the SDK/app-level fix. SQL, Postman, and Bellboy docs are unchanged because no server/API contract changed.
36
+ - Design decision: display-name preservation belongs in SDK hydration so every React surface, including timeline and channel rows, receives consistent message user data.
37
+ - Performance: no React-side complexity changes; SDK user selection adds only constant-candidate checks per hydrated encrypted message and no network/backend work.
38
+ - Verification: `npm run build:sdk`, `npm run build:react`, `yarn workspace uhm-chat build`, and `yarn workspace @ermis-network/ermis-chat-sdk test:repair` passed.
39
+
40
+ ### 2026-06-19 - E2EE Quoted Reply Preview
41
+
42
+ - Goal: render quoted reply UI for sent messages and avoid `Message unavailable` when the replied-to message is already decrypted locally.
43
+ - Code changed: `MessageItem` now resolves a missing or unrenderable `quoted_message` from active channel message sets/pinned messages, treats `type: 'sticker'` quote previews as renderable, and `useMessageSend` includes reply/edit state in the send callback dependencies. `QuotedMessagePreview` renders sticker/attachment previews before encrypted-unavailable fallback checks. `useScrollToMessage` now maps message IDs to rendered VList indexes that include date separators. `useChannelMessages` keeps full IndexedDB E2EE cache hydration for channel open/recovery paths but realtime events only overlay local cache entries for currently rendered message IDs and their quoted IDs, preventing older cached reply messages from being reinserted into the visible list during append. `VirtualMessageList` now reads live VList bottom metrics, snaps appended messages in a layout effect before paint, temporarily blocks scroll-triggered pagination while auto-following new messages, and disables browser scroll anchoring so reply sends/realtime receives do not briefly jump to the quoted message before returning to the newest message.
44
+ - Docs/artifacts changed: this README records the React UI behavior. SDK and UHM README files record the matching cache hydration and app-level fix. SQL, Postman, and Bellboy docs are unchanged because no server/API contract changed.
45
+ - Design decision: React keeps a synchronous render fallback for already-loaded timeline messages, while the SDK handles durable IndexedDB hydration for reload/sync paths. Full local-cache windows are reserved for explicit open/recovery flows; realtime append/update paths are visible-list overlays so local persisted history cannot reset the virtualized list anchor. Scroll-to-message must use VList's rendered child indexes, not raw message-array indexes, because date separators are also VList children. Realtime bottom-follow uses instant snaps, not smooth scrolling, and suppresses load-more during the snap window because transient VList scroll offsets can otherwise prepend older history and expose an older quoted-message anchor between renders.
46
+ - Performance: fallback lookup is `O(M)` per rendered item only when `quoted_message` is missing, rendered-index lookup is `O(M)` only on explicit quote/search jumps, realtime local-cache overlay is `O(V + Q)` for visible message IDs plus quoted IDs instead of loading a fixed 100-message IndexedDB window, and live bottom checks are `O(1)` reads from VList metrics; no network or backend work is added.
47
+ - Verification: `npm run build:sdk`, `npm run build:react`, `yarn workspace uhm-chat build`, and `yarn workspace @ermis-network/ermis-chat-sdk test:repair` passed. The latest scroll refinement was reverified with `npm run build:react` and a sequential `yarn workspace uhm-chat build`.
48
+
49
+ ### 2026-06-17 - Encryption Naming API Cleanup
50
+
51
+ - Goal: align React package integration points with the SDK encryption naming cleanup.
52
+ - Code changed: React hooks/components now read `client.encryptionManager`, use encryption initialization naming, and expose Channel Info props as `encryptionInitialized` / `encryptionEpoch`.
53
+ - Docs/artifacts changed: this README records the rename boundary. Bellboy wire fields remain `mls_*`, so API docs, SQL, and Postman artifacts are unchanged.
54
+ - Design decision: UI package names should describe the product feature as encryption; OpenMLS remains an implementation detail below the SDK boundary.
55
+ - Performance: no runtime complexity, memory, storage, network, payload, or scaling behavior changes.
56
+ - Verification: `npm run build:react`, `yarn workspace uhm-chat build`, static forbidden-name checks, and Node SDK export smoke test passed. Targeted UHM ESLint was attempted but is blocked by existing app lint errors unrelated to this rename.
57
+
58
+ ### 2026-06-17 - E2EE Topic Preview Refresh
59
+
60
+ - Goal: fix topic-enabled channel list previews staying on `Encrypted message` after a hidden topic message decrypts.
61
+ - Code changed: `useChannelRowUpdates()` and `useTopicGroupUpdates()` now listen for E2EE decrypted/local-cache refresh events and recompute row previews for the matching channel or topic group.
62
+ - Docs changed: E2EE UI support notes now mention channel/topic-group preview refresh behavior.
63
+ - Design decision: keep the fix in React render-state wiring; the SDK already merges successful decrypted messages into channel state before dispatching `e2ee.message_decrypted`.
64
+ - Verification: `npm run build:react` and `yarn workspace uhm-chat build` passed.
65
+
66
+ ### 2026-06-16 - E2EE Recovery Policy Create Flow
67
+
68
+ - Goal: expose Bellboy recovery policy selection to React create-channel consumers.
69
+ - Code changed: `CreateChannelModalProps` now includes `e2eeRecoveryPolicy`, and `CreateChannelModal` sends `data.e2ee_recovery_policy` when creating E2EE direct/group channels.
70
+ - Code changed: Channel Info enable E2EE now passes the recovery policy to `EncryptionManager.enableE2ee()`, defaulting to `member_assisted`.
71
+ - Design decision: the default remains `member_assisted`; apps that need strict self-owned recovery can pass `self_owned_only` without changing the encryption bundle flow.
72
+ - Verification: `npm run build:react` passed.
73
+
74
+ ### 2026-05-17 - Production
75
+
76
+ - Goal: fix E2EE self-leave from React channel actions so OpenMLS does not reject a self-removal commit.
77
+ - Code changed: `ChannelInfo.tsx` and `ChannelActions.tsx` now call `channel.leaveChannelE2ee(currentUserId)` for E2EE leave actions instead of `encryptionManager.evictMember(...)` or a plain `removeMembers(...)` call.
78
+ - Follow-up audit: E2EE remove-member actions now fail early if encryption is not initialized instead of falling back to standard `removeMembers`, and remove errors are rethrown to the confirmation/action caller.
79
+ - Docs changed: this README now distinguishes E2EE remove-member commits from self-leave with `self_remove=true`.
80
+ - Design decision: self-leave remains a channel membership update; the existing `member.removed` handler cleans local encryption state for the leaving user only after the server emits the removal event and lets a remaining designated member commit the encryption eviction with `selfLeft=true`.
81
+ - Verification: `./node_modules/.bin/tsc --noEmit -p packages/ermis-chat-react/tsconfig.json` and `yarn workspace @ermis-network/ermis-chat-react build` passed.
82
+ - Next step: browser retest the E2EE leave action with at least one remaining online designated evictor.
83
+
84
+ ### 2026-05-29 - PIN Restore Local Sync
85
+
86
+ - Goal: refresh the visible message list immediately after PIN archive restore writes decrypted messages into SDK storage.
87
+
88
+ ### 2026-06-01 - PIN Recovery Gate and Restore Progress
89
+
90
+ - Goal: expose production PIN recovery UX primitives for setup, unlock, incomplete restore prompts, and terminal gap display.
91
+ - Code changed: `useRecoveryPin()` now surfaces SDK recovery status and queue enqueueing, while `RecoveryGate` and `RecoveryRestoreProgress` provide dialog/progress rendering helpers.
92
+ - Design decision: the recovery gate is a non-blocking dialog. Permanent gaps render as recovery metadata and do not create fake timeline messages.
93
+ - Code changed: `useChannelMessages` now merges `event.messages` from `e2ee.local_messages_loaded` before reloading the encryption local cache.
94
+ - Verification: `yarn workspace @ermis-network/ermis-chat-react build` and `yarn workspace uhm-chat build` passed.
95
+
96
+ ### 2026-06-01 - Restore Progress Event Wiring
97
+
98
+ - Goal: let consuming apps react to resumable PIN restore progress without polling.
99
+ - Code changed: `useRecoveryPin()` now subscribes to `e2ee.initialized` and `e2ee.restore_progress`, refreshes recovery status, and exposes `loadRestoreProgress(channelType, channelId)` for active-channel badges and gap banners.
100
+ - Verification: `npm run build:uhm` passed, including SDK, React package, and uhm-chat builds.
101
+
102
+ ### 2026-06-19 - PIN Settings Restore Diagnostics
103
+
104
+ - Goal: let account-level PIN settings summarize unavailable history without showing permanent-gap warnings inside every channel.
105
+ - Code changed: `useRecoveryPin()` now carries SDK `restoreProgressWithIssues` records through `recoveryStatus` so apps can render channel-level diagnostics in one settings surface.
106
+ - Verification: `npm run build:sdk`, `npm run build:react`, `yarn workspace uhm-chat build`, and `yarn workspace @ermis-network/ermis-chat-sdk test:repair` passed.
107
+
108
+ ### 2026-06-01 - Initial Archive and Gate Refresh Fixes
109
+
110
+ - Goal: close real-app gaps where recovery UI mounted before encryption init and new E2EE rooms could miss their first epoch archive.
111
+ - Code changed: `useRecoveryPin()` now retries status refresh while encryption initialization is still attaching the manager, and `CreateChannelModal` archives the current epoch immediately after the created E2EE channel is available.
112
+ - Design decision: archive upload still belongs to the SDK manager; React only triggers the post-create hook after the channel exists on the server.
113
+ - Verification: `npm run build:uhm` passed.
114
+
115
+ ### 2026-06-01 - Non-blocking Initial Archive Hook
116
+
117
+ - Goal: keep E2EE room creation usable even if local deferred archive encryption or archive upload fails.
118
+ - Code changed: `CreateChannelModal` now fires the post-create initial archive hook as best-effort and logs failures without rejecting the channel creation flow.
119
+ - Verification: `npm run build:uhm` passed.
120
+
121
+ ### 2026-06-13 - Account PIN and Channel Repair APIs
122
+
123
+ - Goal: let apps move PIN management to account settings and expose message-level encrypted-history repair in Channel Info.
124
+ - Code changed: `useRecoveryPin()` now exposes `changeUnlockedRecoveryPin()` and `repairRecoveryChannel()`, and reports `ready` only when the recovery vault is actually unlocked.
125
+ - Code changed: custom `ChannelInfoActions` receive the selected channel for correct topic/timeline repair.
126
+ - Design decision: locked vault UI must not expose change PIN; repair callers can choose failed-only retry or full selected-channel recheck.
127
+ - UX decision: consuming apps should normally present one Repair action. Uhm Chat uses full selected-channel recheck internally and keeps retry-mode terminology out of the user interface.
128
+ - UX decision: the repair card is conversation-oriented, uses a neutral secondary action, and expands result metrics plus remaining issue details inline from a detail row.
129
+ - Verification: `npm run build:react`, `yarn workspace uhm-chat build`, and targeted Uhm ESLint for the new PIN/repair components passed.
130
+
131
+ ### 2026-06-13 - Encrypted State Repair Hook
132
+
133
+ - Goal: expose the SDK safe-cursor replay/reset repair API to React apps without forcing users to pick retry modes.
134
+ - Code changed: `useRecoveryPin()` now exposes `repairEncryptedChannel(channelType, channelId, { mode })` and returns the SDK result with `requiresPin`, `resetAvailable`, processed counts, and message repair summary.
135
+ - Design decision: apps should call replay from the primary Repair button. If `requiresPin` is true, open the PIN dialog and resume repair after unlock; if `resetAvailable` is true, show the advanced reset action with a warning.
136
+ - Verification: `npm run build:react` and `yarn workspace uhm-chat build` passed.
137
+
138
+ ### 2026-06-14 - Archive-First Repair Semantics
139
+
140
+ - `repairEncryptedChannel()` keeps the same React contract, but the SDK now tries PIN archive recovery before protocol replay and only exposes reset after protocol replay failure.
141
+ - Missing archive material remains a normal unavailable-history result and must not show the reset warning.
142
+ - PIN unlock automatically rechecks accepted E2EE timelines once per unlock session.
143
+
144
+ ### 2026-06-15 - Vault Revision and V2 Rollout
145
+
146
+ - `useRecoveryPin()` keeps the account PIN flow unchanged while the SDK enforces Bellboy vault revisions internally.
147
+ - Repair UI must remain compatible with V1 archive discovery until Bellboy completes manifest/recipient backfill; V2 availability is a transport/storage optimization and does not introduce a second user-facing repair mode.
148
+
5
149
  ## Documentation
6
150
 
7
151
  For full documentation, component references, and integration guides, please visit our official documentation website: