Direct messages beta: desktop right-click parity, release notes, and production hardening - #1
Merged
DaDevMikey merged 6 commits intoAug 11, 2026
Conversation
Co-authored-by: DaDevMikey <169651161+DaDevMikey@users.noreply.github.com>
Co-authored-by: DaDevMikey <169651161+DaDevMikey@users.noreply.github.com>
… scope Co-authored-by: DaDevMikey <169651161+DaDevMikey@users.noreply.github.com>
Copilot created this pull request from a session on behalf of
DaDevMikey
August 11, 2026 15:02
View session
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Introduces a beta Direct Messages surface (separate direct_threads collection with handles + rollout tags), adds an in-app Release Notes modal, and applies a broader UI/UX refresh plus production-hardening changes (cleanup batching, crypto-grade codes, chat perf improvements).
Changes:
- Added Direct Messages UI, handle/username reservation utilities, rollout controls, and DM/thread cleanup flows.
- Hardened Firestore rules and client behavior around identity, message encryption (incl. reply previews), and cleanup batching.
- Added “What’s new” release notes (data + modal) and multiple UI/accessibility improvements across views and components.
Reviewed changes
Copilot reviewed 25 out of 26 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.js | Build output tuning (chunking + build flags). |
| src/views/LoginView.jsx | Username reservation-based login + beta tag seeding + DM handle allocation; login UI refresh. |
| src/views/HomeView.jsx | Home UI refresh; join-by-code validation; DM entry point behind beta flag. |
| src/views/DirectMessagesView.jsx | New DM list + “start DM by handle” + delete thread flow. |
| src/views/CreateRoomView.jsx | Secure room code generation + UI/accessibility polish. |
| src/views/ChatRoomView.jsx | DM/room unification (isDirect), message windowing + decryption cache, reply preview encryption, composer UX updates. |
| src/utils/profile.js | New identity reservation + profile sync + beta preference helpers. |
| src/utils/beta.js | New rollout utilities + secure code / DM handle generation constants. |
| src/utils/batch.js | New chunked batch delete helper for Firestore 500-write limit. |
| src/styles.css | Large design-system update (tokens, One UI ergonomics, dialogs, chips, chat layout). |
| src/releaseNotes.js | New release notes data + CURRENT_RELEASE. |
| src/components/UserSettingsModal.jsx | Settings UI refactor; DM beta toggle; entry point to release notes. |
| src/components/TopAppBar.jsx | App bar layout/accessibility improvements. |
| src/components/Snackbar.jsx | ARIA live region + layout tweaks. |
| src/components/RoomCard.jsx | Memoization + semantic markup + minor timer robustness. |
| src/components/ReleaseNotesModal.jsx | New release notes modal implementation. |
| src/components/PrivacyModal.jsx | Refactored content + accessibility attributes. |
| src/components/PrivacyBanner.jsx | Accessibility improvements; replaces anchor with button. |
| src/components/MessageBubble.jsx | Touch action sheet via long-press + portal; toolbar/accessibility updates. |
| src/components/DialogModal.jsx | Escape-to-close + scroll lock; better dialog semantics; optional cancel button. |
| src/App.jsx | Adds DM routes, release notes gating, profile sync, cleanup batching, beta preference toggle, and purge adjustments. |
| README.md | Updates feature list + documents data model/security posture. |
| package.json | Version bump to 2.2.0. |
| package-lock.json | Version bump to 2.2.0. |
| index.html | Viewport/safe-area tuning + PWA-ish meta tags + defer firebase config load. |
| firestore.rules | Major rules hardening + new collections (direct_threads, usernames, handles) + identity binding. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+28
to
+33
| function ownsName(name) { | ||
| return name is string | ||
| && name.size() > 0 | ||
| && (!exists(usernamePath(name)) | ||
| || get(usernamePath(name)).data.authUid == request.auth.uid); | ||
| } |
Comment on lines
+219
to
+223
| // Authors edit their own text; anyone in the conversation can react. | ||
| allow update: if isSignedIn() && ( | ||
| (isMessageAuthor() && onlyChanged(['content', 'edited', 'reactions'])) | ||
| || onlyChanged(['reactions']) | ||
| ); |
Comment on lines
+71
to
+76
| if (updated.usernameConflict) { | ||
| localStorage.removeItem('tempchats_user'); | ||
| setUser(null); | ||
| showSnackbar('That username now belongs to someone else. Please pick a new one.', 'error'); | ||
| return; | ||
| } |
Comment on lines
+87
to
+95
| const tags = await db.runTransaction(async (tx) => { | ||
| const fresh = await tx.get(ref); | ||
| const freshTags = (fresh.exists && fresh.data().tags && typeof fresh.data().tags === 'object') | ||
| ? fresh.data().tags | ||
| : null; | ||
|
|
||
| const current = freshTags || {}; | ||
| if (!shouldEnrolOnRefresh(current)) { | ||
| if (freshTags) return freshTags; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a Direct Messages feature (1:1, end-to-end encrypted, auto-cleared after 24h) behind a gradual rollout, an in-app release notes dialog, and confirms desktop right-click parity for mobile long-press actions. Follow-up work widens the rollout (random per-load enrolment plus a Settings toggle) and hardens the app so the new surface can't be exploited.
Direct messages
swift-otter-4821); handles are the only way to start a DM.direct_threadscollection, notrooms. This matters for security rules: a participant-only read must be provable from the query. Keeping DMs inroomswould have forced a disjunctive read rule, which breaks the public-room listener, join-by-code, and logout ownership queries.ChatRoomViewis parameterised withisDirect+ aroomRef, so both collections share one chat UI.Rollout controls
tags.betaon the user document gates the feature; absent/false means no access.beta: true.tags.betaOptOut, which suppresses future rolls. Re-roll runs in a transaction so it can't clobber a concurrent opt-out.Identity and security rules
usernames/{lowercase}andhandles/{handle}bind a name to an auth uid. Lookups areget-by-id, sousersdocuments are now readable only by their owner (previously enumerable, and handle lookup via.limit(1)query was capture-prone).senderand a room/thread'screatorto the caller's reservation; message creates require membership in the target thread; direct-thread membership, key and expiry are immutable; room/message writes are owner/author-scoped, with reaction-only updates for everyone else.crypto.getRandomValuesrather thanMath.random.reply_to.contentpreviews are encrypted (previously stored as plaintext inside otherwise-encrypted threads).Release notes
src/releaseNotes.jsholds versioned entries;ReleaseNotesModalauto-opens once perCURRENT_RELEASEand is reopenable from Settings. The DM entry is labelled as a gradual beta rollout.Robustness
src/utils/batch.js, chunked under Firestore's 500-write batch limit.tagsmap are seeded and re-rolled; a username claimed by another account signs the stale session out with a clear message.Notes for reviewers
MessageBubbleonContextMenu); no change was needed, only documentation.firestore.rulesand the README: message ciphertext plus metadata is readable by any signed-in client (aroom_idquery can't prove thread membership); private room codes are visible to anyone listing rooms, which is what makes join-by-code work; typing/presence in public rooms isn't identity-bound.firebase-toolscould not be installed in this environment, so the rules were reviewed by hand. Worth runningfirebase emulators:start --only firestoreagainst them before deploying.