faradayfuture Claude Opus 5.5 commited on
Commit
fae2f7e
·
1 Parent(s): 20f08ad

egoSample viewers: use top-frame WeixinJSBridge for autoplay inside index iframe

Browse files

WeChat iOS injects WeixinJSBridge only into the top frame, so the iframe'd
viewers never got the bridge callback and stayed paused. Look it up on
parent/top, start via the bridge first in WeChat, ?wxdebug shows a log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

egoSample/ego-legacy/demo02/viewer.html CHANGED
@@ -287,15 +287,28 @@ window.addEventListener('load',update);update();
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
 
 
 
 
 
 
 
 
 
 
 
 
290
  function autoStart(force){
291
  if(started||playing)return;
292
  var vs=vlist();
293
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
294
  started=true; if(iv){clearInterval(iv);iv=null;}
295
  vs.forEach(function(v){v.muted=true;});
296
- Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
 
297
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
298
- }).catch(function(){
299
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
300
  started=false; arm();
301
  });
@@ -311,9 +324,9 @@ window.addEventListener('load',update);update();
311
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
312
  armed=false; autoStart(true); }
313
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
314
- if(window.WeixinJSBridge&&WeixinJSBridge.invoke) WeixinJSBridge.invoke('getNetworkType',{},function(){autoStart(true);});
315
  }
316
- document.addEventListener('WeixinJSBridgeReady',function(){autoStart(true);},false);
317
  window.addEventListener('load',function(){autoStart();});
318
  iv=setInterval(autoStart,400);
319
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
 
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
290
+ /* WeChat injects WeixinJSBridge into the top frame only (this page usually runs in
291
+ index.html's iframe): look on parent/top too; ?wxdebug on the top URL shows a log */
292
+ var inWx=/MicroMessenger/i.test(navigator.userAgent), dbgEl=null;
293
+ function frames(){var ws=[];try{ws.push(window.top);}catch(e){}try{ws.push(window.parent);}catch(e){}ws.push(window);return ws;}
294
+ function dbg(m){try{if(!/wxdebug/.test(window.top.location.search+window.location.search))return;}catch(e){return;}
295
+ if(!dbgEl){dbgEl=document.createElement('pre');dbgEl.style.cssText='position:fixed;left:0;bottom:0;z-index:99999;max-height:40vh;overflow:auto;margin:0;padding:4px 6px;font:10px/1.3 monospace;background:rgba(0,0,0,.8);color:#7f7;pointer-events:none;white-space:pre-wrap';document.body.appendChild(dbgEl);}
296
+ dbgEl.textContent+=(performance.now()/1000).toFixed(2)+' '+m+'\n';}
297
+ function bridge(){var ws=frames();for(var i=0;i<ws.length;i++){try{if(ws[i].WeixinJSBridge&&ws[i].WeixinJSBridge.invoke)return ws[i].WeixinJSBridge;}catch(e){}}return null;}
298
+ function wxCall(cb){var b=bridge();dbg('bridge '+(b?'yes':'no')+' top='+(window.top===window));
299
+ if(b){b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});return;}
300
+ function on(){var b=bridge();dbg('bridge ready '+(b?'yes':'no'));if(b)b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});}
301
+ frames().forEach(function(w){try{w.document.addEventListener('WeixinJSBridgeReady',on,{once:true});}catch(e){}});}
302
  function autoStart(force){
303
  if(started||playing)return;
304
  var vs=vlist();
305
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
306
  started=true; if(iv){clearInterval(iv);iv=null;}
307
  vs.forEach(function(v){v.muted=true;});
308
+ dbg('play() rs='+vs.map(function(v){return v.readyState;}).join(','));
309
+ Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){ dbg('play ok');
310
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
311
+ }).catch(function(err){ dbg('play rejected '+(err&&err.name));
312
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
313
  started=false; arm();
314
  });
 
324
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
325
  armed=false; autoStart(true); }
326
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
327
+ wxCall(function(){autoStart(true);});
328
  }
329
+ if(inWx) wxCall(function(){autoStart(true);});
330
  window.addEventListener('load',function(){autoStart();});
331
  iv=setInterval(autoStart,400);
332
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
egoSample/ego-legacy/demo05/viewer.html CHANGED
@@ -287,15 +287,28 @@ window.addEventListener('load',update);update();
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
 
 
 
 
 
 
 
 
 
 
 
 
290
  function autoStart(force){
291
  if(started||playing)return;
292
  var vs=vlist();
293
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
294
  started=true; if(iv){clearInterval(iv);iv=null;}
295
  vs.forEach(function(v){v.muted=true;});
296
- Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
 
297
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
298
- }).catch(function(){
299
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
300
  started=false; arm();
301
  });
@@ -311,9 +324,9 @@ window.addEventListener('load',update);update();
311
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
312
  armed=false; autoStart(true); }
