bep40 commited on
Commit
4c90cb6
·
verified ·
1 Parent(s): 60e5c0b

feat: 24h article videos render in TikTok 9:16 fullscreen mode

Browse files
Files changed (1) hide show
  1. app_wrapper.py +47 -11
app_wrapper.py CHANGED
@@ -1,4 +1,4 @@
1
- """Entry point that adds shorts carousel then imports app."""
2
  import sys, os
3
 
4
  # 1. First import shorts_carousel module
@@ -8,32 +8,34 @@ from shorts_carousel import scrape_24h_news_shorts, render_shorts_carousel, SHOR
8
  # 2. Now import and monkey-patch app
9
  import app
10
 
 
 
 
 
 
 
 
 
 
 
11
  # Patch CSS
12
  if "vslide-shorts-item" not in app.CSS:
13
  app.CSS += SHORTS_CSS
14
-
15
- # Patch fetch_homepage to include shorts
16
- _orig_fetch_homepage = app.fetch_homepage
17
- def _patched_fetch_homepage():
18
- result = _orig_fetch_homepage()
19
- return result
20
- app.fetch_homepage = _patched_fetch_homepage
21
 
22
  # Patch render_homepage_html to include shorts carousel
23
  _orig_render_homepage = app.render_homepage_html
24
  def _patched_render_homepage(articles, *args, **kwargs):
25
  html = _orig_render_homepage(articles, *args, **kwargs)
26
- # Fetch shorts and prepend carousel
27
  try:
28
  shorts = scrape_24h_news_shorts()[:15]
29
  shorts_html = render_shorts_carousel(shorts, app.esc, app.safe_url, app.make_id, app.slug)
30
  if shorts_html:
31
- # Insert after bdp-wrap opening but before the video carousel
32
  insert_point = html.find('<div class="vslide-wrap">')
33
  if insert_point > 0:
34
  html = html[:insert_point] + shorts_html + html[insert_point:]
35
  else:
36
- # Insert at start of bdp-wrap content
37
  insert_point = html.find('<div class="bdp-wrap">') + len('<div class="bdp-wrap">')
38
  if insert_point > len('<div class="bdp-wrap">'):
39
  html = html[:insert_point] + shorts_html + html[insert_point:]
@@ -42,6 +44,40 @@ def _patched_render_homepage(articles, *args, **kwargs):
42
  return html
43
  app.render_homepage_html = _patched_render_homepage
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  # Re-create the Gradio demo with patched CSS
46
  app.demo.css = app.CSS
47
 
 
1
+ """Entry point that adds shorts carousel + TikTok-style article video, then imports app."""
2
  import sys, os
3
 
4
  # 1. First import shorts_carousel module
 
8
  # 2. Now import and monkey-patch app
9
  import app
10
 
11
+ # Extra CSS for TikTok-style article video (9:16)
12
+ TIKTOK_ARTICLE_CSS = """
13
+ /* TikTok-style video in article (9:16) */
14
+ .bdp-tiktok-article-video{position:relative;width:100%;max-width:400px;margin:14px auto;aspect-ratio:9/16;background:#000;border-radius:14px;overflow:hidden}
15
+ .bdp-tiktok-article-video video{width:100%;height:100%;object-fit:contain;display:block}
16
+ .bdp-tiktok-article-video .tiktok-unmute-hint{position:absolute;top:10px;right:10px;background:rgba(0,0,0,.6);color:#fff;font-size:11px;padding:5px 10px;border-radius:14px;cursor:pointer;z-index:4}
17
+ .bdp-tiktok-article-video .tiktok-seek-controls{position:absolute;bottom:50px;left:50%;transform:translateX(-50%);display:flex;gap:30px;z-index:4}
18
+ .bdp-tiktok-article-video .tiktok-seek-btn{background:rgba(0,0,0,.4);color:#fff;border:none;padding:6px 12px;border-radius:16px;font-size:11px;cursor:pointer;backdrop-filter:blur(4px)}
19
+ """
20
+
21
  # Patch CSS
22
  if "vslide-shorts-item" not in app.CSS:
