diff --git a/memento-note/extension/dist-chrome-store/sidepanel.css b/memento-note/extension/dist-chrome-store/sidepanel.css index 7f85205..16b66a9 100644 --- a/memento-note/extension/dist-chrome-store/sidepanel.css +++ b/memento-note/extension/dist-chrome-store/sidepanel.css @@ -23,6 +23,8 @@ html, body { font-size: 13px; color: var(--ink); background: var(--paper); + overflow-wrap: break-word; + word-break: break-word; } .shell { @@ -32,6 +34,20 @@ html, body { background: var(--paper); } +/* Responsive : le side panel peut faire 280px (Chrome défaut) ou 480px+ (Firefox). + On adapte les paddings/margins en fonction de la largeur disponible. */ +@media (max-width: 380px) { + html, body { font-size: 12px; } + .header { padding: 12px 14px; } + .main { padding: 12px 14px 16px; gap: 12px; } + .footer { padding: 8px 14px 12px; } + .field span, .label, .sub { letter-spacing: 0.1em; } +} +@media (min-width: 420px) { + .main { padding: 20px 22px; gap: 18px; } + .header { padding: 18px 22px; } +} + .header { display: flex; align-items: center; @@ -215,29 +231,33 @@ input[type="text"]:focus, } .page-card { - padding: 14px; border: 1px solid var(--border); border-radius: var(--radius); + padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius); background: #fff; box-shadow: 0 1px 0 rgba(255,255,255,0.8) inset; + min-width: 0; } .page-card .sub { - font-size: 9px; text-transform: uppercase; letter-spacing: 0.14em; + font-size: 10px; text-transform: uppercase; letter-spacing: 0.14em; color: var(--muted); font-weight: 700; display: block; margin-bottom: 8px; } -.page-row { display: flex; gap: 10px; align-items: flex-start; min-width: 0; } +.page-row { display: flex; gap: 12px; align-items: flex-start; min-width: 0; } .page-row img { - width: 20px; height: 20px; border-radius: 5px; + width: 22px; height: 22px; border-radius: 5px; flex-shrink: 0; margin-top: 2px; } .page-text { min-width: 0; flex: 1; } .page-row .title { - font-size: 12px; font-weight: 700; line-height: 1.45; + font-size: 13px; font-weight: 700; line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; unicode-bidi: plaintext; + word-break: break-word; + overflow-wrap: anywhere; } .page-row .url { font-size: 10px; color: var(--muted); margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: ltr; text-align: left; + max-width: 100%; } .text-rtl { @@ -255,6 +275,7 @@ input[type="text"]:focus, min-height: 140px; display: flex; flex-direction: column; + flex: 1 1 auto; } .selection-panel.has-text { @@ -263,24 +284,30 @@ input[type="text"]:focus, box-shadow: 0 0 0 1px rgba(14, 165, 233, 0.12); } .selection-hint { - padding: 16px; + padding: 18px; border: 1px dashed var(--border); border-radius: var(--radius); text-align: center; background: #fff; + min-height: 120px; + display: flex; + align-items: center; + justify-content: center; } .selection-hint p { margin: 0; - font-size: 11px; + font-size: 12px; color: var(--muted); - line-height: 1.55; + line-height: 1.6; } .selection-head { display: flex; align-items: center; justify-content: space-between; - padding: 12px 14px; + gap: 8px; + padding: 14px 16px; background: linear-gradient(180deg, #fff 0%, #fdfcfa 100%); border-bottom: 1px solid var(--border); + flex-wrap: wrap; } .selection-head .status { display: flex; align-items: center; gap: 8px; @@ -293,24 +320,26 @@ input[type="text"]:focus, background: var(--paper); padding: 4px 8px; border-radius: 999px; } .selection-head .count.active { color: var(--accent); background: var(--accent-soft); } - .selection-body { - flex: 1; - padding: 14px; + flex: 1 1 auto; + padding: 14px 16px; font-size: 13px; - line-height: 1.75; + line-height: 1.65; color: rgba(28, 28, 28, 0.88); - max-height: 220px; + min-height: 80px; + max-height: none; overflow-y: auto; unicode-bidi: plaintext; border-inline-start: 3px solid transparent; + word-break: break-word; + overflow-wrap: anywhere; } .selection-panel.has-text .selection-body { border-inline-start-color: #38bdf8; - padding-inline-start: 16px; + padding-inline-start: 18px; font-style: italic; - font-size: 12px; - max-height: 150px; + font-size: 13px; + min-height: 100px; } .pulse-dot { @@ -328,15 +357,18 @@ input[type="text"]:focus, .clear-btn:hover { color: var(--ink); background: var(--paper); } .actions { - display: flex; flex-direction: column; gap: 10px; - margin-top: auto; padding-top: 6px; + display: flex; flex-direction: column; gap: 12px; + margin-top: auto; padding-top: 8px; } .btn { - padding: 14px 16px; border-radius: var(--radius); border: none; cursor: pointer; - font-weight: 700; font-size: 10px; text-transform: uppercase; + padding: 16px 18px; border-radius: var(--radius); border: none; cursor: pointer; + font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: 0.1em; - display: flex; align-items: center; justify-content: center; gap: 8px; + display: flex; align-items: center; justify-content: center; gap: 10px; + min-height: 48px; transition: transform 0.12s ease, opacity 0.12s ease, filter 0.12s ease; + word-break: break-word; + text-align: center; } .btn:active { transform: scale(0.98); } .btn:disabled { @@ -361,8 +393,9 @@ input[type="text"]:focus, } .btn-secondary:hover:not(:disabled) { background: #e5e7eb; } .btn-sm { - padding: 10px 12px; - font-size: 10px; + padding: 12px 14px; + font-size: 11px; + min-height: 40px; } .btn-danger { background: var(--danger); color: #fff; } .btn-link.link-only { @@ -372,8 +405,8 @@ input[type="text"]:focus, gap: 6px; } .btn-link { - background: none; border: none; color: var(--muted); font-size: 11px; - cursor: pointer; padding: 8px; font-weight: 500; + background: none; border: none; color: var(--muted); font-size: 12px; + cursor: pointer; padding: 10px; font-weight: 500; } .btn-link:hover { color: var(--ink); text-decoration: underline; } .btn-icon { width: 14px; height: 14px; display: inline-flex; } @@ -505,3 +538,23 @@ html[dir="rtl"] .label, html[dir="rtl"] .sub { text-align: right; } + +/* Firefox sidebar : plus large que Chrome Side Panel par défaut, + on aère la mise en page. */ +@-moz-document url-prefix("chrome:") { + .shell { min-height: 100vh; } +} +/* Fallback : on cible aussi le web-extension panel de Firefox */ +@media (min-width: 480px) { + .selection-panel { min-height: 160px; } + .selection-body { font-size: 14px; } + .page-row .title { font-size: 14px; } +} + +/* Très petits écrans (mobile debug, fenetres étirées) */ +@media (max-width: 320px) { + .brand-text { display: none; } + .header-right { gap: 4px; } + .icon-btn { width: 28px; height: 28px; } + .btn { padding: 14px 12px; font-size: 11px; } +} diff --git a/memento-note/extension/dist-chrome-store/sidepanel.js b/memento-note/extension/dist-chrome-store/sidepanel.js index d441400..907aacf 100644 --- a/memento-note/extension/dist-chrome-store/sidepanel.js +++ b/memento-note/extension/dist-chrome-store/sidepanel.js @@ -160,18 +160,32 @@ async function getActiveTab() { } async function ensureContentScript(tabId) { + // PING initial : si le script est déjà injecté, on retourne immédiatement. try { const resp = await chrome.tabs.sendMessage(tabId, { type: 'PING' }) if (resp?.ok) return true } catch { - /* inject */ + /* pas injecté */ } + // Sinon, injection manuelle via chrome.scripting.executeScript. try { await chrome.scripting.executeScript({ target: { tabId }, files: ['content.js'] }) - return true } catch { return false } + // L'injection est async côté page : le script doit finir de s'initialiser + // (IIFE, listeners, flag globalThis) avant qu'on puisse lui parler. + // On PING avec retry pour attendre qu'il soit prêt. + for (let i = 0; i < 8; i++) { + await new Promise(r => setTimeout(r, 80 + i * 30)) + try { + const resp = await chrome.tabs.sendMessage(tabId, { type: 'PING' }) + if (resp?.ok) return true + } catch { + /* pas encore prêt */ + } + } + return false } async function setPickModeOnTab(enabled) { @@ -181,7 +195,7 @@ async function setPickModeOnTab(enabled) { try { await chrome.tabs.sendMessage(activeTabId, { type: 'SET_PICK_MODE', enabled }) } catch { - /* ignore */ + /* ignore — retry au prochain syncPickMode */ } } diff --git a/memento-note/extension/dist-firefox/sidepanel.css b/memento-note/extension/dist-firefox/sidepanel.css index 7f85205..16b66a9 100644 --- a/memento-note/extension/dist-firefox/sidepanel.css +++ b/memento-note/extension/dist-firefox/sidepanel.css @@ -23,6 +23,8 @@ html, body { font-size: 13px; color: var(--ink); background: var(--paper); + overflow-wrap: break-word; + word-break: break-word; } .shell { @@ -32,6 +34,20 @@ html, body { background: var(--paper); } +/* Responsive : le side panel peut faire 280px (Chrome défaut) ou 480px+ (Firefox). + On adapte les paddings/margins en fonction de la largeur disponible. */ +@media (max-width: 380px) { + html, body { font-size: 12px; } + .header { padding: 12px 14px; } + .main { padding: 12px 14px 16px; gap: 12px; } + .footer { padding: 8px 14px 12px; } + .field span, .label, .sub { letter-spacing: 0.1em; } +} +@media (min-width: 420px) { + .main { padding: 20px 22px; gap: 18px; } + .header { padding: 18px 22px; } +} + .header { display: flex; align-items: center; @@ -215,29 +231,33 @@ input[type="text"]:focus, } .page-card { - padding: 14px; border: 1px solid var(--border); border-radius: var(--radius); + padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius); background: #fff; box-shadow: 0 1px 0 rgba(255,255,255,0.8) inset; + min-width: 0; } .page-card .sub { - font-size: 9px; text-transform: uppercase; letter-spacing: 0.14em; + font-size: 10px; text-transform: uppercase; letter-spacing: 0.14em; color: var(--muted); font-weight: 700; display: block; margin-bottom: 8px; } -.page-row { display: flex; gap: 10px; align-items: flex-start; min-width: 0; } +.page-row { display: flex; gap: 12px; align-items: flex-start; min-width: 0; } .page-row img { - width: 20px; height: 20px; border-radius: 5px; + width: 22px; height: 22px; border-radius: 5px; flex-shrink: 0; margin-top: 2px; } .page-text { min-width: 0; flex: 1; } .page-row .title { - font-size: 12px; font-weight: 700; line-height: 1.45; + font-size: 13px; font-weight: 700; line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; unicode-bidi: plaintext; + word-break: break-word; + overflow-wrap: anywhere; } .page-row .url { font-size: 10px; color: var(--muted); margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: ltr; text-align: left; + max-width: 100%; } .text-rtl { @@ -255,6 +275,7 @@ input[type="text"]:focus, min-height: 140px; display: flex; flex-direction: column; + flex: 1 1 auto; } .selection-panel.has-text { @@ -263,24 +284,30 @@ input[type="text"]:focus, box-shadow: 0 0 0 1px rgba(14, 165, 233, 0.12); } .selection-hint { - padding: 16px; + padding: 18px; border: 1px dashed var(--border); border-radius: var(--radius); text-align: center; background: #fff; + min-height: 120px; + display: flex; + align-items: center; + justify-content: center; } .selection-hint p { margin: 0; - font-size: 11px; + font-size: 12px; color: var(--muted); - line-height: 1.55; + line-height: 1.6; } .selection-head { display: flex; align-items: center; justify-content: space-between; - padding: 12px 14px; + gap: 8px; + padding: 14px 16px; background: linear-gradient(180deg, #fff 0%, #fdfcfa 100%); border-bottom: 1px solid var(--border); + flex-wrap: wrap; } .selection-head .status { display: flex; align-items: center; gap: 8px; @@ -293,24 +320,26 @@ input[type="text"]:focus, background: var(--paper); padding: 4px 8px; border-radius: 999px; } .selection-head .count.active { color: var(--accent); background: var(--accent-soft); } - .selection-body { - flex: 1; - padding: 14px; + flex: 1 1 auto; + padding: 14px 16px; font-size: 13px; - line-height: 1.75; + line-height: 1.65; color: rgba(28, 28, 28, 0.88); - max-height: 220px; + min-height: 80px; + max-height: none; overflow-y: auto; unicode-bidi: plaintext; border-inline-start: 3px solid transparent; + word-break: break-word; + overflow-wrap: anywhere; } .selection-panel.has-text .selection-body { border-inline-start-color: #38bdf8; - padding-inline-start: 16px; + padding-inline-start: 18px; font-style: italic; - font-size: 12px; - max-height: 150px; + font-size: 13px; + min-height: 100px; } .pulse-dot { @@ -328,15 +357,18 @@ input[type="text"]:focus, .clear-btn:hover { color: var(--ink); background: var(--paper); } .actions { - display: flex; flex-direction: column; gap: 10px; - margin-top: auto; padding-top: 6px; + display: flex; flex-direction: column; gap: 12px; + margin-top: auto; padding-top: 8px; } .btn { - padding: 14px 16px; border-radius: var(--radius); border: none; cursor: pointer; - font-weight: 700; font-size: 10px; text-transform: uppercase; + padding: 16px 18px; border-radius: var(--radius); border: none; cursor: pointer; + font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: 0.1em; - display: flex; align-items: center; justify-content: center; gap: 8px; + display: flex; align-items: center; justify-content: center; gap: 10px; + min-height: 48px; transition: transform 0.12s ease, opacity 0.12s ease, filter 0.12s ease; + word-break: break-word; + text-align: center; } .btn:active { transform: scale(0.98); } .btn:disabled { @@ -361,8 +393,9 @@ input[type="text"]:focus, } .btn-secondary:hover:not(:disabled) { background: #e5e7eb; } .btn-sm { - padding: 10px 12px; - font-size: 10px; + padding: 12px 14px; + font-size: 11px; + min-height: 40px; } .btn-danger { background: var(--danger); color: #fff; } .btn-link.link-only { @@ -372,8 +405,8 @@ input[type="text"]:focus, gap: 6px; } .btn-link { - background: none; border: none; color: var(--muted); font-size: 11px; - cursor: pointer; padding: 8px; font-weight: 500; + background: none; border: none; color: var(--muted); font-size: 12px; + cursor: pointer; padding: 10px; font-weight: 500; } .btn-link:hover { color: var(--ink); text-decoration: underline; } .btn-icon { width: 14px; height: 14px; display: inline-flex; } @@ -505,3 +538,23 @@ html[dir="rtl"] .label, html[dir="rtl"] .sub { text-align: right; } + +/* Firefox sidebar : plus large que Chrome Side Panel par défaut, + on aère la mise en page. */ +@-moz-document url-prefix("chrome:") { + .shell { min-height: 100vh; } +} +/* Fallback : on cible aussi le web-extension panel de Firefox */ +@media (min-width: 480px) { + .selection-panel { min-height: 160px; } + .selection-body { font-size: 14px; } + .page-row .title { font-size: 14px; } +} + +/* Très petits écrans (mobile debug, fenetres étirées) */ +@media (max-width: 320px) { + .brand-text { display: none; } + .header-right { gap: 4px; } + .icon-btn { width: 28px; height: 28px; } + .btn { padding: 14px 12px; font-size: 11px; } +} diff --git a/memento-note/extension/dist-firefox/sidepanel.js b/memento-note/extension/dist-firefox/sidepanel.js index d441400..907aacf 100644 --- a/memento-note/extension/dist-firefox/sidepanel.js +++ b/memento-note/extension/dist-firefox/sidepanel.js @@ -160,18 +160,32 @@ async function getActiveTab() { } async function ensureContentScript(tabId) { + // PING initial : si le script est déjà injecté, on retourne immédiatement. try { const resp = await chrome.tabs.sendMessage(tabId, { type: 'PING' }) if (resp?.ok) return true } catch { - /* inject */ + /* pas injecté */ } + // Sinon, injection manuelle via chrome.scripting.executeScript. try { await chrome.scripting.executeScript({ target: { tabId }, files: ['content.js'] }) - return true } catch { return false } + // L'injection est async côté page : le script doit finir de s'initialiser + // (IIFE, listeners, flag globalThis) avant qu'on puisse lui parler. + // On PING avec retry pour attendre qu'il soit prêt. + for (let i = 0; i < 8; i++) { + await new Promise(r => setTimeout(r, 80 + i * 30)) + try { + const resp = await chrome.tabs.sendMessage(tabId, { type: 'PING' }) + if (resp?.ok) return true + } catch { + /* pas encore prêt */ + } + } + return false } async function setPickModeOnTab(enabled) { @@ -181,7 +195,7 @@ async function setPickModeOnTab(enabled) { try { await chrome.tabs.sendMessage(activeTabId, { type: 'SET_PICK_MODE', enabled }) } catch { - /* ignore */ + /* ignore — retry au prochain syncPickMode */ } } diff --git a/memento-note/extension/memento-web-clipper-chrome-store.zip b/memento-note/extension/memento-web-clipper-chrome-store.zip index 0701cc7..cf739c7 100644 Binary files a/memento-note/extension/memento-web-clipper-chrome-store.zip and b/memento-note/extension/memento-web-clipper-chrome-store.zip differ diff --git a/memento-note/extension/memento-web-clipper-firefox.xpi b/memento-note/extension/memento-web-clipper-firefox.xpi index 62a9bba..77d5db0 100644 Binary files a/memento-note/extension/memento-web-clipper-firefox.xpi and b/memento-note/extension/memento-web-clipper-firefox.xpi differ diff --git a/memento-note/extension/sidepanel.css b/memento-note/extension/sidepanel.css index 7f85205..16b66a9 100644 --- a/memento-note/extension/sidepanel.css +++ b/memento-note/extension/sidepanel.css @@ -23,6 +23,8 @@ html, body { font-size: 13px; color: var(--ink); background: var(--paper); + overflow-wrap: break-word; + word-break: break-word; } .shell { @@ -32,6 +34,20 @@ html, body { background: var(--paper); } +/* Responsive : le side panel peut faire 280px (Chrome défaut) ou 480px+ (Firefox). + On adapte les paddings/margins en fonction de la largeur disponible. */ +@media (max-width: 380px) { + html, body { font-size: 12px; } + .header { padding: 12px 14px; } + .main { padding: 12px 14px 16px; gap: 12px; } + .footer { padding: 8px 14px 12px; } + .field span, .label, .sub { letter-spacing: 0.1em; } +} +@media (min-width: 420px) { + .main { padding: 20px 22px; gap: 18px; } + .header { padding: 18px 22px; } +} + .header { display: flex; align-items: center; @@ -215,29 +231,33 @@ input[type="text"]:focus, } .page-card { - padding: 14px; border: 1px solid var(--border); border-radius: var(--radius); + padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius); background: #fff; box-shadow: 0 1px 0 rgba(255,255,255,0.8) inset; + min-width: 0; } .page-card .sub { - font-size: 9px; text-transform: uppercase; letter-spacing: 0.14em; + font-size: 10px; text-transform: uppercase; letter-spacing: 0.14em; color: var(--muted); font-weight: 700; display: block; margin-bottom: 8px; } -.page-row { display: flex; gap: 10px; align-items: flex-start; min-width: 0; } +.page-row { display: flex; gap: 12px; align-items: flex-start; min-width: 0; } .page-row img { - width: 20px; height: 20px; border-radius: 5px; + width: 22px; height: 22px; border-radius: 5px; flex-shrink: 0; margin-top: 2px; } .page-text { min-width: 0; flex: 1; } .page-row .title { - font-size: 12px; font-weight: 700; line-height: 1.45; + font-size: 13px; font-weight: 700; line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; unicode-bidi: plaintext; + word-break: break-word; + overflow-wrap: anywhere; } .page-row .url { font-size: 10px; color: var(--muted); margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: ltr; text-align: left; + max-width: 100%; } .text-rtl { @@ -255,6 +275,7 @@ input[type="text"]:focus, min-height: 140px; display: flex; flex-direction: column; + flex: 1 1 auto; } .selection-panel.has-text { @@ -263,24 +284,30 @@ input[type="text"]:focus, box-shadow: 0 0 0 1px rgba(14, 165, 233, 0.12); } .selection-hint { - padding: 16px; + padding: 18px; border: 1px dashed var(--border); border-radius: var(--radius); text-align: center; background: #fff; + min-height: 120px; + display: flex; + align-items: center; + justify-content: center; } .selection-hint p { margin: 0; - font-size: 11px; + font-size: 12px; color: var(--muted); - line-height: 1.55; + line-height: 1.6; } .selection-head { display: flex; align-items: center; justify-content: space-between; - padding: 12px 14px; + gap: 8px; + padding: 14px 16px; background: linear-gradient(180deg, #fff 0%, #fdfcfa 100%); border-bottom: 1px solid var(--border); + flex-wrap: wrap; } .selection-head .status { display: flex; align-items: center; gap: 8px; @@ -293,24 +320,26 @@ input[type="text"]:focus, background: var(--paper); padding: 4px 8px; border-radius: 999px; } .selection-head .count.active { color: var(--accent); background: var(--accent-soft); } - .selection-body { - flex: 1; - padding: 14px; + flex: 1 1 auto; + padding: 14px 16px; font-size: 13px; - line-height: 1.75; + line-height: 1.65; color: rgba(28, 28, 28, 0.88); - max-height: 220px; + min-height: 80px; + max-height: none; overflow-y: auto; unicode-bidi: plaintext; border-inline-start: 3px solid transparent; + word-break: break-word; + overflow-wrap: anywhere; } .selection-panel.has-text .selection-body { border-inline-start-color: #38bdf8; - padding-inline-start: 16px; + padding-inline-start: 18px; font-style: italic; - font-size: 12px; - max-height: 150px; + font-size: 13px; + min-height: 100px; } .pulse-dot { @@ -328,15 +357,18 @@ input[type="text"]:focus, .clear-btn:hover { color: var(--ink); background: var(--paper); } .actions { - display: flex; flex-direction: column; gap: 10px; - margin-top: auto; padding-top: 6px; + display: flex; flex-direction: column; gap: 12px; + margin-top: auto; padding-top: 8px; } .btn { - padding: 14px 16px; border-radius: var(--radius); border: none; cursor: pointer; - font-weight: 700; font-size: 10px; text-transform: uppercase; + padding: 16px 18px; border-radius: var(--radius); border: none; cursor: pointer; + font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: 0.1em; - display: flex; align-items: center; justify-content: center; gap: 8px; + display: flex; align-items: center; justify-content: center; gap: 10px; + min-height: 48px; transition: transform 0.12s ease, opacity 0.12s ease, filter 0.12s ease; + word-break: break-word; + text-align: center; } .btn:active { transform: scale(0.98); } .btn:disabled { @@ -361,8 +393,9 @@ input[type="text"]:focus, } .btn-secondary:hover:not(:disabled) { background: #e5e7eb; } .btn-sm { - padding: 10px 12px; - font-size: 10px; + padding: 12px 14px; + font-size: 11px; + min-height: 40px; } .btn-danger { background: var(--danger); color: #fff; } .btn-link.link-only { @@ -372,8 +405,8 @@ input[type="text"]:focus, gap: 6px; } .btn-link { - background: none; border: none; color: var(--muted); font-size: 11px; - cursor: pointer; padding: 8px; font-weight: 500; + background: none; border: none; color: var(--muted); font-size: 12px; + cursor: pointer; padding: 10px; font-weight: 500; } .btn-link:hover { color: var(--ink); text-decoration: underline; } .btn-icon { width: 14px; height: 14px; display: inline-flex; } @@ -505,3 +538,23 @@ html[dir="rtl"] .label, html[dir="rtl"] .sub { text-align: right; } + +/* Firefox sidebar : plus large que Chrome Side Panel par défaut, + on aère la mise en page. */ +@-moz-document url-prefix("chrome:") { + .shell { min-height: 100vh; } +} +/* Fallback : on cible aussi le web-extension panel de Firefox */ +@media (min-width: 480px) { + .selection-panel { min-height: 160px; } + .selection-body { font-size: 14px; } + .page-row .title { font-size: 14px; } +} + +/* Très petits écrans (mobile debug, fenetres étirées) */ +@media (max-width: 320px) { + .brand-text { display: none; } + .header-right { gap: 4px; } + .icon-btn { width: 28px; height: 28px; } + .btn { padding: 14px 12px; font-size: 11px; } +} diff --git a/memento-note/extension/sidepanel.js b/memento-note/extension/sidepanel.js index 716975b..e0f9511 100644 --- a/memento-note/extension/sidepanel.js +++ b/memento-note/extension/sidepanel.js @@ -160,18 +160,32 @@ async function getActiveTab() { } async function ensureContentScript(tabId) { + // PING initial : si le script est déjà injecté, on retourne immédiatement. try { const resp = await chrome.tabs.sendMessage(tabId, { type: 'PING' }) if (resp?.ok) return true } catch { - /* inject */ + /* pas injecté */ } + // Sinon, injection manuelle via chrome.scripting.executeScript. try { await chrome.scripting.executeScript({ target: { tabId }, files: ['content.js'] }) - return true } catch { return false } + // L'injection est async côté page : le script doit finir de s'initialiser + // (IIFE, listeners, flag globalThis) avant qu'on puisse lui parler. + // On PING avec retry pour attendre qu'il soit prêt. + for (let i = 0; i < 8; i++) { + await new Promise(r => setTimeout(r, 80 + i * 30)) + try { + const resp = await chrome.tabs.sendMessage(tabId, { type: 'PING' }) + if (resp?.ok) return true + } catch { + /* pas encore prêt */ + } + } + return false } async function setPickModeOnTab(enabled) { @@ -181,7 +195,7 @@ async function setPickModeOnTab(enabled) { try { await chrome.tabs.sendMessage(activeTabId, { type: 'SET_PICK_MODE', enabled }) } catch { - /* ignore */ + /* ignore — retry au prochain syncPickMode */ } }