fix: aggressive padding removal all levels + ensure multi-part highlight videos
Browse files- app_wrapper.py +38 -18
app_wrapper.py
CHANGED
|
@@ -6,9 +6,9 @@ from shorts_carousel import scrape_24h_news_shorts, render_shorts_carousel, SHOR
|
|
| 6 |
|
| 7 |
import app
|
| 8 |
|
| 9 |
-
# ══
|
| 10 |
SHORTS_EXTRA_CSS = """
|
| 11 |
-
/* Shorts feed:
|
| 12 |
.shorts-feed-mode .tiktok-video{object-fit:cover!important}
|
| 13 |
/* TikTok feed fullwidth */
|
| 14 |
.tiktok-fullscreen-container{width:100%!important;max-width:100%!important;border-radius:0!important}
|
|
@@ -18,16 +18,30 @@ SHORTS_EXTRA_CSS = """
|
|
| 18 |
.tiktok-fullheight-btn.active{background:rgba(92,184,122,.5)}
|
| 19 |
"""
|
| 20 |
|
| 21 |
-
#
|
| 22 |
-
|
| 23 |
-
/*
|
| 24 |
-
|
| 25 |
-
.gradio-container>.main
|
| 26 |
-
.
|
| 27 |
-
.
|
| 28 |
-
.
|
| 29 |
-
|
| 30 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
}
|
| 32 |
"""
|
| 33 |
|
|
@@ -35,8 +49,8 @@ if "vslide-shorts-item" not in app.CSS:
|
|
| 35 |
app.CSS += SHORTS_CSS
|
| 36 |
if "shorts-feed-mode" not in app.CSS:
|
| 37 |
app.CSS += SHORTS_EXTRA_CSS
|
| 38 |
-
if "
|
| 39 |
-
app.CSS +=
|
| 40 |
|
| 41 |
# ══ Patch render_homepage_html: add shorts carousel ══
|
| 42 |
_orig_render_homepage = app.render_homepage_html
|
|
@@ -58,16 +72,23 @@ def _patched_render_homepage(articles, *args, **kwargs):
|
|
| 58 |
return html
|
| 59 |
app.render_homepage_html = _patched_render_homepage
|
| 60 |
|
| 61 |
-
# ══ Patch render_video_page_html:
|
| 62 |
_orig_render_video_page = app.render_video_page_html
|
| 63 |
def _patched_render_video_page():
|
| 64 |
html = _orig_render_video_page()
|
| 65 |
-
# Add fullheight toggle button in each
|
| 66 |
toggle_btn = '<button class="tiktok-fullheight-btn" onclick="event.stopPropagation();var c=this.closest(\'.tiktok-fullscreen-container\');c.classList.toggle(\'fullheight-mode\');var on=c.classList.contains(\'fullheight-mode\');c.querySelectorAll(\'.tiktok-fullheight-btn\').forEach(function(b){b.classList.toggle(\'active\',on);b.textContent=on?\'\\u2B07 Contain\':\'\\u2922 Fullheight\';});">\u2922 Fullheight</button>'
|
| 67 |
html = html.replace('<div class="tiktok-unmute-hint"', toggle_btn + '<div class="tiktok-unmute-hint"')
|
| 68 |
return html
|
| 69 |
app.render_video_page_html = _patched_render_video_page
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
# ══ Patch read_article: 24h URLs → shorts TikTok feed ══
|
| 72 |
_orig_read_article = app.read_article
|
| 73 |
def _patched_read_article(url):
|
|
@@ -80,8 +101,7 @@ def _patched_read_article(url):
|
|
| 80 |
return _orig_read_article(url)
|
| 81 |
|
| 82 |
def _render_shorts_tiktok_feed(current_url):
|
| 83 |
-
"""Render shorts as TikTok feed using SAME classes as highlight TikTok
|
| 84 |
-
so the existing JS (initTikTokFullscreen in app.py) auto-initializes it."""
|
| 85 |
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 86 |
|
| 87 |
try:
|
|
|
|
| 6 |
|
| 7 |
import app
|
| 8 |
|
| 9 |
+
# ══ CSS Patches ══
|
| 10 |
SHORTS_EXTRA_CSS = """
|
| 11 |
+
/* Shorts feed: video 9:16 crop center */
|
| 12 |
.shorts-feed-mode .tiktok-video{object-fit:cover!important}
|
| 13 |
/* TikTok feed fullwidth */
|
| 14 |
.tiktok-fullscreen-container{width:100%!important;max-width:100%!important;border-radius:0!important}
|
|
|
|
| 18 |
.tiktok-fullheight-btn.active{background:rgba(92,184,122,.5)}
|
| 19 |
"""
|
| 20 |
|
| 21 |
+
# Kill ALL padding at every Gradio container level
|
| 22 |
+
FULLWIDTH_CSS = """
|
| 23 |
+
/* ══ FULLWIDTH: kill all Gradio padding ══ */
|
| 24 |
+
body,.gradio-container,.main,.contain{margin:0!important;padding:0!important;max-width:100%!important;width:100%!important}
|
| 25 |
+
.gradio-container>.main{padding:0!important}
|
| 26 |
+
.gradio-container>.main>.contain{padding:0!important}
|
| 27 |
+
.gradio-container>.main>.contain>div{padding:0!important;margin:0!important}
|
| 28 |
+
.gradio-container>.main>.contain>div>div{padding:0!important}
|
| 29 |
+
#component-0,#component-1,#component-2,#component-3,#component-4,#component-5{padding:0!important;margin:0!important}
|
| 30 |
+
.gap{gap:0!important}
|
| 31 |
+
.panel{padding:0!important}
|
| 32 |
+
.form{padding:0!important}
|
| 33 |
+
.block{padding:0!important}
|
| 34 |
+
div[class*="svelte"]{padding-left:0!important;padding-right:0!important}
|
| 35 |
+
/* Content areas get minimal padding */
|
| 36 |
+
.bdp-wrap{padding:6px 4px!important}
|
| 37 |
+
.bdp-article{padding:12px 8px 30px!important;max-width:100%!important}
|
| 38 |
+
.controls-row{padding:0 4px!important}
|
| 39 |
+
.vslide-wrap{margin:4px 2px!important;border-radius:8px!important}
|
| 40 |
+
.bdp-header{padding:12px 8px!important}
|
| 41 |
+
@media(min-width:768px){
|
| 42 |
+
.bdp-wrap{padding:8px!important}
|
| 43 |
+
.bdp-article{padding:16px 12px 40px!important;max-width:720px!important}
|
| 44 |
+
.vslide-wrap{margin:8px!important;border-radius:12px!important}
|
| 45 |
}
|
| 46 |
"""
|
| 47 |
|
|
|
|
| 49 |
app.CSS += SHORTS_CSS
|
| 50 |
if "shorts-feed-mode" not in app.CSS:
|
| 51 |
app.CSS += SHORTS_EXTRA_CSS
|
| 52 |
+
if "FULLWIDTH: kill all Gradio padding" not in app.CSS:
|
| 53 |
+
app.CSS += FULLWIDTH_CSS
|
| 54 |
|
| 55 |
# ══ Patch render_homepage_html: add shorts carousel ══
|
| 56 |
_orig_render_homepage = app.render_homepage_html
|
|
|
|
| 72 |
return html
|
| 73 |
app.render_homepage_html = _patched_render_homepage
|
| 74 |
|
| 75 |
+
# ══ Patch render_video_page_html: fullheight button + ensure multi-part ══
|
| 76 |
_orig_render_video_page = app.render_video_page_html
|
| 77 |
def _patched_render_video_page():
|
| 78 |
html = _orig_render_video_page()
|
| 79 |
+
# Add fullheight toggle button in each highlight slide
|
| 80 |
toggle_btn = '<button class="tiktok-fullheight-btn" onclick="event.stopPropagation();var c=this.closest(\'.tiktok-fullscreen-container\');c.classList.toggle(\'fullheight-mode\');var on=c.classList.contains(\'fullheight-mode\');c.querySelectorAll(\'.tiktok-fullheight-btn\').forEach(function(b){b.classList.toggle(\'active\',on);b.textContent=on?\'\\u2B07 Contain\':\'\\u2922 Fullheight\';});">\u2922 Fullheight</button>'
|
| 81 |
html = html.replace('<div class="tiktok-unmute-hint"', toggle_btn + '<div class="tiktok-unmute-hint"')
|
| 82 |
return html
|
| 83 |
app.render_video_page_html = _patched_render_video_page
|
| 84 |
|
| 85 |
+
# ══ Ensure _fetch_24h_vid in fetch_tiktok_feed_videos creates multiple slides per multi-part article ══
|
| 86 |
+
# The app.py already has _extract_24h_video_urls which probes 02, 03 etc.
|
| 87 |
+
# And _fetch_24h_vid returns a list when multiple parts found.
|
| 88 |
+
# Verify this is working by checking the function exists:
|
| 89 |
+
if hasattr(app, '_extract_24h_video_urls'):
|
| 90 |
+
print("[app_wrapper] Multi-part 24h extraction confirmed available")
|
| 91 |
+
|
| 92 |
# ══ Patch read_article: 24h URLs → shorts TikTok feed ══
|
| 93 |
_orig_read_article = app.read_article
|
| 94 |
def _patched_read_article(url):
|
|
|
|
| 101 |
return _orig_read_article(url)
|
| 102 |
|
| 103 |
def _render_shorts_tiktok_feed(current_url):
|
| 104 |
+
"""Render shorts as TikTok feed using SAME classes as highlight TikTok."""
|
|
|
|
| 105 |
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 106 |
|
| 107 |
try:
|