Merge pull request #17 from richardnixondev/chore/remove-cmdk-palette
chore: remove Cmd+K command palette (kept blocking navigation)
This commit is contained in:
commit
74c6c4d759
4 changed files with 5 additions and 204 deletions
|
|
@ -7,7 +7,7 @@ packages = ["src"]
|
|||
|
||||
[project]
|
||||
name = "reddit-media-collector"
|
||||
version = "1.5.2"
|
||||
version = "1.5.3"
|
||||
description = "Self-hosted media collector for Reddit with Immich integration"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
|
|
|
|||
|
|
@ -1360,87 +1360,8 @@ body:not(.discreet) .discreet-banner {
|
|||
}
|
||||
}
|
||||
|
||||
/* Cmd+K palette overlay */
|
||||
/* Alpine x-cloak — still useful for other Alpine components mounted later */
|
||||
[x-cloak] { display: none !important; }
|
||||
.cmdk-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding-top: 10vh;
|
||||
z-index: 3000;
|
||||
}
|
||||
.cmdk-card {
|
||||
background: #272729;
|
||||
border: 1px solid #343536;
|
||||
border-radius: 10px;
|
||||
width: 90%;
|
||||
max-width: 560px;
|
||||
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.6);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.cmdk-close {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
z-index: 2;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #818384;
|
||||
font-size: 22px;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.cmdk-close:hover {
|
||||
background: #343536;
|
||||
color: #ff4500;
|
||||
}
|
||||
.cmdk-card > input {
|
||||
border: none;
|
||||
border-bottom: 1px solid #343536;
|
||||
border-radius: 0;
|
||||
padding: 16px;
|
||||
font-size: 16px;
|
||||
background: #1a1a1b;
|
||||
}
|
||||
.cmdk-card > input:focus {
|
||||
border-color: #ff4500;
|
||||
}
|
||||
.cmdk-results {
|
||||
max-height: 50vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.cmdk-group-label {
|
||||
padding: 8px 16px 4px;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
color: #818384;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.cmdk-item {
|
||||
padding: 8px 16px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
.cmdk-item.active,
|
||||
.cmdk-item:hover {
|
||||
background: #343536;
|
||||
color: #ff4500;
|
||||
}
|
||||
.cmdk-hint {
|
||||
padding: 8px 16px;
|
||||
font-size: 11px;
|
||||
color: #818384;
|
||||
border-top: 1px solid #343536;
|
||||
background: #1a1a1b;
|
||||
}
|
||||
|
||||
/* PIN unlock screen */
|
||||
.unlock-wrap {
|
||||
|
|
|
|||
|
|
@ -1727,105 +1727,9 @@ async function removeTagRelation(parentId, childId, kind) {
|
|||
}
|
||||
window.removeTagRelation = removeTagRelation;
|
||||
|
||||
// ---- Cmd+K palette (Alpine component) ----
|
||||
|
||||
// Hard close: removes overlay from layout via plain DOM, bypassing Alpine.
|
||||
// Used by document-level listeners and the X button so a stuck Alpine state
|
||||
// can never trap the user.
|
||||
function cmdkForceClose() {
|
||||
const el = document.getElementById('cmdk-overlay');
|
||||
if (!el) return;
|
||||
el.style.display = 'none';
|
||||
const data = window.Alpine && Alpine.$data ? Alpine.$data(el) : null;
|
||||
if (data) data.open = false;
|
||||
}
|
||||
window.cmdkForceClose = cmdkForceClose;
|
||||
|
||||
// Document-level listener installed once at DOMContentLoaded. Uses
|
||||
// `capture: true` so it runs before any focused input swallows the key.
|
||||
// Independent of Alpine, so it works even if the component never mounted.
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
const el = document.getElementById('cmdk-overlay');
|
||||
if (el && getComputedStyle(el).display !== 'none') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
cmdkForceClose();
|
||||
}
|
||||
} else if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
|
||||
e.preventDefault();
|
||||
const el = document.getElementById('cmdk-overlay');
|
||||
const data = window.Alpine && Alpine.$data && el ? Alpine.$data(el) : null;
|
||||
if (data) data.toggle();
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
|
||||
function cmdkPalette() {
|
||||
return {
|
||||
open: false,
|
||||
query: '',
|
||||
active: 0,
|
||||
results: {authors: [], subreddits: [], tags: []},
|
||||
toggle() { this.open = !this.open; if (this.open) { this.query=''; this.results={authors:[],subreddits:[],tags:[]}; this.active=0; this.$nextTick(()=>this.$el.querySelector('input')?.focus()); } },
|
||||
close() { this.open = false; cmdkForceClose(); },
|
||||
async search() {
|
||||
const q = this.query.trim();
|
||||
if (!q) { this.results = {authors: [], subreddits: [], tags: []}; return; }
|
||||
try {
|
||||
const r = await fetch(`/api/search?q=${encodeURIComponent(q)}&limit=6`);
|
||||
if (r.ok) this.results = await r.json();
|
||||
this.active = 0;
|
||||
} catch (_) {}
|
||||
},
|
||||
groups() {
|
||||
const out = [];
|
||||
if (this.results.authors?.length) out.push({label: 'Autores', items: this.results.authors.map(a => ({label: 'u/'+a, kind: 'author', value: a}))});
|
||||
if (this.results.subreddits?.length) out.push({label: 'Subreddits', items: this.results.subreddits.map(s => ({label: 'r/'+s, kind: 'subreddit', value: s}))});
|
||||
if (this.results.tags?.length) out.push({label: 'Tags', items: this.results.tags.map(t => ({label: `#${t.name}${t.category ? ' ('+t.category+')' : ''}`, kind: 'tag', value: t.name}))});
|
||||
return out;
|
||||
},
|
||||
hasResults() { return this.groups().some(g => g.items.length > 0); },
|
||||
flatIndex(gi, ii) {
|
||||
let n = 0;
|
||||
const gs = this.groups();
|
||||
for (let i = 0; i < gi; i++) n += gs[i].items.length;
|
||||
return n + ii;
|
||||
},
|
||||
flatItems() {
|
||||
return this.groups().flatMap(g => g.items);
|
||||
},
|
||||
move(d) {
|
||||
const total = this.flatItems().length;
|
||||
if (!total) return;
|
||||
this.active = (this.active + d + total) % total;
|
||||
},
|
||||
choose() {
|
||||
const items = this.flatItems();
|
||||
if (items[this.active]) this.select(items[this.active]);
|
||||
},
|
||||
select(item) {
|
||||
this.close();
|
||||
if (item.kind === 'author') {
|
||||
switchTab('gallery', true);
|
||||
document.getElementById('filter-author').value = item.value;
|
||||
loadGallery();
|
||||
} else if (item.kind === 'subreddit') {
|
||||
switchTab('gallery', true);
|
||||
document.getElementById('filter-subreddit').value = item.value;
|
||||
loadGallery();
|
||||
} else if (item.kind === 'tag') {
|
||||
// No tag filter on gallery yet — drop into the tag in the bulk
|
||||
// bar as a shortcut for adding to current selection.
|
||||
const bulk = document.getElementById('bulk-tag-input');
|
||||
if (bulk) bulk.value = item.value;
|
||||
showAlert(`Tag "${item.value}" pronta para bulk-aplicar`, 'success');
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
window.cmdkPalette = cmdkPalette;
|
||||
// (The Cmd+K command palette was removed — it kept blocking navigation
|
||||
// regardless of how many close paths we added. `/api/search` stays in the
|
||||
// backend in case anything wants the universal typeahead by URL.)
|
||||
|
||||
// Alpine.store('prefs') — NSFW gate + discreet mode (Fase 1).
|
||||
document.addEventListener('alpine:init', () => {
|
||||
|
|
|
|||
|
|
@ -58,29 +58,5 @@
|
|||
{% include 'partials/_modal_author.html' %}
|
||||
{% include 'partials/_modal_media.html' %}
|
||||
{% include 'partials/_modal_tag.html' %}
|
||||
|
||||
<div id="cmdk-overlay" class="cmdk-overlay" x-data="cmdkPalette()" x-show="open" x-cloak
|
||||
@click.self="close()"
|
||||
onclick="if(event.target===this){cmdkForceClose();}">
|
||||
<div class="cmdk-card" @click.stop onclick="event.stopPropagation();">
|
||||
<button type="button" class="cmdk-close" onclick="cmdkForceClose();" title="Fechar (Esc)">×</button>
|
||||
<input type="text" x-model="query" @input.debounce.150ms="search()"
|
||||
@keydown.arrow-down.prevent="move(1)" @keydown.arrow-up.prevent="move(-1)"
|
||||
@keydown.enter.prevent="choose()"
|
||||
onkeydown="if(event.key==='Escape'){event.preventDefault();event.stopPropagation();cmdkForceClose();}"
|
||||
placeholder="Buscar autores, subreddits, tags..." autocomplete="off">
|
||||
<div class="cmdk-results" x-show="hasResults()">
|
||||
<template x-for="(group, gi) in groups()" :key="gi">
|
||||
<div>
|
||||
<div class="cmdk-group-label" x-text="group.label"></div>
|
||||
<template x-for="(item, ii) in group.items" :key="gi + ':' + ii">
|
||||
<div class="cmdk-item" :class="{active: flatIndex(gi, ii) === active}" @click="select(item)" x-text="item.label"></div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="cmdk-hint">⌘K / Ctrl+K para abrir · Esc ou X para fechar · clique fora também fecha</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue