v0.2
This commit is contained in:
+277
@@ -0,0 +1,277 @@
|
||||
(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();
|
||||
})();
|
||||
Reference in New Issue
Block a user