@capytale/meta-player 0.9.8 → 0.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capytale/meta-player",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"sass": "^1.75.0",
|
|
52
52
|
"typescript": "^5.7.2",
|
|
53
53
|
"typescript-eslint": "^8.22.0",
|
|
54
|
-
"vite": "^7.3.
|
|
54
|
+
"vite": "^7.3.5"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"react": "^18.3.1",
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
FC,
|
|
3
|
+
ReactNode,
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
} from "react";
|
|
3
9
|
import { Toast } from "primereact/toast";
|
|
4
10
|
import { useActivityJS } from "../../activityJS/ActivityJSProvider";
|
|
5
11
|
import { useAppSelector } from "../../../app/hooks";
|
|
@@ -9,8 +15,8 @@ import {
|
|
|
9
15
|
} from "../../activityData/activityDataSlice";
|
|
10
16
|
import { Button } from "primereact/button";
|
|
11
17
|
import { useSave } from "../../activityData/hooks";
|
|
12
|
-
import serverClock from "../../../utils/server-clock";
|
|
13
18
|
import { selectShowSaveForStudents } from "../../layout/layoutSlice";
|
|
19
|
+
import useRemainingTimeMs from "./useRemainingTimeMs";
|
|
14
20
|
|
|
15
21
|
// TODO use https://capytale2.ac-paris.fr/vanilla/time-s.php
|
|
16
22
|
// https://forge.apps.education.fr/capytale/activity-js/-/blob/main/src/backend/capytale/clock.ts?ref_type=heads
|
|
@@ -40,7 +46,9 @@ const Countdown: FC = () => {
|
|
|
40
46
|
oneMinuteWarningShown.current = true;
|
|
41
47
|
toast.current?.show({
|
|
42
48
|
severity: "warn",
|
|
43
|
-
summary: showWarningsBecauseNoSave
|
|
49
|
+
summary: showWarningsBecauseNoSave
|
|
50
|
+
? "Temps presque écoulé"
|
|
51
|
+
: "Activité non sauvegardée",
|
|
44
52
|
detail: (
|
|
45
53
|
<>
|
|
46
54
|
<div>
|
|
@@ -89,7 +97,9 @@ const Countdown: FC = () => {
|
|
|
89
97
|
fifteenSecondsWarningShown.current = true;
|
|
90
98
|
toast.current?.show({
|
|
91
99
|
severity: "error",
|
|
92
|
-
summary: showWarningsBecauseNoSave
|
|
100
|
+
summary: showWarningsBecauseNoSave
|
|
101
|
+
? "Temps presque écoulé"
|
|
102
|
+
: "Activité non sauvegardée",
|
|
93
103
|
detail: (
|
|
94
104
|
<>
|
|
95
105
|
<div>
|
|
@@ -139,32 +149,25 @@ const Countdown: FC = () => {
|
|
|
139
149
|
? null
|
|
140
150
|
: activityJS.activitySession?.activityBunch.access_timerange.value?.end;
|
|
141
151
|
|
|
142
|
-
const
|
|
152
|
+
const diffMs = useRemainingTimeMs();
|
|
143
153
|
|
|
144
|
-
|
|
145
|
-
if (!
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
const deadlineUTC = deadline.getTime();
|
|
149
|
-
const nowUTC = serverClock.now();
|
|
150
|
-
const newDiffMs = deadlineUTC - nowUTC;
|
|
151
|
-
setDiffMs(newDiffMs);
|
|
152
|
-
if (mode !== "assignment") {
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
if (!diffMs || mode !== "assignment") {
|
|
153
156
|
return;
|
|
154
157
|
}
|
|
155
158
|
if (
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
diffMs != null &&
|
|
160
|
+
diffMs < MS_PER_MINUTE &&
|
|
161
|
+
diffMs > 35000 &&
|
|
159
162
|
(isDirty || showWarningsBecauseNoSave) &&
|
|
160
163
|
!oneMinuteWarningShown.current
|
|
161
164
|
) {
|
|
162
165
|
showOneMinuteWarning();
|
|
163
166
|
}
|
|
164
167
|
if (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
diffMs != null &&
|
|
169
|
+
diffMs < 30000 &&
|
|
170
|
+
diffMs > 0 &&
|
|
168
171
|
shouldSaveAt30s.current &&
|
|
169
172
|
!save30sAttempted.current
|
|
170
173
|
) {
|
|
@@ -176,14 +179,14 @@ const Countdown: FC = () => {
|
|
|
176
179
|
}
|
|
177
180
|
if (
|
|
178
181
|
(isDirty || showWarningsBecauseNoSave) &&
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
+
diffMs != null &&
|
|
183
|
+
diffMs < 15000 &&
|
|
184
|
+
diffMs > 0 &&
|
|
182
185
|
!fifteenSecondsWarningShown.current
|
|
183
186
|
) {
|
|
184
187
|
showFifteenSecondsWarning();
|
|
185
188
|
}
|
|
186
|
-
if (
|
|
189
|
+
if (diffMs <= 0 && !zeroSecondsWarningShown.current) {
|
|
187
190
|
zeroSecondsWarningShown.current = true;
|
|
188
191
|
toast.current?.clear();
|
|
189
192
|
setTimeout(() => {
|
|
@@ -195,9 +198,7 @@ const Countdown: FC = () => {
|
|
|
195
198
|
});
|
|
196
199
|
}, 500);
|
|
197
200
|
}
|
|
198
|
-
}, [
|
|
199
|
-
|
|
200
|
-
useInterval(updateDiffMs, 1000, !!deadline);
|
|
201
|
+
}, [diffMs, mode, isDirty, showWarningsBecauseNoSave]);
|
|
201
202
|
|
|
202
203
|
const displayed = useMemo<ReactNode>(() => {
|
|
203
204
|
if (!deadline || diffMs == null) {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { useWindowSize } from "@uidotdev/usehooks";
|
|
17
17
|
import { selectShowSaveForStudents } from "../../layout/layoutSlice";
|
|
18
18
|
import settings from "../../../settings";
|
|
19
|
+
import useRemainingTimeMs from "./useRemainingTimeMs";
|
|
19
20
|
|
|
20
21
|
const CountdownAndSaveButton: FC = () => {
|
|
21
22
|
const dispatch = useAppDispatch();
|
|
@@ -31,12 +32,21 @@ const CountdownAndSaveButton: FC = () => {
|
|
|
31
32
|
);
|
|
32
33
|
const hasEvaluations = useAppSelector(selectHasEvaluations);
|
|
33
34
|
|
|
35
|
+
const remainingTimeMs = useRemainingTimeMs();
|
|
36
|
+
const timeOver = useMemo(
|
|
37
|
+
() => remainingTimeMs !== null && remainingTimeMs <= 0,
|
|
38
|
+
[remainingTimeMs],
|
|
39
|
+
);
|
|
40
|
+
|
|
34
41
|
const mode = useAppSelector(selectMode);
|
|
35
42
|
const showSaveButton = useAppSelector(selectShowSaveButton);
|
|
36
43
|
const showSaveForStudents = useAppSelector(selectShowSaveForStudents);
|
|
37
44
|
const hasSaveButton = useMemo(
|
|
38
|
-
() =>
|
|
39
|
-
|
|
45
|
+
() =>
|
|
46
|
+
showSaveButton &&
|
|
47
|
+
!(mode === "assignment" && !showSaveForStudents) &&
|
|
48
|
+
!timeOver,
|
|
49
|
+
[showSaveButton, mode, showSaveForStudents, timeOver],
|
|
40
50
|
);
|
|
41
51
|
|
|
42
52
|
const [editForbiddenDialogVisible, setEditForbiddenDialogVisible] =
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
import { useActivityJS } from "../../activityJS/ActivityJSProvider";
|
|
3
|
+
import serverClock from "../../../utils/server-clock";
|
|
4
|
+
import { useInterval } from "primereact/hooks";
|
|
5
|
+
|
|
6
|
+
const useRemainingTimeMs = () => {
|
|
7
|
+
const activityJS = useActivityJS();
|
|
8
|
+
const deadlineMode =
|
|
9
|
+
activityJS.activitySession?.activityBunch.access_tr_mode.value;
|
|
10
|
+
const deadline =
|
|
11
|
+
!deadlineMode || deadlineMode === "none"
|
|
12
|
+
? null
|
|
13
|
+
: activityJS.activitySession?.activityBunch.access_timerange.value?.end;
|
|
14
|
+
|
|
15
|
+
const [diffMs, setDiffMs] = useState<number | null>(null);
|
|
16
|
+
|
|
17
|
+
const updateDiffMs = useCallback(() => {
|
|
18
|
+
if (!deadline) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const deadlineUTC = deadline.getTime();
|
|
22
|
+
const nowUTC = serverClock.now();
|
|
23
|
+
const newDiffMs = deadlineUTC - nowUTC;
|
|
24
|
+
setDiffMs(newDiffMs);
|
|
25
|
+
}, [deadline]);
|
|
26
|
+
|
|
27
|
+
useInterval(updateDiffMs, 1000, !!deadline);
|
|
28
|
+
|
|
29
|
+
return diffMs;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default useRemainingTimeMs;
|