|
| 1 | +# Tasks: Fix Wayland Screenshare Preview Window |
| 2 | + |
| 3 | +Based on PRD: [prd-wayland-screenshare-preview-fix.md](prd-wayland-screenshare-preview-fix.md) |
| 4 | + |
| 5 | +## System Analysis |
| 6 | + |
| 7 | +### ADR Review |
| 8 | + |
| 9 | +No formal Architecture Decision Records (ADRs) found in `docs/adr/`. However, the codebase follows these implicit architectural decisions: |
| 10 | + |
| 11 | +- **IPC Communication Pattern**: Use of `ipcMain.on` for notifications and `ipcMain.handle` for request-response patterns |
| 12 | +- **Global State Management**: Screen sharing state stored in `global.selectedScreenShareSource` |
| 13 | +- **Diagnostic Logging**: Consistent use of `[SCREEN_SHARE_DIAG]` prefix for screen sharing related logs |
| 14 | +- **Code Style**: Use of `const`/`let` (no `var`), async/await patterns, private fields with `#` syntax |
| 15 | + |
| 16 | +### Documentation Review |
| 17 | + |
| 18 | +From `app/screenSharing/README.md`: |
| 19 | +- StreamSelector expects source IDs in format `screen:x:0` or `window:x:0` (line 73-74 of `app/screenSharing/index.js`) |
| 20 | +- desktopCapturer.getSources() provides source objects with `id`, `name`, `thumbnail`, and other properties |
| 21 | +- The module bridges Teams web app with Electron's native desktopCapturer API |
| 22 | +- Platform differences documented for X11 vs Wayland (X11 is more permissive, Wayland requires strict format) |
| 23 | + |
| 24 | +### Pattern Analysis |
| 25 | + |
| 26 | +**Current Screen Sharing Flow:** |
| 27 | +1. User clicks "Share" in Teams → triggers `setDisplayMediaRequestHandler` (app/mainAppWindow/index.js) |
| 28 | +2. StreamSelector.show() displays source picker |
| 29 | +3. User selects source → `setupScreenSharing(selectedSource)` called (app/mainAppWindow/index.js:226) |
| 30 | +4. **Line 228**: `global.selectedScreenShareSource = selectedSource` stores desktopCapturer source object |
| 31 | +5. **Line 231**: `createScreenSharePreviewWindow()` creates preview window |
| 32 | +6. Electron creates MediaStream from selected source |
| 33 | +7. **injectedScreenSharing.js:113-119**: Intercepts stream, sends IPC with `stream.id` (UUID) |
| 34 | +8. **app/index.js:162**: IPC handler **OVERWRITES** `global.selectedScreenShareSource` with UUID |
| 35 | +9. Preview window tries to use UUID → fails on Wayland |
| 36 | + |
| 37 | +**Key Pattern Identified**: The bug occurs because step 8 overwrites the correct value set in step 4. |
| 38 | + |
| 39 | +### Conflicts and Constraints |
| 40 | + |
| 41 | +**Conflict**: Two different processes setting `global.selectedScreenShareSource`: |
| 42 | +- `setupScreenSharing()` sets it correctly (desktopCapturer source object/id) |
| 43 | +- `screen-sharing-started` IPC handler overwrites it incorrectly (MediaStream UUID) |
| 44 | + |
| 45 | +**Constraint**: The `injectedScreenSharing.js` runs in the renderer process and does NOT have access to the desktopCapturer source object - it only receives the MediaStream after creation. |
| 46 | + |
| 47 | +**Resolution Strategy**: Prevent the IPC handler from overwriting the correct value by either: |
| 48 | +1. Not sending sourceId from renderer process, OR |
| 49 | +2. Only updating global state if received value is in correct format |
| 50 | + |
| 51 | +### Research Spikes Identified |
| 52 | + |
| 53 | +No research spikes required - this is a straightforward bug fix with clear root cause. |
| 54 | + |
| 55 | +## Relevant Files |
| 56 | + |
| 57 | +### Files Modified |
| 58 | + |
| 59 | +- `app/screenSharing/injectedScreenSharing.js` - Removed stream.id UUID logic, now sends null to preserve desktopCapturer source ID |
| 60 | +- `app/index.js` - Added validation to `screen-sharing-started` IPC handler to prevent overwriting with invalid format |
| 61 | +- `app/screenSharing/README.md` - Added documentation about source ID format requirement and ADR reference |
| 62 | +- `docs/adr/001-use-desktopcapturer-source-id-format.md` - Created ADR documenting the technical decision |
| 63 | + |
| 64 | +### Files Already Correct (No Changes) |
| 65 | + |
| 66 | +- `app/mainAppWindow/index.js` - Line 228 already stores correct source object |
| 67 | +- `app/screenSharing/previewWindow.html` - Already uses sourceId correctly, just needs correct value |
| 68 | +- `app/screenSharing/index.js` - StreamSelector already expects correct format |
| 69 | + |
| 70 | +### Notes |
| 71 | + |
| 72 | +- Run `npm run lint` before committing |
| 73 | +- Test on both Wayland (`XDG_SESSION_TYPE=wayland`) and X11 (`XDG_SESSION_TYPE=x11`) |
| 74 | +- No automated tests exist for this module - rely on manual testing |
| 75 | +- Follow existing diagnostic logging patterns with `[SCREEN_SHARE_DIAG]` prefix |
| 76 | + |
| 77 | +## Tasks |
| 78 | + |
| 79 | +- [x] 1.0 Fix source ID handling in renderer process (injectedScreenSharing.js) |
| 80 | + - [x] 1.1 Remove the sourceId calculation from lines 113-115 (stream.id logic) |
| 81 | + - [x] 1.2 Update line 119 to send `null` instead of `sourceId` to `sendScreenSharingStarted()` |
| 82 | + |
| 83 | +- [x] 2.0 Add validation to IPC handler to prevent incorrect overwrites |
| 84 | + - [x] 2.1 In `app/index.js` line 162, check if `sourceId` is null before updating |
| 85 | + - [x] 2.2 If `sourceId` is not null, validate it matches format `screen:x:y` or `window:x:y` |
| 86 | + - [x] 2.3 Only update `global.selectedScreenShareSource` if validation passes |
| 87 | + - [x] 2.4 Log warning if UUID format detected (helps catch future regressions) |
| 88 | + |
| 89 | +- [x] 3.0 Update diagnostic logging for better debugging |
| 90 | + - [x] 3.1 Log the received sourceId vs existing sourceId in IPC handler |
| 91 | + - [x] 3.2 Add log in injectedScreenSharing.js showing we're NOT sending stream.id |
| 92 | + - [x] 3.3 Update existing log at line 166 to show validation result |
| 93 | + |
| 94 | +- [x] 4.0 Create ADR and update documentation |
| 95 | + - [x] 4.1 Create `docs/adr/` directory if it doesn't exist |
| 96 | + - [x] 4.2 Create ADR documenting decision to use desktopCapturer source ID format (`screen:x:y` or `window:x:y`) |
| 97 | + - [x] 4.3 ADR should explain: why MediaStream.id (UUID) cannot be used, Wayland requirements, and impact on preview window |
| 98 | + - [x] 4.4 Update `app/screenSharing/README.md` referencing the ADR |
| 99 | + |
| 100 | +- [x] 5.0 Manual testing on Wayland and X11 |
| 101 | + - [x] 5.1 Test on Wayland: Start screenshare, verify preview opens, check console for `screen:x:y` format |
| 102 | + - [x] 5.2 Test on X11: Start screenshare, verify no regression, preview still works |
| 103 | + - [x] 5.3 Test multiple screens on both platforms |
| 104 | + - [x] 5.4 Test window sharing on both platforms |
| 105 | + - [x] 5.5 Run `npm run lint` and fix any violations |
| 106 | + - [x] 5.6 Verify console logs show correct source ID format (not UUID) |
| 107 | + |
| 108 | +## Future Improvements |
| 109 | + |
| 110 | +### Priority 2 (Nice-to-Have) |
| 111 | + |
| 112 | +- Refactor global state management into a proper ScreenSharingManager class to encapsulate `global.selectedScreenShareSource` and related state |
| 113 | + |
| 114 | +### Technical Debt Considerations |
| 115 | + |
| 116 | +- Global state management (`global.selectedScreenShareSource`) should be encapsulated in a dedicated module |
0 commit comments