Skip to content

improvement: remove content picker#353

Open
iparaskev wants to merge 5 commits into
mainfrom
change_content_picker
Open

improvement: remove content picker#353
iparaskev wants to merge 5 commits into
mainfrom
change_content_picker

Conversation

@iparaskev

@iparaskev iparaskev commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added an in-app screen-selection overlay for starting screen sharing, including keyboard navigation (Enter/Escape) and monitor/window focus behavior.
    • Screen-share startup now selects the target screen automatically (no separate picker window).
  • Bug Fixes

    • Improved screen-selection rendering and redraw/input handling so selection mode behaves consistently.
  • Breaking Changes

    • Removed the content-picker flow and related UI/commands from the app and frontend.
  • Tests

    • Updated screensharing and routing expectations to match the new selection/event behavior.

@iparaskev iparaskev requested a review from konsalex as a code owner July 3, 2026 08:06
@netlify

netlify Bot commented Jul 3, 2026

Copy link
Copy Markdown

Deploy Preview for hoppdocs ready!

Name Link
🔨 Latest commit bd3b69f
🔍 Latest deploy log https://app.netlify.com/projects/hoppdocs/deploys/6a4c14a7bf4fb30008fafc3f
😎 Deploy Preview https://deploy-preview-353--hoppdocs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cfe47ce7-2493-4cef-a0b7-5269a6e2c2df

📥 Commits

Reviewing files that changed from the base of the PR and between df6bd62 and bd3b69f.

📒 Files selected for processing (12)
  • core/socket_lib/src/lib.rs
  • core/src/graphics/graphics_context.rs
  • core/src/graphics/iced_canvas.rs
  • core/src/graphics/iced_renderer.rs
  • core/src/lib.rs
  • core/src/window_manager.rs
  • core/tests/src/screenshare_client.rs
  • tauri/src-tauri/src/main.rs
  • tauri/src-tauri/src/permissions.rs
  • tauri/src-tauri/src/permissions/default.rs
  • tauri/src-tauri/src/permissions/macos.rs
  • tauri/src/components/ui/call-center.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/src/graphics/iced_renderer.rs
  • core/tests/src/screenshare_client.rs

📝 Walkthrough

Walkthrough

This PR removes the content-picker flow and replaces it with an in-app screen-selection overlay. It also updates capture, socket, Tauri, graphics, tests, and frontend code to use direct screen-selection and new screen-share permission handling.

Changes

Screen selection replaces content picker