313
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
314
- if(window.WeixinJSBridge&&WeixinJSBridge.invoke) WeixinJSBridge.invoke('getNetworkType',{},function(){autoStart(true);});
315
  }
316
- document.addEventListener('WeixinJSBridgeReady',function(){autoStart(true);},false);
317
  window.addEventListener('load',function(){autoStart();});
318
  iv=setInterval(autoStart,400);
319
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
 
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
290
+ /* WeChat injects WeixinJSBridge into the top frame only (this page usually runs in
291
+ index.html's iframe): look on parent/top too; ?wxdebug on the top URL shows a log */
292
+ var inWx=/MicroMessenger/i.test(navigator.userAgent), dbgEl=null;
293
+ function frames(){var ws=[];try{ws.push(window.top);}catch(e){}try{ws.push(window.parent);}catch(e){}ws.push(window);return ws;}
294
+ function dbg(m){try{if(!/wxdebug/.test(window.top.location.search+window.location.search))return;}catch(e){return;}
295
+ if(!dbgEl){dbgEl=document.createElement('pre');dbgEl.style.cssText='position:fixed;left:0;bottom:0;z-index:99999;max-height:40vh;overflow:auto;margin:0;padding:4px 6px;font:10px/1.3 monospace;background:rgba(0,0,0,.8);color:#7f7;pointer-events:none;white-space:pre-wrap';document.body.appendChild(dbgEl);}
296
+ dbgEl.textContent+=(performance.now()/1000).toFixed(2)+' '+m+'\n';}
297
+ function bridge(){var ws=frames();for(var i=0;i<ws.length;i++){try{if(ws[i].WeixinJSBridge&&ws[i].WeixinJSBridge.invoke)return ws[i].WeixinJSBridge;}catch(e){}}return null;}
298
+ function wxCall(cb){var b=bridge();dbg('bridge '+(b?'yes':'no')+' top='+(window.top===window));
299
+ if(b){b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});return;}
300
+ function on(){var b=bridge();dbg('bridge ready '+(b?'yes':'no'));if(b)b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});}
301
+ frames().forEach(function(w){try{w.document.addEventListener('WeixinJSBridgeReady',on,{once:true});}catch(e){}});}
302
  function autoStart(force){
303
  if(started||playing)return;
304
  var vs=vlist();
305
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
306
  started=true; if(iv){clearInterval(iv);iv=null;}
307
  vs.forEach(function(v){v.muted=true;});
308
+ dbg('play() rs='+vs.map(function(v){return v.readyState;}).join(','));
309
+ Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){ dbg('play ok');
310
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
311
+ }).catch(function(err){ dbg('play rejected '+(err&&err.name));
312
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
313
  started=false; arm();
314
  });
 
324
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
325
  armed=false; autoStart(true); }
326
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
327
+ wxCall(function(){autoStart(true);});
328
  }
329
+ if(inWx) wxCall(function(){autoStart(true);});
330
  window.addEventListener('load',function(){autoStart();});
331
  iv=setInterval(autoStart,400);
332
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
egoSample/ego-legacy/demo07/viewer.html CHANGED
@@ -287,15 +287,28 @@ window.addEventListener('load',update);update();
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
 
 
 
 
 
 
 
 
 
 
 
 
290
  function autoStart(force){
291
  if(started||playing)return;
292
  var vs=vlist();
293
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
294
  started=true; if(iv){clearInterval(iv);iv=null;}
295
  vs.forEach(function(v){v.muted=true;});
296
- Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
 
297
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
298
- }).catch(function(){
299
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
300
  started=false; arm();
301
  });
@@ -311,9 +324,9 @@ window.addEventListener('load',update);update();
311
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
312
  armed=false; autoStart(true); }
313
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
314
- if(window.WeixinJSBridge&&WeixinJSBridge.invoke) WeixinJSBridge.invoke('getNetworkType',{},function(){autoStart(true);});
315
  }
316
- document.addEventListener('WeixinJSBridgeReady',function(){autoStart(true);},false);
317
  window.addEventListener('load',function(){autoStart();});
318
  iv=setInterval(autoStart,400);
