From 24648e45f76e98490f27f8d45f367b63417c1073 Mon Sep 17 00:00:00 2001 From: soup Date: Sun, 4 May 2025 19:36:39 +0200 Subject: [PATCH] feat(web): persist releases incognito state (#2042) * refactor(web): persist incognito state * feat: merge incognito state into SettingsContext * feat: merge incognito state into SettingsContext --- web/src/screens/dashboard/ActivityTable.tsx | 54 +++++++++------ web/src/screens/releases/ReleaseTable.tsx | 62 ++++++++++------- web/src/utils/Context.ts | 4 +- web/src/utils/index.ts | 75 +++++++++++++++------ 4 files changed, 124 insertions(+), 71 deletions(-) diff --git a/web/src/screens/dashboard/ActivityTable.tsx b/web/src/screens/dashboard/ActivityTable.tsx index 51303f4..9b527c2 100644 --- a/web/src/screens/dashboard/ActivityTable.tsx +++ b/web/src/screens/dashboard/ActivityTable.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { useSuspenseQuery } from "@tanstack/react-query"; import { useReactTable, @@ -15,9 +15,10 @@ import { EyeIcon, EyeSlashIcon } from "@heroicons/react/24/solid"; import { EmptyListState } from "@components/emptystates"; import * as DataTable from "@components/data-table"; -import { RandomLinuxIsos } from "@utils"; +import { RandomLinuxIsos, RandomIsoTracker } from "@utils"; import { ReleasesLatestQueryOptions } from "@api/queries"; import { IndexerCell } from "@components/data-table"; +import { SettingsContext } from "@utils/Context"; interface TableProps { columns: ColumnDef[]; @@ -93,7 +94,7 @@ function Table({ columns, data }: TableProps) { } export const ActivityTable = () => { - const columns = React.useMemo[]>(() => [ + const columns = React.useMemo[]>(() => [ { header: "Age", accessorKey: "timestamp", @@ -102,7 +103,7 @@ export const ActivityTable = () => { { header: "Release", accessorKey: "name", - cell: DataTable.TitleCell, + cell: DataTable.TitleCell }, { header: "Actions", @@ -119,7 +120,30 @@ export const ActivityTable = () => { const { isLoading, data } = useSuspenseQuery(ReleasesLatestQueryOptions()); const [modifiedData, setModifiedData] = useState([]); - const [showLinuxIsos, setShowLinuxIsos] = useState(false); + const [settings, setSettings] = SettingsContext.use(); + + useEffect(() => { + if (settings.incognitoMode && data?.data) { + const randomIsoNames = RandomLinuxIsos(data.data.length); + const randomTorrentSiteNames = RandomIsoTracker(data.data.length); + const newData: Release[] = data.data.map((item, index) => { + const siteName = randomTorrentSiteNames[index % randomTorrentSiteNames.length]; + return { + ...item, + name: randomIsoNames[index], + indexer: { + id: 0, + name: siteName, + identifier: siteName, + identifier_external: siteName, + }, + }; + }); + setModifiedData(newData); + } else { + setModifiedData([]); + } + }, [settings.incognitoMode, data?.data]); if (isLoading) { return ( @@ -135,24 +159,10 @@ export const ActivityTable = () => { } const toggleReleaseNames = () => { - setShowLinuxIsos(!showLinuxIsos); - if (!showLinuxIsos && data && data.data) { - const randomNames = RandomLinuxIsos(data.data.length); - const newData: Release[] = data.data.map((item, index) => ({ - ...item, - name: `${randomNames[index]}.iso`, - indexer: { - id: 0, - name: index % 2 === 0 ? "distrowatch" : "linuxtracker", - identifier: index % 2 === 0 ? "distrowatch" : "linuxtracker", - identifier_external: index % 2 === 0 ? "distrowatch" : "linuxtracker", - }, - })); - setModifiedData(newData); - } + setSettings(prev => ({ ...prev, incognitoMode: !prev.incognitoMode })); }; - const displayData = showLinuxIsos ? modifiedData : (data?.data ?? []); + const displayData = settings.incognitoMode ? modifiedData : (data?.data ?? []); return (
@@ -168,7 +178,7 @@ export const ActivityTable = () => { aria-label="Toggle view" title="Go incognito" > - {showLinuxIsos ? ( + {settings.incognitoMode ? ( ) : ( diff --git a/web/src/screens/releases/ReleaseTable.tsx b/web/src/screens/releases/ReleaseTable.tsx index afd50a5..5aa8d82 100644 --- a/web/src/screens/releases/ReleaseTable.tsx +++ b/web/src/screens/releases/ReleaseTable.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { useQuery } from "@tanstack/react-query"; import { useSearch } from "@tanstack/react-router"; import { @@ -25,11 +25,12 @@ import { } from "@heroicons/react/24/solid"; import { ReleasesListQueryOptions } from "@api/queries"; -import { RandomLinuxIsos } from "@utils"; +import { RandomLinuxIsos, RandomIsoTracker } from "@utils"; import { RingResizeSpinner } from "@components/Icons"; import { IndexerSelectColumnFilter, PushStatusSelectColumnFilter, SearchColumnFilter } from "./ReleaseFilters"; import { EmptyListState } from "@components/emptystates"; import { TableButton, TablePageButton, AgeCell, IndexerCell, LinksCell, NameCell, ReleaseStatusCell } from "@components/data-table"; +import { SettingsContext } from "@utils/Context"; declare module '@tanstack/react-table' { //allows us to define custom properties for our columns @@ -147,34 +148,43 @@ export const ReleaseTable = () => { } = useQuery(ReleasesListQueryOptions(pagination.pageIndex * pagination.pageSize, pagination.pageSize, columnFilters)); const [modifiedData, setModifiedData] = useState([]); - const [showLinuxIsos, setShowLinuxIsos] = useState(false); + const [settings, setSettings] = SettingsContext.use(); + + useEffect(() => { + if (settings.incognitoMode && data?.data) { + const randomIsoNames = RandomLinuxIsos(data.data.length); + const randomTorrentSiteNames = RandomIsoTracker(data.data.length); + const newData: Release[] = data.data.map((item, index) => { + const siteName = randomTorrentSiteNames[index % randomTorrentSiteNames.length]; + return { + ...item, + name: randomIsoNames[index], + indexer: { + id: 0, + name: siteName, + identifier: siteName, + identifier_external: siteName, + }, + category: "Linux ISOs", + size: index % 2 === 0 ? 4566784529 : (index % 3 === 0 ? 7427019812 : 2312122455), + source: "", + container: "", + codec: "", + resolution: "", + }; + }); + setModifiedData(newData); + } else { + setModifiedData([]); + } + }, [settings.incognitoMode, data?.data]); const toggleReleaseNames = () => { - setShowLinuxIsos(!showLinuxIsos); - if (!showLinuxIsos && data && data.data) { - const randomNames = RandomLinuxIsos(data.data.length); - const newData: Release[] = data.data.map((item, index) => ({ - ...item, - name: `${randomNames[index]}.iso`, - indexer: { - id: 0, - name: index % 2 === 0 ? "distrowatch" : "linuxtracker", - identifier: index % 2 === 0 ? "distrowatch" : "linuxtracker", - identifier_external: index % 2 === 0 ? "distrowatch" : "linuxtracker", - }, - category: "Linux ISOs", - size: index % 2 === 0 ? 4566784529 : (index % 3 === 0 ? 7427019812 : 2312122455), - source: "", - container: "", - codec: "", - resolution: "", - })); - setModifiedData(newData); - } + setSettings(prev => ({ ...prev, incognitoMode: !prev.incognitoMode })); }; const defaultData = React.useMemo(() => [], []) - const displayData = showLinuxIsos ? modifiedData : (data?.data ?? defaultData); + const displayData = settings.incognitoMode ? modifiedData : (data?.data ?? defaultData); const tableInstance = useReactTable({ columns, @@ -392,7 +402,7 @@ export const ReleaseTable = () => { aria-label="Toggle view" title="Go incognito" > - {showLinuxIsos ? ( + {settings.incognitoMode ? ( ) : ( diff --git a/web/src/utils/Context.ts b/web/src/utils/Context.ts index 91382f9..85af67f 100644 --- a/web/src/utils/Context.ts +++ b/web/src/utils/Context.ts @@ -12,6 +12,7 @@ interface SettingsType { scrollOnNewLog: boolean; indentLogLines: boolean; hideWrappedText: boolean; + incognitoMode: boolean; } export type FilterListState = { @@ -42,7 +43,8 @@ const SettingsContextDefaults: SettingsType = { darkTheme: window.matchMedia('(prefers-color-scheme: dark)').matches, scrollOnNewLog: false, indentLogLines: false, - hideWrappedText: false + hideWrappedText: false, + incognitoMode: false }; const FilterListContextDefaults: FilterListState = { diff --git a/web/src/utils/index.ts b/web/src/utils/index.ts index c104f40..7164cf9 100644 --- a/web/src/utils/index.ts +++ b/web/src/utils/index.ts @@ -128,29 +128,61 @@ export function humanFileSize(sizeBytes: number | bigint): string { export const RandomLinuxIsos = (count: number) => { const linuxIsos = [ - "ubuntu-20.04.4-lts-focal-fossa-desktop-amd64-secure-boot", - "debian-11.3.0-bullseye-amd64-DVD-1-with-nonfree-firmware-netinst", - "fedora-36-workstation-x86_64-live-iso-with-rpmfusion-free-and-nonfree", - "archlinux-2023.04.01-x86_64-advanced-installation-environment", - "linuxmint-20.3-uma-cinnamon-64bit-full-multimedia-support-edition", - "centos-stream-9-x86_64-dvd1-full-install-iso-with-extended-repositories", - "opensuse-tumbleweed-20230415-DVD-x86_64-full-packaged-desktop-environments", - "manjaro-kde-21.1.6-210917-linux514-full-hardware-support-edition", - "elementaryos-6.1-odin-amd64-20230104-iso-with-pantheon-desktop-environment", - "pop_os-21.10-amd64-nvidia-proprietary-drivers-included-live", - "kali-linux-2023.2-live-amd64-iso-with-persistent-storage-and-custom-tools", - "zorin-os-16-pro-ultimate-edition-64-bit-r1-iso-with-windows-app-support", - "endeavouros-2023.04.15-x86_64-iso-with-offline-installer-and-xfce4", - "mx-linux-21.2-aarch64-xfce-iso-with-ahs-enabled-kernel-and-snapshot-feature", - "solus-4.3-budgie-desktop-environment-full-iso-with-software-center", - "slackware-15.0-install-dvd-iso-with-extended-documentation-and-extras", - "alpine-standard-3.15.0-x86_64-iso-for-container-and-server-use", - "gentoo-livecd-amd64-minimal-20230407-stage3-tarball-included", - "peppermint-11-20210903-amd64-iso-with-hybrid-lxde-xfce-desktop", - "deepin-20.3-amd64-iso-with-deepin-desktop-environment-and-app-store" + "debian-live-12.10.0-amd64-kde.iso", + "xubuntu-25.04-desktop-amd64.iso", + "ubuntu-25.04-live-server-amd64.iso", + "ubuntu-25.04-desktop-amd64.iso", + "edubuntu-25.04-desktop-amd64.iso", + "deepin-desktop-community-23.1-amd64.iso", + "TUXEDO-OS-202504150920.iso", + "tails-amd64-6.14.2.iso", + "manjaro-kde-25.0.0-250414-linux612.iso", + "Fedora-KDE-Desktop-Live-x86_64-42.iso", + "manjaro-xfce-25.0.0-250414-linux612.iso", + "manjaro-gnome-25.0.0-250414-linux612.iso", + "neon-user-20250410-1320.iso", + "sparkylinux-7.7-x86_64-xfce.iso", + "Gobo-017.01-x86_64.iso", + "lite-7.4-64bit.iso", + "EndeavourOS_Mercury-Neo-2025.03.19.iso", + "elementary-8.0.1-20250314.iso", + "debian-12.10.0-amd64-DVD-1.iso", + "finnix-250.iso", + "kali-linux-2025.1a-installer-amd64.iso", + "linuxmint-22.1-cinnamon-64bit.iso", + "MX-23.5_x64.iso", + "Solus-Plasma-Release-2025-01-26.iso" ]; - return Array.from({ length: count }, () => linuxIsos[Math.floor(Math.random() * linuxIsos.length)]); + const selectedIsos = []; + const availableIsos = [...linuxIsos]; + const numToSelect = Math.min(count, availableIsos.length); + + for (let i = 0; i < numToSelect; i++) { + const randomIndex = Math.floor(Math.random() * availableIsos.length); + selectedIsos.push(availableIsos.splice(randomIndex, 1)[0]); + } + + return selectedIsos; +}; + +export const RandomIsoTracker = (count: number) => { + const fossTorrentSites = [ + "fosstorrents", + "linuxtracker", + "distrowatch", + ]; + + const selectedSites = []; + const availableSites = [...fossTorrentSites]; + const numToSelect = Math.min(count, availableSites.length); + + for (let i = 0; i < numToSelect; i++) { + const randomIndex = Math.floor(Math.random() * availableSites.length); + selectedSites.push(availableSites.splice(randomIndex, 1)[0]); + } + + return selectedSites; }; export async function CopyTextToClipboard(text: string) { @@ -187,4 +219,3 @@ export async function CopyTextToClipboard(text: string) { } document.body.removeChild(textarea); } -