Layer / File(s) Summary
Socket protocol and payload updates
core/socket_lib/src/lib.rs
Removes content-picker-related message variants and payload fields, and updates response routing for screen-share results.
Capture trait and platform mappings
core/Cargo.toml, core/src/capture/capturer.rs, core/src/capture/linux.rs, core/src/capture/macos.rs, core/src/capture/windows.rs
Drops available-content discovery and monitor-size helpers, adds monitor-to-content-id lookup, and updates platform implementations.
Screen-selection rendering pipeline
core/src/graphics/graphics_context.rs, core/src/graphics/iced_canvas.rs, core/src/graphics/iced_renderer.rs
Threads screen-selection state through rendering and adds the selection overlay UI.
Application screen-selection flow
core/src/lib.rs, core/src/window/camera_window.rs
Starts selection from the available-content event, tracks active selection mode, maps window clicks to screen-share messages, and clears selection on screenshare start.
WindowManager selection windows
core/src/window_manager.rs
Adds selection-window creation, focus, resize, hide, and directional navigation helpers.
Core tests and test harness updates
core/tests/src/*
Switches tests to env-based screen IDs, updates session tuple shapes, and removes available-content test paths.
Tauri backend commands and permissions
tauri/src-tauri/src/main.rs, tauri/src-tauri/src/permissions.rs, tauri/src-tauri/src/permissions/default.rs, tauri/src-tauri/src/permissions/macos.rs, tauri/src-tauri/src/app_activation.rs, tauri/src-tauri/src/shortcuts.rs, tauri/src-tauri/capabilities/migrated.json
Removes screenshare/content-picker commands, adds screen-share permission requests, forwards screen-share result events, and drops picker-specific branches.
Frontend content-picker removal
tauri/contentPicker.html, tauri/src/windows/contentPicker/main.tsx, tauri/src/core_payloads.ts, tauri/src/windows/window-utils.ts, tauri/src/components/ui/call-center.tsx, tauri/src/App.css, tauri/vite.config.ts
Deletes the picker page and related types, rewires utilities to fetch available content, and updates the screen-share UI path.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • gethopp/hopp#217: Both PRs change the same graphics rendering path in core/src/graphics/*.
  • gethopp/hopp#235: Both PRs modify core/socket_lib/src/lib.rs message definitions.
  • gethopp/hopp#241: Both PRs touch core/src/window_manager.rs and core/src/graphics/graphics_context.rs.

Suggested reviewers: konsalex

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change: removing the content picker flow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch change_content_picker

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
core/src/capture/capturer.rs (1)

356-377: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Release the capturer lock between polls
Holding capturer.lock() across the sleep loop blocks the same DesktopCapturer from being driven by run_capture_frame(), so get_source_rect() can stay empty and the caller can wait the full timeout. Re-lock on each iteration instead of sleeping with the mutex held.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/capture/capturer.rs` around lines 356 - 377, The polling loop in
capturer acquisition is holding the DesktopCapturer mutex across sleeps, which
can block run_capture_frame() from updating the source rect. Update the logic in
capturer / get_selected_monitor so the lock is acquired only for each call to
get_source_rect(), then released before sleeping and before the next iteration.
Keep the monitor matching behavior the same, but avoid keeping capturer.lock()
alive for the entire loop so the capturer can make progress between polls.
core/tests/src/remote_cursor.rs (1)

289-304: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Unused sender/event_socket will fail cargo clippy -D warnings.

With the multi-resolution/content loop removed, neither sender nor event_socket is used anywhere else in test_cursor_move, which will trigger unused-variable warnings promoted to errors under CI's clippy gate.

🐛 Proposed fix
-    let (sender, event_socket) = screenshare_client::start_screenshare_session()?;
+    let (_sender, _event_socket) = screenshare_client::start_screenshare_session()?;

As per coding guidelines, "core/**/*.rs: ... Ensure code passes cargo clippy -D warnings in CI".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/tests/src/remote_cursor.rs` around lines 289 - 304, The
`test_cursor_move` function in `remote_cursor.rs` creates `sender` and
`event_socket` from `screenshare_client::start_screenshare_session()` but never
uses them, which will trip `cargo clippy -D warnings`. Remove the unused
bindings or change the destructuring so only the needed value is bound, keeping
the rest of the logic in `test_cursor_move` and `internal_cursor_move`
unchanged.

Source: Coding guidelines

🧹 Nitpick comments (2)
core/tests/src/camera.rs (1)

324-335: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate env-parsing logic instead of reusing screen_id().

This block re-implements the exact same HOPP_TEST_SCREEN_ID parsing/fallback logic as screenshare_client::screen_id(). Since that helper is currently private (fn screen_id()), consider making it pub(crate) and calling it here to avoid divergence if the env var name or fallback ever changes.

♻️ Proposed dedup
-        let screen_id = std::env::var("HOPP_TEST_SCREEN_ID")
-            .ok()
-            .and_then(|s| s.parse().ok())
-            .unwrap_or(0u32);
+        let screen_id = screenshare_client::screen_id();