319
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
 
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
290
+ /* WeChat injects WeixinJSBridge into the top frame only (this page usually runs in
291
+ index.html's iframe): look on parent/top too; ?wxdebug on the top URL shows a log */
292
+ var inWx=/MicroMessenger/i.test(navigator.userAgent), dbgEl=null;
293
+ function frames(){var ws=[];try{ws.push(window.top);}catch(e){}try{ws.push(window.parent);}catch(e){}ws.push(window);return ws;}
294
+ function dbg(m){try{if(!/wxdebug/.test(window.top.location.search+window.location.search))return;}catch(e){return;}
295
+ if(!dbgEl){dbgEl=document.createElement('pre');dbgEl.style.cssText='position:fixed;left:0;bottom:0;z-index:99999;max-height:40vh;overflow:auto;margin:0;padding:4px 6px;font:10px/1.3 monospace;background:rgba(0,0,0,.8);color:#7f7;pointer-events:none;white-space:pre-wrap';document.body.appendChild(dbgEl);}
296
+ dbgEl.textContent+=(performance.now()/1000).toFixed(2)+' '+m+'\n';}
297
+ function bridge(){var ws=frames();for(var i=0;i<ws.length;i++){try{if(ws[i].WeixinJSBridge&&ws[i].WeixinJSBridge.invoke)return ws[i].WeixinJSBridge;}catch(e){}}return null;}
298
+ function wxCall(cb){var b=bridge();dbg('bridge '+(b?'yes':'no')+' top='+(window.top===window));
299
+ if(b){b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});return;}
300
+ function on(){var b=bridge();dbg('bridge ready '+(b?'yes':'no'));if(b)b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});}
301
+ frames().forEach(function(w){try{w.document.addEventListener('WeixinJSBridgeReady',on,{once:true});}catch(e){}});}
302
  function autoStart(force){
303
  if(started||playing)return;
304
  var vs=vlist();
305
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
306
  started=true; if(iv){clearInterval(iv);iv=null;}
307
  vs.forEach(function(v){v.muted=true;});
308
+ dbg('play() rs='+vs.map(function(v){return v.readyState;}).join(','));
309
+ Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){ dbg('play ok');
310
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
311
+ }).catch(function(err){ dbg('play rejected '+(err&&err.name));
312
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
313
  started=false; arm();
314
  });
 
324
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
325
  armed=false; autoStart(true); }
326
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
327
+ wxCall(function(){autoStart(true);});
328
  }
329
+ if(inWx) wxCall(function(){autoStart(true);});
330
  window.addEventListener('load',function(){autoStart();});
331
  iv=setInterval(autoStart,400);
332
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
egoSample/ego-legacy/demo08/viewer.html CHANGED
@@ -287,15 +287,28 @@ window.addEventListener('load',update);update();
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
 
 
 
 
 
 
 
 
 
 
 
 
290
  function autoStart(force){
291
  if(started||playing)return;
292
  var vs=vlist();
293
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
294
  started=true; if(iv){clearInterval(iv);iv=null;}
295
  vs.forEach(function(v){v.muted=true;});
296
- Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
 
297
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
298
- }).catch(function(){
299
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
300
  started=false; arm();
301
  });
@@ -311,9 +324,9 @@ window.addEventListener('load',update);update();
311
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
312
  armed=false; autoStart(true); }
313
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
314
- if(window.WeixinJSBridge&&WeixinJSBridge.invoke) WeixinJSBridge.invoke('getNetworkType',{},function(){autoStart(true);});
315
  }
316
- document.addEventListener('WeixinJSBridgeReady',function(){autoStart(true);},false);
317
  window.addEventListener('load',function(){autoStart();});
318
  iv=setInterval(autoStart,400);
319
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
 
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
290
+ /* WeChat injects WeixinJSBridge into the top frame only (this page usually runs in
291
+ index.html's iframe): look on parent/top too; ?wxdebug on the top URL shows a log */
292
+ var inWx=/MicroMessenger/i.test(navigator.userAgent), dbgEl=null;
293
+ function frames(){var ws=[];try{ws.push(window.top);}catch(e){}try{ws.push(window.parent);}catch(e){}ws.push(window);return ws;}
294
+ function dbg(m){try{if(!/wxdebug/.test(window.top.location.search+window.location.search))return;}catch(e){return;}
295
+ if(!dbgEl){dbgEl=document.createElement('pre');dbgEl.style.cssText='position:fixed;left:0;bottom:0;z-index:99999;max-height:40vh;overflow:auto;margin:0;padding:4px 6px;font:10px/1.3 monospace;background:rgba(0,0,0,.8);color:#7f7;pointer-events:none;white-space:pre-wrap';document.body.appendChild(dbgEl);}
296
+ dbgEl.textContent+=(performance.now()/1000).toFixed(2)+' '+m+'\n';}
297
+ function bridge(){var ws=frames();for(var i=0;i<ws.length;i++){try{if(ws[i].WeixinJSBridge&&ws[i].WeixinJSBridge.invoke)return ws[i].WeixinJSBridge;}catch(e){}}return null;}
298
+ function wxCall(cb){var b=bridge();dbg('bridge '+(b?'yes':'no')+' top='+(window.top===window));
299
+ if(b){b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});return;}
300
+ function on(){var b=bridge();dbg('bridge ready '+(b?'yes':'no'));if(b)b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});}
301
+ frames().forEach(function(w){try{w.document.addEventListener('WeixinJSBridgeReady',on,{once:true});}catch(e){}});}
302
  function autoStart(force){
303
  if(started||playing)return;
304
  var vs=vlist();
305
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
306
  started=true; if(iv){clearInterval(iv);iv=null;}
307
  vs.forEach(function(v){v.muted=true;});
308
+ dbg('play() rs='+vs.map(function(v){return v.readyState;}).join(','));
309
+ Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){ dbg('play ok');
310
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
311
+ }).catch(function(err){ dbg('play rejected '+(err&&err.name));
312
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
313
  started=false; arm();
314
  });
 
