This commit is contained in:
parent
c88d1886c9
commit
7f74aaced8
190
static/app.js
190
static/app.js
@ -56,13 +56,28 @@
|
||||
const graphModalClose = document.getElementById("graphModalClose");
|
||||
const channelMap = new Map();
|
||||
const transcriptCache = new Map();
|
||||
const SETTINGS_KEY = "tlc-search-settings";
|
||||
const DEFAULT_SETTINGS = {
|
||||
channel: "",
|
||||
year: "",
|
||||
sort: "relevant",
|
||||
size: "10",
|
||||
exact: true,
|
||||
fuzzy: true,
|
||||
phrase: true,
|
||||
external: false,
|
||||
queryString: false,
|
||||
};
|
||||
let settings = loadSettings();
|
||||
let lastFocusBeforeModal = null;
|
||||
let pendingChannelSelection = "";
|
||||
let channelsReady = false;
|
||||
let previousToggleState = { exact: true, fuzzy: true, phrase: true };
|
||||
let currentPage =
|
||||
parseInt(qs.get("page") || "0", 10) ||
|
||||
0;
|
||||
let previousToggleState = {
|
||||
exact: settings.exact,
|
||||
fuzzy: settings.fuzzy,
|
||||
phrase: settings.phrase,
|
||||
};
|
||||
let currentPage = 0;
|
||||
|
||||
function toggleAboutPanel(show) {
|
||||
if (!aboutPanel) return;
|
||||
@ -73,13 +88,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function parseBoolParam(name, defaultValue) {
|
||||
const raw = qs.get(name);
|
||||
if (raw === null) return defaultValue;
|
||||
const lowered = raw.toLowerCase();
|
||||
return !["0", "false", "no"].includes(lowered);
|
||||
}
|
||||
|
||||
function parseChannelParam(params) {
|
||||
if (!params) return "";
|
||||
const seen = new Set();
|
||||
@ -102,6 +110,69 @@
|
||||
return first || "";
|
||||
}
|
||||
|
||||
function loadSettings() {
|
||||
try {
|
||||
const raw = localStorage.getItem(SETTINGS_KEY);
|
||||
if (!raw) return { ...DEFAULT_SETTINGS };
|
||||
const parsed = JSON.parse(raw);
|
||||
return { ...DEFAULT_SETTINGS, ...parsed };
|
||||
} catch (err) {
|
||||
console.warn("Failed to load settings", err);
|
||||
return { ...DEFAULT_SETTINGS };
|
||||
}
|
||||
}
|
||||
|
||||
function persistSettings() {
|
||||
try {
|
||||
localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings));
|
||||
} catch (err) {
|
||||
console.warn("Failed to persist settings", err);
|
||||
}
|
||||
}
|
||||
|
||||
function applyStoredSettings() {
|
||||
yearSel.value = settings.year || "";
|
||||
sortSel.value = settings.sort || "relevant";
|
||||
sizeSel.value = settings.size || "10";
|
||||
exactToggle.checked = settings.exact;
|
||||
fuzzyToggle.checked = settings.fuzzy;
|
||||
phraseToggle.checked = settings.phrase;
|
||||
if (externalToggle) {
|
||||
externalToggle.checked = settings.external;
|
||||
}
|
||||
if (queryToggle) {
|
||||
queryToggle.checked = settings.queryString;
|
||||
}
|
||||
}
|
||||
|
||||
function currentTogglePreferences() {
|
||||
if (queryToggle && queryToggle.checked) {
|
||||
return { ...previousToggleState };
|
||||
}
|
||||
return {
|
||||
exact: !!exactToggle.checked,
|
||||
fuzzy: !!fuzzyToggle.checked,
|
||||
phrase: !!phraseToggle.checked,
|
||||
};
|
||||
}
|
||||
|
||||
function syncSettingsFromControls() {
|
||||
const togglePrefs = currentTogglePreferences();
|
||||
const next = {
|
||||
...settings,
|
||||
channel: channelSelect ? channelSelect.value || "" : "",
|
||||
year: yearSel.value || "",
|
||||
sort: sortSel.value || "relevant",
|
||||
size: sizeSel.value || "10",
|
||||
external: externalToggle ? !!externalToggle.checked : false,
|
||||
queryString: queryToggle ? !!queryToggle.checked : false,
|
||||
...togglePrefs,
|
||||
};
|
||||
settings = next;
|
||||
persistSettings();
|
||||
return settings;
|
||||
}
|
||||
|
||||
function getSelectedChannels() {
|
||||
if (!channelSelect) return [];
|
||||
const value = channelSelect.value;
|
||||
@ -130,20 +201,18 @@
|
||||
|
||||
function setFromQuery() {
|
||||
qInput.value = qs.get("q") || "";
|
||||
yearSel.value = qs.get("year") || "";
|
||||
sortSel.value = qs.get("sort") || "relevant";
|
||||
sizeSel.value = qs.get("size") || "10";
|
||||
pendingChannelSelection = parseChannelParam(qs);
|
||||
const urlChannel = parseChannelParam(qs);
|
||||
if (urlChannel) {
|
||||
pendingChannelSelection = urlChannel;
|
||||
settings.channel = urlChannel;
|
||||
persistSettings();
|
||||
} else {
|
||||
pendingChannelSelection = settings.channel || "";
|
||||
}
|
||||
applyStoredSettings();
|
||||
if (channelSelect) {
|
||||
channelSelect.value = pendingChannelSelection || "";
|
||||
}
|
||||
exactToggle.checked = parseBoolParam("exact", true);
|
||||
fuzzyToggle.checked = parseBoolParam("fuzzy", true);
|
||||
phraseToggle.checked = parseBoolParam("phrase", true);
|
||||
if (externalToggle) {
|
||||
externalToggle.checked = parseBoolParam("external", false);
|
||||
}
|
||||
queryToggle.checked = parseBoolParam("query_string", false);
|
||||
applyQueryMode();
|
||||
rememberToggleState();
|
||||
}
|
||||
@ -157,6 +226,8 @@
|
||||
fuzzy: fuzzyToggle.checked,
|
||||
phrase: phraseToggle.checked,
|
||||
};
|
||||
settings = { ...settings, ...previousToggleState };
|
||||
persistSettings();
|
||||
}
|
||||
exactToggle.checked = false;
|
||||
fuzzyToggle.checked = false;
|
||||
@ -172,6 +243,8 @@
|
||||
fuzzyToggle.checked = previousToggleState.fuzzy;
|
||||
phraseToggle.checked = previousToggleState.phrase;
|
||||
}
|
||||
settings.queryString = !!(queryToggle && queryToggle.checked);
|
||||
persistSettings();
|
||||
}
|
||||
|
||||
function rememberToggleState() {
|
||||
@ -181,6 +254,8 @@
|
||||
fuzzy: !!fuzzyToggle.checked,
|
||||
phrase: !!phraseToggle.checked,
|
||||
};
|
||||
settings = { ...settings, ...previousToggleState };
|
||||
persistSettings();
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,6 +388,8 @@
|
||||
} else {
|
||||
channelSelect.value = "";
|
||||
}
|
||||
settings.channel = channelSelect.value || "";
|
||||
persistSettings();
|
||||
|
||||
channelsReady = true;
|
||||
} catch (err) {
|
||||
@ -322,25 +399,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
function updateUrl(q, sort, channels, year, page, size, exact, fuzzy, phrase, queryMode, includeExternal) {
|
||||
function updateUrl(q) {
|
||||
const next = new URL(window.location.href);
|
||||
if (q) {
|
||||
next.searchParams.set("q", q);
|
||||
next.searchParams.set("sort", sort);
|
||||
} else {
|
||||
next.searchParams.delete("q");
|
||||
}
|
||||
next.searchParams.delete("page");
|
||||
next.searchParams.delete("sort");
|
||||
next.searchParams.delete("channel_id");
|
||||
next.searchParams.delete("channel");
|
||||
channels.forEach((id) => next.searchParams.append("channel_id", id));
|
||||
if (year) {
|
||||
next.searchParams.set("year", year);
|
||||
} else {
|
||||
next.searchParams.delete("year");
|
||||
}
|
||||
next.searchParams.set("page", page);
|
||||
next.searchParams.set("size", size);
|
||||
next.searchParams.set("exact", exact ? "1" : "0");
|
||||
next.searchParams.set("fuzzy", fuzzy ? "1" : "0");
|
||||
next.searchParams.set("phrase", phrase ? "1" : "0");
|
||||
next.searchParams.set("query_string", queryMode ? "1" : "0");
|
||||
next.searchParams.set("external", includeExternal ? "1" : "0");
|
||||
next.searchParams.delete("size");
|
||||
next.searchParams.delete("exact");
|
||||
next.searchParams.delete("fuzzy");
|
||||
next.searchParams.delete("phrase");
|
||||
next.searchParams.delete("query_string");
|
||||
next.searchParams.delete("external");
|
||||
history.pushState({}, "", next.toString());
|
||||
}
|
||||
|
||||
@ -1542,24 +1618,14 @@ async function updateFrequencyChart(term, channels, year, queryMode, toggles = {
|
||||
fuzzy,
|
||||
phrase,
|
||||
};
|
||||
settings = { ...settings, ...previousToggleState };
|
||||
persistSettings();
|
||||
}
|
||||
const page = pageOverride != null ? pageOverride : currentPage;
|
||||
currentPage = page;
|
||||
|
||||
if (pushState) {
|
||||
updateUrl(
|
||||
q,
|
||||
sort,
|
||||
channels,
|
||||
year,
|
||||
page,
|
||||
size,
|
||||
exact,
|
||||
fuzzy,
|
||||
phrase,
|
||||
queryMode,
|
||||
includeExternal
|
||||
);
|
||||
updateUrl(q);
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
@ -1575,6 +1641,8 @@ async function updateFrequencyChart(term, channels, year, queryMode, toggles = {
|
||||
channels.forEach((id) => params.append("channel_id", id));
|
||||
if (year) params.set("year", year);
|
||||
|
||||
syncSettingsFromControls();
|
||||
|
||||
const res = await fetch(`/api/search?${params.toString()}`);
|
||||
const payload = await res.json();
|
||||
renderResults(payload, page);
|
||||
@ -1598,31 +1666,39 @@ async function updateFrequencyChart(term, channels, year, queryMode, toggles = {
|
||||
if (channelSelect) {
|
||||
channelSelect.addEventListener("change", () => {
|
||||
pendingChannelSelection = channelSelect.value || "";
|
||||
settings.channel = pendingChannelSelection;
|
||||
persistSettings();
|
||||
if (channelsReady) {
|
||||
runSearch(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
yearSel.addEventListener("change", () => runSearch(0));
|
||||
sortSel.addEventListener("change", () => runSearch(0));
|
||||
sizeSel.addEventListener("change", () => runSearch(0));
|
||||
exactToggle.addEventListener("change", () => { rememberToggleState(); runSearch(0); });
|
||||
fuzzyToggle.addEventListener("change", () => { rememberToggleState(); runSearch(0); });
|
||||
phraseToggle.addEventListener("change", () => { rememberToggleState(); runSearch(0); });
|
||||
yearSel.addEventListener("change", () => { syncSettingsFromControls(); runSearch(0); });
|
||||
sortSel.addEventListener("change", () => { syncSettingsFromControls(); runSearch(0); });
|
||||
sizeSel.addEventListener("change", () => { syncSettingsFromControls(); runSearch(0); });
|
||||
exactToggle.addEventListener("change", () => { rememberToggleState(); syncSettingsFromControls(); runSearch(0); });
|
||||
fuzzyToggle.addEventListener("change", () => { rememberToggleState(); syncSettingsFromControls(); runSearch(0); });
|
||||
phraseToggle.addEventListener("change", () => { rememberToggleState(); syncSettingsFromControls(); runSearch(0); });
|
||||
if (externalToggle) {
|
||||
externalToggle.addEventListener("change", () => {
|
||||
pendingChannelSelection = "";
|
||||
settings.external = !!externalToggle.checked;
|
||||
persistSettings();
|
||||
loadChannels().then(() => runSearch(0));
|
||||
});
|
||||
}
|
||||
if (queryToggle) {
|
||||
queryToggle.addEventListener("change", () => { applyQueryMode(); runSearch(0); });
|
||||
queryToggle.addEventListener("change", () => {
|
||||
applyQueryMode();
|
||||
syncSettingsFromControls();
|
||||
runSearch(0);
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener("popstate", () => {
|
||||
qs = new URLSearchParams(window.location.search);
|
||||
setFromQuery();
|
||||
currentPage = parseInt(qs.get("page") || "0", 10) || 0;
|
||||
currentPage = 0;
|
||||
runSearch(currentPage, false);
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user