Skip to content

Added screen share consent modal to trackpad route with i18n support#364

Open
Aryan-en wants to merge 1 commit into
AOSSIE-Org:mainfrom
Aryan-en:main
Open

Added screen share consent modal to trackpad route with i18n support#364
Aryan-en wants to merge 1 commit into
AOSSIE-Org:mainfrom
Aryan-en:main

Conversation

@Aryan-en

@Aryan-en Aryan-en commented Jul 12, 2026

Copy link
Copy Markdown

… so issue raised by imxade, it will always ask for Screen sharing person on browser with matching UI

Addressed Issues:

Fixes #(issue number)

Description

Screenshots/Recordings:

Functional Verification

  • Please check off the behaviors verified with this change.

Screen Mirror

  • Screen MIrror works.

Authentication

  • Connection doesn't work without a valid token.

Basic Gestures

  • One-finger tap: Verified as Left Click.

  • Two-finger tap: Verified as Right Click.

  • Click and drag: Verified selection behavior.

  • Pinch to zoom: Verified zoom functionality (if applicable).

Modes & Settings

  • Cursor mode: Cursor moves smoothly and accurately.

  • Scroll mode: Page scrolls as expected.

  • Sensitivity: Verified changes in cursor speed/sensitivity settings.

  • Copy and Paste: Verified both Copy and Paste functionality.

  • Invert Scrolling: Verified scroll direction toggles correctly.

Advanced Input

  • Key combinations: Verified "hold" behavior for modifiers (e.g., Ctrl+C) and held keys are shown in buffer.

  • Keyboard input: Verified Space, Backspace, and Enter keys work correctly.

  • Glide typing: Verified path drawing and text output.

  • Voice input: Verified speech-to-text functionality for full sentences.

  • Backspace doesn't send the previous input.

Any other gesture or input behavior introduced:

  • New Gestures: Verified any other gesture or input behavior introduced in this PR.

Additional Notes:

Checklist

  • My PR addresses a single issue, fixes a single bug or makes a single improvement.

  • My code follows the project's code style and conventions

  • I have performed a self-review of my own code

  • I have commented my code, particularly in hard-to-understand areas

  • If applicable, I have made corresponding changes or additions to the documentation

  • If applicable, I have made corresponding changes or additions to tests

  • My changes generate no new warnings or errors

  • I have joined the and I will share a link to this PR with the project maintainers there

  • I have read the

  • Once I submit my PR, CodeRabbit AI will automatically review it and I will address CodeRabbit's comments.

  • Incase of UI change I've added a demo video.

⚠️ AI Notice - Important!
We encourage contributors to use AI tools responsibly when creating Pull Requests. While AI can be a valuable aid, it is essential to ensure that your contributions meet the task requirements, build successfully, include relevant tests, and pass all linters. Submissions that do not meet these standards may be closed without warning to maintain the quality and integrity of the project. Please take the time to understand the changes you are proposing and their impact.

Summary by CodeRabbit

  • New Features
    • Added a full-screen consent prompt before screen sharing begins.
    • Users can allow screen sharing, deny access, or try again after denial.
    • Added localized messaging for consent, denial, and retry states.
    • Screen sharing now starts only after consent is granted.

… so issue raised by imxade, it will always ask for Screen sharing person on browser with matching UI
Copilot AI review requested due to automatic review settings July 12, 2026 19:08
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds a localized full-screen screen-share consent component and updates the trackpad route to withhold the WebRTC token until consent is granted, then render the existing streaming flow.

Changes

Screen-share consent

Layer / File(s) Summary
Consent UI and translations
src/utils/i18n.ts, src/components/Trackpad/ScreenShareConsent.tsx
Adds localized consent and denial text, internal denial state, conditional messaging, and allow/deny actions.
Trackpad consent gating
src/routes/trackpad.tsx
Adds consent state, conditionally supplies the WebRTC token, and renders the consent screen before existing error and screen-mirror content.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TrackpadRoute
  participant ScreenShareConsent
  participant useWebRtcStream
  participant ScreenMirror
  TrackpadRoute->>ScreenShareConsent: render before consent
  ScreenShareConsent->>TrackpadRoute: call onAllow
  TrackpadRoute->>useWebRtcStream: provide token
  useWebRtcStream->>ScreenMirror: provide stream