324
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
325
  armed=false; autoStart(true); }
326
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
327
+ wxCall(function(){autoStart(true);});
328
  }
329
+ if(inWx) wxCall(function(){autoStart(true);});
330
  window.addEventListener('load',function(){autoStart();});
331
  iv=setInterval(autoStart,400);
332
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
egoSample/ego-legacy/demo09/viewer.html CHANGED
@@ -287,15 +287,28 @@ window.addEventListener('load',update);update();
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
 
 
 
 
 
 
 
 
 
 
 
 
290
  function autoStart(force){
291
  if(started||playing)return;
292
  var vs=vlist();
293
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
294
  started=true; if(iv){clearInterval(iv);iv=null;}
295
  vs.forEach(function(v){v.muted=true;});
296
- Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
 
297
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
298
- }).catch(function(){
299
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
300
  started=false; arm();
301
  });
@@ -311,9 +324,9 @@ window.addEventListener('load',update);update();
311
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
312
  armed=false; autoStart(true); }
313
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
314
- if(window.WeixinJSBridge&&WeixinJSBridge.invoke) WeixinJSBridge.invoke('getNetworkType',{},function(){autoStart(true);});
315
  }
316
- document.addEventListener('WeixinJSBridgeReady',function(){autoStart(true);},false);
317
  window.addEventListener('load',function(){autoStart();});
318
  iv=setInterval(autoStart,400);
319
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
 
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
290
+ /* WeChat injects WeixinJSBridge into the top frame only (this page usually runs in
291
+ index.html's iframe): look on parent/top too; ?wxdebug on the top URL shows a log */
292
+ var inWx=/MicroMessenger/i.test(navigator.userAgent), dbgEl=null;
293
+ function frames(){var ws=[];try{ws.push(window.top);}catch(e){}try{ws.push(window.parent);}catch(e){}ws.push(window);return ws;}
294
+ function dbg(m){try{if(!/wxdebug/.test(window.top.location.search+window.location.search))return;}catch(e){return;}
295
+ if(!dbgEl){dbgEl=document.createElement('pre');dbgEl.style.cssText='position:fixed;left:0;bottom:0;z-index:99999;max-height:40vh;overflow:auto;margin:0;padding:4px 6px;font:10px/1.3 monospace;background:rgba(0,0,0,.8);color:#7f7;pointer-events:none;white-space:pre-wrap';document.body.appendChild(dbgEl);}
296
+ dbgEl.textContent+=(performance.now()/1000).toFixed(2)+' '+m+'\n';}
297
+ function bridge(){var ws=frames();for(var i=0;i<ws.length;i++){try{if(ws[i].WeixinJSBridge&&ws[i].WeixinJSBridge.invoke)return ws[i].WeixinJSBridge;}catch(e){}}return null;}
298
+ function wxCall(cb){var b=bridge();dbg('bridge '+(b?'yes':'no')+' top='+(window.top===window));
299
+ if(b){b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});return;}
300
+ function on(){var b=bridge();dbg('bridge ready '+(b?'yes':'no'));if(b)b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});}
301
+ frames().forEach(function(w){try{w.document.addEventListener('WeixinJSBridgeReady',on,{once:true});}catch(e){}});}
302
  function autoStart(force){
303
  if(started||playing)return;
304
  var vs=vlist();
305
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
306
  started=true; if(iv){clearInterval(iv);iv=null;}
307
  vs.forEach(function(v){v.muted=true;});
308
+ dbg('play() rs='+vs.map(function(v){return v.readyState;}).join(','));
309
+ Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){ dbg('play ok');
310
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
311
+ }).catch(function(err){ dbg('play rejected '+(err&&err.name));
312
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
313
  started=false; arm();
314
  });
 
324
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
325
  armed=false; autoStart(true); }
326
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
327
+ wxCall(function(){autoStart(true);});
328
  }
329
+ if(inWx) wxCall(function(){autoStart(true);});
330
  window.addEventListener('load',function(){autoStart();});
331
  iv=setInterval(autoStart,400);
332
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
egoSample/ego-legacy/demo10/viewer.html CHANGED
@@ -287,15 +287,28 @@ window.addEventListener('load',update);update();
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
 
 
 
 
 
 
 
 
 
 
 
 
290
  function autoStart(force){
291
  if(started||playing)return;
292
  var vs=vlist();
293
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
294
  started=true; if(iv){clearInterval(iv);iv=null;}
295
  vs.forEach(function(v){v.muted=true;});
296
- Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){
 
297
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
298
- }).catch(function(){
299
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
300
  started=false; arm();
301
  });
