278 lines
8.0 KiB
JavaScript
278 lines
8.0 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
const browser = globalThis.browser || globalThis.chrome;
|
|
|
|
const statusEl = document.getElementById('status');
|
|
const countBadge = document.getElementById('count-badge');
|
|
const previewEl = document.getElementById('preview');
|
|
const copyBtn = document.getElementById('copy-btn');
|
|
const copyLabel = copyBtn.querySelector('.btn-label');
|
|
const viewNameEl = document.getElementById('view-name');
|
|
|
|
let currentIds = [];
|
|
|
|
function parseViewName(url) {
|
|
if (!url) return null;
|
|
try {
|
|
const u = new URL(url);
|
|
const raw = u.searchParams.get('viewname');
|
|
if (!raw) return null;
|
|
// Format attendu : AppName|ViewName
|
|
const parts = raw.split('|');
|
|
const name = parts.length > 1 ? parts[1] : parts[0];
|
|
return name ? name.trim() : null;
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function setViewName(name) {
|
|
if (!name) {
|
|
viewNameEl.hidden = true;
|
|
viewNameEl.textContent = '';
|
|
viewNameEl.removeAttribute('title');
|
|
return;
|
|
}
|
|
viewNameEl.textContent = name;
|
|
viewNameEl.title = name;
|
|
viewNameEl.hidden = false;
|
|
}
|
|
|
|
function setStatus(text, level) {
|
|
statusEl.textContent = text;
|
|
statusEl.className = 'status status--' + (level || 'info');
|
|
}
|
|
|
|
function setBadge(n) {
|
|
countBadge.textContent = String(n);
|
|
countBadge.classList.toggle('badge--active', n > 0);
|
|
}
|
|
|
|
function setPreview(pairs) {
|
|
// Vide le contenu existant
|
|
while (previewEl.firstChild) previewEl.removeChild(previewEl.firstChild);
|
|
|
|
if (!pairs || pairs.length === 0) return;
|
|
|
|
const MAX_PREVIEW = 50;
|
|
const visible = pairs.slice(0, MAX_PREVIEW);
|
|
|
|
for (const pair of visible) {
|
|
const item = document.createElement('li');
|
|
item.className = 'preview-item';
|
|
|
|
const codeEl = document.createElement('span');
|
|
codeEl.className = 'preview-code';
|
|
codeEl.textContent = pair.code || '(code inconnu)';
|
|
codeEl.title = codeEl.textContent;
|
|
|
|
const idEl = document.createElement('span');
|
|
idEl.className = 'preview-id';
|
|
idEl.textContent = pair.id;
|
|
idEl.title = pair.id;
|
|
|
|
item.appendChild(codeEl);
|
|
item.appendChild(idEl);
|
|
previewEl.appendChild(item);
|
|
}
|
|
|
|
if (pairs.length > MAX_PREVIEW) {
|
|
const more = document.createElement('li');
|
|
more.className = 'preview-more';
|
|
more.textContent = '... et ' + (pairs.length - MAX_PREVIEW) + ' de plus';
|
|
previewEl.appendChild(more);
|
|
}
|
|
}
|
|
|
|
function setButtonState(state) {
|
|
copyBtn.classList.remove('btn--primary', 'btn--ok', 'btn--error');
|
|
switch (state) {
|
|
case 'ok':
|
|
copyBtn.classList.add('btn--ok');
|
|
copyLabel.textContent = 'Copié';
|
|
break;
|
|
case 'error':
|
|
copyBtn.classList.add('btn--error');
|
|
copyLabel.textContent = 'Échec de la copie';
|
|
break;
|
|
case 'idle':
|
|
default:
|
|
copyBtn.classList.add('btn--primary');
|
|
copyLabel.textContent = 'Copier les IDs';
|
|
break;
|
|
}
|
|
}
|
|
|
|
function isSmartUiUrl(url) {
|
|
if (!url) return false;
|
|
try {
|
|
const u = new URL(url);
|
|
return /\/SmartUI\//i.test(u.pathname);
|
|
} catch (e) {
|
|
return /\/SmartUI\//i.test(url);
|
|
}
|
|
}
|
|
|
|
function queryActiveTab() {
|
|
return new Promise((resolve) => {
|
|
try {
|
|
browser.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
resolve(tabs && tabs[0] ? tabs[0] : null);
|
|
});
|
|
} catch (e) {
|
|
resolve(null);
|
|
}
|
|
});
|
|
}
|
|
|
|
function sendMessage(tabId, msg) {
|
|
return new Promise((resolve) => {
|
|
let settled = false;
|
|
const done = (value) => {
|
|
if (settled) return;
|
|
settled = true;
|
|
resolve(value);
|
|
};
|
|
try {
|
|
browser.tabs.sendMessage(tabId, msg, (response) => {
|
|
const err = browser.runtime && browser.runtime.lastError;
|
|
if (err) {
|
|
done({ ok: false, error: err.message || String(err) });
|
|
} else {
|
|
done(response || { ok: false, error: 'empty_response' });
|
|
}
|
|
});
|
|
} catch (e) {
|
|
done({ ok: false, error: String(e && e.message ? e.message : e) });
|
|
}
|
|
setTimeout(() => done({ ok: false, error: 'timeout' }), 1500);
|
|
});
|
|
}
|
|
|
|
async function refresh() {
|
|
const tab = await queryActiveTab();
|
|
if (!tab) {
|
|
setStatus("Impossible de lire l'onglet actif.", 'error');
|
|
setBadge(0);
|
|
setPreview([]);
|
|
setViewName(null);
|
|
copyBtn.disabled = true;
|
|
return;
|
|
}
|
|
|
|
if (!isSmartUiUrl(tab.url)) {
|
|
setStatus("Cette page n'est pas une vue SmartUI.", 'warn');
|
|
setBadge(0);
|
|
setPreview([]);
|
|
setViewName(null);
|
|
copyBtn.disabled = true;
|
|
return;
|
|
}
|
|
|
|
setViewName(parseViewName(tab.url));
|
|
|
|
let resp = await sendMessage(tab.id, { type: 'GET_SELECTED_IDS' });
|
|
|
|
// Si le content script ne repond pas, l'injecter programmatiquement et reessayer
|
|
if (!resp || resp.ok === false) {
|
|
setStatus("Injection du content script...", 'info');
|
|
try {
|
|
await browser.scripting.executeScript({
|
|
target: { tabId: tab.id, allFrames: true },
|
|
files: ['content/content-script.js']
|
|
});
|
|
// Attendre que le script s'initialise
|
|
await new Promise((r) => setTimeout(r, 800));
|
|
resp = await sendMessage(tab.id, { type: 'GET_SELECTED_IDS' });
|
|
} catch (e) {
|
|
console.warn('[TakeID] Injection failed:', e);
|
|
}
|
|
}
|
|
|
|
if (!resp || resp.ok === false) {
|
|
setStatus(
|
|
"Le content script ne répond pas. Rechargez la page SmartUI puis réouvrez le popup.",
|
|
'error'
|
|
);
|
|
setBadge(0);
|
|
setPreview([]);
|
|
copyBtn.disabled = true;
|
|
return;
|
|
}
|
|
|
|
const pairs = Array.isArray(resp.pairs)
|
|
? resp.pairs
|
|
: (Array.isArray(resp.ids) ? resp.ids.map((id) => ({ id, code: null })) : []);
|
|
currentIds = pairs.map((p) => p.id);
|
|
|
|
setBadge(currentIds.length);
|
|
setPreview(pairs);
|
|
|
|
if (currentIds.length === 0) {
|
|
if (!resp.cacheSize) {
|
|
setStatus(
|
|
"Aucune donnée en cache. Naviguez sur la grille (ou rafraîchissez la vue) pour que l'extension capture les IDs.",
|
|
'warn'
|
|
);
|
|
} else if (!resp.selectedCount) {
|
|
setStatus(
|
|
"Aucune ligne sélectionnée. Cochez les lignes dans la grille puis réouvrez le popup.",
|
|
'warn'
|
|
);
|
|
} else {
|
|
setStatus(
|
|
"Lignes sélectionnées détectées mais aucun ID associé trouvé dans le cache.",
|
|
'warn'
|
|
);
|
|
}
|
|
copyBtn.disabled = true;
|
|
} else {
|
|
setStatus(
|
|
currentIds.length + ' ID' + (currentIds.length > 1 ? 's' : '') + ' prêt' + (currentIds.length > 1 ? 's' : '') + ' à copier.',
|
|
'ok'
|
|
);
|
|
copyBtn.disabled = false;
|
|
}
|
|
}
|
|
|
|
async function copyIds() {
|
|
if (!currentIds || currentIds.length === 0) return;
|
|
const text = currentIds.join('\n');
|
|
try {
|
|
await navigator.clipboard.writeText(text);
|
|
setButtonState('ok');
|
|
setStatus(currentIds.length + ' ID(s) copié(s) dans le presse-papier.', 'ok');
|
|
setTimeout(() => setButtonState('idle'), 1400);
|
|
} catch (e) {
|
|
// Fallback : execCommand
|
|
try {
|
|
const ta = document.createElement('textarea');
|
|
ta.value = text;
|
|
ta.style.position = 'fixed';
|
|
ta.style.opacity = '0';
|
|
document.body.appendChild(ta);
|
|
ta.select();
|
|
const ok = document.execCommand('copy');
|
|
document.body.removeChild(ta);
|
|
if (ok) {
|
|
setButtonState('ok');
|
|
setStatus(currentIds.length + ' ID(s) copié(s).', 'ok');
|
|
setTimeout(() => setButtonState('idle'), 1400);
|
|
} else {
|
|
throw new Error('execCommand failed');
|
|
}
|
|
} catch (e2) {
|
|
setButtonState('error');
|
|
setStatus('Échec de la copie : ' + (e2.message || e2), 'error');
|
|
setTimeout(() => setButtonState('idle'), 1800);
|
|
}
|
|
}
|
|
}
|
|
|
|
copyBtn.addEventListener('click', copyIds);
|
|
|
|
document.addEventListener('DOMContentLoaded', refresh);
|
|
if (document.readyState !== 'loading') refresh();
|
|
})();
|