linguabot commited on
Commit
ecb4029
·
verified ·
1 Parent(s): 386301b

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. client/src/pages/TutorialTasks.tsx +39 -43
client/src/pages/TutorialTasks.tsx CHANGED
@@ -890,30 +890,26 @@ const TutorialTasks: React.FC = () => {
890
  return { ...prev, [taskId]: next };
891
  });
892
 
893
- // Defer state updates; on Safari skip refetch to avoid extra DOM churn
894
- if (!isSafari) {
895
- const gridEl = submissionsGridRefs.current[taskId];
896
- const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
897
- if (gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
898
- withPreservedCardOffset(taskId, () => {
899
- React.startTransition(() => {
900
- setTranslationText({ ...translationText, [taskId]: '' });
901
- setSelectedGroups({ ...selectedGroups, [taskId]: 0 });
902
- api.get(`/api/submissions/by-source/${taskId}`).then(r => {
903
- const list = (r.data && r.data.submissions) || [];
904
- setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
905
- requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
906
- }).catch(() => {
907
- requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
908
- });
909
- });
910
- });
911
- } else {
912
  React.startTransition(() => {
913
  setTranslationText({ ...translationText, [taskId]: '' });
914
  setSelectedGroups({ ...selectedGroups, [taskId]: 0 });
 
 
 
 
 
 
 
 
 
915
  });
916
- }
917
  } else {
918
  console.error('Failed to submit translation:', response.data);
919
  }
@@ -989,8 +985,8 @@ const TutorialTasks: React.FC = () => {
989
 
990
  if (response.status === 200) {
991
 
992
- // Optimistic removal to keep UI in sync immediately (Safari skips refetch)
993
- if (taskId) {
994
  setUserSubmissions(prev => {
995
  const list = prev[taskId] || [];
996
  const next = list.filter(s => s._id !== submissionId);
@@ -998,28 +994,28 @@ const TutorialTasks: React.FC = () => {
998
  });
999
  }
1000
 
1001
- // Defer refetch; on Safari skip and rely on optimistic removal
1002
- if (!isSafari) {
1003
- if (taskId) lockCardHeightById(taskId);
1004
- withPreservedCardOffset(taskId || '', () => {
1005
- React.startTransition(() => {
1006
- if (taskId) {
1007
- const gridEl = submissionsGridRefs.current[taskId];
1008
- const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
1009
- if (gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
1010
- api.get(`/api/submissions/by-source/${taskId}`).then(r => {
1011
- const list = (r.data && r.data.submissions) || [];
1012
- setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
1013
- requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
1014
- }).catch(() => {
1015
- requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
1016
- });
1017
- } else {
1018
- requestAnimationFrame(() => requestAnimationFrame(() => fetchUserSubmissions(tutorialTasks)));
1019
- }
1020
- });
1021
  });
1022
- }
1023
  } else {
1024
 
1025
  }
 
890
  return { ...prev, [taskId]: next };
891
  });
892
 
893
+ // Defer state updates and minimal refetch
894
+ // Measure grid height and set spacer before refetch to keep layout height constant
895
+ const gridEl = submissionsGridRefs.current[taskId];
896
+ const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
897
+ if (gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
898
+ withPreservedCardOffset(taskId, () => {
 
 
 
 
 
 
 
 
 
 
 
 
 
899
  React.startTransition(() => {
900
  setTranslationText({ ...translationText, [taskId]: '' });
901
  setSelectedGroups({ ...selectedGroups, [taskId]: 0 });
902
+ // Narrow refetch: only this task's submissions
903
+ api.get(`/api/submissions/by-source/${taskId}`).then(r => {
904
+ const list = (r.data && r.data.submissions) || [];
905
+ setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
906
+ // Release spacer one frame after list update to avoid jump
907
+ requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
908
+ }).catch(() => {
909
+ requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
910
+ });
911
  });
912
+ });
913
  } else {
914
  console.error('Failed to submit translation:', response.data);
915
  }
 
985
 
986
  if (response.status === 200) {
987
 
988
+ // Optimistic removal (disabled on Safari to prevent multi-phase jumps)
989
+ if (taskId && !isSafari) {
990
  setUserSubmissions(prev => {
991
  const list = prev[taskId] || [];
992
  const next = list.filter(s => s._id !== submissionId);
 
994
  });
995
  }
996
 
997
+ // Defer refetch to prevent UI jumping and preserve scroll around DOM updates
998
+ if (taskId) lockCardHeightById(taskId);
999
+ withPreservedCardOffset(taskId || '', () => {
1000
+ React.startTransition(() => {
1001
+ // Narrow refetch: only this task's submissions
1002
+ if (taskId) {
1003
+ const gridEl = submissionsGridRefs.current[taskId];
1004
+ const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
1005
+ if (gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
1006
+ api.get(`/api/submissions/by-source/${taskId}`).then(r => {
1007
+ const list = (r.data && r.data.submissions) || [];
1008
+ setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
1009
+ requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
1010
+ }).catch(() => {
1011
+ requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
1012
+ });
1013
+ } else {
1014
+ // Fallback
1015
+ requestAnimationFrame(() => requestAnimationFrame(() => fetchUserSubmissions(tutorialTasks)));
1016
+ }
1017
  });
1018
+ });
1019
  } else {
1020
 
1021
  }