📱 feat: Optimize mobile display

This commit is contained in:
jarvis2f 2024-12-24 13:30:55 +08:00
parent 3ce64a3cc3
commit 59a7ab046b
7 changed files with 62 additions and 23 deletions

View file

@ -37,7 +37,7 @@ export default function ChatSelect({ disabled }: { disabled: boolean }) {
variant="outline"
role="combobox"
aria-expanded={open}
className="w-[250px] justify-between"
className="w-full md:w-[250px] justify-between"
>
{selectedChat ? (
<div className="flex items-center gap-2">

View file

@ -56,7 +56,7 @@ export function FileCard({ file }: FileCardProps) {
<div className="flex-1">
<h3 className="mb-1 font-medium">{file.name}</h3>
<div className="mb-2 text-sm text-muted-foreground">
{prettyBytes(file.size)} {file.type}
{prettyBytes(file.size)} {file.type} {file.downloadStatus}
</div>
<div className="mb-2 w-full overflow-hidden">
<FileProgress file={file} />

View file

@ -39,14 +39,14 @@ export function FileFilters({
}: FileFiltersProps) {
return (
<div className="mb-6 flex flex-col justify-between md:flex-row">
<div className="flex flex-col gap-4 md:flex-row">
<div className="grid grid-cols-2 gap-4 md:flex-row md:flex">
<Input
placeholder="Search files..."
value={filters.search}
onChange={(e) =>
onFiltersChange({ ...filters, search: e.target.value })
}
className="md:w-[300px]"
className="col-span-2 md:w-[300px]"
/>
<FileTypeFilter
@ -65,7 +65,7 @@ export function FileFilters({
})
}
>
<SelectTrigger className="w-[150px]">
<SelectTrigger className="w-full md:w-[150px]">
<SelectValue placeholder="Download status" />
</SelectTrigger>
<SelectContent>
@ -78,7 +78,7 @@ export function FileFilters({
</Select>
</div>
<div className="flex gap-4">
<div className="hidden gap-4 md:flex">
<TableColumnFilter
columns={columns}
onColumnConfigChange={onColumnConfigChange}

View file

@ -49,6 +49,7 @@ import prettyBytes from "pretty-bytes";
import FileProgress from "@/components/file-progress";
import FileNotFount from "@/components/file-not-found";
import FileExtra from "@/components/file-extra";
import useIsMobile from "@/hooks/use-is-mobile";
interface FileListProps {
accountId: string;
@ -100,7 +101,7 @@ const PhotoColumnImage = memo(function PhotoColumnImage({
});
export function FileList({ accountId, chatId }: FileListProps) {
const [isMobile, setIsMobile] = useState(false);
const isMobile = useIsMobile();
const [selectedFiles, setSelectedFiles] = useState<Set<number>>(new Set());
const observerTarget = useRef(null);
const [columns, setColumns] = useState<Column[]>(COLUMNS);
@ -110,16 +111,6 @@ export function FileList({ accountId, chatId }: FileListProps) {
const { filters, handleFilterChange, isLoading, files, handleLoadMore } =
useFiles(accountId, chatId);
useEffect(() => {
const checkMobile = () => {
setIsMobile(window.innerWidth < 768);
};
checkMobile();
window.addEventListener("resize", checkMobile);
return () => window.removeEventListener("resize", checkMobile);
}, []);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
@ -162,6 +153,16 @@ export function FileList({ accountId, chatId }: FileListProps) {
if (isMobile) {
return (
<div className="space-y-4">
<FileFilters
telegramId={accountId}
chatId={chatId}
filters={filters}
onFiltersChange={handleFilterChange}
columns={columns}
onColumnConfigChange={setColumns}
rowHeight={rowHeight}
setRowHeight={setRowHeight}
/>
<div className="grid grid-cols-1 gap-4">
{files.map((file, index) => (
<FileCard

View file

@ -48,7 +48,7 @@ export default function FileTypeFilter({
value={type}
onValueChange={(value) => onTypeChange(value as FileType)}
>
<SelectTrigger className="w-[150px]">
<SelectTrigger className="w-full md:w-[150px]">
<SelectValue placeholder="File type" />
</SelectTrigger>
<SelectContent>

View file

@ -30,23 +30,28 @@ import ChatSelect from "@/components/chat-select";
import Link from "next/link";
import TelegramIcon from "@/components/telegram-icon";
import AutoDownloadDialog from "@/components/auto-download-dialog";
import useIsMobile from "@/hooks/use-is-mobile";
import { useState } from "react";
import {Button} from "@/components/ui/button";
export function Header() {
const { isLoading, getAccounts, accountId, account, handleAccountChange } =
useTelegramAccount();
const { connectionStatus, accountDownloadSpeed } = useWebsocket();
const accounts = getAccounts("active");
const isMobile = useIsMobile();
const [showMore, setShowMore] = useState(false);
return (
<Card className="mb-6">
<CardContent className="p-4">
<div className="flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
<div className="flex flex-1 flex-col gap-4 md:flex-row md:items-center">
<div className="relative flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
<div className="w-full flex flex-1 flex-col gap-4 md:flex-row md:items-center">
<Link href={"/"} className="hidden md:inline-flex">
<TelegramIcon className="h-6 w-6" />
</Link>
<div className="flex items-center gap-2">
<div className="w-full md:w-auto">
<Select value={accountId} onValueChange={handleAccountChange}>
<SelectTrigger className="w-full md:w-[200px]">
<SelectValue placeholder="Select account ...">
@ -99,9 +104,14 @@ export function Header() {
</Select>
</div>
<ChatSelect disabled={!accountId} />
{(!isMobile || showMore) && (
<>
<ChatSelect disabled={!accountId} />
<AutoDownloadDialog />
</>
)}
<AutoDownloadDialog />
</div>
<div className="flex items-center gap-4">
@ -147,6 +157,15 @@ export function Header() {
<SettingsDialog />
</div>
<Button
size="xs"
variant="ghost"
onClick={() => setShowMore(!showMore)}
className="absolute bottom-0 right-0 md:hidden"
>
<Ellipsis className="h-4 w-4" />
</Button>
</div>
</CardContent>
</Card>

View file

@ -0,0 +1,19 @@
import { useLayoutEffect, useState } from "react";
const useIsMobile = (): boolean => {
const [isMobile, setIsMobile] = useState(false);
useLayoutEffect(() => {
const checkMobile = () => {
setIsMobile(window.innerWidth < 768);
};
checkMobile();
window.addEventListener("resize", checkMobile);
return () => window.removeEventListener("resize", checkMobile);
}, []);
return isMobile;
};
export default useIsMobile;