Fix cross-device sync for attach logs preference (MM-67856)#9667
Fix cross-device sync for attach logs preference (MM-67856)#9667
Conversation
WatermelonDB query .observe() only emits when records enter/leave the result set, not when a field on an existing record changes. This caused the attach logs toggle to not sync across devices after the initial creation. Fix by subscribing to the individual record's .observe() via switchMap, which emits on any field change. Extract observePreferenceAsBool helper to app/queries/servers/preference.ts and use it in both report_a_problem and quick_actions enhanced components. Also adds unit tests, E2E tests, and debug logging for preference WS events. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Coverage Comparison ReportGenerated on April 14, 2026 at 15:03:32 UTC |
There was a problem hiding this comment.
Pull request overview
Fixes a realtime sync issue where the “Attach app logs” preference didn’t update across devices because the underlying WatermelonDB query observable didn’t emit on field updates for existing records.
Changes:
- Introduced
observePreferenceAsBoolto correctly react to preference value updates and reused it in Report a Problem and post draft quick actions. - Added unit test coverage for reacting to preference updates and a new Detox E2E suite for the attach logs toggle/attachment menu behavior.
- Added debug logging for preference WebSocket events.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
detox/e2e/test/products/channels/account/attach_logs.e2e.ts |
Adds E2E coverage for attach logs toggle visibility and attachment menu option. |
detox/e2e/support/ui/screen/report_problem.ts |
Adds a Detox screen object for the Report a Problem screen interactions. |
detox/e2e/support/ui/screen/index.ts |
Exports the new ReportProblemScreen helper. |
app/screens/report_a_problem/index.ts |
Switches attach logs observable to the new per-record preference observer. |
app/screens/report_a_problem/index.test.tsx |
Adds a unit test to ensure UI reacts to preference value changes. |
app/queries/servers/preference.ts |
Adds observePreferenceAsBool helper for reactive boolean preferences. |
app/components/post_draft/quick_actions/index.ts |
Updates quick actions gating logic to use boolean preference observable. |
app/components/post_draft/quick_actions/attachment_quick_action/index.test.tsx |
Adds a test to ensure showAttachLogs is passed through correctly. |
app/actions/websocket/preferences.ts |
Adds debug logs for preference change WebSocket events. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| testID = { | ||
| reportProblemScreen: 'ReportProblem', | ||
| enableLogAttachmentsToggleOff: 'report_problem.enable_log_attachments.toggled.false.button', | ||
| enableLogAttachmentsToggleOn: 'report_problem.enable_log_attachments.toggled.true.button', | ||
| closeButton: 'close-report-problem', | ||
| }; | ||
|
|
||
| reportProblemScreen = element(by.id(this.testID.reportProblemScreen)); | ||
| enableLogAttachmentsToggleOff = element(by.id(this.testID.enableLogAttachmentsToggleOff)); | ||
| enableLogAttachmentsToggleOn = element(by.id(this.testID.enableLogAttachmentsToggleOn)); | ||
| closeButton = element(by.id(this.testID.closeButton)); |
There was a problem hiding this comment.
reportProblemScreen is set to the testID ReportProblem, but the app code for the Report a Problem screen doesn't expose a matching testID (and close-report-problem also doesn't appear to be wired up anywhere). This will likely make toBeVisible()/close() fail in E2E. Consider anchoring visibility/close interactions on existing, stable IDs (e.g. the RNN back button screen.back.button from navigation options), or add a dedicated screen-level testID in the app and reference ${id}.screen like other settings screens.
| const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl); | ||
| const preference: PreferenceType = JSON.parse(msg.data.preference); | ||
| logDebug('[WS] PREFERENCE_CHANGED', preference.category, preference.name, preference.value); | ||
| handleSavePostAdded(serverUrl, [preference]); |
There was a problem hiding this comment.
These logDebug statements log preference values received over WebSocket. Preference values can be large (e.g., theme JSON) and may contain sensitive/user-specific data; logging them can bloat logs and impact performance in production. Consider logging only category/name (and maybe value length), or gating value logging behind a debug/dev flag.
| const canUploadFiles = observeCanUploadFiles(database); | ||
| const maxFileCount = observeMaxFileCount(database); | ||
| const allowDownloadLogs = observeConfigBooleanValue(database, 'AllowDownloadLogs', true); | ||
| const attachLogsPref = queryPreferencesByCategoryAndName( | ||
| database, | ||
| Preferences.CATEGORIES.ADVANCED_SETTINGS, | ||
| Preferences.ATTACH_APP_LOGS, | ||
| ).observe(); | ||
| const attachLogsPref = observePreferenceAsBool(database, Preferences.CATEGORIES.ADVANCED_SETTINGS, Preferences.ATTACH_APP_LOGS); | ||
|
|
There was a problem hiding this comment.
attachLogsPref now holds an Observable<boolean> (via observePreferenceAsBool), not a preference model/array. Renaming it to something like attachLogsEnabled (or similar) would avoid confusion when reading the combineLatest logic.
- Add testID to Report a Problem screen and use screen.back.button in Detox screen object to match existing settings screen patterns - Remove unused REPORT_PROBLEM_CLOSE_BUTTON_ID export - Omit preference values from debug logs to avoid logging large or sensitive data - Rename attachLogsPref to attachLogsEnabled for clarity Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Follow up of #9633
WatermelonDB query .observe() only emits when records enter/leave the result set, not when a field on an existing record changes. This caused the attach logs toggle to not sync across devices after the initial creation. Fix by subscribing to the individual record's .observe() via switchMap, which emits on any field change.
Extract observePreferenceAsBool helper to app/queries/servers/preference.ts and use it in both report_a_problem and quick_actions enhanced components.
Also adds unit tests, E2E tests, and debug logging for preference WS events.
Ticket Link
MM-67856
Checklist
E2E/Run(orE2E/Run-iOS/E2E/Run-Androidfor platform-specific runs).Device Information
This PR was tested on: pixel 8, ios sim
Release Note