bep40 commited on
Commit
f013786
·
verified ·
1 Parent(s): 0ac0a87

feat: unique vid per TikTok slide, share+hash per video, fix multi-part match all parts in feed

Browse files
Files changed (1) hide show
  1. app.py +45 -5
app.py CHANGED
@@ -587,16 +587,17 @@ def render_video_page_html():
587
  src_label = "24h" if v.get("source")=="24h" else "BDP"
588
  badge_cls = "bdp-badge-24h" if v.get("source")=="24h" else "bdp-badge-bdp"
589
  aid = make_id(v.get("link",""))
 
590
  sl = slug(v.get("title",""))
591
  open_js = f"event.stopPropagation();window.bdpOpen('{esc(v.get('link',''))}','{aid}','{sl}')"
592
- share_js = f"event.stopPropagation();window.bdpShareHash('{title_esc}','{sl}','{aid}')"
593
 
594
  if vtype == "hls":
595
  video_tag = f'<video class="tiktok-video" playsinline preload="metadata"{poster_attr} data-hls-src="{vsrc}" muted loop></video>'
596
  else:
597
  video_tag = f'<video class="tiktok-video" playsinline preload="metadata"{poster_attr} muted loop><source src="{safe_url(vsrc)}" type="video/mp4"></video>'
598
 
599
- slides.append(f'''<div class="tiktok-slide" data-index="{vi}" data-aid="{aid}">
600
  {video_tag}
601
  <div class="tiktok-pause-icon">▶</div>
602
  <div class="tiktok-seek-controls">
@@ -608,7 +609,7 @@ def render_video_page_html():
608
  <p class="tiktok-title">{v.get("title","")}</p>
609
  <div class="tiktok-actions">
610
  <button class="tiktok-action-btn" onclick="{open_js}">📰 Đọc</button>
611
- <button class="tiktok-action-btn" onclick="{share_js}">📤</button>
612
  </div>
613
  </div>
614
  <div class="tiktok-unmute-hint" onclick="window.bdpTikTokUnmute(this)">🔇 Nhấn để bật tiếng</div>
@@ -907,6 +908,17 @@ window.bdpShareHash=async function(title,sl,aid){
907
  document.body.removeChild(ta);
908
  };
909
 
 
 
 
 
 
 
 
 
 
 
 
910
  window.bdpToast=function(m){var e=document.getElementById('bdp-toast');if(!e){e=document.createElement('div');e.id='bdp-toast';e.className='bdp-toast';document.body.appendChild(e);}e.innerText=m;e.classList.add('show');setTimeout(function(){e.classList.remove('show');},2200);};
911
 
912
  window.bdpSlideScroll=function(dir,trackId){
@@ -978,7 +990,7 @@ window.bdpOpenTikTok=function(url,aid){
978
  var slides=feed.querySelectorAll('.tiktok-slide');
979
  var targetIdx=-1;
980
  slides.forEach(function(sl,i){
981
- if(sl.getAttribute('data-aid')===aid) targetIdx=i;
982
  });
983
  if(targetIdx>=0 && slides[targetIdx]){
984
  slides[targetIdx].scrollIntoView({behavior:'smooth'});
@@ -1104,7 +1116,35 @@ setInterval(function(){
1104
  },1500);
1105
 
1106
  var hh=window.location.hash;
1107
- if(hh&&hh.startsWith('#cat/')){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1108
  /* Category hash: #cat/video, #cat/thoi-su, etc. */
1109
  var catSlug=hh.slice(5);
1110
  var catMap={""" + ",".join(f"'{ci[2]}':'{esc(CAT_KEYS[i])}'" for i,ci in enumerate(CAT_ICONS)) + """};
 
587
  src_label = "24h" if v.get("source")=="24h" else "BDP"
588
  badge_cls = "bdp-badge-24h" if v.get("source")=="24h" else "bdp-badge-bdp"
589
  aid = make_id(v.get("link",""))
590
+ vid = make_id(vsrc)
591
  sl = slug(v.get("title",""))
592
  open_js = f"event.stopPropagation();window.bdpOpen('{esc(v.get('link',''))}','{aid}','{sl}')"
593
+ share_js = f"event.stopPropagation();window.bdpShareTikTok('{title_esc}','{sl}','{vid}')"
594
 
595
  if vtype == "hls":
596
  video_tag = f'<video class="tiktok-video" playsinline preload="metadata"{poster_attr} data-hls-src="{vsrc}" muted loop></video>'
597
  else:
598
  video_tag = f'<video class="tiktok-video" playsinline preload="metadata"{poster_attr} muted loop><source src="{safe_url(vsrc)}" type="video/mp4"></video>'
599
 
600
+ slides.append(f'''<div class="tiktok-slide" data-index="{vi}" data-aid="{aid}" data-vid="{vid}">
601
  {video_tag}
602
  <div class="tiktok-pause-icon">▶</div>
603
  <div class="tiktok-seek-controls">
 
609
  <p class="tiktok-title">{v.get("title","")}</p>
610
  <div class="tiktok-actions">
611
  <button class="tiktok-action-btn" onclick="{open_js}">📰 Đọc</button>
612
+ <button class="tiktok-action-btn" onclick="{share_js}">📤 Chia sẻ</button>
613
  </div>
614
  </div>
615
  <div class="tiktok-unmute-hint" onclick="window.bdpTikTokUnmute(this)">🔇 Nhấn để bật tiếng</div>
 
908
  document.body.removeChild(ta);
909
  };
