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:
@@ -3,12 +3,6 @@ const ALLOW_INSTANCE_CONFIG = true
|
||||
const DEFAULT_BASE = 'https://memento-note.com'
|
||||
const STORAGE_KEYS = { baseUrl: 'memento_clipper_base_url', notebookId: 'memento_clipper_notebook_id' }
|
||||
|
||||
/** Compatibilité Chrome/Firefox : Firefox expose l'API sous `browser.*`,
|
||||
* Chrome sous `chrome.*`. On normalise pour utiliser `chrome.*` partout dans le code. */
|
||||
if (typeof chrome === 'undefined' && typeof browser !== 'undefined') {
|
||||
globalThis.chrome = browser
|
||||
}
|
||||
|
||||
let state = 'idle'
|
||||
let notebooks = []
|
||||
let selectedNotebookId = ''
|
||||
@@ -160,32 +154,18 @@ 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 {
|
||||
/* pas injecté */
|
||||
/* 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) {
|
||||
@@ -195,7 +175,7 @@ async function setPickModeOnTab(enabled) {
|
||||
try {
|
||||
await chrome.tabs.sendMessage(activeTabId, { type: 'SET_PICK_MODE', enabled })
|
||||
} catch {
|
||||
/* ignore — retry au prochain syncPickMode */
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,9 +246,6 @@ function bindIdleHandlers() {
|
||||
document.getElementById('clipSelBtn')?.addEventListener('click', () => void runAnalyze('selection'))
|
||||
document.getElementById('clipPageBtn')?.addEventListener('click', () => void runAnalyze('page'))
|
||||
document.getElementById('clipLinkBtn')?.addEventListener('click', () => void runAnalyze('link'))
|
||||
document.getElementById('openLoginFromHint')?.addEventListener('click', () => {
|
||||
chrome.tabs.create({ url: apiBase() })
|
||||
})
|
||||
|
||||
// Gérer l'erreur de chargement du favicon
|
||||
document.querySelector('.page-favicon')?.addEventListener('error', function() {
|
||||
@@ -307,41 +284,11 @@ function updateSelectionUI() {
|
||||
}
|
||||
|
||||
function applySelectionFromMessage(msg) {
|
||||
if (!msg) return
|
||||
// Tolérance sur la comparaison d'URL : ignorer trailing slash, query,
|
||||
// fragment. Si pageUrl est vide (panel ouvert avant refreshPageContext),
|
||||
// on accepte la première sélection qui arrive.
|
||||
const normalize = (u) => {
|
||||
try {
|
||||
const p = new URL(u)
|
||||
return `${p.origin}${p.pathname.replace(/\/$/, '')}`
|
||||
} catch { return u || '' }
|
||||
}
|
||||
// Si on n'a pas encore de pageUrl mais qu'un message arrive avec URL,
|
||||
// on l'utilise pour amorcer la fiche page. Très utile quand chrome.tabs.query
|
||||
// rate (ex. onglet sans permission, side panel non focus, etc.).
|
||||
if (msg.url && (!pageUrl || normalize(msg.url) !== normalize(pageUrl))) {
|
||||
if (!pageUrl) {
|
||||
pageUrl = msg.url
|
||||
pageTitle = msg.title || pageTitle || ''
|
||||
try {
|
||||
const u = new URL(msg.url)
|
||||
pageDomain = u.hostname
|
||||
pageFavicon = `https://www.google.com/s2/favicons?domain=${u.hostname}&sz=32`
|
||||
} catch { /* ignore */ }
|
||||
} else {
|
||||
// URL vraiment différente — ignorer.
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!msg || msg.url !== pageUrl) return
|
||||
selectionText = msg.text || ''
|
||||
if (msg.dir?.toLowerCase() === 'rtl') pageDir = 'rtl'
|
||||
if (msg.lang) pageLang = msg.lang
|
||||
if (state === 'idle') {
|
||||
updateSelectionUI()
|
||||
} else {
|
||||
console.debug('[memento] selection updated while busy, deferring UI')
|
||||
}
|
||||
if (state === 'idle') updateSelectionUI()
|
||||
}
|
||||
|
||||
async function refreshPageContext() {
|
||||
@@ -410,15 +357,12 @@ async function loadSettings() {
|
||||
async function loadNotebooks(preferredId) {
|
||||
try {
|
||||
await ensureApiPermission()
|
||||
const url = `${apiBase()}/api/clip/notebooks`
|
||||
const res = await fetch(url, { credentials: 'include' })
|
||||
const res = await fetch(`${apiBase()}/api/clip/notebooks`, { credentials: 'include' })
|
||||
if (!res.ok) {
|
||||
connected = false
|
||||
updateConnBadge()
|
||||
if (res.status === 401) {
|
||||
// Diagnostic : préciser l'URL configurée pour aider l'utilisateur à
|
||||
// diagnostiquer un mismatch (localhost vs 127.0.0.1 vs LAN IP).
|
||||
throw new Error(`${t('errLoginRequired')}\n${t('errLoginHintUrl', apiBase())}`)
|
||||
throw new Error(t('errLoginRequired'))
|
||||
}
|
||||
throw new Error(t('errLoadNotebooks'))
|
||||
}
|
||||
@@ -459,11 +403,7 @@ function renderIdle() {
|
||||
|
||||
const authHint =
|
||||
!connected && errorMessage
|
||||
? `<div class="auth-hint">${escapeHtml(errorMessage).replace(/\n/g, '<br/>')}
|
||||
<div style="margin-top:8px">
|
||||
<button type="button" class="btn btn-secondary btn-sm" id="openLoginFromHint">${escapeHtml(t('openMomento'))}</button>
|
||||
</div>
|
||||
</div>`
|
||||
? `<div class="auth-hint">${escapeHtml(errorMessage)}</div>`
|
||||
: ''
|
||||
|
||||
els.screen.innerHTML = `
|
||||
|
||||
Reference in New Issue
Block a user