discovery-media-player 0.1.52 → 0.1.54

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discovery-media-player",
3
- "version": "0.1.52",
3
+ "version": "0.1.54",
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
@@ -2389,13 +2389,30 @@ ${LEGAL_CSS}
2389
2389
  //
2390
2390
  // Le drapeau posé sur la fenêtre permet au banc d'EXIGER le refus, au lieu de constater une
2391
2391
  // absence de rendu qui aurait dix causes.
2392
+ // ⚠️ ON NE FERME QUE CE QUI DÉPEND DU WORKER. Le premier correctif gatait la mise en route du
2393
+ // lecteur ENTIER — or elle sert aussi au chemin IMAGE, qui n appelle pdf.js à aucun moment. Un
2394
+ // worker invérifiable empêchait donc d afficher un PNG : une porte fermée sur une pièce que le
2395
+ // code refusé ne pouvait pas atteindre.
2396
+ //
2397
+ // ⚠️ PAS D ACCENT GRAVE ICI : ce commentaire vit dans le gabarit de la page, un accent grave y
2398
+ // ferme la chaîne. Troisième fois aujourd hui.
2399
+ //
2400
+ // Trouvé par le harnais de l hôte, pas ici : son essai d assistant a cessé de démarrer, et j ai
2401
+ // d abord diagnostiqué un artefact de jsdom. Corriger le harnais aurait masqué le défaut.
2402
+ //
2403
+ // Le refus reste ENTIER pour un PDF, là où le worker s exécute.
2404
+ function refuserWorker(){
2405
+ window.__workerRefuse=1;
2406
+ if(IS_IMG){ start(); return; }
2407
+ loadError("Document non affiche : une dependance n a pas pu etre verifiee.");
2408
+ }
2392
2409
  var wsrc=CFG.pdfjs+'/pdf.worker.min.js';
2393
2410
  try{
2394
2411
  Player.viewer.workerBlobUrl(wsrc,'${TIERS.pdfWorker.sri}').then(function(u){
2395
- if(!u){ window.__workerRefuse=1; loadError("Document non affiche : une dependance n a pas pu etre verifiee."); return; }
2412
+ if(!u){ refuserWorker(); return; }
2396
2413
  pdfjsLib.GlobalWorkerOptions.workerSrc=u; start();
2397
- }).catch(function(){ window.__workerRefuse=1; loadError("Document non affiche : une dependance n a pas pu etre verifiee."); });
2398
- }catch(e){ window.__workerRefuse=1; loadError("Document non affiche : une dependance n a pas pu etre verifiee."); }
2414
+ }).catch(refuserWorker);
2415
+ }catch(e){ refuserWorker(); }
2399
2416
  // Bord à bord en une-page mobile : chaque millimètre compte, surtout pour un PDF paysage.
2400
2417
  function baseWidth(){ var pad=(onePage&&window.innerWidth<=820)?0:30; return (scrollEl.clientWidth||900)-pad; }
2401
2418
  // Hauteur du document OCCULTÉE par la bottom sheet du bot (mobile, état compagnon) : la page une-page se
