cheogram-www

created pr with cheogram-www/unread-filter.1 on 2026-10-26T01:58:16Z · by 9e834e0d
added cheogram-www/unread-filter.2 on 2026-10-26T19:27:04Z · by 3c31bc8c
1: 9d343f3 = 1: efc44ba Allow filtering by unread
-: ------- > 2: 2da6059 Combine unread and tag into filter.
cmds
checkout latest patchset:
ssh pr.pico.sh pull cheogram-www:unread-filter | git am -3
checkout specific patchset revision:
ssh pr.pico.sh pull cheogram-www:unread-filter [rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh cheogram-www:unread-filter
add comment to patch request:
ssh pr.pico.sh comment cheogram-www:unread-filter "lgtm!"
+31 -18 src/components/Chats.tsx #
......@@ -13,7 +13,7 @@ import {
1313 } from "@mui/material";
1414 import { QRCanvas, frontalCamera } from "qr/dom.js";
1515 import { Virtuoso, VirtuosoHandle } from "react-virtuoso";
16-import { useQueryState } from "nuqs";
16+import { parseAsBoolean, useQueryState } from "nuqs";
1717 import { useState, useEffect, useRef, useCallback, useContext } from "react";
1818 import {
1919 Outlet,
......@@ -66,6 +66,10 @@ export const Chats = () => {
6666 const [searchParams] = useSearchParams();
6767 const [searchQ, setSearchQ] = useQueryState("q");
6868 const [searchTag, setSearchTag] = useQueryState("tag");
69+ const [searchUnread, setSearchUnread] = useQueryState(
70+ "unread",
71+ parseAsBoolean.withDefault(false),
72+ );
6973 const { persistence, client, status, setStatus, logout } = useOutletContext<{
7074 persistence: borogove.Persistence & borogove.persistence.KeyValueStore;
7175 client: borogove.Client;
......@@ -307,9 +311,9 @@ export const Chats = () => {
307311 }
308312 }
309313 }
310- return searchTag
311- ? results.filter((c) => c.getTags().includes(searchTag))
312- : results;
314+ return results
315+ .filter((c) => !searchTag || c.getTags().includes(searchTag))
316+ .filter((c) => !searchUnread || c.unreadCount() > 0);
313317 };
314318
315319 const [searchResultLimit, setSearchResultLimit] = useState(5);
......@@ -611,21 +615,30 @@ export const Chats = () => {
611615 />
612616 )}
613617 </AwaitOnce>
614- {tags.size > 0 && (
615- <select
616- id="tag-nav"
617- onChange={(e) =>
618- setSearchTag(e.target.value ? e.target.value : null)
618+ <select
619+ id="tag-nav"
620+ value={
621+ searchUnread ? "unread" : searchTag ? `tag:${searchTag}` : "all"
622+ }
623+ onChange={(e) => {
624+ const value = e.target.value;
625+ if (value.startsWith("tag:")) {
626+ setSearchUnread(false);
627+ setSearchTag(value.slice("tag:".length));
628+ } else {
629+ setSearchTag(null);
630+ setSearchUnread(value === "unread");
619631 }
620- >
621- <option value="">All Chats</option>
622- {tags.keys().map((t) => (
623- <option value={t} key={t} selected={searchTag === t}>
624- {t}
625- </option>
626- ))}
627- </select>
628- )}
632+ }}
633+ >
634+ <option value="all">All Chats</option>
635+ <option value="unread">Unread</option>
636+ {tags.keys().map((t) => (
637+ <option value={`tag:${t}`} key={t}>
638+ {t}
639+ </option>
640+ ))}
641+ </select>
629642 {subnav !== "apps" && subnav != "requests" && (
630643 <nav aria-label="Chat List">
631644 {searchQ && searchQ.length > 0 && (
Back to top