Loading

Suggested labels: Typescript Lang

Suggested reviewers: copilot

Poem

I’m a bunny guarding the share,
“Allow” hops when you’re prepared.
“Deny” brings a gentle retry,
Then streams sparkle across the sky.
Consent keeps the path just right!

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description mostly repeats the template and leaves required sections like issue link, summary, screenshots, and verification unfilled. Add a concrete summary, issue number, screenshots or recording, and completed functional verification/checklist items.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a screen-share consent modal with i18n support to the trackpad route.
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 unit tests (beta)
  • Create PR with unit tests

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.

Copilot AI 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.

Pull request overview

Introduces a screen-sharing consent step in the /trackpad route to ensure users explicitly opt in before starting screen mirroring/control, and adds i18n strings to support the new UI.

Changes:

  • Added a screen share consent overlay to the trackpad page and gated WebRTC session initiation behind user consent.
  • Added new i18n translation keys for the consent modal copy and actions.
  • Cleaned up package-lock.json by removing extraneous entries.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/utils/i18n.ts Adds screenShareConsent translation strings used by the new consent UI.
src/routes/trackpad.tsx Introduces consent state and uses it to gate WebRTC stream setup in the trackpad route.
src/components/Trackpad/ScreenShareConsent.tsx New consent modal component shown before screen share begins.
package-lock.json Removes extraneous dependency entries from the lockfile.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/routes/trackpad.tsx
Comment on lines +46 to 51
const [screenShareConsented, setScreenShareConsented] = useState(false)
const { status, send, sendCombo } = useRemoteConnection()
const { trackActive, videoStream, error, errorHandle, reconnect } =
useWebRtcStream({
token,
token: screenShareConsented ? token : null,
})
Comment on lines +15 to +36
<div className="absolute inset-0 flex items-center justify-center bg-black overflow-hidden select-none touch-none">
<div className="w-full h-full place-content-center p-6 bg-base-300 shadow-2xl flex flex-col items-center text-center gap-6 duration-300">
<div className="relative flex items-center justify-center w-16 h-16 rounded-full bg-primary/10 text-primary">
{denied ? (
<ShieldAlert className="w-8 h-8" />
) : (
<ScreenShare className="w-8 h-8" />
)}
</div>