@@ -311,9 +324,9 @@ window.addEventListener('load',update);update();
311
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
312
  armed=false; autoStart(true); }
313
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
314
- if(window.WeixinJSBridge&&WeixinJSBridge.invoke) WeixinJSBridge.invoke('getNetworkType',{},function(){autoStart(true);});
315
  }
316
- document.addEventListener('WeixinJSBridgeReady',function(){autoStart(true);},false);
317
  window.addEventListener('load',function(){autoStart();});
318
  iv=setInterval(autoStart,400);
319
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
 
287
  var started=false, iv=null;
288
  function vlist(){try{return Object.values(videos);}catch(e){return [];}}
289
  var t0=Date.now(), armed=false;
290
+ /* WeChat injects WeixinJSBridge into the top frame only (this page usually runs in
291
+ index.html's iframe): look on parent/top too; ?wxdebug on the top URL shows a log */
292
+ var inWx=/MicroMessenger/i.test(navigator.userAgent), dbgEl=null;
293
+ function frames(){var ws=[];try{ws.push(window.top);}catch(e){}try{ws.push(window.parent);}catch(e){}ws.push(window);return ws;}
294
+ function dbg(m){try{if(!/wxdebug/.test(window.top.location.search+window.location.search))return;}catch(e){return;}
295
+ if(!dbgEl){dbgEl=document.createElement('pre');dbgEl.style.cssText='position:fixed;left:0;bottom:0;z-index:99999;max-height:40vh;overflow:auto;margin:0;padding:4px 6px;font:10px/1.3 monospace;background:rgba(0,0,0,.8);color:#7f7;pointer-events:none;white-space:pre-wrap';document.body.appendChild(dbgEl);}
296
+ dbgEl.textContent+=(performance.now()/1000).toFixed(2)+' '+m+'\n';}
297
+ function bridge(){var ws=frames();for(var i=0;i<ws.length;i++){try{if(ws[i].WeixinJSBridge&&ws[i].WeixinJSBridge.invoke)return ws[i].WeixinJSBridge;}catch(e){}}return null;}
298
+ function wxCall(cb){var b=bridge();dbg('bridge '+(b?'yes':'no')+' top='+(window.top===window));
299
+ if(b){b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});return;}
300
+ function on(){var b=bridge();dbg('bridge ready '+(b?'yes':'no'));if(b)b.invoke('getNetworkType',{},function(){dbg('bridge cb');cb();});}
301
+ frames().forEach(function(w){try{w.document.addEventListener('WeixinJSBridgeReady',on,{once:true});}catch(e){}});}
302
  function autoStart(force){
303
  if(started||playing)return;
304
  var vs=vlist();
305
  if(!vs.length||(!vs.every(function(v){return v.readyState>=2;})&&!(force||Date.now()-t0>1500&&vs.every(function(v){return v.readyState>=1||v.src;}))))return;
306
  started=true; if(iv){clearInterval(iv);iv=null;}
307
  vs.forEach(function(v){v.muted=true;});
308
+ dbg('play() rs='+vs.map(function(v){return v.readyState;}).join(','));
309
+ Promise.all(vs.map(function(v){return Promise.resolve(v.play());})).then(function(){ dbg('play ok');
310
  playing=true; playBtn.innerHTML='&#10073;&#10073;'; requestAnimationFrame(loop);
311
+ }).catch(function(err){ dbg('play rejected '+(err&&err.name));
312
  vs.forEach(function(v){try{v.pause();}catch(e){}}); playing=false; playBtn.innerHTML='&#9654;';
313
  started=false; arm();
314
  });
 
324
  document.removeEventListener('touchend',once,true); document.removeEventListener('click',once,true);
325
  armed=false; autoStart(true); }
326
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
327
+ wxCall(function(){autoStart(true);});
328
  }
329
+ if(inWx) wxCall(function(){autoStart(true);});
330
  window.addEventListener('load',function(){autoStart();});
331
  iv=setInterval(autoStart,400);
332
  setTimeout(function(){if(iv){clearInterval(iv);iv=null;}},90000);
egoSample/faberu.html CHANGED
@@ -93,11 +93,27 @@ const skc=s=>SKC[s]||'#666';
93
  /* autoplay for in-app WebViews (WeChat iOS/Android X5): they ignore preload, so
94
  canplay never fires until play() is called — don't wait on it forever. If play()
95
  is refused, roll back to paused and retry on WeixinJSBridgeReady / first tap. */
96
- let _autoArmed=false;
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  function _autoStart(){
98
  if(!master||!_toggle) return;
 
 
99
  if(!playing) _toggle();
100
- const m=master; Promise.resolve(m.play()).catch(()=>{ if(playing && master===m) _toggle(); _armRetry(); });
 
101
  }
