Spaces:
Running
Running
fix: replace dropdown hack with hidden textbox+button for reliable category switching + TikTok navigation
Browse files
app.py
CHANGED
|
@@ -746,11 +746,7 @@ footer,.built-with{display:none!important}
|
|
| 746 |
.bdp-header h1{color:#fff;font-size:20px;margin:0;font-weight:800;text-shadow:0 2px 6px rgba(0,0,0,.4)}
|
| 747 |
.bdp-header p{color:rgba(255,255,255,.6);font-size:11px;margin:2px 0 0}
|
| 748 |
@media(min-width:768px){.bdp-header h1{font-size:26px}.bdp-header{padding:20px}}
|
| 749 |
-
|
| 750 |
-
.controls-row>div{background:#111!important;border:none!important}
|
| 751 |
-
.controls-row label{color:#aaa!important;font-size:12px!important}
|
| 752 |
-
.controls-row .wrap{border-color:#333!important;background:#1a1a1a!important}
|
| 753 |
-
.controls-row input,.controls-row select,.controls-row button{color:#eee!important}
|
| 754 |
.vslide-wrap{margin:8px;background:#1a1a1a;border-radius:12px;overflow:hidden;border:1px solid #2a2a2a}
|
| 755 |
.vslide-header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px 6px}
|
| 756 |
.vslide-label{color:#f0c040;font-size:15px;font-weight:700}
|
|
@@ -925,39 +921,16 @@ window.bdpSelectCat=function(catKey,hashSlug){
|
|
| 925 |
document.querySelectorAll('.cat-icon-btn').forEach(function(b){
|
| 926 |
b.classList.toggle('active',b.getAttribute('data-cat')===catKey);
|
| 927 |
});
|
| 928 |
-
/* Trigger
|
| 929 |
-
window.
|
| 930 |
};
|
| 931 |
|
| 932 |
-
window.
|
| 933 |
-
var
|
| 934 |
-
if(
|
| 935 |
-
|
| 936 |
-
|
| 937 |
-
}
|
| 938 |
-
if(!container) container=document.querySelector('.controls-row');
|
| 939 |
-
if(!container) return;
|
| 940 |
-
/* Gradio 4+ dropdown: find the input, set value, fire events */
|
| 941 |
-
var inp=container.querySelector('input');
|
| 942 |
-
if(!inp) return;
|
| 943 |
-
try{
|
| 944 |
-
var nativeSet=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,'value').set;
|
| 945 |
-
nativeSet.call(inp,catKey);
|
| 946 |
-
}catch(e){inp.value=catKey;}
|
| 947 |
-
inp.dispatchEvent(new Event('input',{bubbles:true}));
|
| 948 |
-
inp.dispatchEvent(new Event('change',{bubbles:true}));
|
| 949 |
-
/* Force open dropdown and click the matching option */
|
| 950 |
-
inp.focus();
|
| 951 |
-
inp.dispatchEvent(new KeyboardEvent('keydown',{key:'ArrowDown',bubbles:true}));
|
| 952 |
-
setTimeout(function(){
|
| 953 |
-
var opts=document.querySelectorAll('[role="option"], li.item');
|
| 954 |
-
for(var i=0;i<opts.length;i++){
|
| 955 |
-
if(opts[i].textContent.trim()===catKey||opts[i].innerText.trim()===catKey){
|
| 956 |
-
opts[i].click();
|
| 957 |
-
return;
|
| 958 |
-
}
|
| 959 |
-
}
|
| 960 |
-
},150);
|
| 961 |
};
|
| 962 |
|
| 963 |
function gc(a){try{return JSON.parse(localStorage.getItem('bdp_cmt_'+a))||[];}catch(e){return[];}}
|
|
@@ -990,8 +963,11 @@ window.bdpOpenTikTok=function(url,aid){
|
|
| 990 |
document.querySelectorAll('.cat-icon-btn').forEach(function(b){
|
| 991 |
b.classList.toggle('active',b.getAttribute('data-hash')==='video');
|
| 992 |
});
|
| 993 |
-
/* Trigger
|
| 994 |
-
|
|
|
|
|
|
|
|
|
|
| 995 |
/* After content loads, scroll to the matching video in TikTok feed */
|
| 996 |
var attempts=0;
|
| 997 |
var finder=setInterval(function(){
|
|
@@ -1134,7 +1110,7 @@ if(hh&&hh.startsWith('#cat/')){
|
|
| 1134 |
var catMap={""" + ",".join(f"'{ci[2]}':'{esc(CAT_KEYS[i])}'" for i,ci in enumerate(CAT_ICONS)) + """};
|
| 1135 |
if(catMap[catSlug]){
|
| 1136 |
setTimeout(function(){
|
| 1137 |
-
window.
|
| 1138 |
document.querySelectorAll('.cat-icon-btn').forEach(function(b){
|
| 1139 |
b.classList.toggle('active',b.getAttribute('data-hash')===catSlug);
|
| 1140 |
});
|
|
@@ -1159,26 +1135,29 @@ with gr.Blocks(title="Tin Tức Việt Nam",css=CSS,head=HEAD_META,js=JS_FUNC,th
|
|
| 1159 |
gr.HTML('<div class="bdp-header"><h1>📰 Tin Tức Việt Nam</h1><p>VnExpress · BongDaPlus · 24h · Thời sự · Thế giới · Kinh doanh · Công nghệ · Thể thao · Giải trí · Video</p></div>')
|
| 1160 |
gr.HTML(_build_cat_grid_html())
|
| 1161 |
article_url=gr.Textbox(value="",visible=False,elem_id="article-url-input")
|
| 1162 |
-
|
| 1163 |
-
cat=gr.Dropdown(choices=list(CATEGORIES.keys()),value="🏠 Trang Chủ (Nổi Bật)",label="Chuyên mục",scale=3,interactive=True,elem_id="cat-dropdown")
|
| 1164 |
-
ref_btn=gr.Button("🔄 Làm mới",variant="primary",scale=1)
|
| 1165 |
back_btn=gr.Button("← Quay lại",variant="secondary",visible=False)
|
| 1166 |
news_list=gr.HTML()
|
| 1167 |
article_view=gr.HTML(visible=False)
|
| 1168 |
read_btn=gr.Button("Đọc",visible=False,elem_id="btn-read-article")
|
|
|
|
| 1169 |
def show_article(url):
|
| 1170 |
if not url or url=="#" or len(url)<10:
|
| 1171 |
return gr.update(visible=True),gr.update(visible=False),gr.update(visible=False),""
|
| 1172 |
return (gr.update(visible=False),gr.update(value=read_article(url),visible=True),gr.update(visible=True),"")
|
| 1173 |
-
def
|
| 1174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1175 |
read_btn.click(fn=show_article,inputs=[article_url],outputs=[news_list,article_view,back_btn,article_url])
|
| 1176 |
-
|
| 1177 |
-
|
| 1178 |
-
cat.change(fn=show_list,inputs=[cat],outputs=[news_list,article_view,back_btn])
|
| 1179 |
timer=gr.Timer(value=REFRESH_SECONDS,active=True)
|
| 1180 |
-
timer.tick(fn=fetch_news_list,inputs=
|
| 1181 |
-
demo.load(fn=fetch_news_list,inputs=
|
| 1182 |
|
| 1183 |
if __name__=="__main__":
|
| 1184 |
demo.launch(ssr_mode=False)
|
|
|
|
| 746 |
.bdp-header h1{color:#fff;font-size:20px;margin:0;font-weight:800;text-shadow:0 2px 6px rgba(0,0,0,.4)}
|
| 747 |
.bdp-header p{color:rgba(255,255,255,.6);font-size:11px;margin:2px 0 0}
|
| 748 |
@media(min-width:768px){.bdp-header h1{font-size:26px}.bdp-header{padding:20px}}
|
| 749 |
+
#cat-input,#btn-switch-cat{display:none!important;height:0!important;overflow:hidden!important}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 750 |
.vslide-wrap{margin:8px;background:#1a1a1a;border-radius:12px;overflow:hidden;border:1px solid #2a2a2a}
|
| 751 |
.vslide-header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px 6px}
|
| 752 |
.vslide-label{color:#f0c040;font-size:15px;font-weight:700}
|
|
|
|
| 921 |
document.querySelectorAll('.cat-icon-btn').forEach(function(b){
|
| 922 |
b.classList.toggle('active',b.getAttribute('data-cat')===catKey);
|
| 923 |
});
|
| 924 |
+
/* Trigger server-side category switch via hidden textbox+button */
|
| 925 |
+
window._bdpSetCat(catKey);
|
| 926 |
};
|
| 927 |
|
| 928 |
+
window._bdpSetCat=function(catKey){
|
| 929 |
+
var el=document.getElementById('cat-input');
|
| 930 |
+
if(el){var ta=el.querySelector('textarea')||el.querySelector('input');if(ta){ta.value=catKey;ta.dispatchEvent(new Event('input',{bubbles:true}));}}
|
| 931 |
+
var btn=document.getElementById('btn-switch-cat');
|
| 932 |
+
if(btn){var b=btn.querySelector('button');if(b)b.click();else btn.click();}
|
| 933 |
+
window.scrollTo({top:0,behavior:'smooth'});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 934 |
};
|
| 935 |
|
| 936 |
function gc(a){try{return JSON.parse(localStorage.getItem('bdp_cmt_'+a))||[];}catch(e){return[];}}
|
|
|
|
| 963 |
document.querySelectorAll('.cat-icon-btn').forEach(function(b){
|
| 964 |
b.classList.toggle('active',b.getAttribute('data-hash')==='video');
|
| 965 |
});
|
| 966 |
+
/* Trigger server-side switch to Video category */
|
| 967 |
+
var el=document.getElementById('cat-input');
|
| 968 |
+
if(el){var ta=el.querySelector('textarea')||el.querySelector('input');if(ta){ta.value='\U0001f3ac Video T\u1ed5ng H\u1ee3p';ta.dispatchEvent(new Event('input',{bubbles:true}));}}
|
| 969 |
+
var btn=document.getElementById('btn-switch-cat');
|
| 970 |
+
if(btn){var b=btn.querySelector('button');if(b)b.click();else btn.click();}
|
| 971 |
/* After content loads, scroll to the matching video in TikTok feed */
|
| 972 |
var attempts=0;
|
| 973 |
var finder=setInterval(function(){
|
|
|
|
| 1110 |
var catMap={""" + ",".join(f"'{ci[2]}':'{esc(CAT_KEYS[i])}'" for i,ci in enumerate(CAT_ICONS)) + """};
|
| 1111 |
if(catMap[catSlug]){
|
| 1112 |
setTimeout(function(){
|
| 1113 |
+
window._bdpSetCat(catMap[catSlug]);
|
| 1114 |
document.querySelectorAll('.cat-icon-btn').forEach(function(b){
|
| 1115 |
b.classList.toggle('active',b.getAttribute('data-hash')===catSlug);
|
| 1116 |
});
|
|
|
|
| 1135 |
gr.HTML('<div class="bdp-header"><h1>📰 Tin Tức Việt Nam</h1><p>VnExpress · BongDaPlus · 24h · Thời sự · Thế giới · Kinh doanh · Công nghệ · Thể thao · Giải trí · Video</p></div>')
|
| 1136 |
gr.HTML(_build_cat_grid_html())
|
| 1137 |
article_url=gr.Textbox(value="",visible=False,elem_id="article-url-input")
|
| 1138 |
+
cat_input=gr.Textbox(value="",visible=False,elem_id="cat-input")
|
|
|
|
|
|
|
| 1139 |
back_btn=gr.Button("← Quay lại",variant="secondary",visible=False)
|
| 1140 |
news_list=gr.HTML()
|
| 1141 |
article_view=gr.HTML(visible=False)
|
| 1142 |
read_btn=gr.Button("Đọc",visible=False,elem_id="btn-read-article")
|
| 1143 |
+
cat_btn=gr.Button("Cat",visible=False,elem_id="btn-switch-cat")
|
| 1144 |
def show_article(url):
|
| 1145 |
if not url or url=="#" or len(url)<10:
|
| 1146 |
return gr.update(visible=True),gr.update(visible=False),gr.update(visible=False),""
|
| 1147 |
return (gr.update(visible=False),gr.update(value=read_article(url),visible=True),gr.update(visible=True),"")
|
| 1148 |
+
def switch_cat(cat_key):
|
| 1149 |
+
cat_key=cat_key.strip()
|
| 1150 |
+
if not cat_key or cat_key not in CATEGORIES:
|
| 1151 |
+
cat_key=list(CATEGORIES.keys())[0]
|
| 1152 |
+
return (gr.update(value=fetch_news_list(cat_key),visible=True),gr.update(visible=False),gr.update(visible=False),"")
|
| 1153 |
+
def show_list_home():
|
| 1154 |
+
return (gr.update(value=fetch_news_list(list(CATEGORIES.keys())[0]),visible=True),gr.update(visible=False),gr.update(visible=False))
|
| 1155 |
read_btn.click(fn=show_article,inputs=[article_url],outputs=[news_list,article_view,back_btn,article_url])
|
| 1156 |
+
cat_btn.click(fn=switch_cat,inputs=[cat_input],outputs=[news_list,article_view,back_btn,cat_input])
|
| 1157 |
+
back_btn.click(fn=show_list_home,inputs=[],outputs=[news_list,article_view,back_btn])
|
|
|
|
| 1158 |
timer=gr.Timer(value=REFRESH_SECONDS,active=True)
|
| 1159 |
+
timer.tick(fn=lambda: fetch_news_list(list(CATEGORIES.keys())[0]),inputs=None,outputs=news_list)
|
| 1160 |
+
demo.load(fn=lambda: fetch_news_list(list(CATEGORIES.keys())[0]),inputs=None,outputs=news_list)
|
| 1161 |
|
| 1162 |
if __name__=="__main__":
|
| 1163 |
demo.launch(ssr_mode=False)
|