<div className="space-y-2">
<h3 className="text-xl font-bold text-base-content">
{denied
? t("screenShareConsent", "deniedTitle")
: t("screenShareConsent", "title")}
</h3>
<p className="text-sm text-base-content/70 max-w-sm px-2">
{denied
? t("screenShareConsent", "deniedDescription")
: t("screenShareConsent", "description")}
</p>
</div>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@src/components/Trackpad/ScreenShareConsent.tsx`:
- Around line 14-61: Update the consent overlay in ScreenShareConsent to expose
modal semantics with role="dialog", aria-modal="true", and an accessible label
tied to the dialog heading. Make the overlay focusable and move focus to it when
the component mounts, using the existing component lifecycle and a ref while
preserving the current button interactions.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c65a2e47-32b1-4c5a-a473-742f3e1d0fdb

📥 Commits

Reviewing files that changed from the base of the PR and between 753c6f5 and dde96f5.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • src/components/Trackpad/ScreenShareConsent.tsx
  • src/routes/trackpad.tsx
  • src/utils/i18n.ts

Comment on lines +14 to +61
return (
<div className="absolute inset-0 flex items-center justify-center bg-black overflow-hidden select-none touch-none">
<div className="w-full h-full place-content-center p-6 bg-base-300 shadow-2xl flex flex-col items-center text-center gap-6 duration-300">
<div className="relative flex items-center justify-center w-16 h-16 rounded-full bg-primary/10 text-primary">
{denied ? (
<ShieldAlert className="w-8 h-8" />
) : (
<ScreenShare className="w-8 h-8" />
)}
</div>

<div className="space-y-2">
<h3 className="text-xl font-bold text-base-content">
{denied
? t("screenShareConsent", "deniedTitle")
: t("screenShareConsent", "title")}
</h3>
<p className="text-sm text-base-content/70 max-w-sm px-2">
{denied
? t("screenShareConsent", "deniedDescription")
: t("screenShareConsent", "description")}
</p>
</div>
<div className="divider my-0 opacity-40" />
<div className="space-y-3 w-full max-w-xs">
<button
type="button"
onClick={onAllow}
className="btn btn-block btn-primary gap-2 shadow-lg shadow-primary/20 hover:scale-[1.02] active:scale-[0.98] transition-all duration-200"
>
<ScreenShare className="w-4 h-4" />
{denied
? t("screenShareConsent", "tryAgain")
: t("screenShareConsent", "allow")}
</button>
{!denied && (
<button
type="button"
onClick={() => setDenied(true)}
className="btn btn-block btn-ghost"
>
{t("screenShareConsent", "deny")}
</button>
)}
</div>
</div>
</div>
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add ARIA dialog semantics and focus management to the consent overlay.

The overlay functions as a modal dialog but lacks role="dialog", aria-modal="true", and an accessible label. Screen readers may not announce it as a dialog, and focus is not moved to the overlay on mount, leaving keyboard users on the underlying TouchArea. As per path instructions, accessibility blockers that prevent task completion (e.g., non-navigable modals) must be addressed.

♿ Proposed fix for ARIA and focus management
 import { useState } from "react"
+import { useEffect, useRef } from "react"
 import { ScreenShare, ShieldAlert } from "lucide-react"
 import { t } from "../../utils/i18n"
 
 interface ScreenShareConsentProps {
 	onAllow: () => void
 }
 
 export const ScreenShareConsent = ({ onAllow }: ScreenShareConsentProps) => {
 	const [denied, setDenied] = useState(false)
+	const allowButtonRef = useRef<HTMLButtonElement>(null)
+
+	useEffect(() => {
+		allowButtonRef.current?.focus()
+	}, [])
 
 	return (
-		<div className="absolute inset-0 flex items-center justify-center bg-black overflow-hidden select-none touch-none">
+		<div
+			className="absolute inset-0 flex items-center justify-center bg-black overflow-hidden select-none touch-none"
+			role="dialog"
+			aria-modal="true"
+			aria-label={t("screenShareConsent", "title")}
+		>
 			<div className="w-full h-full place-content-center p-6 bg-base-300 shadow-2xl flex flex-col items-center text-center gap-6 duration-300">
 				<div className="relative flex items-center justify-center w-16 h-16 rounded-full bg-primary/10 text-primary">
 					{denied ? (
 						<ShieldAlert className="w-8 h-8" />
 					) : (
 						<ScreenShare className="w-8 h-8" />
 					)}
 				</div>
 
 				<div className="space-y-2">
 					<h3 className="text-xl font-bold text-base-content">
 						{denied
 							? t("screenShareConsent", "deniedTitle")
 							: t("screenShareConsent", "title")}
 					</h3>
 					<p className="text-sm text-base-content/70 max-w-sm px-2">
 						{denied
 							? t("screenShareConsent", "deniedDescription")
 							: t("screenShareConsent", "description")}
 					</p>
 				</div>
 				<div className="divider my-0 opacity-40" />
 				<div className="space-y-3 w-full max-w-xs">
 					<button
+						ref={allowButtonRef}
 						type="button"
 						onClick={onAllow}
 						className="btn btn-block btn-primary gap-2 shadow-lg shadow-primary/20 hover:scale-[1.02] active:scale-[0.98] transition-all duration-200"
 					>
 						<ScreenShare className="w-4 h-4" />
 						{denied
 							? t("screenShareConsent", "tryAgain")
 							: t("screenShareConsent", "allow")}
 					</button>
 					{!denied && (
 						<button
 							type="button"
 							onClick={() => setDenied(true)}
 							className="btn btn-block btn-ghost"
 						>
 							{t("screenShareConsent", "deny")}
 						</button>
 					)}
 				</div>
 			</div>
 		</div>
 	)
 }

As per path instructions, accessibility blockers that prevent task completion such as non-navigable modals must be addressed.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return (
<div className="absolute inset-0 flex items-center justify-center bg-black overflow-hidden select-none touch-none">
<div className="w-full h-full place-content-center p-6 bg-base-300 shadow-2xl flex flex-col items-center text-center gap-6 duration-300">
<div className="relative flex items-center justify-center w-16 h-16 rounded-full bg-primary/10 text-primary">
{denied ? (
<ShieldAlert className="w-8 h-8" />
) : (
<ScreenShare className="w-8 h-8" />
)}
</div>
<div className="space-y-2">
<h3 className="text-xl font-bold text-base-content">
{denied
? t("screenShareConsent", "deniedTitle")
: t("screenShareConsent", "title")}
</h3>
<p className="text-sm text-base-content/70 max-w-sm px-2">
{denied
? t("screenShareConsent", "deniedDescription")
: t("screenShareConsent", "description")}
</p>
</div>
<div className="divider my-0 opacity-40" />
<div className="space-y-3 w-full max-w-xs">
<button
type="button"
onClick={onAllow}
className="btn btn-block btn-primary gap-2 shadow-lg shadow-primary/20 hover:scale-[1.02] active:scale-[0.98] transition-all duration-200"
>
<ScreenShare className="w-4 h-4" />
{denied
? t("screenShareConsent", "tryAgain")
: t("screenShareConsent", "allow")}
</button>
{!denied && (
<button
type="button"
onClick={() => setDenied(true)}
className="btn btn-block btn-ghost"
>
{t("screenShareConsent", "deny")}
</button>
)}
</div>
</div>
</div>
)
import { useEffect, useRef, useState } from "react"
import { ScreenShare, ShieldAlert } from "lucide-react"
import { t } from "../../utils/i18n"
interface ScreenShareConsentProps {
onAllow: () => void
}
export const ScreenShareConsent = ({ onAllow }: ScreenShareConsentProps) => {
const [denied, setDenied] = useState(false)
const allowButtonRef = useRef<HTMLButtonElement>(null)
useEffect(() => {
allowButtonRef.current?.focus()
}, [])
return (
<div
className="absolute inset-0 flex items-center justify-center bg-black overflow-hidden select-none touch-none"
role="dialog"
aria-modal="true"
aria-label={t("screenShareConsent", "title")}
>
<div className="w-full h-full place-content-center p-6 bg-base-300 shadow-2xl flex flex-col items-center text-center gap-6 duration-300">
<div className="relative flex items-center justify-center w-16 h-16 rounded-full bg-primary/10 text-primary">
{denied ? (
<ShieldAlert className="w-8 h-8" />
) : (
<ScreenShare className="w-8 h-8" />
)}
</div>
<div className="space-y-2">
<h3 className="text-xl font-bold text-base-content">
{denied
? t("screenShareConsent", "deniedTitle")
: t("screenShareConsent", "title")}
</h3>
<p className="text-sm text-base-content/70 max-w-sm px-2">
{denied
? t("screenShareConsent", "deniedDescription")
: t("screenShareConsent", "description")}
</p>
</div>
<div className="divider my-0 opacity-40" />
<div className="space-y-3 w-full max-w-xs">
<button
ref={allowButtonRef}
type="button"
onClick={onAllow}
className="btn btn-block btn-primary gap-2 shadow-lg shadow-primary/20 hover:scale-[1.02] active:scale-[0.98] transition-all duration-200"
>
<ScreenShare className="w-4 h-4" />
{denied
? t("screenShareConsent", "tryAgain")
: t("screenShareConsent", "allow")}
</button>
{!denied && (
<button
type="button"
onClick={() => setDenied(true)}
className="btn btn-block btn-ghost"
>
{t("screenShareConsent", "deny")}
</button>
)}
</div>
</div>
</div>
)
}
🤖 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 `@src/components/Trackpad/ScreenShareConsent.tsx` around lines 14 - 61, Update
the consent overlay in ScreenShareConsent to expose modal semantics with
role="dialog", aria-modal="true", and an accessible label tied to the dialog
heading. Make the overlay focusable and move focus to it when the component
mounts, using the existing component lifecycle and a ref while preserving the
current button interactions.

Source: Path instructions

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.

2 participants