-
Notifications
You must be signed in to change notification settings - Fork 221
Expand file tree
/
Copy pathResolutionWarning.tsx
More file actions
128 lines (117 loc) · 4.37 KB
/
Copy pathResolutionWarning.tsx
File metadata and controls
128 lines (117 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import {
Modal, Text, Title, Stack,
} from '@mantine/core';
import { useEffect, useState, useRef } from 'react';
import { IconAlertTriangle } from '@tabler/icons-react';
import { useNavigate } from 'react-router';
import { useStorageEngine } from '../../storage/storageEngineHooks';
import { useStudyId } from '../../routes/utils';
import { useStudyConfig } from '../../store/hooks/useStudyConfig';
export function ResolutionWarning() {
const studyConfig = useStudyConfig();
const minWidth = studyConfig.uiConfig.minWidthSize;
const minHeight = studyConfig.uiConfig.minHeightSize;
const [showWarning, setShowWarning] = useState(false);
const [isRejected, setIsRejected] = useState(false);
const [timeLeft, setTimeLeft] = useState(60);
const [isTimedOut, setIsTimedOut] = useState(false);
const [detectedSize, setDetectedSize] = useState({ width: 0, height: 0 });
const countdownIntervalRef = useRef<NodeJS.Timeout | null>(null);
const { storageEngine } = useStorageEngine();
const studyId = useStudyId();
const navigate = useNavigate();
useEffect(() => {
const handleResize = () => {
setDetectedSize({ width: window.innerWidth, height: window.innerHeight });
if (minWidth === undefined || minHeight === undefined) {
return;
}
const widthTooSmall = window.innerWidth < minWidth;
const heightTooSmall = window.innerHeight < minHeight;
const needsResize = widthTooSmall || heightTooSmall;
const startCountdown = () => {
setTimeLeft(60);
// Clear existing countdown
if (countdownIntervalRef.current) {
clearInterval(countdownIntervalRef.current);
countdownIntervalRef.current = null;
}
countdownIntervalRef.current = setInterval(() => {
setTimeLeft((currentTime) => {
if (currentTime <= 1) {
if (countdownIntervalRef.current) {
clearInterval(countdownIntervalRef.current);
countdownIntervalRef.current = null;
}
// Reject participant if they haven't resized in time
if (storageEngine && !isRejected) {
setIsRejected(true);
setIsTimedOut(true);
storageEngine.rejectCurrentParticipant('Screen resolution too small')
.catch(() => {
console.error('Failed to reject participant who failed training');
});
}
return 0;
}
return currentTime - 1;
});
}, 1000);
};
if (isRejected) return;
if (needsResize) {
setShowWarning(true);
startCountdown();
} else {
setShowWarning(false);
if (countdownIntervalRef.current) {
clearInterval(countdownIntervalRef.current);
countdownIntervalRef.current = null;
}
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
if (countdownIntervalRef.current) {
clearInterval(countdownIntervalRef.current);
}
};
}, [minWidth, minHeight, storageEngine, studyId, navigate, isRejected]);
if (!showWarning) {
return null;
}
return (
<Modal opened={showWarning} onClose={() => {}} fullScreen withCloseButton={false}>
<Stack align="center" justify="center">
<IconAlertTriangle size={64} color="orange" />
<Title order={3}> Screen Resolution Warning </Title>
<Text size="md" ta="center">
{isTimedOut ? (
<>
Thank you for participating in this study. You have been timed out and will not be able to continue.
<br />
You may now close this page.
</>
) : (
<>
Your screen resolution is below the minimum requirement:
<br />
{minWidth !== undefined && ` Width: ${minWidth}px`}
{minHeight !== undefined && ` Height: ${minHeight}px`}
<br />
{`Detected: Width: ${detectedSize.width}px Height: ${detectedSize.height}px`}
<br />
Please resize your browser window to the minimum required size within
{' '}
{timeLeft}
{' '}
seconds.
</>
)}
</Text>
</Stack>
</Modal>
);
}