diff --git a/css/style.css b/css/style.css
index c624ef6..89667c3 100644
--- a/css/style.css
+++ b/css/style.css
@@ -2133,6 +2133,16 @@ input[type="range"]::-webkit-slider-thumb {
color: var(--text);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
+.qs-mode {
+ display: flex; gap: 2px; padding: 2px; flex-shrink: 0;
+ background: var(--bg-elev-2); border-radius: 999px;
+}
+.qs-mode button {
+ border: 0; background: none; cursor: pointer;
+ color: var(--text-dim); font-size: 12px;
+ padding: 4px 10px; border-radius: 999px;
+}
+.qs-mode button.is-on { background: var(--accent); color: #fff; }
.quick-search-acts {
display: flex; gap: 2px; flex-shrink: 0;
}
diff --git a/index.html b/index.html
index a5655eb..778bb67 100644
--- a/index.html
+++ b/index.html
@@ -1231,6 +1231,12 @@
+
+
+
+
+
Esc
diff --git a/js/app.overlays.js b/js/app.overlays.js
index 981bc26..eb8638c 100644
--- a/js/app.overlays.js
+++ b/js/app.overlays.js
@@ -27,6 +27,39 @@ let quickSearchHideAfter = false;
// HWND and is waiting for cmd://autofill/execute. On pick we SendInput
// the password instead of copying to the clipboard.
let quickSearchFillMode = false;
+// CE QUE L'UTILISATEUR PREFERE quand une cible existe : remplir, ou copier
+// quand meme - le remplissage echoue vers une application lancee en
+// administrateur, ou quand le gestionnaire de Chrome s'en mele. Retenu en pref
+// DPAPI : localStorage se vide a chaque lancement (port ephemere).
+let quickSearchPreferCopy = false;
+
+/// Remplit-on vraiment ? Il faut une cible ET ne pas avoir choisi Copy.
+function qsFills() { return quickSearchFillMode && !quickSearchPreferCopy; }
+
+function qsApplyMode() {
+ const box = document.getElementById('qsMode');
+ if (box) {
+ box.hidden = !quickSearchFillMode;
+ box.querySelectorAll('[data-qsmode]').forEach(b =>
+ b.classList.toggle('is-on', (b.dataset.qsmode === 'fill') === qsFills()));
+ }
+ const hintEl = document.querySelector('#quickSearchModal .quick-search-hint');
+ if (hintEl) {
+ hintEl.textContent = qsFills()
+ ? 'Enter / click = password · Shift+Enter / right-click = user+password · Ctrl+Enter / Ctrl+click = username · Esc = cancel'
+ : 'Enter / click = copy password · Ctrl+Enter / Ctrl+click = copy username · Esc = close';
+ }
+}
+
+document.addEventListener('click', ev => {
+ const b = ev.target.closest && ev.target.closest('[data-qsmode]');
+ if (!b) return;
+ quickSearchPreferCopy = b.dataset.qsmode === 'copy';
+ if (Bridge.active) Bridge.setPref('qsCopy', quickSearchPreferCopy ? '1' : '0');
+ qsApplyMode();
+ quickSearchRender();
+ document.getElementById('quickSearchInput').focus();
+});
function quickSearchScoreEntry(e, q) {
if (!q) return 1; // empty query → all entries pass, ordering preserved
@@ -89,7 +122,7 @@ function quickSearchRender() {
row.appendChild(avatar);
row.appendChild(main);
// Un bouton par valeur presente : pas besoin de retenir clic / Ctrl+clic.
- const verb = quickSearchFillMode ? 'Fill ' : 'Copy ';
+ const verb = qsFills() ? 'Fill ' : 'Copy ';
const acts = el('div', { class: 'quick-search-acts' });
const act = (ic, title, mode) => {
const b = el('button', { class: 'icon-btn icon-btn-sm', type: 'button', title });
@@ -133,7 +166,7 @@ async function quickSearchPickEntry(entry, mode) {
try { if (secret && secret !== '[ERROR]') code = (await generateTOTP(secret)).code; }
catch (_) { code = ''; }
if (!code) { toast('2FA: cannot read the secret', 'error'); return; }
- if (quickSearchFillMode) {
+ if (qsFills()) {
autofillPendingToast = entryDisplayName(entry) + ' · 2FA code sent';
if (Bridge.active) Bridge.executeAutofill('', code, quickSearchHideAfter);
quickSearchFillMode = false;
@@ -159,7 +192,7 @@ async function quickSearchPickEntry(entry, mode) {
// Fill mode (Ctrl+Shift+Q hotkey): SendInput directly into the HWND
// Delphi saved when the hotkey fired. No clipboard touch.
- if (quickSearchFillMode) {
+ if (qsFills()) {
if (mode === 'user') {
const u = entry.username || '';
if (!u) { toast('No username on this entry', 'warning'); return; }
@@ -527,12 +560,15 @@ function openQuickSearchModal(hideAfter, forFill) {
quickSearchSelected = 0;
quickSearchHideAfter = !!hideAfter;
quickSearchFillMode = !!forFill;
- // Subtle hint to the user about what Enter will do.
- const hintEl = modal.querySelector('.quick-search-hint');
- if (hintEl) {
- hintEl.textContent = forFill
- ? 'Enter / click = password · Shift+Enter / right-click = user+password · Ctrl+Enter / Ctrl+click = username · Esc = cancel'
- : 'Enter / click = copy password · Ctrl+Enter / Ctrl+click = copy username · Esc = close';
+ qsApplyMode();
+ // La preference arrive de Delphi : on affiche tout de suite, et on
+ // rectifie des qu'elle est la (une fraction de seconde).
+ if (forFill && Bridge.active) {
+ Bridge.getPref('qsCopy').then(v => {
+ quickSearchPreferCopy = v === '1';
+ qsApplyMode();
+ quickSearchRender();
+ }).catch(() => {});
}
quickSearchRender();
setTimeout(() => input.focus(), 50);