JS6969 commited on
Commit
f066549
·
verified ·
1 Parent(s): 879ce88

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +104 -104
app.py CHANGED
@@ -949,111 +949,111 @@ with gr.Blocks(css=BASE_CSS, title="ForgeCaptions") as demo:
949
  export_txt_btn = gr.Button("Export captions as .txt (zip)")
950
  txt_zip = gr.File(label="TXT zip", visible=False)
951
 
952
- gr.HTML("""
953
- <script>
954
- (() => {
955
- // ---- Config: your wrapper IDs
956
- const GAL_WRAP_SEL = "#cfGal"; // wrapper around the gallery
957
- const TABLE_WRAP_SEL = "#cfTableWrap"; // wrapper around your table
958
-
959
- // ---- Helpers
960
- const clamp = (v, a, b) => Math.max(a, Math.min(b, v));
961
-
962
- function findGalleryHost() {
963
- const wrap = document.querySelector(GAL_WRAP_SEL);
964
- if (!wrap) return null;
965
- // Prefer explicit gallery node if present; otherwise use wrapper
966
- return wrap.querySelector('[data-testid="gallery"], [data-testid="image-gallery"]') || wrap;
967
- }
968
-
969
- function findTableHost() {
970
- return document.querySelector(TABLE_WRAP_SEL);
971
- }
972
-
973
- function setMaxHeights(gal, tab) {
974
- const targetH = clamp(tab.clientHeight || 520, 360, 520);
975
- gal.style.maxHeight = targetH + "px";
976
- gal.style.overflowY = "auto";
977
- tab.style.maxHeight = targetH + "px";
978
- tab.style.overflowY = "auto";
979
- }
980
-
981
- function attachScrollSync(a, b) {
982
- if (!a || !b) return () => {};
983
- let lock = false;
984
-
985
- // Use scroll ratio so different scrollHeights stay aligned
986
- const sync = (src, dst) => {
987
- const maxSrc = Math.max(1, src.scrollHeight - src.clientHeight);
988
- const r = src.scrollTop / maxSrc;
989
- const maxDst = Math.max(1, dst.scrollHeight - dst.clientHeight);
990
- const next = r * maxDst;
991
- if (Math.abs(dst.scrollTop - next) > 1) {
992
- dst.scrollTop = next;
993
  }
994
- };
995
-
996
- const onA = () => { if (lock) return; lock = true; requestAnimationFrame(() => { sync(a, b); lock = false; }); };
997
- const onB = () => { if (lock) return; lock = true; requestAnimationFrame(() => { sync(b, a); lock = false; }); };
998
-
999
- a.addEventListener("scroll", onA, { passive: true });
1000
- b.addEventListener("scroll", onB, { passive: true });
1001
-
1002
- // Return cleanup
1003
- return () => {
1004
- a.removeEventListener("scroll", onA);
1005
- b.removeEventListener("scroll", onB);
1006
- };
1007
- }
1008
-
1009
- let cleanupScroll = null;
1010
- let resizeObs = null;
1011
-
1012
- function wireUp() {
1013
- const gal = findGalleryHost();
1014
- const tab = findTableHost();
1015
- if (!gal || !tab) return false;
1016
-
1017
- // (Re)apply heights & listeners
1018
- setMaxHeights(gal, tab);
1019
- if (cleanupScroll) cleanupScroll();
1020
- cleanupScroll = attachScrollSync(gal, tab);
1021
-
1022
- // Keep heights in sync on resize/content changes
1023
- if (resizeObs) resizeObs.disconnect();
1024
- resizeObs = new ResizeObserver(() => setMaxHeights(gal, tab));
1025
- resizeObs.observe(tab);
1026
- resizeObs.observe(gal);
1027
-
1028
- return true;
1029
- }
1030
-
1031
- // First attempt immediately (fast path)
1032
- if (wireUp()) return;
1033
-
1034
- // Observe DOM for late mounts / Gradio re-renders
1035
- const mo = new MutationObserver(() => {
1036
- if (wireUp()) {
1037
- // Once wired, continue watching for *re-renders* to re-wire
1038
- // If you prefer, remove this `disconnect()` to keep watching forever
1039
- // but then you should also detect detach and clean up.
1040
- // Here we keep observing to handle re-renders:
1041
- }
1042
- });
1043
-
1044
- mo.observe(document.documentElement || document.body, {
1045
- childList: true,
1046
- subtree: true,
1047
- });
1048
-
1049
- // Optional: cleanup on page unload
1050
- window.addEventListener("beforeunload", () => {
1051
- mo.disconnect();
1052
- if (resizeObs) resizeObs.disconnect();
1053
- if (cleanupScroll) cleanupScroll();
1054
- });
1055
- })();
1056
- </script> """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1057
 
1058
 
1059
  # ---- Chunking logic
 
949
  export_txt_btn = gr.Button("Export captions as .txt (zip)")
950
  txt_zip = gr.File(label="TXT zip", visible=False)
951
 
952
+ gr.HTML("""
953
+ <script>
954
+ (() => {
955
+ // ---- Config: your wrapper IDs
956
+ const GAL_WRAP_SEL = "#cfGal"; // wrapper around the gallery
957
+ const TABLE_WRAP_SEL = "#cfTableWrap"; // wrapper around your table
958
+
959
+ // ---- Helpers
960
+ const clamp = (v, a, b) => Math.max(a, Math.min(b, v));
961
+
962
+ function findGalleryHost() {
963
+ const wrap = document.querySelector(GAL_WRAP_SEL);
964
+ if (!wrap) return null;
965
+ // Prefer explicit gallery node if present; otherwise use wrapper
966
+ return wrap.querySelector('[data-testid="gallery"], [data-testid="image-gallery"]') || wrap;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
967
  }
968
+
969
+ function findTableHost() {
970
+ return document.querySelector(TABLE_WRAP_SEL);
971
+ }
972
+
973
+ function setMaxHeights(gal, tab) {
974
+ const targetH = clamp(tab.clientHeight || 520, 360, 520);
975
+ gal.style.maxHeight = targetH + "px";
976
+ gal.style.overflowY = "auto";
977
+ tab.style.maxHeight = targetH + "px";
978
+ tab.style.overflowY = "auto";
979
+ }
980
+
981
+ function attachScrollSync(a, b) {
982
+ if (!a || !b) return () => {};
983
+ let lock = false;
984
+
985
+ // Use scroll ratio so different scrollHeights stay aligned
986
+ const sync = (src, dst) => {
987
+ const maxSrc = Math.max(1, src.scrollHeight - src.clientHeight);
988
+ const r = src.scrollTop / maxSrc;
989
+ const maxDst = Math.max(1, dst.scrollHeight - dst.clientHeight);
990
+ const next = r * maxDst;
991
+ if (Math.abs(dst.scrollTop - next) > 1) {
992
+ dst.scrollTop = next;
993
+ }
994
+ };
995
+
996
+ const onA = () => { if (lock) return; lock = true; requestAnimationFrame(() => { sync(a, b); lock = false; }); };
997
+ const onB = () => { if (lock) return; lock = true; requestAnimationFrame(() => { sync(b, a); lock = false; }); };
998
+
999
+ a.addEventListener("scroll", onA, { passive: true });
1000
+ b.addEventListener("scroll", onB, { passive: true });
1001
+
1002
+ // Return cleanup
1003
+ return () => {
1004
+ a.removeEventListener("scroll", onA);
1005
+ b.removeEventListener("scroll", onB);
1006
+ };
1007
+ }
1008
+
1009
+ let cleanupScroll = null;
1010
+ let resizeObs = null;
1011
+
1012
+ function wireUp() {
1013
+ const gal = findGalleryHost();
1014
+ const tab = findTableHost();
1015
+ if (!gal || !tab) return false;
1016
+
1017
+ // (Re)apply heights & listeners
1018
+ setMaxHeights(gal, tab);
1019
+ if (cleanupScroll) cleanupScroll();
1020
+ cleanupScroll = attachScrollSync(gal, tab);
1021
+
1022
+ // Keep heights in sync on resize/content changes
1023
+ if (resizeObs) resizeObs.disconnect();
1024
+ resizeObs = new ResizeObserver(() => setMaxHeights(gal, tab));
1025
+ resizeObs.observe(tab);
1026
+ resizeObs.observe(gal);
1027
+
1028
+ return true;
1029
+ }
1030
+
1031
+ // First attempt immediately (fast path)
1032
+ if (wireUp()) return;
1033
+
1034
+ // Observe DOM for late mounts / Gradio re-renders
1035
+ const mo = new MutationObserver(() => {
1036
+ if (wireUp()) {
1037
+ // Once wired, continue watching for *re-renders* to re-wire
1038
+ // If you prefer, remove this `disconnect()` to keep watching forever
1039
+ // but then you should also detect detach and clean up.
1040
+ // Here we keep observing to handle re-renders:
1041
+ }
1042
+ });
1043
+
1044
+ mo.observe(document.documentElement || document.body, {
1045
+ childList: true,
1046
+ subtree: true,
1047
+ });
1048
+
1049
+ // Optional: cleanup on page unload
1050
+ window.addEventListener("beforeunload", () => {
1051
+ mo.disconnect();
1052
+ if (resizeObs) resizeObs.disconnect();
1053
+ if (cleanupScroll) cleanupScroll();
1054
+ });
1055
+ })();
1056
+ </script> """)
1057
 
1058
 
1059
  # ---- Chunking logic