From b566d13c8da23ed18dd22312101ec1d5ce155bd2 Mon Sep 17 00:00:00 2001 From: diced Date: Wed, 2 Jul 2025 20:41:37 -0700 Subject: [PATCH] fix: random visual bugs + enhancements --- SECURITY.md | 10 +-- .../file/DashboardFile/FileModal.tsx | 5 +- src/components/file/DashboardFileType.tsx | 90 ++++++++++--------- src/components/pages/metrics/index.tsx | 43 ++++++++- .../pages/serverSettings/parts/Domains.tsx | 33 +++++-- src/components/pages/upload/File/index.tsx | 52 ++++++----- src/components/pages/upload/Text/index.tsx | 19 ++-- src/components/render/code/HighlightCode.tsx | 2 +- src/lib/config/read/index.ts | 4 + 9 files changed, 166 insertions(+), 92 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 8bd7c633..10387a04 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,11 +2,11 @@ ## Supported Versions -| Version | Supported | -| ------- | ------------------------------------- | -| 4.x.x | :white_check_mark: | -| < 3 | :white_check_mark: (EOL at June 2025) | -| < 2 | :x: | +| Version | Supported | +| ------- | ------------------ | +| 4.2.x | :white_check_mark: | +| < 3 | :x: | +| < 2 | :x: | ## Reporting a Vulnerability diff --git a/src/components/file/DashboardFile/FileModal.tsx b/src/components/file/DashboardFile/FileModal.tsx index cd5dd8b1..25b41509 100755 --- a/src/components/file/DashboardFile/FileModal.tsx +++ b/src/components/file/DashboardFile/FileModal.tsx @@ -18,7 +18,6 @@ import { Modal, Pill, PillsInput, - ScrollArea, SimpleGrid, Text, Title, @@ -61,8 +60,8 @@ import { removeFromFolder, viewFile, } from '../actions'; -import FileStat from './FileStat'; import EditFileDetailsModal from './EditFileDetailsModal'; +import FileStat from './FileStat'; function ActionButton({ Icon, @@ -189,9 +188,9 @@ export default function FileModal({ } size='auto' + maw='90vw' centered zIndex={200} - scrollAreaComponent={ScrollArea.Autosize} > {file ? ( <> diff --git a/src/components/file/DashboardFileType.tsx b/src/components/file/DashboardFileType.tsx index 548388b9..38369557 100755 --- a/src/components/file/DashboardFileType.tsx +++ b/src/components/file/DashboardFileType.tsx @@ -11,7 +11,7 @@ import { Text, } from '@mantine/core'; import { Icon, IconFileUnknown, IconPlayerPlay, IconShieldLockFilled } from '@tabler/icons-react'; -import { useEffect, useState } from 'react'; +import { useEffect, useState, useCallback, useMemo } from 'react'; import { renderMode } from '../pages/upload/renderMode'; import Render from '../render/Render'; import fileIcon from './fileIcon'; @@ -30,7 +30,7 @@ function PlaceholderContent({ text, Icon }: { text: string; Icon: Icon }) { function Placeholder({ text, Icon, ...props }: { text: string; Icon: Icon; onClick?: () => void }) { return ( -
+
); @@ -83,57 +83,60 @@ export default function DashboardFileType({ const disableMediaPreview = useSettingsStore((state) => state.settings.disableMediaPreview); const dbFile = 'id' in file; - const renderIn = renderMode(file.name.split('.').pop() || ''); + const renderIn = useMemo(() => renderMode(file.name.split('.').pop() || ''), [file.name]); const [fileContent, setFileContent] = useState(''); const [type, setType] = useState(file.type.split('/')[0]); const [open, setOpen] = useState(false); - const gettext = async () => { - if (!dbFile) { - const reader = new FileReader(); - reader.onload = () => { - if ((reader.result! as string).length > 1 * 1024 * 1024) { - setFileContent( - reader.result!.slice(0, 1 * 1024 * 1024) + - '\n...\nThe file is too big to display click the download icon to view/download it.', - ); - } else { - setFileContent(reader.result as string); - } - }; - reader.readAsText(file); + const getText = useCallback(async () => { + try { + if (!dbFile) { + const reader = new FileReader(); + reader.onload = () => { + if ((reader.result! as string).length > 1 * 1024 * 1024) { + setFileContent( + reader.result!.slice(0, 1 * 1024 * 1024) + + '\n...\nThe file is too big to display click the download icon to view/download it.', + ); + } else { + setFileContent(reader.result as string); + } + }; + reader.readAsText(file); + return; + } - return; - } - - if (file.size > 1 * 1024 * 1024) { - const res = await fetch(`/raw/${file.name}${password ? `?pw=${password}` : ''}`, { - headers: { - Range: 'bytes=0-' + 1 * 1024 * 1024, // 0 mb to 1 mb - }, - }); + if (file.size > 1 * 1024 * 1024) { + const res = await fetch(`/raw/${file.name}${password ? `?pw=${password}` : ''}`, { + headers: { + Range: 'bytes=0-' + 1 * 1024 * 1024, // 0 mb to 1 mb + }, + }); + if (!res.ok) throw new Error('Failed to fetch file'); + const text = await res.text(); + setFileContent( + text + '\n...\nThe file is too big to display click the download icon to view/download it.', + ); + return; + } + const res = await fetch(`/raw/${file.name}${password ? `?pw=${password}` : ''}`); + if (!res.ok) throw new Error('Failed to fetch file'); const text = await res.text(); - setFileContent( - text + '\n...\nThe file is too big to display click the download icon to view/download it.', - ); - return; + setFileContent(text); + } catch { + setFileContent('Error loading file.'); } - - const res = await fetch(`/raw/${file.name}${password ? `?pw=${password}` : ''}`); - const text = await res.text(); - - setFileContent(text); - }; + }, [dbFile, file, password]); useEffect(() => { if (code) { setType('text'); - gettext(); + getText(); } else if (overrideType === 'text' || type === 'text') { - gettext(); + getText(); } else { return; } @@ -177,7 +180,10 @@ export default function DashboardFileType({ /> ) : (file as DbFile).thumbnail && dbFile ? ( - +
); case 'audio': diff --git a/src/components/pages/metrics/index.tsx b/src/components/pages/metrics/index.tsx index 7e8b8f87..e4450deb 100755 --- a/src/components/pages/metrics/index.tsx +++ b/src/components/pages/metrics/index.tsx @@ -7,6 +7,7 @@ import FilesUrlsCountGraph from './parts/FilesUrlsCountGraph'; import { useApiStats } from './useStats'; import { StatsCardsSkeleton } from './parts/StatsCards'; import { StatsTablesSkeleton } from './parts/StatsTables'; +import dayjs from 'dayjs'; const StatsCards = dynamic(() => import('./parts/StatsCards')); const StatsTables = dynamic(() => import('./parts/StatsTables')); @@ -14,9 +15,11 @@ const StorageGraph = dynamic(() => import('./parts/StorageGraph')); const ViewsGraph = dynamic(() => import('./parts/ViewsGraph')); export default function DashboardMetrics() { + const today = dayjs(); + const [dateRange, setDateRange] = useState<[string | null, string | null]>([ - new Date(Date.now() - 86400000 * 7).toISOString(), - new Date().toISOString(), + today.subtract(7, 'day').toISOString(), + today.toISOString(), ]); const [open, setOpen] = useState(false); @@ -40,17 +43,49 @@ export default function DashboardMetrics() { return ( <> setOpen(false)} size='auto'> - + - + diff --git a/src/components/pages/serverSettings/parts/Domains.tsx b/src/components/pages/serverSettings/parts/Domains.tsx index e554dc1e..edaac41d 100644 --- a/src/components/pages/serverSettings/parts/Domains.tsx +++ b/src/components/pages/serverSettings/parts/Domains.tsx @@ -63,12 +63,35 @@ export default function Domains({ - + {domains.map((domain, index) => ( - - -
- {domain} + + +
+ {domain}