@@ -2691,6 +2708,18 @@ function presentHtml(pres, nonce, logoUrl, supaUrl, supaKey) {
2691
2708
  if(!PDF) return;
2692
2709
  n=Math.max(1,Math.min(total||1, n||1)); cur=n;
2693
2710
  var c=document.getElementById('cur'); if(c)c.textContent=n;
2711
+ // Une image tient sur une page : on la pose, ajustée au cadre, et le reste de la vue —
2712
+ // synchronisation, présence, chat — continue de fonctionner à l identique.
2713
+ if(PDF.image){
2714
+ var pgi=document.getElementById('page'); if(!pgi) return;
2715
+ var dispoW=Math.max(120, stage.clientWidth-40), dispoH=Math.max(120, stage.clientHeight-40);
2716
+ var ech=Math.min(dispoW/(PDF.image.naturalWidth||1), dispoH/(PDF.image.naturalHeight||1), 1);
2717
+ var el=PDF.image.cloneNode(false);
2718
+ el.style.width=Math.round((PDF.image.naturalWidth||1)*ech)+'px';
2719
+ el.style.height='auto'; el.style.display='block';
2720
+ pgi.innerHTML=''; pgi.appendChild(el);
2721
+ return;
2722
+ }
2694
2723
  PDF.getPage(n).then(function(page){
2695
2724
  var availW=Math.max(120, stage.clientWidth-40), availH=Math.max(120, stage.clientHeight-40);
2696
2725
  var v1=page.getViewport({scale:1});
@@ -2709,7 +2738,48 @@ function presentHtml(pres, nonce, logoUrl, supaUrl, supaKey) {
2709
2738
  pdfjsLib.GlobalWorkerOptions.workerSrc=u; load();
2710
2739
  }).catch(function(){ window.__workerRefuse=1; var _e=document.getElementById('pg'); if(_e)_e.textContent="Document non affiche : une dependance n a pas pu etre verifiee."; });
2711
2740
  }
2741
+ // ⚠️ UNE PRÉSENTATION PEUT PORTER UNE IMAGE, ET CETTE VUE NE LE SAVAIT PAS. Le bouton
2742
+ // Présenter s apparait sans condition sur le type de document : un présentateur qui regarde un
2743
+ // PNG peut donc le présenter, et son audience recevait une page qui appelait pdf.js sur une
2744
+ // image — « Document indisponible ». Un bouton qui mène à une page morte est pire qu un bouton
2745
+ // absent.
2746
+ //
2747
+ // Ce n est PAS une régression du refus de worker : ce chemin était muet bien avant, et
2748
+ // personne ne l avait vu parce qu on ne présente pas souvent une image. Trouvé par le second
2749
+ // hôte, en POSANT LA QUESTION là où nous aurions affirmé — sa vue à lui sert des images, il a
2750
+ // demandé si la nôtre pouvait en recevoir.
2751
+ // ⚠️ Évalué AU CHARGEMENT, pas à l analyse du script : posé en constante de haut niveau, il
2752
+ // s exécutait avant que tout soit en place et emportait le reste du bloc avec lui — le
2753
+ // gestionnaire d état n était plus exposé, et la couche live ne pouvait plus se brancher. Un
2754
+ // essai l a dit tout de suite. Une question posée au bon moment ne coûte rien ; posée trop tôt,
2755
+ // elle emporte ce qui vient après.
2756
+ // ⚠️ SUR L URL D ORIGINE, JAMAIS SUR L URL DE PROXY. Premier jet : je passais
2757
+ // CFG.fileUrl, qui vaut /api/doc?present=...&file=1 — aucune extension, donc la réponse était
2758
+ // toujours « ce n est pas une image », et la page repartait sur pdf.js avec un PNG. Pire, un
2759
+ // try/catch posé par prudence avalait tout : la sonde n a rien vu jusqu à ce qu on lise le
2760
+ // sous-titre du loader, qui disait « Document indisponible ».
2761
+ //
2762
+ // Une garde défensive qui rend faux sur erreur ne protège pas, elle CACHE. Retirée.
2763
+ //
2764
+ // ⚠️ ET IL N Y A QU UNE SEULE CORRECTION ICI, alors que j en avais écrit deux. J avais aussi
2765
+ // ajouté le nom du fichier au cfg — chacune suffisait, donc aucune mutation ne pouvait faire
2766
+ // rougir le banc : retirer l une laissait l autre agir. Deux correctifs pour un symptôme
2767
+ // rendent un essai ininterprétable. Celle-ci est conservée parce qu elle ne change rien à ce
2768
+ // que la page reçoit ; retirer l URL d origine fait bien tomber le banc.
2769
+ function estImage(){ return Player.viewer.isImageDocument("", CFG.docUrl); }
2770
+ function chargerImage(){
2771
+ var im=new Image();
2772
+ im.onload=function(){
2773
+ total=1; ready=true; PDF={image:im};
2774
+ var tot=document.getElementById('tot'); if(tot)tot.textContent=1;
2775
+ show(1); hideLoader();
2776
+ if(!CFG.active) ended();
2777
+ };
2778
+ im.onerror=function(){ var l=document.getElementById('load'); if(l)l.querySelector('.lsub').textContent="Document indisponible."; };
2779
+ im.src=CFG.fileUrl;
2780
+ }
2712
2781
  function load(){
2782
+ if(estImage()){ chargerImage(); return; }
2713
2783
  pdfjsLib.getDocument({url:CFG.fileUrl,isEvalSupported:false}).promise.then(function(pdf){
2714
2784
  PDF=pdf; total=pdf.numPages; ready=true;
2715
2785
  var tot=document.getElementById('tot'); if(tot)tot.textContent=total;
@@ -53,3 +53,20 @@ $$;
53
53
 
54
54
  -- Le player parle à la base avec la clé de service ; personne d'autre n'a à appeler ceci.
55
55
  revoke all on function public.player_rate_limit_bump(text, integer, integer) from public, anon, authenticated;
56
+
57
+ -- ⚠️ LE `revoke` CI-DESSUS NE SUFFIT PAS À RENDRE CE FICHIER VRAI TOUT SEUL — signalé par le
58
+ -- second hôte, qui a interrogé `has_function_privilege` au lieu de relire la migration. Chez
59
+ -- Supabase, `service_role` conserve l'exécution parce que les privilèges par défaut la lui
60
+ -- accordent explicitement : le fichier marche par une propriété de la plateforme, pas par ce qu'il
61
+ -- dit. Porté sur un Postgres nu, le `revoke ... from public` emporterait aussi le compte de
62
+ -- service — et le player perdrait sa limite EN SILENCE, puisqu'un appel qui échoue laisse passer.
63
+ --
64
+ -- On accorde donc explicitement, et seulement si le rôle existe : sur une base sans `service_role`,
65
+ -- l'exploitant accorde l'exécution au rôle que son instance utilise réellement.
66
+ do $$
67
+ begin
68
+ if exists (select 1 from pg_roles where rolname = 'service_role') then
69
+ grant execute on function public.player_rate_limit_bump(text, integer, integer) to service_role;
70
+ end if;
71
+ end
72
+ $$;