910
 
911
+ window.bdpShareTikTok=async function(title,sl,vid){
912
+ var hashUrl=SPACE_BASE+'/#/v/'+sl+'/'+vid;
913
+ var sd={title:title,url:hashUrl,text:title};
914
+ if(navigator.share){try{await navigator.share(sd);return;}catch(e){if(e.name==='AbortError')return;}}
915
+ if(navigator.clipboard&&navigator.clipboard.writeText){try{await navigator.clipboard.writeText(hashUrl);window.bdpToast('Đã sao chép liên kết!');return;}catch(e){}}
916
+ var ta=document.createElement('textarea');ta.value=hashUrl;ta.style.cssText='position:fixed;opacity:0';
917
+ document.body.appendChild(ta);ta.focus();ta.select();
918
+ try{document.execCommand('copy');window.bdpToast('Đã sao chép liên kết!');}catch(e){window.prompt('Sao chép:',hashUrl);}
919
+ document.body.removeChild(ta);
920
+ };
921
+
922
  window.bdpToast=function(m){var e=document.getElementById('bdp-toast');if(!e){e=document.createElement('div');e.id='bdp-toast';e.className='bdp-toast';document.body.appendChild(e);}e.innerText=m;e.classList.add('show');setTimeout(function(){e.classList.remove('show');},2200);};
923
 
924
  window.bdpSlideScroll=function(dir,trackId){
 
990
  var slides=feed.querySelectorAll('.tiktok-slide');
991
  var targetIdx=-1;
992
  slides.forEach(function(sl,i){
993
+ if(targetIdx<0 && sl.getAttribute('data-aid')===aid) targetIdx=i;
994
  });
995
  if(targetIdx>=0 && slides[targetIdx]){
996
  slides[targetIdx].scrollIntoView({behavior:'smooth'});
 
1116
  },1500);
1117
 
1118
  var hh=window.location.hash;
1119
+ if(hh&&hh.startsWith('#/v/')){
1120
+ /* TikTok video hash: #/v/slug/vid - switch to video page then scroll to vid */
1121
+ var vps=hh.slice(4).split('/');
1122
+ var vid=vps[vps.length-1];
1123
+ setTimeout(function(){
1124
+ /* Switch to Video category */
1125
+ window._bdpSetCat('\U0001f3ac Video T\u1ed5ng H\u1ee3p');
1126
+ document.querySelectorAll('.cat-icon-btn').forEach(function(b){
1127
+ b.classList.toggle('active',b.getAttribute('data-hash')==='video');
1128
+ });
1129
+ /* Poll for TikTok feed to appear then scroll to matching vid */
1130
+ var att=0;
1131
+ var ff=setInterval(function(){
1132
+ att++;
1133
+ var feed=document.querySelector('.tiktok-fullscreen-feed');
1134
+ if(feed){
1135
+ clearInterval(ff);
1136
+ var slides=feed.querySelectorAll('.tiktok-slide');
1137
+ slides.forEach(function(sl,i){
1138
+ if(sl.getAttribute('data-vid')===vid){
1139
+ sl.scrollIntoView({behavior:'smooth'});
1140
+ }
1141
+ });
1142
+ window.scrollTo({top:0,behavior:'smooth'});
1143
+ }
1144
+ if(att>30) clearInterval(ff);
1145
+ },300);
1146
+ },1500);
1147
+ } else if(hh&&hh.startsWith('#cat/')){
1148
  /* Category hash: #cat/video, #cat/thoi-su, etc. */
1149
  var catSlug=hh.slice(5);
1150
  var catMap={""" + ",".join(f"'{ci[2]}':'{esc(CAT_KEYS[i])}'" for i,ci in enumerate(CAT_ICONS)) + """};