mirror of
https://github.com/avinal/sciezka.git
synced 2026-07-03 23:30:09 +05:30
feat: add inline config panel for search method and mode order
Assisted-by: Claude Code Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com>
This commit is contained in:
+142
@@ -149,6 +149,148 @@ body {
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Config button */
|
||||||
|
#config-btn {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.12s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#config-btn:hover {
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
#config-btn.active {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Config panel */
|
||||||
|
#config-panel {
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-section {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-section:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-label {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-dim);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-hint {
|
||||||
|
font-weight: 400;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: 0;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-method-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-method-btn {
|
||||||
|
flex: 1;
|
||||||
|
padding: 6px 0;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-dim);
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.12s, color 0.12s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-method-btn:hover {
|
||||||
|
background: var(--hover);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-method-btn.active {
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-order-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-order-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 6px 10px;
|
||||||
|
background: var(--bg-alt);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
cursor: grab;
|
||||||
|
transition: background 0.08s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-order-row:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-order-row.dragging {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-order-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-arrows {
|
||||||
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-arrow-btn {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.08s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-arrow-btn:hover:not(:disabled) {
|
||||||
|
background: var(--hover);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-arrow-btn:disabled {
|
||||||
|
opacity: 0.3;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mode bar */
|
/* Mode bar */
|
||||||
#mode-bar {
|
#mode-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -12,9 +12,15 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<input id="search-input" type="text" placeholder="Search tabs, history, bookmarks..." autofocus>
|
<input id="search-input" type="text" placeholder="Search tabs, history, bookmarks..." autofocus>
|
||||||
<span id="method-badge">fuzzy</span>
|
<span id="method-badge">fuzzy</span>
|
||||||
|
<button id="config-btn" title="Settings">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="mode-bar"></div>
|
<div id="mode-bar"></div>
|
||||||
<div id="results"></div>
|
<div id="results"></div>
|
||||||
|
<div id="config-panel" style="display:none"></div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<span class="hint"><kbd>↑↓</kbd> navigate</span>
|
<span class="hint"><kbd>↑↓</kbd> navigate</span>
|
||||||
<span class="hint"><kbd>Enter</kbd> open</span>
|
<span class="hint"><kbd>Enter</kbd> open</span>
|
||||||
|
|||||||
+30
-1
@@ -1,4 +1,21 @@
|
|||||||
import type { Message, SearchRequest, ActionRequest, SearchItem } from "./types";
|
import type { Message, SearchRequest, ActionRequest, SearchItem, Settings } from "./types";
|
||||||
|
|
||||||
|
const DEFAULT_SETTINGS: Settings = {
|
||||||
|
defaultMethod: "fuzzy",
|
||||||
|
modeOrder: ["tabs", "history", "bookmarks", "closed"],
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getSettings(): Promise<Settings> {
|
||||||
|
const data = await chrome.storage.sync.get(["defaultMethod", "modeOrder"]);
|
||||||
|
return { ...DEFAULT_SETTINGS, ...data } as Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveSettings(partial: Partial<Settings>): Promise<Settings> {
|
||||||
|
const current = await getSettings();
|
||||||
|
const updated = { ...current, ...partial };
|
||||||
|
await chrome.storage.sync.set(updated);
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
function sortByRecent(items: SearchItem[]): SearchItem[] {
|
function sortByRecent(items: SearchItem[]): SearchItem[] {
|
||||||
return items.sort((a, b) => (b.lastAccessed ?? 0) - (a.lastAccessed ?? 0));
|
return items.sort((a, b) => (b.lastAccessed ?? 0) - (a.lastAccessed ?? 0));
|
||||||
@@ -135,5 +152,17 @@ chrome.runtime.onMessage.addListener(
|
|||||||
handleAction(message).then(() => sendResponse({ ok: true }));
|
handleAction(message).then(() => sendResponse({ ok: true }));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (message.type === "getSettings") {
|
||||||
|
getSettings().then((settings) => {
|
||||||
|
sendResponse({ type: "settingsResponse", settings });
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (message.type === "saveSettings") {
|
||||||
|
saveSettings(message.settings).then((settings) => {
|
||||||
|
sendResponse({ type: "settingsResponse", settings });
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-1
@@ -98,7 +98,7 @@ window.addEventListener("message", (event) => {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.type === "search" || data.type === "action") {
|
if (data.type === "search" || data.type === "action" || data.type === "getSettings" || data.type === "saveSettings") {
|
||||||
chrome.runtime.sendMessage(data, (response: unknown) => {
|
chrome.runtime.sendMessage(data, (response: unknown) => {
|
||||||
const msg = typeof response === "object" && response ? { ...(response as Record<string, unknown>), _nonce: messageNonce } : response;
|
const msg = typeof response === "object" && response ? { ...(response as Record<string, unknown>), _nonce: messageNonce } : response;
|
||||||
iframe?.contentWindow?.postMessage(msg, EXTENSION_ORIGIN);
|
iframe?.contentWindow?.postMessage(msg, EXTENSION_ORIGIN);
|
||||||
|
|||||||
+160
-10
@@ -1,7 +1,7 @@
|
|||||||
import { search } from "./search";
|
import { search } from "./search";
|
||||||
import type { SearchItem, SearchMode, SearchMethod, SearchResult, Message } from "./types";
|
import type { SearchItem, SearchMode, SearchMethod, SearchResult, Message, Settings } from "./types";
|
||||||
|
|
||||||
const MODES: SearchMode[] = ["tabs", "history", "bookmarks", "closed"];
|
const ALL_MODES: SearchMode[] = ["tabs", "history", "bookmarks", "closed"];
|
||||||
const MODE_LABELS: Record<SearchMode, string> = {
|
const MODE_LABELS: Record<SearchMode, string> = {
|
||||||
tabs: "Tabs",
|
tabs: "Tabs",
|
||||||
history: "History",
|
history: "History",
|
||||||
@@ -9,20 +9,29 @@ const MODE_LABELS: Record<SearchMode, string> = {
|
|||||||
closed: "Closed",
|
closed: "Closed",
|
||||||
};
|
};
|
||||||
const METHODS: SearchMethod[] = ["fuzzy", "fulltext", "prefix"];
|
const METHODS: SearchMethod[] = ["fuzzy", "fulltext", "prefix"];
|
||||||
|
const METHOD_LABELS: Record<SearchMethod, string> = {
|
||||||
|
fuzzy: "Fuzzy",
|
||||||
|
fulltext: "Full Text",
|
||||||
|
prefix: "Prefix",
|
||||||
|
};
|
||||||
|
|
||||||
const MESSAGE_NONCE = location.hash.slice(1);
|
const MESSAGE_NONCE = location.hash.slice(1);
|
||||||
|
|
||||||
|
let modes: SearchMode[] = [...ALL_MODES];
|
||||||
let currentMode: SearchMode = "tabs";
|
let currentMode: SearchMode = "tabs";
|
||||||
let currentMethod: SearchMethod = "fuzzy";
|
let currentMethod: SearchMethod = "fuzzy";
|
||||||
let results: SearchResult[] = [];
|
let results: SearchResult[] = [];
|
||||||
let selectedIndex = 0;
|
let selectedIndex = 0;
|
||||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
let configOpen = false;
|
||||||
|
|
||||||
const input = document.getElementById("search-input") as HTMLInputElement;
|
const input = document.getElementById("search-input") as HTMLInputElement;
|
||||||
const resultsContainer = document.getElementById("results") as HTMLDivElement;
|
const resultsContainer = document.getElementById("results") as HTMLDivElement;
|
||||||
const modeBar = document.getElementById("mode-bar") as HTMLDivElement;
|
const modeBar = document.getElementById("mode-bar") as HTMLDivElement;
|
||||||
const methodBadge = document.getElementById("method-badge") as HTMLSpanElement;
|
const methodBadge = document.getElementById("method-badge") as HTMLSpanElement;
|
||||||
const root = document.getElementById("sciezka-root") as HTMLDivElement;
|
const root = document.getElementById("sciezka-root") as HTMLDivElement;
|
||||||
|
const configPanel = document.getElementById("config-panel") as HTMLDivElement;
|
||||||
|
const configBtn = document.getElementById("config-btn") as HTMLButtonElement;
|
||||||
|
|
||||||
function notifyResize(): void {
|
function notifyResize(): void {
|
||||||
const height = Math.min(root.scrollHeight, 520);
|
const height = Math.min(root.scrollHeight, 520);
|
||||||
@@ -42,10 +51,17 @@ function sendMessage(msg: Message): Promise<unknown> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function persistSettings(): void {
|
||||||
|
sendMessage({
|
||||||
|
type: "saveSettings",
|
||||||
|
settings: { defaultMethod: currentMethod, modeOrder: modes },
|
||||||
|
} as Message);
|
||||||
|
}
|
||||||
|
|
||||||
function renderModeBar(): void {
|
function renderModeBar(): void {
|
||||||
modeBar.innerHTML = "";
|
modeBar.innerHTML = "";
|
||||||
for (let i = 0; i < MODES.length; i++) {
|
for (let i = 0; i < modes.length; i++) {
|
||||||
const mode = MODES[i];
|
const mode = modes[i];
|
||||||
const btn = document.createElement("button");
|
const btn = document.createElement("button");
|
||||||
btn.className = `mode-btn${mode === currentMode ? " active" : ""}`;
|
btn.className = `mode-btn${mode === currentMode ? " active" : ""}`;
|
||||||
btn.innerHTML = `<span class="mode-label">${MODE_LABELS[mode]}</span><kbd>${i + 1}</kbd>`;
|
btn.innerHTML = `<span class="mode-label">${MODE_LABELS[mode]}</span><kbd>${i + 1}</kbd>`;
|
||||||
@@ -62,6 +78,114 @@ function renderMethodBadge(): void {
|
|||||||
methodBadge.textContent = currentMethod;
|
methodBadge.textContent = currentMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleConfig(): void {
|
||||||
|
configOpen = !configOpen;
|
||||||
|
configBtn.classList.toggle("active", configOpen);
|
||||||
|
if (configOpen) {
|
||||||
|
resultsContainer.style.display = "none";
|
||||||
|
configPanel.style.display = "block";
|
||||||
|
renderConfigPanel();
|
||||||
|
} else {
|
||||||
|
configPanel.style.display = "none";
|
||||||
|
resultsContainer.style.display = "";
|
||||||
|
}
|
||||||
|
notifyResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderConfigPanel(): void {
|
||||||
|
configPanel.innerHTML = "";
|
||||||
|
|
||||||
|
const methodSection = document.createElement("div");
|
||||||
|
methodSection.className = "config-section";
|
||||||
|
methodSection.innerHTML = `<div class="config-label">Search Method</div>`;
|
||||||
|
const methodRow = document.createElement("div");
|
||||||
|
methodRow.className = "config-method-row";
|
||||||
|
for (const m of METHODS) {
|
||||||
|
const btn = document.createElement("button");
|
||||||
|
btn.className = `config-method-btn${m === currentMethod ? " active" : ""}`;
|
||||||
|
btn.textContent = METHOD_LABELS[m];
|
||||||
|
btn.addEventListener("click", () => {
|
||||||
|
currentMethod = m;
|
||||||
|
renderMethodBadge();
|
||||||
|
renderConfigPanel();
|
||||||
|
persistSettings();
|
||||||
|
doSearch();
|
||||||
|
});
|
||||||
|
methodRow.appendChild(btn);
|
||||||
|
}
|
||||||
|
methodSection.appendChild(methodRow);
|
||||||
|
configPanel.appendChild(methodSection);
|
||||||
|
|
||||||
|
const orderSection = document.createElement("div");
|
||||||
|
orderSection.className = "config-section";
|
||||||
|
orderSection.innerHTML = `<div class="config-label">Tab Order <span class="config-hint">drag or use arrows</span></div>`;
|
||||||
|
const orderList = document.createElement("div");
|
||||||
|
orderList.className = "config-order-list";
|
||||||
|
|
||||||
|
for (let i = 0; i < modes.length; i++) {
|
||||||
|
const mode = modes[i];
|
||||||
|
const row = document.createElement("div");
|
||||||
|
row.className = "config-order-row";
|
||||||
|
row.draggable = true;
|
||||||
|
row.dataset.index = String(i);
|
||||||
|
|
||||||
|
const label = document.createElement("span");
|
||||||
|
label.className = "config-order-label";
|
||||||
|
label.textContent = MODE_LABELS[mode];
|
||||||
|
|
||||||
|
const arrows = document.createElement("span");
|
||||||
|
arrows.className = "config-arrows";
|
||||||
|
|
||||||
|
const upBtn = document.createElement("button");
|
||||||
|
upBtn.className = "config-arrow-btn";
|
||||||
|
upBtn.textContent = "\u25B2";
|
||||||
|
upBtn.disabled = i === 0;
|
||||||
|
upBtn.addEventListener("click", () => { swapModes(i, i - 1); });
|
||||||
|
|
||||||
|
const downBtn = document.createElement("button");
|
||||||
|
downBtn.className = "config-arrow-btn";
|
||||||
|
downBtn.textContent = "\u25BC";
|
||||||
|
downBtn.disabled = i === modes.length - 1;
|
||||||
|
downBtn.addEventListener("click", () => { swapModes(i, i + 1); });
|
||||||
|
|
||||||
|
arrows.appendChild(upBtn);
|
||||||
|
arrows.appendChild(downBtn);
|
||||||
|
row.appendChild(label);
|
||||||
|
row.appendChild(arrows);
|
||||||
|
|
||||||
|
row.addEventListener("dragstart", (e) => {
|
||||||
|
e.dataTransfer?.setData("text/plain", String(i));
|
||||||
|
row.classList.add("dragging");
|
||||||
|
});
|
||||||
|
row.addEventListener("dragend", () => { row.classList.remove("dragging"); });
|
||||||
|
row.addEventListener("dragover", (e) => { e.preventDefault(); });
|
||||||
|
row.addEventListener("drop", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const from = parseInt(e.dataTransfer?.getData("text/plain") ?? "", 10);
|
||||||
|
if (!isNaN(from) && from !== i) {
|
||||||
|
const moved = modes.splice(from, 1)[0];
|
||||||
|
modes.splice(i, 0, moved);
|
||||||
|
if (currentMode === modes[0]) currentMode = modes[0];
|
||||||
|
renderModeBar();
|
||||||
|
renderConfigPanel();
|
||||||
|
persistSettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
orderList.appendChild(row);
|
||||||
|
}
|
||||||
|
orderSection.appendChild(orderList);
|
||||||
|
configPanel.appendChild(orderSection);
|
||||||
|
notifyResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
function swapModes(a: number, b: number): void {
|
||||||
|
[modes[a], modes[b]] = [modes[b], modes[a]];
|
||||||
|
renderModeBar();
|
||||||
|
renderConfigPanel();
|
||||||
|
persistSettings();
|
||||||
|
}
|
||||||
|
|
||||||
function highlightText(text: string, positions: number[], offset: number): string {
|
function highlightText(text: string, positions: number[], offset: number): string {
|
||||||
const posSet = new Set(positions.map((p) => p - offset).filter((p) => p >= 0 && p < text.length));
|
const posSet = new Set(positions.map((p) => p - offset).filter((p) => p >= 0 && p < text.length));
|
||||||
let result = "";
|
let result = "";
|
||||||
@@ -188,12 +312,20 @@ input.addEventListener("input", () => {
|
|||||||
debounceTimer = setTimeout(doSearch, 50);
|
debounceTimer = setTimeout(doSearch, 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
configBtn.addEventListener("click", toggleConfig);
|
||||||
|
|
||||||
document.addEventListener("keydown", (e) => {
|
document.addEventListener("keydown", (e) => {
|
||||||
if (e.key === "Escape") {
|
if (e.key === "Escape") {
|
||||||
|
if (configOpen) {
|
||||||
|
toggleConfig();
|
||||||
|
return;
|
||||||
|
}
|
||||||
window.parent.postMessage({ type: "closeSaka", _nonce: MESSAGE_NONCE }, "*");
|
window.parent.postMessage({ type: "closeSaka", _nonce: MESSAGE_NONCE }, "*");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (configOpen) return;
|
||||||
|
|
||||||
if (e.key === "ArrowDown" || (e.ctrlKey && e.key === "j")) {
|
if (e.key === "ArrowDown" || (e.ctrlKey && e.key === "j")) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
selectedIndex = Math.min(selectedIndex + 1, results.length - 1);
|
selectedIndex = Math.min(selectedIndex + 1, results.length - 1);
|
||||||
@@ -227,8 +359,8 @@ document.addEventListener("keydown", (e) => {
|
|||||||
if (e.key === "Tab") {
|
if (e.key === "Tab") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const dir = e.shiftKey ? -1 : 1;
|
const dir = e.shiftKey ? -1 : 1;
|
||||||
const idx = MODES.indexOf(currentMode);
|
const idx = modes.indexOf(currentMode);
|
||||||
currentMode = MODES[(idx + dir + MODES.length) % MODES.length];
|
currentMode = modes[(idx + dir + modes.length) % modes.length];
|
||||||
renderModeBar();
|
renderModeBar();
|
||||||
doSearch();
|
doSearch();
|
||||||
return;
|
return;
|
||||||
@@ -239,6 +371,7 @@ document.addEventListener("keydown", (e) => {
|
|||||||
const idx = METHODS.indexOf(currentMethod);
|
const idx = METHODS.indexOf(currentMethod);
|
||||||
currentMethod = METHODS[(idx + 1) % METHODS.length];
|
currentMethod = METHODS[(idx + 1) % METHODS.length];
|
||||||
renderMethodBadge();
|
renderMethodBadge();
|
||||||
|
persistSettings();
|
||||||
doSearch();
|
doSearch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -255,11 +388,11 @@ document.addEventListener("keydown", (e) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.ctrlKey && e.key >= "1" && e.key <= "5") {
|
if (e.ctrlKey && e.key >= "1" && e.key <= "4") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const modeIdx = parseInt(e.key, 10) - 1;
|
const modeIdx = parseInt(e.key, 10) - 1;
|
||||||
if (modeIdx < MODES.length) {
|
if (modeIdx < modes.length) {
|
||||||
currentMode = MODES[modeIdx];
|
currentMode = modes[modeIdx];
|
||||||
renderModeBar();
|
renderModeBar();
|
||||||
doSearch();
|
doSearch();
|
||||||
}
|
}
|
||||||
@@ -267,7 +400,24 @@ document.addEventListener("keydown", (e) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
async function loadSettings(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const response = await sendMessage({ type: "getSettings" } as Message);
|
||||||
|
const data = response as { type: string; settings: Settings };
|
||||||
|
if (data?.settings) {
|
||||||
|
currentMethod = data.settings.defaultMethod;
|
||||||
|
if (data.settings.modeOrder?.length) {
|
||||||
|
modes = data.settings.modeOrder;
|
||||||
|
currentMode = modes[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// defaults
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
|
await loadSettings();
|
||||||
renderModeBar();
|
renderModeBar();
|
||||||
renderMethodBadge();
|
renderMethodBadge();
|
||||||
input.focus();
|
input.focus();
|
||||||
|
|||||||
+23
-1
@@ -48,10 +48,32 @@ export interface ResizeMessage {
|
|||||||
height: number;
|
height: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Settings {
|
||||||
|
defaultMethod: SearchMethod;
|
||||||
|
modeOrder: SearchMode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetSettingsRequest {
|
||||||
|
type: "getSettings";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SaveSettingsRequest {
|
||||||
|
type: "saveSettings";
|
||||||
|
settings: Partial<Settings>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SettingsResponse {
|
||||||
|
type: "settingsResponse";
|
||||||
|
settings: Settings;
|
||||||
|
}
|
||||||
|
|
||||||
export type Message =
|
export type Message =
|
||||||
| SearchRequest
|
| SearchRequest
|
||||||
| SearchResponse
|
| SearchResponse
|
||||||
| ActionRequest
|
| ActionRequest
|
||||||
| ToggleMessage
|
| ToggleMessage
|
||||||
| CloseMessage
|
| CloseMessage
|
||||||
| ResizeMessage;
|
| ResizeMessage
|
||||||
|
| GetSettingsRequest
|
||||||
|
| SaveSettingsRequest
|
||||||
|
| SettingsResponse;
|
||||||
|
|||||||
Reference in New Issue
Block a user