kalamishere Claude Opus 4.7 commited on
Commit
5d74df3
Β·
1 Parent(s): 2fcdf15

fix(wallet-bridge): CSS-hide textbox so it stays mounted in the DOM

Browse files

Codex diagnosis: gr.Textbox(visible=False) pulls the element out of
the DOM in Gradio v6, so the popup OAuth bridge JS's
document.getElementById('wallet-bridge-key') returns null and the
deliver() function never writes the sk_... key. The .change handler
on the textbox is wired and would fire β€” but only if something
manages to set the input's value, which silently nothing does.

Swap visible=False for a dc-wallet-bridge-hidden CSS class that
keeps the element mounted at -9999px / 1Γ—1 / opacity 0 / no pointer.
Gradio keeps the input in the DOM tree, the bridge JS finds it,
deliver() writes the key, .change fires save_key_from_fragment, and
the original tab adopts the wallet without a reload.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Files changed (2) hide show
  1. app.py +18 -7
  2. theme.py +16 -0
app.py CHANGED
@@ -1907,13 +1907,24 @@ def build_ui() -> gr.Blocks:
1907
  elem_classes=["dc-script-only"],
1908
  )
1909
  _fragment_key = gr.Textbox(visible=False, value="")
1910
- # Second wallet inbound β€” populated by the OAuth popup
1911
- # postMessage'ing the api_key back to its opener tab so the
1912
- # original tab (with all its analysis / variant state intact)
1913
- # can adopt the key without a reload. .change handler below
1914
- # routes to the same save_key_from_fragment as the fragment path.
1915
- _wallet_bridge_key = gr.Textbox(visible=False, value="",
1916
- elem_id="wallet-bridge-key")
 
 
 
 
 
 
 
 
 
 
 
1917
 
1918
  # Per-visitor crate isolation β€” random opaque id used to scope every
1919
  # crate read/write to /tmp/abv1-crate/{session_id}/. Initialized by
 
1907
  elem_classes=["dc-script-only"],
1908
  )
1909
  _fragment_key = gr.Textbox(visible=False, value="")
1910
+ # Wallet popup bridge β€” when the OAuth popup posts its api_key
1911
+ # back to this opener tab, the message listener (installed in the
1912
+ # fragment-capture demo.load below) drops the key here, which
1913
+ # fires _wallet_bridge_key.change β†’ save_key_from_fragment.
1914
+ #
1915
+ # Crucial: this textbox is CSS-hidden, NOT visible=False. Gradio
1916
+ # treats visible=False as "do not mount in the DOM", which makes
1917
+ # the JS document.getElementById('wallet-bridge-key') return null
1918
+ # and silently no-ops the bridge (Codex diagnosis 2026-06-25).
1919
+ # Off-screen positioning keeps the element present so the JS can
1920
+ # find + write to it.
1921
+ _wallet_bridge_key = gr.Textbox(
1922
+ value="",
1923
+ show_label=False,
1924
+ container=False,
1925
+ elem_id="wallet-bridge-key",
1926
+ elem_classes=["dc-wallet-bridge-hidden"],
1927
+ )
1928
 
1929
  # Per-visitor crate isolation β€” random opaque id used to scope every
1930
  # crate read/write to /tmp/abv1-crate/{session_id}/. Initialized by
theme.py CHANGED
@@ -478,6 +478,22 @@ h3 { font-size: 13px; color: var(--ink2); }
478
  display: none !important;
479
  }
480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  /* ---- Pollen balance pill β€” doubles as wallet button */
482
  .dc-pollen-pill {
483
  display: inline-flex;
 
478
  display: none !important;
479
  }
480
 
481
+ /* Off-screen hide for the wallet-bridge textbox. NOT display:none and
482
+ NOT visible=False on the gr.Textbox β€” both pull the element out of
483
+ the DOM, so the popup OAuth bridge JS can't find it to write the
484
+ sk_... key. Off-screen + 1px + opacity 0 keeps the input mounted,
485
+ focusable by JS, and addressable by getElementById('wallet-bridge-key'). */
486
+ .dc-wallet-bridge-hidden {
487
+ position: fixed !important;
488
+ left: -9999px !important;
489
+ top: auto !important;
490
+ width: 1px !important;
491
+ height: 1px !important;
492
+ overflow: hidden !important;
493
+ opacity: 0 !important;
494
+ pointer-events: none !important;
495
+ }
496
+
497
  /* ---- Pollen balance pill β€” doubles as wallet button */
498
  .dc-pollen-pill {
499
  display: inline-flex;