102
  function _armRetry(){
103
  if(_autoArmed) return; _autoArmed=true;
@@ -106,9 +122,8 @@ function _armRetry(){
106
  _autoArmed=false; if(!playing) _autoStart(); };
107
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
108
  const wx=()=>{ if(!playing) _autoStart(); };
109
- if(window.WeixinJSBridge && WeixinJSBridge.invoke) WeixinJSBridge.invoke('getNetworkType',{},wx);
110
  }
111
- document.addEventListener('WeixinJSBridgeReady',()=>{ if(master && !playing) _autoStart(); },false);
112
  function _whenReady(go){
113
  if(master.readyState>=3){ go(); return; }
114
  let fired=false; const f=()=>{ if(fired) return; fired=true; go(); };
 
93
  /* autoplay for in-app WebViews (WeChat iOS/Android X5): they ignore preload, so
94
  canplay never fires until play() is called — don't wait on it forever. If play()
95
  is refused, roll back to paused and retry on WeixinJSBridgeReady / first tap. */
96
+ /* WeChat injects WeixinJSBridge into the top frame only, and these pages run inside
97
+ index.html's iframe — so look on parent/top too. play() issued from the bridge
98
+ callback is allowed without a tap. ?wxdebug on the top URL shows a log. */
99
+ const _inWx=/MicroMessenger/i.test(navigator.userAgent);
100
+ const _frames=()=>{ const ws=[]; try{ ws.push(window.top); }catch(e){} try{ ws.push(window.parent); }catch(e){} ws.push(window); return ws; };
101
+ let _dbgEl=null; const _dbg=(...a)=>{ try{ if(!/wxdebug/.test(window.top.location.search+window.location.search)) return; }catch(e){ return; }
102
+ if(!_dbgEl){ _dbgEl=document.createElement('pre'); _dbgEl.style.cssText='position:fixed;left:0;bottom:0;z-index:99999;max-height:40vh;overflow:auto;margin:0;padding:4px 6px;font:10px/1.3 monospace;background:rgba(0,0,0,.8);color:#7f7;pointer-events:none;white-space:pre-wrap'; document.body.appendChild(_dbgEl); }
103
+ _dbgEl.textContent+=((performance.now()/1000).toFixed(2)+' '+a.join(' ')+'\n'); };
104
+ function _wxBridge(){ for(const w of _frames()){ try{ if(w.WeixinJSBridge && w.WeixinJSBridge.invoke) return w.WeixinJSBridge; }catch(e){} } return null; }
105
+ function _wx(cb){ const b=_wxBridge(); _dbg('bridge', b?'yes':'no', 'top='+(window.top===window));
106
+ if(b){ b.invoke('getNetworkType',{},()=>{ _dbg('bridge cb'); cb(); }); return; }
107
+ const on=()=>{ const b=_wxBridge(); _dbg('bridge ready', b?'yes':'no'); if(b) b.invoke('getNetworkType',{},()=>{ _dbg('bridge cb'); cb(); }); };
108
+ _frames().forEach(w=>{ try{ w.document.addEventListener('WeixinJSBridgeReady',on,{once:true}); }catch(e){} }); }
109
+ let _autoArmed=false, _wxTried=false;
110
  function _autoStart(){
111
  if(!master||!_toggle) return;
112
+ if(_inWx && !_wxTried){ _wxTried=true; _wx(()=>{ if(!playing) _autoStart(); });
113
+ setTimeout(()=>{ if(!playing) _autoStart(); },1500); return; }
114
  if(!playing) _toggle();
115
+ const m=master; _dbg('play() rs='+m.readyState);
116
+ Promise.resolve(m.play()).then(()=>_dbg('play ok')).catch(err=>{ _dbg('play rejected', err&&err.name); if(playing && master===m) _toggle(); _armRetry(); });
117
  }
118
  function _armRetry(){
119
  if(_autoArmed) return; _autoArmed=true;
 
122
  _autoArmed=false; if(!playing) _autoStart(); };
123
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
124
  const wx=()=>{ if(!playing) _autoStart(); };
125
+ _wx(wx);
126
  }
 
