Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions public/rtl-exp-ar/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,32 @@
"autoDownloadStudy": false,
"withSidebar": false,
"showTitleBar": false,
"recordScreen": true,
"recordScreenFPS": 30,
"showTitle": false,
"nextButtonText": "التالي"
},
"importedLibraries": [
"screen-recording"
],
"components": {
"consent": {
"type": "markdown",
"path": "rtl-exp-ar/assets/consent.md",
"response": []
},
"screenRecordingPermissionAr": {
"baseComponent": "$screen-recording.co.screenRecordingPermission",
"nextButtonText": "التالي",
"response": [
{
"hidden": true,
"type": "reactive",
"id": "screenRecordingPermission",
"prompt": "تم تفعيل تسجيل الشاشة"
}
]
},
"demographics": {
"type": "questionnaire",
"instruction": "<div dir=\"rtl\">قبل بدء الدراسة، يرجى الإجابة على أسئلة ديموغرافية التالية.</div>",
Expand Down Expand Up @@ -1532,6 +1549,7 @@
"order": "fixed",
"components": [
"consent",
"screenRecordingPermissionAr",
"demographics",
{
"order": "random",
Expand Down
8 changes: 8 additions & 0 deletions public/rtl-exp-en/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@
"withProgressBar": false,
"autoDownloadStudy": false,
"withSidebar": false,
"recordScreen": true,
"recordScreenFPS": 30,
"showTitleBar": false,
"showTitle": false
},

"importedLibraries": [
"screen-recording"
],

"baseComponents": {
"trial-numerical": {
"type": "website",
Expand Down Expand Up @@ -1528,6 +1535,7 @@
"order": "fixed",
"components": [
"consent",
"$screen-recording.components.screenRecordingPermission",
"demographics",
{
"order": "random",
Expand Down
25 changes: 21 additions & 4 deletions src/components/interface/ScreenRecordingRejection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,35 @@ import {
Modal, Text, Title, Stack,
} from '@mantine/core';
import { IconAlertTriangle } from '@tabler/icons-react';
import { useStudyId } from '../../routes/utils';

const AR_LABELS = {
title: 'تم إيقاف تسجيل الشاشة',
message: 'شكراً لمشاركتك في هذه الدراسة. تم إيقاف تسجيل الشاشة.لا يمكنك المتابعة.',
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

Arabic message string is missing a space after the period: تم إيقاف تسجيل الشاشة.لا يمكنك المتابعة. This reads like a typo in the UI; add a space (or appropriate punctuation) between the sentences.

Suggested change
message: 'شكراً لمشاركتك في هذه الدراسة. تم إيقاف تسجيل الشاشة.لا يمكنك المتابعة.',
message: 'شكراً لمشاركتك في هذه الدراسة. تم إيقاف تسجيل الشاشة. لا يمكنك المتابعة.',

Copilot uses AI. Check for mistakes.
closeMessage: 'يمكنك إغلاق هذه الصفحة الآن.',
};

const EN_LABELS = {
title: 'Screen Recording Stopped',
message: 'Thank you for participating in this study. Screen recording was stopped and you will not be able to continue.',
closeMessage: 'You may now close this page.',
};

export function ScreenRecordingRejection() {
const studyId = useStudyId();
const isArabic = studyId === 'rtl-exp-ar';
const labels = isArabic ? AR_LABELS : EN_LABELS;

return (
<Modal opened onClose={() => {}} fullScreen withCloseButton={false}>
<Modal opened onClose={() => {}} fullScreen withCloseButton={false} dir={isArabic ? 'rtl' : 'ltr'}>
<Stack align="center" justify="center">
<IconAlertTriangle size={64} color="orange" />
<Title order={3}> Screen Recording Stopped </Title>
<Title order={3}>{labels.title}</Title>
<Text size="md" ta="center">
<>
Thank you for participating in this study. Screen recording was stopped and you will not be able to continue.
{labels.message}
<br />
You may now close this page.
{labels.closeMessage}
</>
</Text>
</Stack>
Expand Down
85 changes: 49 additions & 36 deletions src/public/libraries/screen-recording/assets/ScreenRecording.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { useEffect, useState } from 'react';
import { useScreenRecordingContext } from '../../../../store/hooks/useScreenRecording';
import { StimulusParams } from '../../../../store/types';
import { RecordingAudioWaveform } from '../../../../components/interface/RecordingAudioWaveform';
import { useStudyId } from '../../../../routes/utils';

function ScreenRecordingPermission({ setAnswer }: StimulusParams<undefined>) {
const studyId = useStudyId();
const isArabicStudy = studyId === 'rtl-exp-ar';
const {
recordAudio,
recordVideoRef,
Expand Down Expand Up @@ -74,37 +77,44 @@ function ScreenRecordingPermission({ setAnswer }: StimulusParams<undefined>) {
window.requestAnimationFrame(detectSound);
}, [audioMediaStream, screenCapturing, setAnswer]);

const titleText = isArabicStudy
? (recordAudio ? 'إذن تسجيل الشاشة والصوت' : 'إذن تسجيل الشاشة')
: `Screen${recordAudio ? ' and Audio' : ''} Recording Permission`;

const startRecordingText = isArabicStudy ? 'بدء التسجيل' : 'Start Recording';
const stopRecordingText = isArabicStudy ? 'إيقاف التسجيل' : 'Stop Recording';
const noteShareCorrectTabText = isArabicStudy
? 'ملاحظة: تأكد من اختيار تبويب المتصفح أو النافذة الصحيحة. إذا اخترت الخيار الخطأ، أوقف المشاركة ثم اختر الصحيح.'
: 'Note: Please make sure you are recording the correct tab or window. Otherwise, stop and re-share the correct one.';
const exitStudyText = isArabicStudy
? (recordAudio
? 'تتطلب هذه الدراسة تسجيل شاشتك وصوتك. إذا لم تكن مرتاحًا لذلك، يمكنك الخروج وإرجاع الدراسة.'
: 'تتطلب هذه الدراسة تسجيل شاشتك. إذا لم تكن مرتاحًا لذلك، يمكنك الخروج وإرجاع الدراسة.')
: (recordAudio
? 'This study requires recording of your screen and audio. If you\'re not comfortable, you may exit and return the study.'
: 'This study requires recording of your screen. If you\'re not comfortable, you may exit and return the study.');

return (
<Box p="md">
<Box p="md" dir={isArabicStudy ? 'rtl' : 'ltr'} style={{ direction: isArabicStudy ? 'rtl' : 'ltr' }}>
<Title order={1} size="h2">
Screen
{recordAudio && ' and Audio'}
{' '}
Recording Permission
{titleText}
</Title>

{recordAudio ? (
<>
{/* Record both screen and audio */}
<p>
This study requires recording of your
{' '}
<strong>screen</strong>
{' '}
and
{' '}
<strong>audio</strong>
. If you&apos;re not comfortable, you may exit and return the study.
{exitStudyText}
</p>
<p>Follow the steps below to grant screen and audio recording permissions.</p>
<p>{isArabicStudy ? 'اتبع الخطوات التالية لمنح أذونات تسجيل الشاشة والصوت.' : 'Follow the steps below to grant screen and audio recording permissions.'}</p>

<ol>
<li>
<strong>Click the button below</strong>
<strong>{isArabicStudy ? 'انقر على الزر أدناه' : 'Click the button below'}</strong>
{' '}
to enable screen and audio recording.
{isArabicStudy ? 'لتفعيل تسجيل الشاشة والصوت.' : 'to enable screen and audio recording.'}
<Button type="button" onClick={screenCapturing ? stopCapture : startCapture} display="block" mt="sm">
{screenCapturing ? 'Stop Recording' : 'Start Recording'}
{screenCapturing ? stopRecordingText : startRecordingText}
</Button>
<video
ref={recordVideoRef}
Expand All @@ -114,42 +124,45 @@ function ScreenRecordingPermission({ setAnswer }: StimulusParams<undefined>) {
style={{ width: '400px', border: '1px solid #ccc', marginTop: '1rem' }}
/>
{error && <p style={{ color: 'red' }}>{error}</p>}
<p><i>Note: Please make sure you are recording the correct tab or window. Otherwise, stop and re-share the correct one.</i></p>
<p><i>{noteShareCorrectTabText}</i></p>

</li>
<li>
<strong>Speak</strong>
<strong>{isArabicStudy ? 'تحدّث' : 'Speak'}</strong>
{' '}
into your microphone to check if audio is working.
{isArabicStudy ? 'في الميكروفون للتأكد من أن الصوت يعمل.' : 'into your microphone to check if audio is working.'}
{(recordAudio && screenCapturing) ? <Box h={200} w={400} bd="1px solid #ccc"><RecordingAudioWaveform height={200} width={400} /></Box> : <Box h={200} w={400} bd="1px solid #ccc" />}
</li>
</ol>
<strong>Note:</strong>
<ul>
<li>
After we hear you say something, the
{' '}
<b>Continue</b>
{' '}
button will be enabled.
{isArabicStudy
? 'بعد أن نكتشف صوتًا، سيتم تفعيل زر المتابعة.'
: (
<>
After we hear you say something, the
{' '}
<b>Continue</b>
{' '}
button will be enabled.
</>
)}
</li>
<li>Please do not close the window or screen recording until the entire study is completed.</li>
<li>{isArabicStudy ? 'يرجى عدم إغلاق النافذة أو إيقاف التسجيل حتى تنتهي الدراسة بالكامل.' : 'Please do not close the window or screen recording until the entire study is completed.'}</li>
</ul>
</>
) : (
<>
{/* Record screen only */}
<p>
This study requires recording of your
{' '}
<strong>screen</strong>
. If you&apos;re not comfortable, you may exit and return the study.
{exitStudyText}
</p>
<strong>Click the button below</strong>
<strong>{isArabicStudy ? 'انقر على الزر أدناه' : 'Click the button below'}</strong>
{' '}
to enable screen recording.
{isArabicStudy ? 'لتفعيل تسجيل الشاشة.' : 'to enable screen recording.'}
<Button type="button" onClick={screenCapturing ? stopCapture : startCapture} display="block" mt="sm">
{screenCapturing ? 'Stop Recording' : 'Start Recording'}
{screenCapturing ? stopRecordingText : startRecordingText}
</Button>
<video
ref={recordVideoRef}
Expand All @@ -159,11 +172,11 @@ function ScreenRecordingPermission({ setAnswer }: StimulusParams<undefined>) {
style={{ width: '400px', border: '1px solid #ccc', marginTop: '1rem' }}
/>
{error && <p style={{ color: 'red' }}>{error}</p>}
<p><i>Note: Please make sure you are recording the correct tab or window. Otherwise, stop and re-share the correct one.</i></p>
<p><i>{noteShareCorrectTabText}</i></p>

<strong>Note:</strong>
<strong>{isArabicStudy ? 'ملاحظة:' : 'Note:'}</strong>
<ul>
<li>Please do not close the window or screen recording until the entire study is completed.</li>
<li>{isArabicStudy ? 'يرجى عدم إغلاق النافذة أو إيقاف التسجيل حتى تنتهي الدراسة بالكامل.' : 'Please do not close the window or screen recording until the entire study is completed.'}</li>
</ul>
</>
)}
Expand Down
6 changes: 5 additions & 1 deletion src/store/hooks/useScreenRecording.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ export function useScreenRecording() {
}, []);

useEffect(() => {
if (currentComponent !== '$screen-recording.co.screenRecordingPermission' && currentComponent !== 'end' && screenCaptureStarted && !isScreenCapturing) {
const isPermissionComponent = currentComponent === '$screen-recording.co.screenRecordingPermission'
|| currentComponent === '$screen-recording.components.screenRecordingPermission'
|| currentComponent === 'screenRecordingPermissionAr';

if (!isPermissionComponent && currentComponent !== 'end' && screenCaptureStarted && !isScreenCapturing) {
Comment on lines +181 to +185
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

isPermissionComponent hard-codes the study-specific component key screenRecordingPermissionAr. Since any study can wrap $screen-recording.*.screenRecordingPermission in a derived component with an arbitrary name, this check won’t generalize and could cause false rejections. Consider detecting permission pages by resolving the current component config (via studyConfig.components[currentComponent] / getComponent) and treating it as a permission component when its resolved/base component is $screen-recording.*.screenRecordingPermission (or ends with .screenRecordingPermission).

Copilot uses AI. Check for mistakes.
setIsRejected(true);
}
}, [currentComponent, isScreenCapturing, screenCaptureStarted]);
Expand Down
Loading