linguabot commited on
Commit
1b274b8
·
verified ·
1 Parent(s): 9a5548c

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. client/src/pages/TutorialTasks.tsx +30 -5
client/src/pages/TutorialTasks.tsx CHANGED
@@ -170,6 +170,28 @@ const TutorialTasks: React.FC = () => {
170
  el.style.minHeight = '';
171
  };
172
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  const withPreservedCardOffset = (taskId: string, fn: () => void) => {
174
  // If scroll is frozen, avoid additional scroll adjustments that can fight WebKit
175
  if (scrollLockState.current) {
@@ -852,11 +874,13 @@ const TutorialTasks: React.FC = () => {
852
  return;
853
  }
854
 
 
855
  try {
856
  setMutatingTaskId(taskId);
857
  if (isSafari) {
858
  try { (document.activeElement as HTMLElement | null)?.blur?.(); } catch {}
859
  freezeScroll();
 
860
  }
861
  lockListHeight();
862
  lockCardHeightById(taskId);
@@ -923,7 +947,7 @@ const TutorialTasks: React.FC = () => {
923
  unlockListHeight();
924
  unlockCardHeightById(taskId);
925
  unlockGridHeightById(taskId);
926
- if (isSafari) unfreezeScroll();
927
  };
928
  if (isSafari) {
929
  requestAnimationFrame(() => requestAnimationFrame(() => requestAnimationFrame(release)));
@@ -975,9 +999,10 @@ const TutorialTasks: React.FC = () => {
975
  const handleDeleteSubmission = async (submissionId: string, taskId?: string) => {
976
 
977
 
 
978
  try {
979
  if (taskId) setMutatingTaskId(taskId);
980
- if (isSafari) freezeScroll();
981
  lockListHeight();
982
  const response = await api.delete(`/api/submissions/${submissionId}`);
983
 
@@ -1028,7 +1053,7 @@ const TutorialTasks: React.FC = () => {
1028
  unlockCardHeightById(taskId);
1029
  unlockGridHeightById(taskId);
1030
  }
1031
- if (isSafari) unfreezeScroll();
1032
  setMutatingTaskId(null);
1033
  }));
1034
  };
@@ -2295,7 +2320,7 @@ const TutorialTasks: React.FC = () => {
2295
 
2296
  {/* All Submissions for this Task */}
2297
  {userSubmissions[task._id] && userSubmissions[task._id].length > 0 && (
2298
- <div ref={(el) => { submissionsContainerRefs.current[task._id] = el; }} className="bg-gradient-to-r from-white to-indigo-50 rounded-xl p-6 mb-6 border border-stone-200" style={{ overflowAnchor: 'none' }}>
2299
  <div className="flex items-center justify-between mb-4">
2300
  <div className="flex items-center space-x-2">
2301
  <div className="bg-indigo-100 rounded-full p-1">
@@ -2322,7 +2347,7 @@ const TutorialTasks: React.FC = () => {
2322
  expandedSections[task._id]
2323
  ? 'max-h-none overflow-visible'
2324
  : 'max-h-0 overflow-hidden'
2325
- }`}>
2326
  {userSubmissions[task._id].map((submission, index) => (
2327
  <div key={submission._id} className="bg-white rounded-lg p-3 border border-stone-200 flex flex-col justify-between h-full">
2328
  <div className="flex items-center justify-between mb-2">
 
170
  el.style.minHeight = '';
171
  };
172
 
173
+ // During volatile mutations on Safari, actively compensate scroll by negating
174
+ // vertical position changes of the task card across a burst of resizes.
175
+ const startCardScrollCompensator = (id: string): (() => void) => {
176
+ try {
177
+ const el = cardRefs.current[id];
178
+ if (!el || typeof ResizeObserver === 'undefined') return () => {};
179
+ let lastTop = el.getBoundingClientRect().top;
180
+ const observer = new ResizeObserver(() => {
181
+ try {
182
+ const currentTop = el.getBoundingClientRect().top;
183
+ const delta = currentTop - lastTop;
184
+ if (delta !== 0) {
185
+ window.scrollBy(0, delta);
186
+ lastTop = currentTop; // keep tracking relative to last applied position
187
+ }
188
+ } catch {}
189
+ });
190
+ observer.observe(el);
191
+ return () => { try { observer.disconnect(); } catch {} };
192
+ } catch { return () => {}; }
193
+ };
194
+
195
  const withPreservedCardOffset = (taskId: string, fn: () => void) => {
196
  // If scroll is frozen, avoid additional scroll adjustments that can fight WebKit
197
  if (scrollLockState.current) {
 
874
  return;
875
  }
876
 
877
+ let stopCompLocal: (() => void) | null = null;
878
  try {
879
  setMutatingTaskId(taskId);
880
  if (isSafari) {
881
  try { (document.activeElement as HTMLElement | null)?.blur?.(); } catch {}
882
  freezeScroll();
883
+ stopCompLocal = startCardScrollCompensator(taskId);
884
  }
885
  lockListHeight();
886
  lockCardHeightById(taskId);
 
947
  unlockListHeight();
948
  unlockCardHeightById(taskId);
949
  unlockGridHeightById(taskId);
950
+ if (isSafari) { try { stopCompLocal?.(); } catch {}; unfreezeScroll(); }
951
  };
952
  if (isSafari) {
953
  requestAnimationFrame(() => requestAnimationFrame(() => requestAnimationFrame(release)));
 
999
  const handleDeleteSubmission = async (submissionId: string, taskId?: string) => {
1000
 
1001
 
1002
+ let stopCompLocal: (() => void) | null = null;
1003
  try {
1004
  if (taskId) setMutatingTaskId(taskId);
1005
+ if (isSafari) { freezeScroll(); stopCompLocal = startCardScrollCompensator(taskId || ''); }
1006
  lockListHeight();
1007
  const response = await api.delete(`/api/submissions/${submissionId}`);
1008
 
 
1053
  unlockCardHeightById(taskId);
1054
  unlockGridHeightById(taskId);
1055
  }
1056
+ if (isSafari) { try { stopCompLocal?.(); } catch {}; unfreezeScroll(); }
1057
  setMutatingTaskId(null);
1058
  }));
1059
  };
 
2320
 
2321
  {/* All Submissions for this Task */}
2322
  {userSubmissions[task._id] && userSubmissions[task._id].length > 0 && (
2323
+ <div ref={(el) => { submissionsContainerRefs.current[task._id] = el; }} className="bg-gradient-to-r from-white to-indigo-50 rounded-xl p-6 mb-6 border border-stone-200" style={{ overflowAnchor: 'none', contain: isSafari ? ('layout paint size' as any) : undefined, transform: isSafari ? 'translateZ(0)' : undefined, willChange: isSafari ? ('contents' as any) : undefined }}>
2324
  <div className="flex items-center justify-between mb-4">
2325
  <div className="flex items-center space-x-2">
2326
  <div className="bg-indigo-100 rounded-full p-1">
 
2347
  expandedSections[task._id]
2348
  ? 'max-h-none overflow-visible'
2349
  : 'max-h-0 overflow-hidden'
2350
+ }`} style={{ contain: isSafari ? ('layout paint size' as any) : undefined, transform: isSafari ? 'translateZ(0)' : undefined, willChange: isSafari ? ('contents' as any) : undefined }}>
2351
  {userSubmissions[task._id].map((submission, index) => (
2352
  <div key={submission._id} className="bg-white rounded-lg p-3 border border-stone-200 flex flex-col justify-between h-full">
2353
  <div className="flex items-center justify-between mb-2">