From 67fa53d7f4b4fc603f5411d27d70ef20b8a553a8 Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Mon, 2 Dec 2024 19:24:24 +0100 Subject: [PATCH 1/6] Add search button --- src/tribler/ui/src/components/ui/autocomplete.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/tribler/ui/src/components/ui/autocomplete.tsx b/src/tribler/ui/src/components/ui/autocomplete.tsx index 11a23c1560a..11716d1bfb3 100644 --- a/src/tribler/ui/src/components/ui/autocomplete.tsx +++ b/src/tribler/ui/src/components/ui/autocomplete.tsx @@ -1,4 +1,6 @@ import { useRef, useState } from "react"; +import { Button } from "./button"; +import { SearchIcon } from "lucide-react"; export function Autocomplete({ placeholder, completions, onChange }: { placeholder: string, completions: (filter: string) => Promise, onChange: (query: string) => void }) { @@ -61,6 +63,19 @@ export function Autocomplete({ placeholder, completions, onChange }: { placehold value={inputValue} ref={inputRef} /> +
From 2434752363c0f7cd69c1d84def99b23b8d9793de Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Mon, 2 Dec 2024 19:25:50 +0100 Subject: [PATCH 2/6] Hide suggestions list when empty --- src/tribler/ui/src/components/ui/autocomplete.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/tribler/ui/src/components/ui/autocomplete.tsx b/src/tribler/ui/src/components/ui/autocomplete.tsx index 11716d1bfb3..fcb5c47ae84 100644 --- a/src/tribler/ui/src/components/ui/autocomplete.tsx +++ b/src/tribler/ui/src/components/ui/autocomplete.tsx @@ -78,8 +78,8 @@ export function Autocomplete({ placeholder, completions, onChange }: { placehold
-
- {focus && ( + {focus && suggestions.length > 0 &&( +
{suggestions.length > 0 && (suggestions.map((suggestion, index) => (
@@ -92,10 +92,9 @@ export function Autocomplete({ placeholder, completions, onChange }: { placehold
)))}
- )} -
+
+ )} - ); } From 7e0a68f26ff80efde0aa6769c7a6ab217968252c Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Mon, 2 Dec 2024 20:28:27 +0100 Subject: [PATCH 3/6] Show spinner while shutting down --- src/tribler/ui/src/components/layouts/Header.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tribler/ui/src/components/layouts/Header.tsx b/src/tribler/ui/src/components/layouts/Header.tsx index 61a26c804fb..28b14c13d13 100644 --- a/src/tribler/ui/src/components/layouts/Header.tsx +++ b/src/tribler/ui/src/components/layouts/Header.tsx @@ -14,7 +14,7 @@ import { useEffect, useRef, useState } from "react"; import toast, { Toaster } from 'react-hot-toast'; import Cookies from "js-cookie"; import { DialogDescription } from "@radix-ui/react-dialog"; -import { Ban } from "lucide-react"; +import { Ban, Loader } from "lucide-react"; import { useTranslation } from "react-i18next"; import { ScrollArea } from "../ui/scroll-area"; @@ -84,7 +84,8 @@ export function Header() { }} > - + + {online ? : } {online ? "Tribler is shutting down" : (shutdownLogs.length > 0 From bd755c4bae7959c0591f0637bbc6e4ba8d327365 Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Tue, 3 Dec 2024 13:11:06 +0100 Subject: [PATCH 4/6] Navigate directly to a submenu --- .../ui/src/components/layouts/SideLayout.tsx | 31 ++++++++++++++----- src/tribler/ui/src/config/menu.ts | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/tribler/ui/src/components/layouts/SideLayout.tsx b/src/tribler/ui/src/components/layouts/SideLayout.tsx index fc9517a18b8..67c2fedaa2d 100644 --- a/src/tribler/ui/src/components/layouts/SideLayout.tsx +++ b/src/tribler/ui/src/components/layouts/SideLayout.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { NavLink, Outlet, useLocation } from "react-router-dom"; +import { NavLink, Outlet, useLocation, useNavigate } from "react-router-dom"; import { Header } from "./Header"; import { Accordion } from "@radix-ui/react-accordion"; import { sideMenu } from "@/config/menu"; @@ -15,6 +15,8 @@ import { useTranslation } from "react-i18next"; export function SideLayout() { const { t } = useTranslation(); const location = useLocation(); + const navigate = useNavigate(); + const [history, setHistory] = useState(new Map()); const [accordionValue, setAccordionValue] = useState(() => { return "item-" + sideMenu.findIndex(item => item.items !== undefined ? item.items.filter(subitem => subitem.to !== undefined).map(subitem => subitem.to).includes(location.pathname) : false) }); @@ -44,12 +46,19 @@ export function SideLayout() { {sideMenu.filter((item) => !item.hide || item.hide() !== true).map((item, index) => ( item.items !== undefined ? ( - subitem.to !== undefined).map(subitem => subitem.to)) - .includes(location.pathname) ? 'bg-accent' : 'hover:bg-accent', - "justify-between hover:no-underline" - )}> + subitem.to !== undefined).map(subitem => subitem.to)) + .includes(location.pathname) ? 'bg-accent' : 'hover:bg-accent', + "justify-between hover:no-underline" + )} + onClick={() => { + const target = history.get(item.title) || item.items?.at(0)?.to; + if (target) { + navigate(target); + } + }}>
{item.icon && } {t(item.title)}
@@ -59,7 +68,13 @@ export function SideLayout() { setShowNav(false)} + onClick={() => { + setShowNav(false); + if (item.title && submenu.to) { + // Keep track of which submenus we navigated to + setHistory(map => new Map(map.set(item.title, submenu.to))); + } + }} className={({ isActive }) => cn( buttonVariants({ variant: "ghost" }), isActive ? "bg-accent" : "hover:bg-accent", diff --git a/src/tribler/ui/src/config/menu.ts b/src/tribler/ui/src/config/menu.ts index 75098d794ae..cc12fec5f3e 100644 --- a/src/tribler/ui/src/config/menu.ts +++ b/src/tribler/ui/src/config/menu.ts @@ -16,7 +16,7 @@ interface NavItem { } interface NavItemWithChildren extends NavItem { - items?: NavItemWithChildren[] + items?: NavItem[] } export const sideMenu: NavItemWithChildren[] = [ From f75040112071210c4de9836c38f173ab8ef8ad25 Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Tue, 3 Dec 2024 17:35:24 +0100 Subject: [PATCH 5/6] Allow selecting all items in a table using a shortcut --- src/tribler/ui/package-lock.json | 16 ++++++++++++++++ src/tribler/ui/package.json | 1 + .../ui/src/components/ui/simple-table.tsx | 15 +++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/tribler/ui/package-lock.json b/src/tribler/ui/package-lock.json index 1db75c3130e..bfe7783ee15 100644 --- a/src/tribler/ui/package-lock.json +++ b/src/tribler/ui/package-lock.json @@ -41,6 +41,7 @@ "react-router-dom": "^6.16.0", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.7", + "use-keyboard-shortcut": "^1.1.6", "zod": "^3.22.4" }, "devDependencies": { @@ -4083,6 +4084,15 @@ } } }, + "node_modules/use-keyboard-shortcut": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/use-keyboard-shortcut/-/use-keyboard-shortcut-1.1.6.tgz", + "integrity": "sha512-tOKjR7eKXQIfAgFMwhelpWSRTrwE1GaB8CE/47ohtcVCKxUdn7UbfNNhiigTkATpUVoPu+5tRPbHrwjIBgTYoQ==", + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/use-sidecar": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", @@ -6720,6 +6730,12 @@ "tslib": "^2.0.0" } }, + "use-keyboard-shortcut": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/use-keyboard-shortcut/-/use-keyboard-shortcut-1.1.6.tgz", + "integrity": "sha512-tOKjR7eKXQIfAgFMwhelpWSRTrwE1GaB8CE/47ohtcVCKxUdn7UbfNNhiigTkATpUVoPu+5tRPbHrwjIBgTYoQ==", + "requires": {} + }, "use-sidecar": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", diff --git a/src/tribler/ui/package.json b/src/tribler/ui/package.json index 45ef3f2e6c7..872065ca6d1 100644 --- a/src/tribler/ui/package.json +++ b/src/tribler/ui/package.json @@ -42,6 +42,7 @@ "react-router-dom": "^6.16.0", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.7", + "use-keyboard-shortcut": "^1.1.6", "zod": "^3.22.4" }, "devDependencies": { diff --git a/src/tribler/ui/src/components/ui/simple-table.tsx b/src/tribler/ui/src/components/ui/simple-table.tsx index d5c4885860a..124db9ba51d 100644 --- a/src/tribler/ui/src/components/ui/simple-table.tsx +++ b/src/tribler/ui/src/components/ui/simple-table.tsx @@ -10,6 +10,7 @@ import * as SelectPrimitive from "@radix-ui/react-select" import type { Table as ReactTable } from '@tanstack/react-table'; import { useTranslation } from 'react-i18next'; import { useResizeObserver } from '@/hooks/useResizeObserver'; +import useKeyboardShortcut from 'use-keyboard-shortcut'; export function getHeader(name: string, translate: boolean = true, addSorting: boolean = true): ColumnDefTemplate> | undefined { @@ -97,6 +98,20 @@ function SimpleTable({ const [expanded, setExpanded] = useState({}); const [sorting, setSorting] = useState(getStoredSortingState(storeSortingState) || []); + useKeyboardShortcut( + ["Control", "A"], + keys => { + if (allowMultiSelect) { + table.toggleAllRowsSelected(true); + } + }, + { + overrideSystem: true, + ignoreInputFields: true, + repeatOnHold: false + } + ); + const table = useReactTable({ data, columns, From 0c0d55c500163618e9903eb90990b84a98391932 Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Wed, 4 Dec 2024 14:46:21 +0100 Subject: [PATCH 6/6] Use infohash as rowId --- src/tribler/ui/src/components/ui/simple-table.tsx | 5 ++++- src/tribler/ui/src/pages/Downloads/index.tsx | 1 + src/tribler/ui/src/pages/Popular/index.tsx | 1 + src/tribler/ui/src/pages/Search/index.tsx | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tribler/ui/src/components/ui/simple-table.tsx b/src/tribler/ui/src/components/ui/simple-table.tsx index 124db9ba51d..980e3e65f08 100644 --- a/src/tribler/ui/src/components/ui/simple-table.tsx +++ b/src/tribler/ui/src/components/ui/simple-table.tsx @@ -69,6 +69,7 @@ interface ReactTableProps { maxHeight?: string | number; expandable?: boolean; storeSortingState?: string; + rowId?: (originalRow: T, index: number, parent?: Row) => string, } function SimpleTable({ @@ -87,7 +88,8 @@ function SimpleTable({ filters, maxHeight, expandable, - storeSortingState + storeSortingState, + rowId }: ReactTableProps) { const [pagination, setPagination] = useState({ pageIndex: pageIndex ?? 0, @@ -137,6 +139,7 @@ function SimpleTable({ onExpandedChange: setExpanded, onSortingChange: setSorting, getSubRows: (row: any) => row?.subRows, + getRowId: rowId, }); const { t } = useTranslation(); diff --git a/src/tribler/ui/src/pages/Downloads/index.tsx b/src/tribler/ui/src/pages/Downloads/index.tsx index e5b1fb5ee61..44f37e6d06c 100644 --- a/src/tribler/ui/src/pages/Downloads/index.tsx +++ b/src/tribler/ui/src/pages/Downloads/index.tsx @@ -195,6 +195,7 @@ export default function Downloads({ statusFilter }: { statusFilter: number[] }) onSelectedRowsChange={setSelectedDownloads} maxHeight={Math.max((parentRect?.height ?? 50) - 50, 50)} storeSortingState="download-sorting" + rowId={(row) => row.infohash} /> diff --git a/src/tribler/ui/src/pages/Popular/index.tsx b/src/tribler/ui/src/pages/Popular/index.tsx index 35a749c992e..c5307dec7b0 100644 --- a/src/tribler/ui/src/pages/Popular/index.tsx +++ b/src/tribler/ui/src/pages/Popular/index.tsx @@ -112,6 +112,7 @@ export default function Popular() { data={torrents} columns={torrentColumns} storeSortingState="popular-sorting" + rowId={(row) => row.infohash} /> ) diff --git a/src/tribler/ui/src/pages/Search/index.tsx b/src/tribler/ui/src/pages/Search/index.tsx index 13843422496..be0c139bfa3 100644 --- a/src/tribler/ui/src/pages/Search/index.tsx +++ b/src/tribler/ui/src/pages/Search/index.tsx @@ -151,6 +151,7 @@ export default function Search() { data={torrents} columns={torrentColumns} storeSortingState="search-sorting" + rowId={(row) => row.infohash} /> )