(requires making screen_id() pub(crate) in screenshare_client.rs)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/tests/src/camera.rs` around lines 324 - 335, The test setup in camera.rs
duplicates the HOPP_TEST_SCREEN_ID parsing and fallback logic instead of reusing
the existing screenshare_client::screen_id() helper. Make screen_id() in
screenshare_client.rs pub(crate), then call that helper here so the env parsing
lives in one place and stays consistent if the default or variable name changes.
core/tests/src/screenshare_client.rs (1)

172-201: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

test_every_monitor no longer tests every monitor.

The function is rewritten to test only Rewrote test_every_monitor() to test a single screenshare session for screen_id() (call start → request screenshare → wait → stop → call end), removing the previous iteration over multiple monitors derived from available content. Keeping the old name is misleading — it now exercises a single, env-configured screen rather than iterating over every monitor. Consider renaming (and updating the EveryMonitor CLI variant / call site in main.rs) to something like test_single_monitor to reflect actual behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/tests/src/screenshare_client.rs` around lines 172 - 201,
`test_every_monitor` now performs only one screen-share session for a single
`screen_id()` instead of iterating over all monitors, so the name is misleading.
Rename the function to match its actual behavior (for example,
`test_single_monitor`) and update any related CLI variant and call site in
`main.rs` that still refers to `EveryMonitor` so the entrypoint and test name
stay consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/socket_lib/src/lib.rs`:
- Around line 705-717: The ping is being asserted on the wrong endpoint in
test_request_response_pattern: server_sender.send(Message::Ping) is delivered to
the peer-side receiver, so update the test to read from client_events.events
instead of server_events.events and adjust the accompanying comment to match the
peer endpoint. Use the existing test_pair setup and the
test_request_response_pattern function to locate the change.

In `@core/src/graphics/graphics_context.rs`:
- Around line 273-276: The `set_screen_selection` method in `GraphicsContext`
has a dead commented-out redraw send that leaves the `Activity` import unused;
remove the stale comment and drop the unused import if this setter should remain
a plain state update. If `screen_selection` is still supposed to trigger
repainting, restore the `redraw_thread_sender.send(Activity)` path in real code
instead of leaving it commented out.

In `@core/src/lib.rs`:
- Around line 86-88: The keyboard imports in core/src/lib.rs are unused, so
clean up the import list by removing Key and NamedKey from the winit::keyboard
import in lib.rs; keep the remaining event and event_loop imports intact, and
only reintroduce those symbols if keyboard handling is added in a referenced
function or event handler later.

---

Outside diff comments:
In `@core/src/capture/capturer.rs`:
- Around line 356-377: The polling loop in capturer acquisition is holding the
DesktopCapturer mutex across sleeps, which can block run_capture_frame() from
updating the source rect. Update the logic in capturer / get_selected_monitor so
the lock is acquired only for each call to get_source_rect(), then released
before sleeping and before the next iteration. Keep the monitor matching
behavior the same, but avoid keeping capturer.lock() alive for the entire loop
so the capturer can make progress between polls.

In `@core/tests/src/remote_cursor.rs`:
- Around line 289-304: The `test_cursor_move` function in `remote_cursor.rs`
creates `sender` and `event_socket` from
`screenshare_client::start_screenshare_session()` but never uses them, which
will trip `cargo clippy -D warnings`. Remove the unused bindings or change the
destructuring so only the needed value is bound, keeping the rest of the logic
in `test_cursor_move` and `internal_cursor_move` unchanged.

---

Nitpick comments:
In `@core/tests/src/camera.rs`:
- Around line 324-335: The test setup in camera.rs duplicates the
HOPP_TEST_SCREEN_ID parsing and fallback logic instead of reusing the existing
screenshare_client::screen_id() helper. Make screen_id() in
screenshare_client.rs pub(crate), then call that helper here so the env parsing
lives in one place and stays consistent if the default or variable name changes.

In `@core/tests/src/screenshare_client.rs`:
- Around line 172-201: `test_every_monitor` now performs only one screen-share
session for a single `screen_id()` instead of iterating over all monitors, so
the name is misleading. Rename the function to match its actual behavior (for
example, `test_single_monitor`) and update any related CLI variant and call site
in `main.rs` that still refers to `EveryMonitor` so the entrypoint and test name
stay consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9c877cc2-db8a-453e-874f-96ef63f9c574

📥 Commits

Reviewing files that changed from the base of the PR and between 0735a99 and df6bd62.

⛔ Files ignored due to path filters (1)
  • core/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (31)
  • core/Cargo.toml
  • core/socket_lib/src/lib.rs
  • core/src/capture/capturer.rs
  • core/src/capture/linux.rs
  • core/src/capture/macos.rs
  • core/src/capture/windows.rs
  • core/src/graphics/graphics_context.rs
  • core/src/graphics/iced_canvas.rs
  • core/src/graphics/iced_renderer.rs
  • core/src/lib.rs
  • core/src/window/camera_window.rs
  • core/src/window_manager.rs
  • core/tests/src/camera.rs
  • core/tests/src/local_drawing.rs
  • core/tests/src/main.rs
  • core/tests/src/remote_clipboard.rs
  • core/tests/src/remote_cursor.rs
  • core/tests/src/remote_drawing.rs
  • core/tests/src/remote_keyboard.rs
  • core/tests/src/screenshare_client.rs
  • tauri/contentPicker.html
  • tauri/src-tauri/capabilities/migrated.json
  • tauri/src-tauri/src/app_activation.rs
  • tauri/src-tauri/src/main.rs
  • tauri/src-tauri/src/shortcuts.rs
  • tauri/src/App.css
  • tauri/src/components/ui/call-center.tsx
  • tauri/src/core_payloads.ts
  • tauri/src/windows/contentPicker/main.tsx
  • tauri/src/windows/window-utils.ts
  • tauri/vite.config.ts
💤 Files with no reviewable changes (6)
  • tauri/src-tauri/src/app_activation.rs
  • tauri/vite.config.ts
  • tauri/src/App.css
  • tauri/contentPicker.html
  • core/Cargo.toml
  • tauri/src/windows/contentPicker/main.tsx

Comment on lines 705 to 717
fn test_request_response_pattern() {
let ((server_sender, server_events), (client_sender, client_events)) = test_pair();
let ((server_sender, server_events), (_client_sender, _client_events)) = test_pair();

// Client sends request
client_sender.send(Message::GetAvailableContent).unwrap();
server_sender.send(Message::Ping).unwrap();

// Server receives event
let msg = server_events
.events
.recv_timeout(Duration::from_secs(5))
.unwrap();
assert!(matches!(msg, Message::GetAvailableContent));

// Server sends response
server_sender
.send(Message::AvailableContent(AvailableContentMessage {
content: vec![],
}))
.unwrap();

// Client receives response on responses channel
let response = client_events
.responses
.recv_timeout(Duration::from_secs(5))
.unwrap();
assert!(matches!(response, Message::AvailableContent(_)));
assert!(matches!(msg, Message::Ping));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm socket direction: sender delivers to the peer's EventSocket.
fd -t f 'lib.rs' core/socket_lib/src --exec sed -n '400,520p' {}

Repository: gethopp/hopp

Length of output: 4153


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the test helper and the test in question.
file=core/socket_lib/src/lib.rs

echo '--- test_pair and nearby helpers ---'
rg -n "fn test_pair|test_request_response_pattern|test_send_recv_event|test_send_recv_response|struct SocketSender|struct EventSocket|impl SocketSender|impl EventSocket" "$file"

echo '--- relevant source around test_pair ---'
sed -n '620,760p' "$file"

Repository: gethopp/hopp

Length of output: 3758


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file=core/socket_lib/src/lib.rs

echo '--- SocketSender and EventSocket implementations ---'
sed -n '240,360p' "$file"

echo '--- test_pair and related tests ---'
sed -n '520,725p' "$file"

Repository: gethopp/hopp

Length of output: 11167


Route the ping to the peer-side receiver server_sender.send(Message::Ping) is delivered to client_events.events, not server_events.events, so this test will time out on the wrong channel. Swap the receiver (and comment) to match the peer endpoint.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/socket_lib/src/lib.rs` around lines 705 - 717, The ping is being
asserted on the wrong endpoint in test_request_response_pattern:
server_sender.send(Message::Ping) is delivered to the peer-side receiver, so
update the test to read from client_events.events instead of
server_events.events and adjust the accompanying comment to match the peer
endpoint. Use the existing test_pair setup and the test_request_response_pattern
function to locate the change.

Comment thread core/src/graphics/graphics_context.rs
Comment thread core/src/lib.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant