fix(extension): rollback content/background/sidepanel à v0.3.1, version 0.4.1
Le rollback complet de content.js, background.js et sidepanel.js vers la v0.3.1 (que tu confirmes fonctionner) règle la régression. Mes modifs depuis (forwarder, shim chrome<->browser, setPickMode auto, retry PING) ont introduit une régression silencieuse que je n'ai pas reproduite localement. Je remets le code qui marchait. Manifest = v0.3.1 + ajout sidebar_action + browser_specific_settings.gecko pour le build Firefox. Version bumpée 0.3.1 → 0.4.1.
This commit is contained in:
@@ -1,13 +1,6 @@
|
||||
/**
|
||||
* Content script Memento — sélection live, surlignage, communication avec le side panel.
|
||||
* Injecté automatiquement sur http(s) ; ré-injecté à la demande si l'onglet était déjà ouvert.
|
||||
*
|
||||
* IMPORTANT : la bannière "Surlignez le texte à clipper" s'affiche dès
|
||||
* l'injection du script, sans dépendre de SET_PICK_MODE. C'est volontaire :
|
||||
* en MV3, le routage des messages entre side panel et content script
|
||||
* peut être flaky (race conditions entre injection et listeners), donc
|
||||
* on rend la bannière visible dès qu'on est là. L'utilisateur peut la
|
||||
* fermer via le bouton ✕.
|
||||
* Content script Momento — sélection live, surlignage, communication avec le side panel.
|
||||
* Injecté automatiquement sur http(s) ; ré-injecté à la demande si l’onglet était déjà ouvert.
|
||||
*/
|
||||
;(function initMementoClipperContent() {
|
||||
if (globalThis.__mementoClipperContent) return
|
||||
@@ -18,13 +11,8 @@
|
||||
const STYLE_ID = 'memento-clipper-styles'
|
||||
|
||||
let pickMode = false
|
||||
let bannerDismissed = false
|
||||
let debounceTimer = null
|
||||
|
||||
function isRestrictedUrl(url) {
|
||||
return !url || /^(chrome|chrome-extension|edge|about|moz-extension|devtools|file):/i.test(url)
|
||||
}
|
||||
|
||||
function getSelectionText() {
|
||||
return window.getSelection()?.toString().trim() || ''
|
||||
}
|
||||
@@ -125,64 +113,40 @@
|
||||
|
||||
function ensureBanner() {
|
||||
if (document.getElementById(BANNER_ID)) return
|
||||
if (!shouldShowBanner()) return
|
||||
|
||||
const bannerText =
|
||||
(typeof chrome !== 'undefined' && chrome.i18n?.getMessage?.('bannerPickText')) ||
|
||||
'Highlight the text on the page, or clip the whole page.'
|
||||
const dismissLabel =
|
||||
(typeof chrome !== 'undefined' && chrome.i18n?.getMessage?.('bannerDismiss')) ||
|
||||
'Dismiss'
|
||||
'Highlight the text to clip'
|
||||
|
||||
const host = document.createElement('div')
|
||||
host.id = BANNER_ID
|
||||
// Le host est positionné en fixed (hors flux) au top-center.
|
||||
host.style.cssText =
|
||||
'position:fixed;top:14px;left:50%;transform:translateX(-50%);z-index:2147483647;pointer-events:auto;font-family:Inter,system-ui,-apple-system,sans-serif;'
|
||||
'all:initial;position:fixed;top:16px;left:50%;transform:translateX(-50%);z-index:2147483647;pointer-events:none;font-family:Inter,system-ui,sans-serif;'
|
||||
|
||||
const shadow = host.attachShadow({ mode: 'open' })
|
||||
shadow.innerHTML = `
|
||||
<style>
|
||||
:host { all: initial; }
|
||||
.wrap {
|
||||
display: inline-flex; align-items: center; gap: 10px;
|
||||
padding: 10px 10px 10px 18px; border-radius: 999px;
|
||||
.pill {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 10px 18px; border-radius: 999px;
|
||||
background: #1c1c1c; color: #faf9f5;
|
||||
box-shadow: 0 12px 32px rgba(0,0,0,0.32);
|
||||
box-shadow: 0 12px 32px rgba(0,0,0,0.22);
|
||||
font-size: 12px; font-weight: 600;
|
||||
letter-spacing: 0.01em;
|
||||
max-width: min(640px, calc(100vw - 24px));
|
||||
letter-spacing: 0.02em;
|
||||
animation: slideIn 0.35s cubic-bezier(0.22,1,0.36,1);
|
||||
}
|
||||
.logo {
|
||||
width: 22px; height: 22px; border-radius: 7px;
|
||||
background: #faf9f5; color: #1c1c1c;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-family: Georgia, serif; font-weight: 900; font-size: 13px;
|
||||
flex-shrink: 0;
|
||||
font-family: Georgia, serif; font-weight: 900; font-size: 12px;
|
||||
}
|
||||
.dot {
|
||||
width: 8px; height: 8px; border-radius: 50%;
|
||||
background: #a47148; animation: pulse 1.2s ease infinite;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.text {
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||
min-width: 0;
|
||||
}
|
||||
.close {
|
||||
width: 22px; height: 22px; border-radius: 50%;
|
||||
background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.7);
|
||||
border: none; cursor: pointer; display: flex;
|
||||
align-items: center; justify-content: center;
|
||||
font-size: 14px; line-height: 1; font-weight: 700;
|
||||
flex-shrink: 0; transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
.close:hover {
|
||||
background: rgba(255,255,255,0.18); color: #fff;
|
||||
}
|
||||
@keyframes slideIn {
|
||||
from { opacity: 0; transform: translateY(-10px); }
|
||||
from { opacity: 0; transform: translateY(-8px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@keyframes pulse {
|
||||
@@ -190,26 +154,13 @@
|
||||
50% { opacity: 0.5; transform: scale(0.85); }
|
||||
}
|
||||
</style>
|
||||
<div class="wrap" role="status" aria-live="polite">
|
||||
<div class="pill">
|
||||
<span class="logo">M</span>
|
||||
<span class="dot"></span>
|
||||
<span class="text">${bannerText.replace(/</g, '<')}</span>
|
||||
<button type="button" class="close" aria-label="${dismissLabel}">×</button>
|
||||
<span>${bannerText.replace(/</g, '<')}</span>
|
||||
</div>
|
||||
`
|
||||
|
||||
document.documentElement.appendChild(host)
|
||||
|
||||
// Bind le bouton ✕ — ferme la bannière pour cette session d'onglet.
|
||||
const closeBtn = shadow.querySelector('.close')
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
bannerDismissed = true
|
||||
removeBanner()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function setPickMode(enabled) {
|
||||
@@ -230,21 +181,15 @@
|
||||
if (pickMode) paintHighlight()
|
||||
}
|
||||
|
||||
// Ne rien faire sur les pages restreintes (chrome://, file://, etc.)
|
||||
if (isRestrictedUrl(location.href)) {
|
||||
// On écoute quand même les messages au cas où le side panel veut
|
||||
// quand même parler (ex: pour info).
|
||||
} else {
|
||||
document.addEventListener('selectionchange', broadcastSelection)
|
||||
document.addEventListener('mouseup', broadcastSelection)
|
||||
document.addEventListener('keyup', broadcastSelection)
|
||||
window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true })
|
||||
window.addEventListener('resize', onScrollOrResize, { passive: true })
|
||||
}
|
||||
document.addEventListener('selectionchange', broadcastSelection)
|
||||
document.addEventListener('mouseup', broadcastSelection)
|
||||
document.addEventListener('keyup', broadcastSelection)
|
||||
window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true })
|
||||
window.addEventListener('resize', onScrollOrResize, { passive: true })
|
||||
|
||||
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
||||
if (message?.type === 'PING') {
|
||||
sendResponse({ ok: true, pickMode })
|
||||
sendResponse({ ok: true })
|
||||
return true
|
||||
}
|
||||
if (message?.type === 'GET_CONTEXT') {
|
||||
@@ -259,24 +204,8 @@
|
||||
sendResponse({ ok: true, pickMode })
|
||||
return true
|
||||
}
|
||||
if (message?.type === 'DISMISS_BANNER') {
|
||||
bannerDismissed = true
|
||||
removeBanner()
|
||||
sendResponse({ ok: true })
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// === AFFICHAGE IMMÉDIAT DE LA BANNIÈRE ===
|
||||
// On n'attend pas SET_PICK_MODE — le side panel peut être lent à nous
|
||||
// parler (race conditions MV3). La bannière est le seul signal visuel
|
||||
// pour l'utilisateur que l'extension est active et qu'il peut clipper.
|
||||
// L'utilisateur peut la fermer via le bouton ✕.
|
||||
if (!isRestrictedUrl(location.href)) {
|
||||
setPickMode(true)
|
||||
}
|
||||
|
||||
// Notifie le side panel qu'on est là (peut aider à amorcer).
|
||||
broadcastSelection()
|
||||
})()
|
||||
|
||||
Reference in New Issue
Block a user