feat(filters): "Share view" link button in the sidebar

Add a share button next to Clear all that copies a link reproducing the current
filter view (filters, sort, scope) to the clipboard, with a confirmation toast.
This is the opt-in replacement for the old always-on URL mirroring. Trilingual.
This commit is contained in:
npeter83 2026-06-15 12:29:51 +02:00
parent eef64ef811
commit 78182f3ba6
4 changed files with 31 additions and 0 deletions

View file

@ -10,6 +10,7 @@ import {
Pencil, Pencil,
RefreshCw, RefreshCw,
RotateCcw, RotateCcw,
Share2,
X, X,
} from "lucide-react"; } from "lucide-react";
import { import {
@ -33,6 +34,8 @@ import {
type SidebarLayout, type SidebarLayout,
type WidgetId, type WidgetId,
} from "../lib/sidebarLayout"; } from "../lib/sidebarLayout";
import { shareUrl } from "../lib/urlState";
import { notify } from "../lib/notifications";
// Filter ids; display labels resolved at render time via t("sidebar.sort.<id>") etc. // Filter ids; display labels resolved at render time via t("sidebar.sort.<id>") etc.
const SORT_IDS = [ const SORT_IDS = [
@ -196,6 +199,15 @@ export default function Sidebar({
(dateActive ? 1 : 0); (dateActive ? 1 : 0);
const active = activeCount > 0; const active = activeCount > 0;
async function shareView() {
try {
await navigator.clipboard.writeText(shareUrl(filters));
notify({ message: t("sidebar.shareCopied") });
} catch {
notify({ level: "warning", message: t("sidebar.shareFailed") });
}
}
function clearAll() { function clearAll() {
setCustomDates(false); setCustomDates(false);
setFilters({ ...DEFAULT_SIDEBAR_FILTERS, q: filters.q, scope: filters.scope }); setFilters({ ...DEFAULT_SIDEBAR_FILTERS, q: filters.q, scope: filters.scope });
@ -486,6 +498,16 @@ export default function Sidebar({
{t("sidebar.clearAll")} {t("sidebar.clearAll")}
</button> </button>
)} )}
{!editing && (
<button
onClick={shareView}
title={t("sidebar.shareView")}
aria-label={t("sidebar.shareView")}
className="p-1.5 rounded-lg text-muted hover:text-fg hover:bg-card transition"
>
<Share2 className="w-4 h-4" />
</button>
)}
{editing && ( {editing && (
<button <button
onClick={() => setLayout({ ...DEFAULT_LAYOUT })} onClick={() => setLayout({ ...DEFAULT_LAYOUT })}

View file

@ -26,6 +26,9 @@
"clearDates": "Daten löschen", "clearDates": "Daten löschen",
"reshuffle": "Neu mischen", "reshuffle": "Neu mischen",
"noMatchingTags": "Keine passenden Tags", "noMatchingTags": "Keine passenden Tags",
"shareView": "Link zu dieser Ansicht kopieren",
"shareCopied": "Ansichts-Link in die Zwischenablage kopiert",
"shareFailed": "Link konnte nicht kopiert werden",
"widget": { "widget": {
"show": "Anzeigen", "show": "Anzeigen",
"sort": "Sortierung", "sort": "Sortierung",

View file

@ -26,6 +26,9 @@
"clearDates": "clear dates", "clearDates": "clear dates",
"reshuffle": "Reshuffle", "reshuffle": "Reshuffle",
"noMatchingTags": "No matching tags here", "noMatchingTags": "No matching tags here",
"shareView": "Copy a link to this view",
"shareCopied": "View link copied to clipboard",
"shareFailed": "Couldn't copy the link",
"widget": { "widget": {
"show": "Show", "show": "Show",
"sort": "Sort", "sort": "Sort",

View file

@ -26,6 +26,9 @@
"clearDates": "dátumok törlése", "clearDates": "dátumok törlése",
"reshuffle": "Újrakeverés", "reshuffle": "Újrakeverés",
"noMatchingTags": "Nincs ide illő címke", "noMatchingTags": "Nincs ide illő címke",
"shareView": "Hivatkozás másolása erre a nézetre",
"shareCopied": "Nézet-hivatkozás a vágólapra másolva",
"shareFailed": "Nem sikerült a hivatkozás másolása",
"widget": { "widget": {
"show": "Megjelenítés", "show": "Megjelenítés",
"sort": "Rendezés", "sort": "Rendezés",