Spaces:
Running
Running
CSS update
Browse files- battlewords/ui.py +8 -128
battlewords/ui.py
CHANGED
|
@@ -188,9 +188,6 @@ def inject_styles() -> None:
|
|
| 188 |
.shiny-border:hover::before { left: 100%; }
|
| 189 |
|
| 190 |
.bw-radio-group { display:flex; align-items:flex-start; gap: 10px; flex-flow: row; }
|
| 191 |
-
@media (max-width:1000px) and (min-width:641px) {
|
| 192 |
-
.bw-radio-group { flex-wrap:wrap; gap: 5px; }
|
| 193 |
-
}
|
| 194 |
.bw-radio-item { display:flex; flex-direction:column; align-items:center; gap:6px; text-align:center;}
|
| 195 |
.bw-radio-circle { width: 45px; height: 45px; border-radius: 50%; border: 4px solid; background: rgba(255,255,255,0.06); display: grid; place-items: center; color:#fff; font-weight:700; }
|
| 196 |
.bw-radio-circle .dot { width: 14px; height: 14px; border-radius: 50%; background:#777; box-shadow: inset 0 0 0 2px rgba(255,255,255,0.25); }
|
|
@@ -199,6 +196,13 @@ def inject_styles() -> None:
|
|
| 199 |
.bw-radio-circle.active.miss { background: linear-gradient(135deg, rgba(255,0,0,0.18), rgba(128,0,0,0.38)); }
|
| 200 |
.bw-radio-circle.active.miss .dot { background:#ff4b4b; box-shadow: 0 0 10px rgba(255,75,75,0.85); }
|
| 201 |
.bw-radio-caption { font-size: 0.8rem; color:#fff; opacity:0.85; letter-spacing:0.5px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
|
| 203 |
/* Make the sidebar scrollable */
|
| 204 |
section[data-testid="stSidebar"] {
|
|
@@ -230,130 +234,6 @@ def inject_styles() -> None:
|
|
| 230 |
unsafe_allow_html=True,
|
| 231 |
)
|
| 232 |
|
| 233 |
-
# Bridge to control the wrapper around the iframe component from the parent page
|
| 234 |
-
def _inject_parent_modal_bridge() -> None:
|
| 235 |
-
if st.session_state.get("_bw_parent_bridge", False):
|
| 236 |
-
return
|
| 237 |
-
st.session_state["_bw_parent_bridge"] = True
|
| 238 |
-
st.markdown(
|
| 239 |
-
"""
|
| 240 |
-
<script>
|
| 241 |
-
(function(){
|
| 242 |
-
// Debug: script injection confirmation
|
| 243 |
-
alert('Parent modal bridge script loaded');
|
| 244 |
-
|
| 245 |
-
// Find the Streamlit wrapper around the iframe that renders the modal (components.html wrapper)
|
| 246 |
-
function findWrapper(iframe) {
|
| 247 |
-
if (!iframe) return null;
|
| 248 |
-
// Try Streamlit's typical element wrapper first, then fallback to parentElement
|
| 249 |
-
var el = iframe.closest('.st-emotion-cache-wp60of') || iframe.parentElement;
|
| 250 |
-
// Debug: which wrapper did we find
|
| 251 |
-
alert('findWrapper called, found: ' + (el ? el.className : 'null'));
|
| 252 |
-
return el;
|
| 253 |
-
}
|
| 254 |
-
|
| 255 |
-
// Listen for messages from the iframe (modal page) to toggle visibility/positioning
|
| 256 |
-
window.addEventListener('message', function(e) {
|
| 257 |
-
alert('Message event received');
|
| 258 |
-
|
| 259 |
-
var data = e.data || {};
|
| 260 |
-
var isVisibility = data && data.type === 'bw-bootstrap-modal-visibility';
|
| 261 |
-
var isStreamlitSet = data && data.type === 'streamlit:setComponentValue' && data.key === 'show_gameover_overlay';
|
| 262 |
-
|
| 263 |
-
// Only handle our two message types
|
| 264 |
-
if (!(isVisibility || isStreamlitSet)) return;
|
| 265 |
-
alert('Visibility or StreamlitSet message detected');
|
| 266 |
-
|
| 267 |
-
// Decide if the modal should be visible based on message type
|
| 268 |
-
var shouldBeVisible = isVisibility ? !!data.visible : !!data.value;
|
| 269 |
-
alert('shouldBeVisible: ' + shouldBeVisible);
|
| 270 |
-
|
| 271 |
-
// Try to get the iframe element directly from the message source
|
| 272 |
-
var iframeEl = null;
|
| 273 |
-
try {
|
| 274 |
-
iframeEl = (e.source && e.source.frameElement) ? e.source.frameElement : null;
|
| 275 |
-
} catch(_) {
|
| 276 |
-
iframeEl = null;
|
| 277 |
-
}
|
| 278 |
-
alert('iframeEl direct: ' + (iframeEl ? iframeEl.tagName : 'null'));
|
| 279 |
-
|
| 280 |
-
// Fallback: scan iframes and match by contentWindow reference
|
| 281 |
-
if (!iframeEl) {
|
| 282 |
-
var frames = document.querySelectorAll('iframe');
|
| 283 |
-
for (var i = 0; i < frames.length; i++) {
|
| 284 |
-
var f = frames[i];
|
| 285 |
-
try {
|
| 286 |
-
if (f.contentWindow !== e.source) continue;
|
| 287 |
-
} catch(_) {
|
| 288 |
-
continue;
|
| 289 |
-
}
|
| 290 |
-
iframeEl = f;
|
| 291 |
-
break;
|
| 292 |
-
}
|
| 293 |
-
}
|
| 294 |
-
alert('iframeEl after fallback: ' + (iframeEl ? iframeEl.tagName : 'null'));
|
| 295 |
-
if (!iframeEl) return;
|
| 296 |
-
|
| 297 |
-
// Find the wrapper that we will show/hide and absolutely position
|
| 298 |
-
var wrap = findWrapper(iframeEl);
|
| 299 |
-
alert('Wrapper found: ' + (wrap ? wrap.className : 'null'));
|
| 300 |
-
|
| 301 |
-
if (wrap) {
|
| 302 |
-
wrap.classList.add('bw-modal-wrapper');
|
| 303 |
-
if (shouldBeVisible) {
|
| 304 |
-
alert('Setting wrapper to visible');
|
| 305 |
-
wrap.style.display = 'block';
|
| 306 |
-
wrap.style.position = 'fixed';
|
| 307 |
-
wrap.style.inset = '0';
|
| 308 |
-
wrap.style.zIndex = '99999';
|
| 309 |
-
wrap.style.width = '100vw';
|
| 310 |
-
wrap.style.height = '100vh';
|
| 311 |
-
wrap.style.margin = '0';
|
| 312 |
-
wrap.style.padding = '0';
|
| 313 |
-
} else {
|
| 314 |
-
alert('Setting wrapper to hidden');
|
| 315 |
-
wrap.style.display = 'none';
|
| 316 |
-
wrap.style.position = 'relative';
|
| 317 |
-
}
|
| 318 |
-
}
|
| 319 |
-
|
| 320 |
-
// Always toggle the iframe element itself for robustness
|
| 321 |
-
try {
|
| 322 |
-
if (shouldBeVisible) {
|
| 323 |
-
alert('Setting iframe to visible');
|
| 324 |
-
iframeEl.style.display = 'block';
|
| 325 |
-
iframeEl.style.width = '100vw';
|
| 326 |
-
iframeEl.style.height = '100vh';
|
| 327 |
-
iframeEl.style.borderRadius = '15px';
|
| 328 |
-
iframeEl.style.background = 'rgba(29, 100, 200, 0.5)';
|
| 329 |
-
iframeEl.style.pointerEvents = 'auto';
|
| 330 |
-
iframeEl.style.zIndex = '1000';
|
| 331 |
-
iframeEl.style.position = 'fixed';
|
| 332 |
-
iframeEl.style.inset = '0';
|
| 333 |
-
} else {
|
| 334 |
-
alert('Setting iframe to hidden');
|
| 335 |
-
iframeEl.style.display = 'none';
|
| 336 |
-
iframeEl.style.width = '0px';
|
| 337 |
-
iframeEl.style.height = '0px';
|
| 338 |
-
iframeEl.style.pointerEvents = 'none';
|
| 339 |
-
iframeEl.style.zIndex = '-1';
|
| 340 |
-
iframeEl.style.position = '';
|
| 341 |
-
iframeEl.style.inset = '';
|
| 342 |
-
}
|
| 343 |
-
} catch(_) {
|
| 344 |
-
alert('Error toggling iframe style');
|
| 345 |
-
}
|
| 346 |
-
}, false);
|
| 347 |
-
|
| 348 |
-
// Note: Streamlit's components.html uses an iframe sandbox that includes allow-scripts and allow-same-origin.
|
| 349 |
-
// That combination raises a general warning, but is required here for messaging and proper behavior.
|
| 350 |
-
})();
|
| 351 |
-
</script>
|
| 352 |
-
""",
|
| 353 |
-
unsafe_allow_html=True,
|
| 354 |
-
)
|
| 355 |
-
|
| 356 |
-
|
| 357 |
def _init_session() -> None:
|
| 358 |
if "initialized" in st.session_state and st.session_state.initialized:
|
| 359 |
return
|
|
@@ -1164,7 +1044,7 @@ def run_app():
|
|
| 1164 |
left, right = st.columns([3, 2], gap="medium")
|
| 1165 |
with right:
|
| 1166 |
_render_radar(state.puzzle, size=state.grid_size, r_max=0.8, max_frames=25, sinusoid_expand=True, stagger_radar=False, show_ticks=st.session_state.get("show_grid_ticks", False))
|
| 1167 |
-
one, two = st.columns([1,
|
| 1168 |
with one:
|
| 1169 |
_render_correct_try_again(state)
|
| 1170 |
#_render_hit_miss(state)
|
|
|
|
| 188 |
.shiny-border:hover::before { left: 100%; }
|
| 189 |
|
| 190 |
.bw-radio-group { display:flex; align-items:flex-start; gap: 10px; flex-flow: row; }
|
|
|
|
|
|
|
|
|
|
| 191 |
.bw-radio-item { display:flex; flex-direction:column; align-items:center; gap:6px; text-align:center;}
|
| 192 |
.bw-radio-circle { width: 45px; height: 45px; border-radius: 50%; border: 4px solid; background: rgba(255,255,255,0.06); display: grid; place-items: center; color:#fff; font-weight:700; }
|
| 193 |
.bw-radio-circle .dot { width: 14px; height: 14px; border-radius: 50%; background:#777; box-shadow: inset 0 0 0 2px rgba(255,255,255,0.25); }
|
|
|
|
| 196 |
.bw-radio-circle.active.miss { background: linear-gradient(135deg, rgba(255,0,0,0.18), rgba(128,0,0,0.38)); }
|
| 197 |
.bw-radio-circle.active.miss .dot { background:#ff4b4b; box-shadow: 0 0 10px rgba(255,75,75,0.85); }
|
| 198 |
.bw-radio-caption { font-size: 0.8rem; color:#fff; opacity:0.85; letter-spacing:0.5px; }
|
| 199 |
+
@media (max-width:1000px) and (min-width:641px) {
|
| 200 |
+
.bw-radio-group { flex-wrap:wrap; gap: 5px; margin-bottom: 5px;}
|
| 201 |
+
.bw-radio-item {margin: 0 auto;}
|
| 202 |
+
}
|
| 203 |
+
@media (max-width:640px) {
|
| 204 |
+
.bw-radio-item { margin:unset;}
|
| 205 |
+
}
|
| 206 |
|
| 207 |
/* Make the sidebar scrollable */
|
| 208 |
section[data-testid="stSidebar"] {
|
|
|
|
| 234 |
unsafe_allow_html=True,
|
| 235 |
)
|
| 236 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 237 |
def _init_session() -> None:
|
| 238 |
if "initialized" in st.session_state and st.session_state.initialized:
|
| 239 |
return
|
|
|
|
| 1044 |
left, right = st.columns([3, 2], gap="medium")
|
| 1045 |
with right:
|
| 1046 |
_render_radar(state.puzzle, size=state.grid_size, r_max=0.8, max_frames=25, sinusoid_expand=True, stagger_radar=False, show_ticks=st.session_state.get("show_grid_ticks", False))
|
| 1047 |
+
one, two = st.columns([1, 2], gap="medium")
|
| 1048 |
with one:
|
| 1049 |
_render_correct_try_again(state)
|
| 1050 |
#_render_hit_miss(state)
|