Fix time filter refresh and polish search UI
This commit is contained in:
parent
d7700b154b
commit
5cc21194a0
|
|
@ -1,10 +1,25 @@
|
||||||
const API_BASE = "/api";
|
function apiBase() {
|
||||||
|
const raw =
|
||||||
|
(import.meta?.env?.VITE_API_BASE_URL || "")
|
||||||
|
.toString()
|
||||||
|
.replace(/\/+$/, "");
|
||||||
|
if (raw) return raw + "/api";
|
||||||
|
try {
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
const host = window.location.hostname || "";
|
||||||
|
if (host.startsWith("www.")) {
|
||||||
|
return `https://${host.replace(/^www\./, "")}/api`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
return "/api";
|
||||||
|
}
|
||||||
|
|
||||||
const cache = new Map(); // key -> Promise
|
const cache = new Map(); // key -> Promise
|
||||||
|
|
||||||
export async function fetchDefaultTemplate(typeKey = "news") {
|
export async function fetchDefaultTemplate(typeKey = "news") {
|
||||||
const t = (typeKey || "news").toLowerCase().trim();
|
const t = (typeKey || "news").toLowerCase().trim();
|
||||||
const res = await fetch(`${API_BASE}/templates/default?type=${encodeURIComponent(t)}`, {
|
const res = await fetch(`${apiBase()}/templates/default?type=${encodeURIComponent(t)}`, {
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ export default function TimeFilterButtons({ active, onSelect }) {
|
||||||
{ code: "NOW", label: "Now", icon: "fa-solid fa-bolt" },
|
{ code: "NOW", label: "Now", icon: "fa-solid fa-bolt" },
|
||||||
{ code: "TODAY", label: "Today", icon: "fa-solid fa-sun" },
|
{ code: "TODAY", label: "Today", icon: "fa-solid fa-sun" },
|
||||||
{ code: "RECENT", label: "Recent", icon: "fa-solid fa-clock-rotate-left" },
|
{ code: "RECENT", label: "Recent", icon: "fa-solid fa-clock-rotate-left" },
|
||||||
{ code: "PAST", label: "Past", icon: "fa-solid fa-hourglass-half" },
|
{ code: "PAST", label: "Old", icon: "fa-solid fa-hourglass-half" },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -813,7 +813,6 @@ export function openCenteredOverlay({ map, post, theme, fullScreen = false }) {
|
||||||
<div class="sw-modal-badge">MAIN NEWS</div>
|
<div class="sw-modal-badge">MAIN NEWS</div>
|
||||||
<div class="sw-modal-meta">
|
<div class="sw-modal-meta">
|
||||||
${author ? `<div class="sw-modal-author-avatar" data-username="${escapeHtml(author)}"></div>` : ""}
|
${author ? `<div class="sw-modal-author-avatar" data-username="${escapeHtml(author)}"></div>` : ""}
|
||||||
${author ? `<div class="sw-inline-avatar" data-username="${escapeHtml(author)}"></div>` : ""}
|
|
||||||
${metaLeft ? `<span class="sw-author-link" data-author="${escapeHtml(author)}" style="cursor: pointer; text-decoration: underline;">${escapeHtml(metaLeft)}</span>` : ""}
|
${metaLeft ? `<span class="sw-author-link" data-author="${escapeHtml(author)}" style="cursor: pointer; text-decoration: underline;">${escapeHtml(metaLeft)}</span>` : ""}
|
||||||
${metaRight ? `<span>• ${escapeHtml(metaRight)}</span>` : ""}
|
${metaRight ? `<span>• ${escapeHtml(metaRight)}</span>` : ""}
|
||||||
<span>• ${escapeHtml(relTime)}</span>
|
<span>• ${escapeHtml(relTime)}</span>
|
||||||
|
|
@ -893,7 +892,6 @@ export function openCenteredOverlay({ map, post, theme, fullScreen = false }) {
|
||||||
<div class="sw-modal-badge">${escapeHtml(cat)}</div>
|
<div class="sw-modal-badge">${escapeHtml(cat)}</div>
|
||||||
<div class="sw-modal-meta">
|
<div class="sw-modal-meta">
|
||||||
${author ? `<div class="sw-modal-author-avatar" data-username="${escapeHtml(author)}"></div>` : ""}
|
${author ? `<div class="sw-modal-author-avatar" data-username="${escapeHtml(author)}"></div>` : ""}
|
||||||
${author ? `<div class="sw-inline-avatar" data-username="${escapeHtml(author)}"></div>` : ""}
|
|
||||||
${metaLeft ? `<span class="sw-author-link" data-author="${escapeHtml(author)}" style="cursor: pointer; text-decoration: underline;">${escapeHtml(metaLeft)}</span>` : ""}
|
${metaLeft ? `<span class="sw-author-link" data-author="${escapeHtml(author)}" style="cursor: pointer; text-decoration: underline;">${escapeHtml(metaLeft)}</span>` : ""}
|
||||||
${metaRight ? `<span>• ${escapeHtml(metaRight)}</span>` : ""}
|
${metaRight ? `<span>• ${escapeHtml(metaRight)}</span>` : ""}
|
||||||
<span>• ${escapeHtml(relTime)}</span>
|
<span>• ${escapeHtml(relTime)}</span>
|
||||||
|
|
|
||||||
|
|
@ -858,9 +858,8 @@ export function usePostsEngine({
|
||||||
if (pc !== catCode) return false;
|
if (pc !== catCode) return false;
|
||||||
}
|
}
|
||||||
if (!matchesSubFilter(p, subFilter)) return false;
|
if (!matchesSubFilter(p, subFilter)) return false;
|
||||||
const skipTimeFilter =
|
const postTf = (p?._swTimeFilter || "").toString();
|
||||||
tf === "RECENT" && lastFetchRef.current?.timeFilter === "RECENT";
|
if (postTf !== tf && !matchesTimeFilter(effectivePostTime(p), tf)) return false;
|
||||||
if (!skipTimeFilter && !matchesTimeFilter(effectivePostTime(p), tf)) return false;
|
|
||||||
if (!searchResultsRef.current && !matchesSearch(p, searchQuery)) return false;
|
if (!searchResultsRef.current && !matchesSearch(p, searchQuery)) return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
@ -1075,6 +1074,7 @@ export function usePostsEngine({
|
||||||
const normalized = normalizePostId(p);
|
const normalized = normalizePostId(p);
|
||||||
const key = getPostKey(normalized);
|
const key = getPostKey(normalized);
|
||||||
if (!key) continue;
|
if (!key) continue;
|
||||||
|
if (timeFilter) normalized._swTimeFilter = timeFilter;
|
||||||
const prior = byId.get(key);
|
const prior = byId.get(key);
|
||||||
if (prior) {
|
if (prior) {
|
||||||
byId.set(key, { ...prior, ...normalized });
|
byId.set(key, { ...prior, ...normalized });
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ export default function SmartSearchBar({
|
||||||
const [active, setActive] = useState(-1);
|
const [active, setActive] = useState(-1);
|
||||||
const [err, setErr] = useState("");
|
const [err, setErr] = useState("");
|
||||||
const [hasSearched, setHasSearched] = useState(false);
|
const [hasSearched, setHasSearched] = useState(false);
|
||||||
|
const [focused, setFocused] = useState(false);
|
||||||
|
|
||||||
const abortRef = useRef(null);
|
const abortRef = useRef(null);
|
||||||
const skipSearchRef = useRef(false);
|
const skipSearchRef = useRef(false);
|
||||||
|
|
@ -98,6 +99,7 @@ export default function SmartSearchBar({
|
||||||
abortRef.current = ctrl;
|
abortRef.current = ctrl;
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setErr("");
|
setErr("");
|
||||||
|
setOpen(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('[SmartSearchBar] Searching for:', searchQuery);
|
console.log('[SmartSearchBar] Searching for:', searchQuery);
|
||||||
|
|
@ -112,6 +114,7 @@ export default function SmartSearchBar({
|
||||||
console.error('[SmartSearchBar] Search error:', e);
|
console.error('[SmartSearchBar] Search error:', e);
|
||||||
setErr((e && e.message) ? e.message : "Search error");
|
setErr((e && e.message) ? e.message : "Search error");
|
||||||
setItems([]);
|
setItems([]);
|
||||||
|
setOpen(true);
|
||||||
} finally {
|
} finally {
|
||||||
if (!ctrl.signal.aborted) setLoading(false);
|
if (!ctrl.signal.aborted) setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
@ -125,6 +128,8 @@ export default function SmartSearchBar({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (query) setOpen(true);
|
||||||
|
|
||||||
if (abortRef.current) abortRef.current.abort();
|
if (abortRef.current) abortRef.current.abort();
|
||||||
|
|
||||||
const t = setTimeout(() => {
|
const t = setTimeout(() => {
|
||||||
|
|
@ -137,7 +142,7 @@ export default function SmartSearchBar({
|
||||||
};
|
};
|
||||||
}, [q]);
|
}, [q]);
|
||||||
|
|
||||||
const showList = open && (items.length > 0 || loading || err);
|
const showList = (open || focused) && (items.length > 0 || loading || err || q.trim());
|
||||||
const clearOnFocusRef = useRef(false);
|
const clearOnFocusRef = useRef(false);
|
||||||
|
|
||||||
const pick = (it, reason = "click") => {
|
const pick = (it, reason = "click") => {
|
||||||
|
|
@ -214,6 +219,7 @@ export default function SmartSearchBar({
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onFocus={() => {
|
onFocus={() => {
|
||||||
|
setFocused(true);
|
||||||
if (clearOnFocusRef.current) {
|
if (clearOnFocusRef.current) {
|
||||||
clearOnFocusRef.current = false;
|
clearOnFocusRef.current = false;
|
||||||
setQ("");
|
setQ("");
|
||||||
|
|
@ -228,6 +234,9 @@ export default function SmartSearchBar({
|
||||||
triggerSearch("");
|
triggerSearch("");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
setTimeout(() => setFocused(false), 120);
|
||||||
|
}}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
aria-label="Search"
|
aria-label="Search"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue