mirror of
https://github.com/ClipFusion-org/clipfusion.git
synced 2025-08-03 15:55:07 +00:00
implemented project searching and added safe area margins
This commit is contained in:
parent
38973ff7d3
commit
535fd68197
29
package-lock.json
generated
29
package-lock.json
generated
@ -35,6 +35,8 @@
|
||||
"react-hook-form": "^7.60.0",
|
||||
"sonner": "^2.0.6",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwindcss-safe-area": "^1.0.0",
|
||||
"use-debounce": "^10.0.5",
|
||||
"zod": "^4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -6870,6 +6872,21 @@
|
||||
"integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tailwindcss-safe-area": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss-safe-area/-/tailwindcss-safe-area-1.0.0.tgz",
|
||||
"integrity": "sha512-cg4eFaTe4dFKZ4H6Vrobxqen6Jki/sSvssmHEYX5rFu1IojwGjTmab/eWzzN2gVrtMSIJoYSMS49p4TjBnWBeA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mvllow"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tailwindcss": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz",
|
||||
@ -7195,6 +7212,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/use-debounce": {
|
||||
"version": "10.0.5",
|
||||
"resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.5.tgz",
|
||||
"integrity": "sha512-Q76E3lnIV+4YT9AHcrHEHYmAd9LKwUAbPXDm7FlqVGDHiSOhX3RDjT8dm0AxbJup6WgOb1YEcKyCr11kBJR5KQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/use-sidecar": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
|
||||
|
@ -36,6 +36,8 @@
|
||||
"react-hook-form": "^7.60.0",
|
||||
"sonner": "^2.0.6",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwindcss-safe-area": "^1.0.0",
|
||||
"use-debounce": "^10.0.5",
|
||||
"zod": "^4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
|
||||
@import "tailwindcss-safe-area";
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@theme inline {
|
||||
@ -47,6 +47,7 @@ body {
|
||||
font-family: var(--font-geist), sans-serif;
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import type { Metadata, Viewport } from "next";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import { ReactNode } from "react";
|
||||
import { SidebarProvider } from "@/components/ui/sidebar";
|
||||
@ -24,6 +24,15 @@ export const metadata: Metadata = {
|
||||
description: "Desktop power right in your browser",
|
||||
};
|
||||
|
||||
export const viewport: Viewport = {
|
||||
width: 'device-width',
|
||||
initialScale: 1,
|
||||
viewportFit: 'cover',
|
||||
themeColor: [
|
||||
{ media: "(prefers-color-scheme: dark)", color: "#0a0a0a" },
|
||||
{ media: "(prefers-color-scheme: light)", color: "#ffffff" }
|
||||
]
|
||||
};
|
||||
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
@ -35,7 +44,6 @@ export default async function RootLayout({
|
||||
<head>
|
||||
<meta name="apple-mobile-web-app-title" content="ClipFusion" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<meta name="HandheldFriendly" content="true" />
|
||||
<Analytics/>
|
||||
</head>
|
||||
<body className={`${geist.variable} ${geistMono.variable} antialiased`}>
|
||||
|
@ -5,7 +5,7 @@ import { useLiveQuery } from "dexie-react-hooks";
|
||||
import { db } from "@/lib/db";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CopyIcon, EditIcon, EllipsisIcon, InfoIcon, ListCheckIcon, PencilIcon, PlusIcon, TrashIcon } from "lucide-react";
|
||||
import { CheckCheckIcon, CopyIcon, EditIcon, EllipsisIcon, InfoIcon, ListCheckIcon, PencilIcon, PlusIcon, TrashIcon } from "lucide-react";
|
||||
import { Toggle } from "@/components/ui/toggle";
|
||||
import Search from "@/components/search";
|
||||
import { useIsMobile } from "@/hooks/use-mobile";
|
||||
@ -23,6 +23,7 @@ import { generateUUID } from "@/lib/uuid";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
|
||||
import { useDebounce } from "use-debounce";
|
||||
|
||||
const ProjectInfoFormSchema = z.object({
|
||||
title: z.string().nonempty("Title cannot be empty"),
|
||||
@ -118,6 +119,7 @@ const DeleteProjectDialog = ({ project }: { project: Project }) => {
|
||||
const ProjectDropdown = ({ project }: { project: Project }): ReactNode => {
|
||||
const [renameDialogOpen, setRenameDialogOpen] = useState(false);
|
||||
const [deleteAlertOpen, setDeleteAlertOpen] = useState(false);
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const handleDuplicate = async () => {
|
||||
const newProject = {
|
||||
@ -138,7 +140,7 @@ const ProjectDropdown = ({ project }: { project: Project }): ReactNode => {
|
||||
<EllipsisIcon/>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start" className="min-w-48">
|
||||
<DropdownMenuContent align={isMobile ? "end" : "start"} className="min-w-48">
|
||||
<div className="flex flex-row items-center justify-between">
|
||||
<DropdownMenuLabel className="font-semibold">{project.title}</DropdownMenuLabel>
|
||||
<DropdownMenuItem onClick={() => setRenameDialogOpen(true)}>
|
||||
@ -221,10 +223,11 @@ const ProjectContainer = ({
|
||||
export default function Home(): ReactNode {
|
||||
const isMobile = useIsMobile();
|
||||
const [search, setSearch] = useState('');
|
||||
const [debouncedSearch] = useDebounce(search, 300);
|
||||
|
||||
const projects = useLiveQuery(() => {
|
||||
return db.projects.filter((project) => project.title.includes(search)).toArray();
|
||||
});
|
||||
const projects = useLiveQuery(() => (
|
||||
db.projects.filter((project) => project.title.toLowerCase().includes(debouncedSearch.toLowerCase())).toArray()
|
||||
), [debouncedSearch]);
|
||||
|
||||
const newProjectForm = useForm<z.infer<typeof ProjectInfoFormSchema>>({
|
||||
resolver: zodResolver(ProjectInfoFormSchema),
|
||||
|
@ -33,7 +33,7 @@ const items: DashboardItem[] = [
|
||||
export const Dashboard = (): ReactNode => {
|
||||
return (
|
||||
<Sidebar>
|
||||
<SidebarHeader className="flex justify-center items-center mt-2">
|
||||
<SidebarHeader className="flex justify-center items-center mt-safe-or-2 ml-safe">
|
||||
<Link href="/">
|
||||
<ClipFusionLogo width="30" height="30">
|
||||
<p className="font-bold text-xl select-none">ClipFusion</p>
|
||||
@ -84,7 +84,7 @@ export const Dashboard = (): ReactNode => {
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SidebarFooter className="mb-safe">
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>
|
||||
Links
|
||||
|
@ -7,7 +7,7 @@ export const Search = (props: ComponentProps<typeof Input>): ReactNode => (
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search"
|
||||
className="peer block w-full rounded-md border py-[9px] pl-10 text-sm"
|
||||
className="peer block w-full rounded-md border py-[9px] pl-10"
|
||||
{...props}
|
||||
/>
|
||||
<SearchIcon className="pointer-events-none absolute left-3 top-1/2 h-[18px] w-[18px] -translate-y-1/2" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require("@tailwindcss/line-clamp"),
|
||||
require("@tailwindcss/line-clamp")
|
||||
]
|
||||
};
|
Loading…
Reference in New Issue
Block a user