23
  app.CSS += SHORTS_CSS
24
+ if "bdp-tiktok-article-video" not in app.CSS:
25
+ app.CSS += TIKTOK_ARTICLE_CSS
 
 
 
 
 
26
 
27
  # Patch render_homepage_html to include shorts carousel
28
  _orig_render_homepage = app.render_homepage_html
29
  def _patched_render_homepage(articles, *args, **kwargs):
30
  html = _orig_render_homepage(articles, *args, **kwargs)
 
31
  try:
32
  shorts = scrape_24h_news_shorts()[:15]
33
  shorts_html = render_shorts_carousel(shorts, app.esc, app.safe_url, app.make_id, app.slug)
34
  if shorts_html:
 
35
  insert_point = html.find('<div class="vslide-wrap">')
36
  if insert_point > 0:
37
  html = html[:insert_point] + shorts_html + html[insert_point:]
38
  else:
 
39
  insert_point = html.find('<div class="bdp-wrap">') + len('<div class="bdp-wrap">')
40
  if insert_point > len('<div class="bdp-wrap">'):
41
  html = html[:insert_point] + shorts_html + html[insert_point:]
 
44
  return html
45
  app.render_homepage_html = _patched_render_homepage
46
 
47
+ # Patch render_article_html: when 24h article has video, show in TikTok 9:16 style
48
+ _orig_render_article = app.render_article_html
49
+ def _patched_render_article(article):
50
+ html = _orig_render_article(article)
51
+ # Only patch 24h articles that have video
52
+ if article.get("source") == "24h" and any(item.get("type") == "video" for item in article.get("body", [])):
53
+ # Replace standard video-wrap with TikTok 9:16 container
54
+ html = html.replace(
55
+ '<div class="bdp-video-wrap">',
56
+ '<div class="bdp-tiktok-article-video">'
57
+ )
58
+ # Add seek controls and unmute hint after each video tag
59
+ # Find video tags and add controls
60
+ import re as _re
61
+ def _add_controls(match):
62
+ video_html = match.group(0)
63
+ controls = (
64
+ '<div class="tiktok-unmute-hint" onclick="var v=this.parentElement.querySelector(\'video\');v.muted=!v.muted;this.textContent=v.muted?\'🔇 Bật tiếng\':\'🔊 Đang phát\'">🔇 Bật tiếng</div>'
65
+ '<div class="tiktok-seek-controls">'
66
+ '<button class="tiktok-seek-btn" onclick="var v=this.closest(\'.bdp-tiktok-article-video\').querySelector(\'video\');v.currentTime=Math.max(0,v.currentTime-10)">⏪ 10s</button>'
67
+ '<button class="tiktok-seek-btn" onclick="var v=this.closest(\'.bdp-tiktok-article-video\').querySelector(\'video\');v.currentTime=Math.min(v.duration||9999,v.currentTime+10)">10s ⏩</button>'
68
+ '</div>'
69
+ )
70
+ return video_html + controls
71
+ html = _re.sub(r'</video>', lambda m: '</video>' +
72
+ '<div class="tiktok-unmute-hint" onclick="var v=this.parentElement.querySelector(\'video\');v.muted=!v.muted;this.textContent=v.muted?\'🔇 Bật tiếng\':\'🔊 Đang phát\'">🔇 Bật tiếng</div>'
73
+ '<div class="tiktok-seek-controls">'
74
+ '<button class="tiktok-seek-btn" onclick="var v=this.closest(\'.bdp-tiktok-article-video\').querySelector(\'video\');v.currentTime=Math.max(0,v.currentTime-10)">⏪ 10s</button>'
75
+ '<button class="tiktok-seek-btn" onclick="var v=this.closest(\'.bdp-tiktok-article-video\').querySelector(\'video\');v.currentTime=Math.min(v.duration||9999,v.currentTime+10)">10s ⏩</button>'
76
+ '</div>',
77
+ html, count=1)
78
+ return html
79
+ app.render_article_html = _patched_render_article
80
+
81
  # Re-create the Gradio demo with patched CSS
82
  app.demo.css = app.CSS
83