discovery-media-player 0.1.15 → 0.1.16

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server/handler.js +23 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discovery-media-player",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
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
@@ -1407,7 +1407,27 @@ function viewerHtml(share, nonce, logoUrl, pitch) {
1407
1407
  // INTÉGRÉ (?embed=1) : la visionneuse est en surimpression dans une page hôte de MÊME
1408
1408
  // ORIGINE (le plan d'un lot dans une expérience 3D). L'hôte n'a alors plus besoin de sa
1409
1409
  // propre barre de titre : celle-ci porte la croix, et la sortie remonte en postMessage.
1410
+ // ⚠️ DEUX QUESTIONS DIFFÉRENTES, QU'UNE SEULE VARIABLE CONFONDAIT.
1411
+ //
1412
+ // `embed` décide de l'HABILLAGE : la visionneuse porte sa propre croix, et l'hôte retire sa
1413
+ // barre de titre. L'aperçu a déjà la sienne (`closeBtn`, à droite) — lever la condition
1414
+ // afficherait donc DEUX croix. Le `!preview` n'était pas arbitraire.
1415
+ //
1416
+ // `embedded` répond à l'autre question : cette page est-elle SERVIE dans un cadre ? C'est elle
1417
+ // qui commande la poignée de main. Le serveur le sait déjà — il en tire les `frame-ancestors`
1418
+ // de la réponse — mais le navigateur ne l'apprenait qu'en aperçu de lien tracé.
1419
+ //
1420
+ // ⚠️ Conséquence signalée par le second hôte, et c'est exactement la panne que le contrat
1421
+ // décrit : `embed-ready` n'était jamais émis en aperçu, donc l'hôte recevait un SILENCE. Or le
1422
+ // silence couvre deux cas opposés — instance absente, ou player vivant. Leur guetteur de
1423
+ // démarrage a conclu « injoignable » et remplacé un player qui fonctionnait par la visionneuse
1424
+ // du navigateur, six secondes après l'ouverture, sous les yeux du lecteur. Et l'aperçu est
1425
+ // précisément le mode qu'un hôte utilise pour SES documents.
1426
+ //
1427
+ // La page était pourtant encadrable et parlait déjà (`share`, `close` en postMessage) : il ne
1428
+ // lui manquait que de dire qu'elle était là.
1410
1429
  const embed = !preview && !!share.embed;
1430
+ const embedded = !!share.embed;
1411
1431
  const fileUrl = preview ? share.stream_url : `/api/doc?slug=${encodeURIComponent(share.slug)}&file=1`;
1412
1432
  // Logo de MARQUE du loader : celui du promoteur (brand_logo, ex. MJ
1413
1433
  // Développement) s'il est renseigné, avec la mention de l'éditeur dessous (si configurée)
@@ -1421,7 +1441,7 @@ function viewerHtml(share, nonce, logoUrl, pitch) {
1421
1441
  // En aperçu interne, on embarque de quoi démarrer une présentation live (URL Storage brute + métadonnées).
1422
1442
  // `fileName` : c'est LUI qui dit la nature du document côté page. L'URL publique est
1423
1443
  // `/api/doc?slug=…&file=1`, sans extension — sans ce champ, une image partait dans pdf.js.
1424
- const cfg = JSON.stringify({ brand: PLAYER.branding.name, slug: preview ? "" : share.slug, fileUrl, fileName: share.file_name || "", pdfjs: PDFJS, title, preview, embed, bot: botOn, botGuided: !preview && !!share.bot_enabled && share.bot_guided !== false, botAv: (!preview && share.bot_enabled && share.bot_avatar) || "", botName: (!preview && share.bot_enabled && share.bot_name) || "", botGreet: (!preview && share.bot_enabled && share.bot_greeting) || "", botGreetDoc: (!preview && share.bot_enabled && share.bot_greeting_doc) || "", dl: share.allow_download !== false, autoPresent: !!share.auto_present, botAnim: share.bot_page_anim !== false, botVoice: !preview && !!share.bot_enabled && !!process.env.ELEVENLABS_API_KEY, vIcOn: ICONS.sound, vIcOff: ICONS.mute, kStyle: (!preview && share.bot_enabled && share.bot_karaoke) || "classic", vLayout: (!preview && share.bot_enabled && share.video_layout) || "", vClips: !preview && !!share.bot_vclips, botVAv: (!preview && share.bot_enabled && share.bot_vphoto) || "", resumeSlug: preview ? (share.resume_slug || "") : "", supaUrl: preview ? (share.supa_url || "") : "", supaKey: preview ? (share.supa_key || "") : "", internal: preview && share.internal_email ? { email: share.internal_email, name: share.presenter_name || "", docId: share.doc_id || "" } : null, present: preview ? { url: share.raw_url || "", name: share.file_name || "", title: share.doc_title || "", docId: share.doc_id || "", by: share.presenter_name || "", email: share.internal_email || "", av: share.presenter_avatar || "" } : null });
1444
+ const cfg = JSON.stringify({ brand: PLAYER.branding.name, slug: preview ? "" : share.slug, fileUrl, fileName: share.file_name || "", pdfjs: PDFJS, title, preview, embed, embedded, bot: botOn, botGuided: !preview && !!share.bot_enabled && share.bot_guided !== false, botAv: (!preview && share.bot_enabled && share.bot_avatar) || "", botName: (!preview && share.bot_enabled && share.bot_name) || "", botGreet: (!preview && share.bot_enabled && share.bot_greeting) || "", botGreetDoc: (!preview && share.bot_enabled && share.bot_greeting_doc) || "", dl: share.allow_download !== false, autoPresent: !!share.auto_present, botAnim: share.bot_page_anim !== false, botVoice: !preview && !!share.bot_enabled && !!process.env.ELEVENLABS_API_KEY, vIcOn: ICONS.sound, vIcOff: ICONS.mute, kStyle: (!preview && share.bot_enabled && share.bot_karaoke) || "classic", vLayout: (!preview && share.bot_enabled && share.video_layout) || "", vClips: !preview && !!share.bot_vclips, botVAv: (!preview && share.bot_enabled && share.bot_vphoto) || "", resumeSlug: preview ? (share.resume_slug || "") : "", supaUrl: preview ? (share.supa_url || "") : "", supaKey: preview ? (share.supa_key || "") : "", internal: preview && share.internal_email ? { email: share.internal_email, name: share.presenter_name || "", docId: share.doc_id || "" } : null, present: preview ? { url: share.raw_url || "", name: share.file_name || "", title: share.doc_title || "", docId: share.doc_id || "", by: share.presenter_name || "", email: share.internal_email || "", av: share.presenter_avatar || "" } : null });
1425
1445
  return `<!doctype html><html lang=fr><head><meta charset=utf-8>
1426
1446
  <meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=3,viewport-fit=cover,interactive-widget=resizes-content">
1427
1447
  <meta name=robots content="noindex,nofollow">
@@ -1744,7 +1764,7 @@ ${LEGAL_CSS}
1744
1764
  // qu'on est là — sans cette poignée de main elle ne peut pas savoir si la croix
1745
1765
  // existe (visionneuse d'une version antérieure) et garde la sienne par sécurité.
1746
1766
  // Le format du fil, le targetOrigin et la validation vivent dans player/src/bridge.ts.
1747
- if(CFG.embed){
1767
+ if(CFG.embedded){
1748
1768
  Player.bridge.sendToHost({type:'embed-ready'});
1749
1769
  var _xb=document.getElementById('embedCloseBtn');
1750
1770
  if(_xb) _xb.addEventListener('click',function(){ Player.bridge.sendToHost({type:'close'}); });
@@ -2810,7 +2830,7 @@ async function handler(req, res) {
2810
2830
  }
2811
2831
  const supaUrl = (PLAYER.config && PLAYER.config.supabaseUrl) || "";
2812
2832
  const supaKey = (PLAYER.config && PLAYER.config.supabasePublishableKey) || "";
2813
- const pseudo = { preview: true, slug: "", file_name: String(q.name || "document.pdf"), doc_title: String(q.title || q.name || "Document"), raw_url: url, doc_id: String(q.docId || ""), presenter_name: String(q.by || ""), presenter_avatar: String(q.av || ""), internal_email: String(q.uemail || ""), supa_url: supaUrl, supa_key: supaKey, auto_present: String(q.autopresent || "") === "1", resume_slug: String(q.resume || ""), stream_url: `/api/doc?preview=1&stream=1&url=${encodeURIComponent(url)}&name=${encodeURIComponent(String(q.name || ""))}` };
2833
+ const pseudo = { preview: true, embed, slug: "", file_name: String(q.name || "document.pdf"), doc_title: String(q.title || q.name || "Document"), raw_url: url, doc_id: String(q.docId || ""), presenter_name: String(q.by || ""), presenter_avatar: String(q.av || ""), internal_email: String(q.uemail || ""), supa_url: supaUrl, supa_key: supaKey, auto_present: String(q.autopresent || "") === "1", resume_slug: String(q.resume || ""), stream_url: `/api/doc?preview=1&stream=1&url=${encodeURIComponent(url)}&name=${encodeURIComponent(String(q.name || ""))}` };
2814
2834
  let plogo = ""; try { plogo = await PLAYER.branding.logo(); } catch { /* sans logo */ }
2815
2835
  const pnonce = crypto.randomBytes(16).toString("base64");
2816
2836
  // Aperçu interne : CSP relâchée (supabase-js jsdelivr + Realtime wss) pour la présence + le chat live,