127
  function _whenReady(go){
128
  if(master.readyState>=3){ go(); return; }
129
  let fired=false; const f=()=>{ if(fired) return; fired=true; go(); };
egoSample/jizhi.html CHANGED
@@ -101,11 +101,27 @@ let orbO={yaw:0.6,pitch:-0.45,drag:0};
101
  /* autoplay for in-app WebViews (WeChat iOS/Android X5): they ignore preload, so
102
  canplay never fires until play() is called — don't wait on it forever. If play()
103
  is refused, roll back to paused and retry on WeixinJSBridgeReady / first tap. */
104
- let _autoArmed=false;
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  function _autoStart(){
106
  if(!master||!_toggle) return;
 
 
107
  if(!playing) _toggle();
108
- const m=master; Promise.resolve(m.play()).catch(()=>{ if(playing && master===m) _toggle(); _armRetry(); });
 
109
  }
110
  function _armRetry(){
111
  if(_autoArmed) return; _autoArmed=true;
@@ -114,9 +130,8 @@ function _armRetry(){
114
  _autoArmed=false; if(!playing) _autoStart(); };
115
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
116
  const wx=()=>{ if(!playing) _autoStart(); };
117
- if(window.WeixinJSBridge && WeixinJSBridge.invoke) WeixinJSBridge.invoke('getNetworkType',{},wx);
118
  }
119
- document.addEventListener('WeixinJSBridgeReady',()=>{ if(master && !playing) _autoStart(); },false);
120
  function _whenReady(go){
121
  if(master.readyState>=3){ go(); return; }
122
  let fired=false; const f=()=>{ if(fired) return; fired=true; go(); };
 
101
  /* autoplay for in-app WebViews (WeChat iOS/Android X5): they ignore preload, so
102
  canplay never fires until play() is called — don't wait on it forever. If play()
103
  is refused, roll back to paused and retry on WeixinJSBridgeReady / first tap. */
104
+ /* WeChat injects WeixinJSBridge into the top frame only, and these pages run inside
105
+ index.html's iframe — so look on parent/top too. play() issued from the bridge
106
+ callback is allowed without a tap. ?wxdebug on the top URL shows a log. */
107
+ const _inWx=/MicroMessenger/i.test(navigator.userAgent);
108
+ const _frames=()=>{ const ws=[]; try{ ws.push(window.top); }catch(e){} try{ ws.push(window.parent); }catch(e){} ws.push(window); return ws; };
109
+ let _dbgEl=null; const _dbg=(...a)=>{ try{ if(!/wxdebug/.test(window.top.location.search+window.location.search)) return; }catch(e){ return; }
110
+ if(!_dbgEl){ _dbgEl=document.createElement('pre'); _dbgEl.style.cssText='position:fixed;left:0;bottom:0;z-index:99999;max-height:40vh;overflow:auto;margin:0;padding:4px 6px;font:10px/1.3 monospace;background:rgba(0,0,0,.8);color:#7f7;pointer-events:none;white-space:pre-wrap'; document.body.appendChild(_dbgEl); }
111
+ _dbgEl.textContent+=((performance.now()/1000).toFixed(2)+' '+a.join(' ')+'\n'); };
112
+ function _wxBridge(){ for(const w of _frames()){ try{ if(w.WeixinJSBridge && w.WeixinJSBridge.invoke) return w.WeixinJSBridge; }catch(e){} } return null; }
113
+ function _wx(cb){ const b=_wxBridge(); _dbg('bridge', b?'yes':'no', 'top='+(window.top===window));
114
+ if(b){ b.invoke('getNetworkType',{},()=>{ _dbg('bridge cb'); cb(); }); return; }
115
+ const on=()=>{ const b=_wxBridge(); _dbg('bridge ready', b?'yes':'no'); if(b) b.invoke('getNetworkType',{},()=>{ _dbg('bridge cb'); cb(); }); };
116
+ _frames().forEach(w=>{ try{ w.document.addEventListener('WeixinJSBridgeReady',on,{once:true}); }catch(e){} }); }
117
+ let _autoArmed=false, _wxTried=false;
118
  function _autoStart(){
119
  if(!master||!_toggle) return;
120
+ if(_inWx && !_wxTried){ _wxTried=true; _wx(()=>{ if(!playing) _autoStart(); });
121
+ setTimeout(()=>{ if(!playing) _autoStart(); },1500); return; }
122
  if(!playing) _toggle();
123
+ const m=master; _dbg('play() rs='+m.readyState);
124
+ Promise.resolve(m.play()).then(()=>_dbg('play ok')).catch(err=>{ _dbg('play rejected', err&&err.name); if(playing && master===m) _toggle(); _armRetry(); });
125
  }
126
  function _armRetry(){
127
  if(_autoArmed) return; _autoArmed=true;
 
130
  _autoArmed=false; if(!playing) _autoStart(); };
131
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
132
  const wx=()=>{ if(!playing) _autoStart(); };
133
+ _wx(wx);
134
  }
 
135
  function _whenReady(go){
136
  if(master.readyState>=3){ go(); return; }
137
  let fired=false; const f=()=>{ if(fired) return; fired=true; go(); };
egoSample/mego.html CHANGED
@@ -120,11 +120,27 @@ let orbH={yaw:0,pitch:-0.28,drag:0}, orbP={yaw:0,pitch:-0.28,drag:0};
120
  /* autoplay for in-app WebViews (WeChat iOS/Android X5): they ignore preload, so
121
  canplay never fires until play() is called — don't wait on it forever. If play()
122
  is refused, roll back to paused and retry on WeixinJSBridgeReady / first tap. */
123
- let _autoArmed=false;
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  function _autoStart(){
125
  if(!master||!_toggle) return;
 
 
126
  if(!playing) _toggle();
127
- const m=master; Promise.resolve(m.play()).catch(()=>{ if(playing && master===m) _toggle(); _armRetry(); });
 
128
  }
129
  function _armRetry(){
130
  if(_autoArmed) return; _autoArmed=true;
@@ -133,9 +149,8 @@ function _armRetry(){
133
  _autoArmed=false; if(!playing) _autoStart(); };
134
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
135
  const wx=()=>{ if(!playing) _autoStart(); };
136
- if(window.WeixinJSBridge && WeixinJSBridge.invoke) WeixinJSBridge.invoke('getNetworkType',{},wx);
137
  }
138
- document.addEventListener('WeixinJSBridgeReady',()=>{ if(master && !playing) _autoStart(); },false);
139
  function _whenReady(go){
140
  if(master.readyState>=3){ go(); return; }
141
  let fired=false; const f=()=>{ if(fired) return; fired=true; go(); };
 
120
  /* autoplay for in-app WebViews (WeChat iOS/Android X5): they ignore preload, so
121
  canplay never fires until play() is called — don't wait on it forever. If play()
122
  is refused, roll back to paused and retry on WeixinJSBridgeReady / first tap. */
123
+ /* WeChat injects WeixinJSBridge into the top frame only, and these pages run inside
124
+ index.html's iframe — so look on parent/top too. play() issued from the bridge
125
+ callback is allowed without a tap. ?wxdebug on the top URL shows a log. */
126
+ const _inWx=/MicroMessenger/i.test(navigator.userAgent);
127
+ const _frames=()=>{ const ws=[]; try{ ws.push(window.top); }catch(e){} try{ ws.push(window.parent); }catch(e){} ws.push(window); return ws; };
128
+ let _dbgEl=null; const _dbg=(...a)=>{ try{ if(!/wxdebug/.test(window.top.location.search+window.location.search)) return; }catch(e){ return; }
129
+ if(!_dbgEl){ _dbgEl=document.createElement('pre'); _dbgEl.style.cssText='position:fixed;left:0;bottom:0;z-index:99999;max-height:40vh;overflow:auto;margin:0;padding:4px 6px;font:10px/1.3 monospace;background:rgba(0,0,0,.8);color:#7f7;pointer-events:none;white-space:pre-wrap'; document.body.appendChild(_dbgEl); }
130
+ _dbgEl.textContent+=((performance.now()/1000).toFixed(2)+' '+a.join(' ')+'\n'); };
131
+ function _wxBridge(){ for(const w of _frames()){ try{ if(w.WeixinJSBridge && w.WeixinJSBridge.invoke) return w.WeixinJSBridge; }catch(e){} } return null; }
132
+ function _wx(cb){ const b=_wxBridge(); _dbg('bridge', b?'yes':'no', 'top='+(window.top===window));
133
+ if(b){ b.invoke('getNetworkType',{},()=>{ _dbg('bridge cb'); cb(); }); return; }
134
+ const on=()=>{ const b=_wxBridge(); _dbg('bridge ready', b?'yes':'no'); if(b) b.invoke('getNetworkType',{},()=>{ _dbg('bridge cb'); cb(); }); };
135
+ _frames().forEach(w=>{ try{ w.document.addEventListener('WeixinJSBridgeReady',on,{once:true}); }catch(e){} }); }
136
+ let _autoArmed=false, _wxTried=false;
137
  function _autoStart(){
138
  if(!master||!_toggle) return;
139
+ if(_inWx && !_wxTried){ _wxTried=true; _wx(()=>{ if(!playing) _autoStart(); });
140
+ setTimeout(()=>{ if(!playing) _autoStart(); },1500); return; }
141
  if(!playing) _toggle();
142
+ const m=master; _dbg('play() rs='+m.readyState);
143
+ Promise.resolve(m.play()).then(()=>_dbg('play ok')).catch(err=>{ _dbg('play rejected', err&&err.name); if(playing && master===m) _toggle(); _armRetry(); });
144
  }
145
  function _armRetry(){
146
  if(_autoArmed) return; _autoArmed=true;
 
149
  _autoArmed=false; if(!playing) _autoStart(); };
150
  document.addEventListener('touchend',once,true); document.addEventListener('click',once,true);
151
  const wx=()=>{ if(!playing) _autoStart(); };
152
+ _wx(wx);
153
  }
 
154
  function _whenReady(go){
155
  if(master.readyState>=3){ go(); return; }
156
  let fired=false; const f=()=>{ if(fired) return; fired=true; go(); };