discovery-media-player 0.1.29 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server/handler.js +50 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "discovery-media-player",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "Self-hosted document viewer: per-recipient tracked links, reading analytics, live presentation. The core knows nothing about the application hosting it — everything it borrows arrives through an injected context.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pdf-viewer",
|
package/server/handler.js
CHANGED
|
@@ -241,7 +241,8 @@ var Live=(function(){
|
|
|
241
241
|
function toggleMute(){ MUTED=!MUTED; try{ localStorage.setItem('3dd-present-mute',MUTED?'1':'0'); }catch(e){} if(MUTED)hidePeek(); applyMute(); }
|
|
242
242
|
// Flèche « envoyer » : visible seulement si le champ contient du texte et qu'on peut poster.
|
|
243
243
|
function toggleSend(){ var s=document.getElementById('chatSend'),t=document.getElementById('chatText'); if(!s||!t)return; var can=!(LOCKED&&!canMod()); s.classList.toggle('on', can && (t.value||'').trim().length>0); }
|
|
244
|
-
|
|
244
|
+
// Un SIGNAL, plus une position : la charge utile était crue par l'audience sur un canal public.
|
|
245
|
+
function sendMap(){try{if(ch)ch.send({type:'broadcast',event:'map',payload:{}});}catch(e){}}
|
|
245
246
|
function onMap(fn){_onMap=fn;}
|
|
246
247
|
// État de la présentation diffusé par le présentateur — même canal que la carte. Sert à se
|
|
247
248
|
// passer de la lecture anonyme des tables : l'audience n'a plus besoin de lire la ligne.
|
|
@@ -476,6 +477,10 @@ var Live=(function(){
|
|
|
476
477
|
},{minMs:400});
|
|
477
478
|
}
|
|
478
479
|
var _ordEtat=relireAvec('&state=1',function(d){if(d.state)etatDuServeur(d.state);});
|
|
480
|
+
// ⚠️ Exposé hors de cette fermeture : la carte vit dans un AUTRE bloc de script et doit
|
|
481
|
+
// pouvoir déclencher la relecture. Même raison que window.__presAppliquerEtat — un nom
|
|
482
|
+
// référencé depuis la mauvaise portée part dans un catch muet, et l'audience se fige.
|
|
483
|
+
window.__presRelireEtat=function(){_ordEtat.signaler();};
|
|
479
484
|
function relireEtat(){_ordEtat.signaler();}
|
|
480
485
|
function relireChat(){_ordChat.signaler();}
|
|
481
486
|
var _ordChat=relireAvec('&chat=1',function(d){
|
|
@@ -517,7 +522,10 @@ var Live=(function(){
|
|
|
517
522
|
ch.on('broadcast',{event:'lock'},function(){relireChat();});
|
|
518
523
|
ch.on('broadcast',{event:'state'},function(){relireEtat();});
|
|
519
524
|
ch.on('broadcast',{event:'typing'},function(p){onTyping(p&&p.payload);});
|
|
520
|
-
|
|
525
|
+
// ⚠️ AUCUNE CHARGE NE PASSE. Elle est ignorée plus loin, mais s'arrêter là serait une défense
|
|
526
|
+
// par accident : le jour où quelqu'un rebranche un paramètre, la charge d'un canal public
|
|
527
|
+
// redeviendrait crue sans que rien ne le signale. On coupe le chemin, pas seulement l'usage.
|
|
528
|
+
ch.on('broadcast',{event:'map'},function(){if(_onMap)_onMap();});
|
|
521
529
|
ch.subscribe(function(st){if(st==='SUBSCRIBED'){ch.track({name:me.name,email:me.email,avatar:me.avatar,role:me.role,member:!!me.member,uid:attKey(me)});sendAttend();}});
|
|
522
530
|
_tyIv=setInterval(renderTyping,1500);
|
|
523
531
|
_atIv=setInterval(sendAttend,25000);
|
|
@@ -592,8 +600,34 @@ var Map3DD=(function(){
|
|
|
592
600
|
function state(){ if(!map)return null; if(useG){ var c=map.getCenter(); return {kind:'map',center:[c.lat(),c.lng()],zoom:map.getZoom(),marker:marker?[marker.getPosition().lat(),marker.getPosition().lng()]:null,mapType:map.getMapTypeId()}; }
|
|
593
601
|
var c2=map.getCenter(); return {kind:'map',center:[c2.lat,c2.lng],zoom:map.getZoom(),marker:marker?[marker.getLatLng().lat,marker.getLatLng().lng]:null}; }
|
|
594
602
|
function setCenterZoom(ll,z){ if(useG){ map.setCenter({lat:ll[0],lng:ll[1]}); map.setZoom(z); } else { map.setView(ll,z); } }
|
|
595
|
-
|
|
596
|
-
|
|
603
|
+
// ⚠️ LA POSITION NE VOYAGE PLUS DANS LA DIFFUSION.
|
|
604
|
+
//
|
|
605
|
+
// Elle y voyageait, et l'audience l'appliquait telle quelle. Le canal étant public, n'importe quel
|
|
606
|
+
// participant déplaçait donc la carte de tout le monde, avec les coordonnées de son choix. C'était
|
|
607
|
+
// assumé en 0.1.19 au motif que le signal est « éphémère et sans vérité serveur » — l'argument ne
|
|
608
|
+
// tient pas : PENDANT UN MODE CARTE, CE SIGNAL EST L'IMAGE QUE VOIT L'AUDIENCE. 'typing' peut
|
|
609
|
+
// rester cosmétique, 'map' non. (audit P0-1)
|
|
610
|
+
//
|
|
611
|
+
// Le présentateur persiste sa position (route gatée par JWT), puis émet un signal VIDE. L'audience
|
|
612
|
+
// relit l'état et applique ce que le serveur lui donne. Un participant hostile peut toujours
|
|
613
|
+
// émettre le signal : il provoque une relecture, et n'obtient rien.
|
|
614
|
+
//
|
|
615
|
+
// ⚠️ ORDONNANCEUR ET NON DEBOUNCE, et c'est le cœur du problème. schedPersist repoussait
|
|
616
|
+
// l'écriture de 700 ms à chaque mouvement : pendant un déplacement CONTINU, elle ne partait
|
|
617
|
+
// jamais. C'est précisément pour ça que la position voyageait dans la diffusion. Un ordonnanceur
|
|
618
|
+
// écrit au plus une fois par 500 ms ET sert toujours la dernière position — donc l'audience suit
|
|
619
|
+
// pendant le mouvement, pas seulement à l'arrêt.
|
|
620
|
+
//
|
|
621
|
+
// Le suivi devient PAR PALIERS au lieu d'être continu (environ deux fois par seconde). C'est le
|
|
622
|
+
// prix pour que personne d'autre que le présentateur ne pilote l'écran de l'audience.
|
|
623
|
+
var _ordPersist=null;
|
|
624
|
+
function persistOrd(){ if(!_ordPersist&&window.Player&&Player.live&&Player.live.createScheduler){
|
|
625
|
+
_ordPersist=Player.live.createScheduler(function(fini){ try{ if(map&&persist)persist(state()); }catch(e){} fini(); },{minMs:500}); }
|
|
626
|
+
return _ordPersist; }
|
|
627
|
+
function broadcast(){ if(!map)return; var n=Date.now(); if(n-_bcT<200)return; _bcT=n;
|
|
628
|
+
var o=persistOrd(); if(o)o.signaler();
|
|
629
|
+
try{ if(window.Live) Live.sendMap(); }catch(e){} }
|
|
630
|
+
function schedPersist(){ var o=persistOrd(); if(o)o.signaler(); else { clearTimeout(_psT); _psT=setTimeout(function(){ if(map&&persist)persist(state()); },700); } }
|
|
597
631
|
function enter(content,presenter,persistFn){ isPres=!!presenter; if(persistFn)persist=persistFn;
|
|
598
632
|
if(content&&content.mapType)mapType=content.mapType;
|
|
599
633
|
var wrap=document.getElementById('mapWrap'); var on=wrap&&wrap.classList.contains('on');
|
|
@@ -632,7 +666,14 @@ var Map3DD=(function(){
|
|
|
632
666
|
function goSV(center){ if(!GMAPS_KEY){tempHint('Street View indisponible.');return;} tempHint('Recherche Street View…');
|
|
633
667
|
loadGoogle(function(){ try{ new google.maps.StreetViewService().getPanorama({location:{lat:center[0],lng:center[1]},radius:80},function(data,status){ if(status==='OK'&&data&&data.location){ var ll=data.location.latLng; var content={kind:'streetview',position:[ll.lat(),ll.lng()],pov:{heading:0,pitch:0},zoom:1}; if(persist)persist(content); enterSV(content,true,persist); } else { tempHint('Pas de Street View à cet endroit.'); } }); }catch(e){ tempHint('Street View indisponible.'); } }); }
|
|
634
668
|
function svState(){ if(!pano)return null; var p=pano.getPosition(),v=pano.getPov(); if(!p)return null; return {kind:'streetview',position:[p.lat(),p.lng()],pov:{heading:v.heading,pitch:v.pitch},zoom:pano.getZoom()}; }
|
|
635
|
-
|
|
669
|
+
// Même règle qu'au-dessus : on persiste, on signale, on ne transporte pas la position.
|
|
670
|
+
var _ordSv=null;
|
|
671
|
+
function svOrd(){ if(!_ordSv&&window.Player&&Player.live&&Player.live.createScheduler){
|
|
672
|
+
_ordSv=Player.live.createScheduler(function(fini){ try{ if(persist&&pano)persist(svState()); }catch(e){} fini(); },{minMs:500}); }
|
|
673
|
+
return _ordSv; }
|
|
674
|
+
function svBcast(){ var n=Date.now(); if(n-_svBcT<200)return; _svBcT=n; if(!svState())return;
|
|
675
|
+
var o=svOrd(); if(o)o.signaler();
|
|
676
|
+
try{ if(window.Live)Live.sendMap(); }catch(e){} }
|
|
636
677
|
function svApply(p){ if(!pano||!p)return; try{ if(p.position)pano.setPosition({lat:p.position[0],lng:p.position[1]}); if(p.pov)pano.setPov({heading:p.pov.heading||0,pitch:p.pov.pitch||0}); if(typeof p.zoom!=='undefined')pano.setZoom(p.zoom); }catch(e){} }
|
|
637
678
|
function ensurePano(content){ var el=document.getElementById('svPano'); if(!el||!window.google||!window.google.maps)return;
|
|
638
679
|
var pos=content&&content.position?{lat:content.position[0],lng:content.position[1]}:{lat:48.8584,lng:2.2945};
|
|
@@ -2374,7 +2415,10 @@ function presentHtml(pres, nonce, logoUrl, supaUrl, supaKey) {
|
|
|
2374
2415
|
(function(){
|
|
2375
2416
|
var slug=${JSON.stringify(pres.slug)};
|
|
2376
2417
|
// Carte live : suivre en direct les mouvements du présentateur (broadcast).
|
|
2377
|
-
|
|
2418
|
+
// ⚠️ ON NE CROIT PLUS LA CHARGE. Le signal dit « quelque chose a bougé » ; ce qui a bougé vient
|
|
2419
|
+
// de la relecture d'état, gatée par l'écriture du présentateur. Un participant hostile peut
|
|
2420
|
+
// émettre : il déclenche une relecture bornée, et n'obtient rien.
|
|
2421
|
+
try{ if(window.Live&&window.Map3DD) Live.onMap(function(){ if(window.__presRelireEtat)window.__presRelireEtat(); }); }catch(e){}
|
|
2378
2422
|
// L'état arrive maintenant par DEUX voies : la table (historique) et la diffusion du
|
|
2379
2423
|
// présentateur (nouvelle). Les deux passent par le même filtre, qui ignore un état déjà
|
|
2380
2424
|
// appliqué — recevoir deux fois la même chose ne doit pas re-rendre la page.
|