Upload folder using huggingface_hub
Browse files
client/src/pages/TutorialTasks.tsx
CHANGED
|
@@ -119,6 +119,9 @@ const TutorialTasks: React.FC = () => {
|
|
| 119 |
};
|
| 120 |
|
| 121 |
// Minimal, local scroll-stability helpers for submit/delete
|
|
|
|
|
|
|
|
|
|
| 122 |
const lockListHeight = () => {
|
| 123 |
const el = listRef.current;
|
| 124 |
if (!el) return;
|
|
@@ -849,19 +852,20 @@ const TutorialTasks: React.FC = () => {
|
|
| 849 |
const created = response.data;
|
| 850 |
console.log('Submission created successfully:', created);
|
| 851 |
|
| 852 |
-
// Optimistic append
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
| 857 |
-
|
| 858 |
-
|
|
|
|
| 859 |
|
| 860 |
// Defer state updates and minimal refetch
|
| 861 |
// Measure grid height and set spacer before refetch to keep layout height constant
|
| 862 |
const gridEl = submissionsGridRefs.current[taskId];
|
| 863 |
const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
|
| 864 |
-
if (gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
|
| 865 |
withPreservedCardOffset(taskId, () => {
|
| 866 |
React.startTransition(() => {
|
| 867 |
setTranslationText({ ...translationText, [taskId]: '' });
|
|
@@ -870,8 +874,9 @@ const TutorialTasks: React.FC = () => {
|
|
| 870 |
api.get(`/api/submissions/by-source/${taskId}`).then(r => {
|
| 871 |
const list = (r.data && r.data.submissions) || [];
|
| 872 |
setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
|
| 873 |
-
|
| 874 |
-
|
|
|
|
| 875 |
}).catch(() => {
|
| 876 |
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 877 |
});
|
|
@@ -945,8 +950,8 @@ const TutorialTasks: React.FC = () => {
|
|
| 945 |
|
| 946 |
if (response.status === 200) {
|
| 947 |
|
| 948 |
-
//
|
| 949 |
-
if (taskId) {
|
| 950 |
setUserSubmissions(prev => {
|
| 951 |
const list = prev[taskId] || [];
|
| 952 |
const next = list.filter(s => s._id !== submissionId);
|
|
@@ -962,11 +967,13 @@ const TutorialTasks: React.FC = () => {
|
|
| 962 |
if (taskId) {
|
| 963 |
const gridEl = submissionsGridRefs.current[taskId];
|
| 964 |
const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
|
| 965 |
-
if (gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
|
| 966 |
api.get(`/api/submissions/by-source/${taskId}`).then(r => {
|
| 967 |
const list = (r.data && r.data.submissions) || [];
|
| 968 |
setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
|
| 969 |
-
|
|
|
|
|
|
|
| 970 |
}).catch(() => {
|
| 971 |
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 972 |
});
|
|
|
|
| 119 |
};
|
| 120 |
|
| 121 |
// Minimal, local scroll-stability helpers for submit/delete
|
| 122 |
+
// Basic UA check; Chrome on iOS uses WKWebView but includes 'CriOS'
|
| 123 |
+
const isSafari = typeof navigator !== 'undefined' && /Safari\//.test(navigator.userAgent) && !/Chrome\//.test(navigator.userAgent) && !/CriOS\//.test(navigator.userAgent);
|
| 124 |
+
|
| 125 |
const lockListHeight = () => {
|
| 126 |
const el = listRef.current;
|
| 127 |
if (!el) return;
|
|
|
|
| 852 |
const created = response.data;
|
| 853 |
console.log('Submission created successfully:', created);
|
| 854 |
|
| 855 |
+
// Optimistic append (disabled on Safari to prevent multi-phase jumps)
|
| 856 |
+
if (!isSafari) {
|
| 857 |
+
setUserSubmissions(prev => {
|
| 858 |
+
const current = prev[taskId] || [];
|
| 859 |
+
const next = [{ ...created, isOwner: true }, ...current];
|
| 860 |
+
return { ...prev, [taskId]: next };
|
| 861 |
+
});
|
| 862 |
+
}
|
| 863 |
|
| 864 |
// Defer state updates and minimal refetch
|
| 865 |
// Measure grid height and set spacer before refetch to keep layout height constant
|
| 866 |
const gridEl = submissionsGridRefs.current[taskId];
|
| 867 |
const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
|
| 868 |
+
if (!isSafari && gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
|
| 869 |
withPreservedCardOffset(taskId, () => {
|
| 870 |
React.startTransition(() => {
|
| 871 |
setTranslationText({ ...translationText, [taskId]: '' });
|
|
|
|
| 874 |
api.get(`/api/submissions/by-source/${taskId}`).then(r => {
|
| 875 |
const list = (r.data && r.data.submissions) || [];
|
| 876 |
setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
|
| 877 |
+
if (!isSafari) {
|
| 878 |
+
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 879 |
+
}
|
| 880 |
}).catch(() => {
|
| 881 |
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 882 |
});
|
|
|
|
| 950 |
|
| 951 |
if (response.status === 200) {
|
| 952 |
|
| 953 |
+
// Optimistic removal (disabled on Safari to prevent multi-phase jumps)
|
| 954 |
+
if (taskId && !isSafari) {
|
| 955 |
setUserSubmissions(prev => {
|
| 956 |
const list = prev[taskId] || [];
|
| 957 |
const next = list.filter(s => s._id !== submissionId);
|
|
|
|
| 967 |
if (taskId) {
|
| 968 |
const gridEl = submissionsGridRefs.current[taskId];
|
| 969 |
const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
|
| 970 |
+
if (!isSafari && gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
|
| 971 |
api.get(`/api/submissions/by-source/${taskId}`).then(r => {
|
| 972 |
const list = (r.data && r.data.submissions) || [];
|
| 973 |
setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
|
| 974 |
+
if (!isSafari) {
|
| 975 |
+
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 976 |
+
}
|
| 977 |
}).catch(() => {
|
| 978 |
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 979 |
});
|