-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
48 changed files
with
1,904 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { IWrapServerActions } from "@/shared/types/actions"; | ||
import { deconstructFormData } from "@/shared/utils/type"; | ||
import { wrapAction } from "@/shared/utils/wrap-action"; | ||
import { IUploadChunkData, IUploadClientActions } from "@/upload/models/client"; | ||
import { UploadSlicer } from "@/upload/models/slicer"; | ||
import { FileSystemStorage } from "@/upload/models/storages/file-system"; | ||
import path from "path"; | ||
import { Readable } from "stream"; | ||
|
||
const storage = new FileSystemStorage(path.resolve("node_modules", ".cache")); | ||
|
||
export const uploadActions = { | ||
uploadChunk: wrapAction(async (formData: FormData) => { | ||
"use server"; | ||
const { hash, chunk, index } = | ||
deconstructFormData<IUploadChunkData>(formData); | ||
const slicer = new UploadSlicer(hash, storage); | ||
|
||
if (chunk instanceof Blob) { | ||
const stream = chunk.stream() as any; | ||
await slicer.writeChunk(index, stream); | ||
} else if (chunk instanceof Buffer) { | ||
const stream = Readable.from(chunk as Buffer); | ||
await slicer.writeChunk(index, stream); | ||
} | ||
}), | ||
fileExists: wrapAction(async (hash: string) => { | ||
"use server"; | ||
const slicer = new UploadSlicer(hash, storage); | ||
return await slicer.fileExists(); | ||
}), | ||
chunkExists: wrapAction(async (hash: string, index: number) => { | ||
"use server"; | ||
const slicer = new UploadSlicer(hash, storage); | ||
return await slicer.chunkExists(index); | ||
}), | ||
merge: wrapAction(async (hash: string) => { | ||
"use server"; | ||
const slicer = new UploadSlicer(hash, storage); | ||
await slicer.merge(); | ||
}), | ||
getLastExistedChunkIndex: wrapAction(async (hash) => { | ||
"use server"; | ||
const slicer = new UploadSlicer(hash, storage); | ||
return slicer.getLastExistedChunkIndex(); | ||
}), | ||
} as const satisfies IWrapServerActions<IUploadClientActions>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
"use client"; | ||
|
||
import { GitHubLogoIcon } from "@radix-ui/react-icons"; | ||
import Link from "next/link"; | ||
import React, { useEffect, useState } from "react"; | ||
import { mp } from "../utils/jsx"; | ||
|
||
export const GitLog: React.FC<{}> = (props) => { | ||
const [log, setLog] = useState<string>(); | ||
|
||
useEffect(() => { | ||
fetch("/git.log") | ||
.then((res) => (res.status === 200 ? res.text() : "")) | ||
.then(setLog); | ||
}, []); | ||
return mp( | ||
props, | ||
<div className="text-gray-500 text-xs items-center justify-center flex gap-2 max-md:flex-col"> | ||
<div>{log}</div> | ||
<Link | ||
target="_blank" | ||
href={"https://github.com/xiaosen7/nextjs-large-file-upload-demo"} | ||
> | ||
<GitHubLogoIcon /> | ||
</Link> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { ReloadIcon } from "@radix-ui/react-icons"; | ||
import React from "react"; | ||
|
||
export interface ILoadingProps {} | ||
|
||
export const Loading: React.FC<ILoadingProps> = () => { | ||
return <ReloadIcon className="h-4 w-4 animate-spin" />; | ||
}; |
36 changes: 36 additions & 0 deletions
36
apps/large-file-upload/libs/shared/components/ui/badge.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import * as React from "react" | ||
import { cva, type VariantProps } from "class-variance-authority" | ||
|
||
import { cn } from "@/shared/utils" | ||
|
||
const badgeVariants = cva( | ||
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", | ||
{ | ||
variants: { | ||
variant: { | ||
default: | ||
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80", | ||
secondary: | ||
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", | ||
destructive: | ||
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", | ||
outline: "text-foreground", | ||
}, | ||
}, | ||
defaultVariants: { | ||
variant: "default", | ||
}, | ||
} | ||
) | ||
|
||
export interface BadgeProps | ||
extends React.HTMLAttributes<HTMLDivElement>, | ||
VariantProps<typeof badgeVariants> {} | ||
|
||
function Badge({ className, variant, ...props }: BadgeProps) { | ||
return ( | ||
<div className={cn(badgeVariants({ variant }), className)} {...props} /> | ||
) | ||
} | ||
|
||
export { Badge, badgeVariants } |
56 changes: 56 additions & 0 deletions
56
apps/large-file-upload/libs/shared/components/ui/button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { Slot } from "@radix-ui/react-slot"; | ||
import { cva, type VariantProps } from "class-variance-authority"; | ||
import * as React from "react"; | ||
|
||
import { cn } from "@/shared/utils"; | ||
|
||
const buttonVariants = cva( | ||
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", | ||
{ | ||
variants: { | ||
variant: { | ||
default: "bg-primary text-primary-foreground hover:bg-primary/90", | ||
destructive: | ||
"bg-destructive text-destructive-foreground hover:bg-destructive/90", | ||
outline: | ||
"border border-input bg-background hover:bg-accent hover:text-accent-foreground", | ||
secondary: | ||
"bg-secondary text-secondary-foreground hover:bg-secondary/80", | ||
ghost: "hover:bg-accent hover:text-accent-foreground", | ||
link: "text-primary underline-offset-4 hover:underline", | ||
}, | ||
size: { | ||
default: "h-10 px-4 py-2", | ||
sm: "h-9 rounded-md px-3", | ||
lg: "h-11 rounded-md px-8", | ||
icon: "h-10 w-10", | ||
}, | ||
}, | ||
defaultVariants: { | ||
variant: "default", | ||
size: "default", | ||
}, | ||
} | ||
); | ||
|
||
export interface ButtonProps | ||
extends React.ButtonHTMLAttributes<HTMLButtonElement>, | ||
VariantProps<typeof buttonVariants> { | ||
asChild?: boolean; | ||
} | ||
|
||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( | ||
({ className, variant, size, asChild = false, ...props }, ref) => { | ||
const Comp = asChild ? Slot : "button"; | ||
return ( | ||
<Comp | ||
className={cn(buttonVariants({ variant, size, className }))} | ||
ref={ref} | ||
{...props} | ||
/> | ||
); | ||
} | ||
); | ||
Button.displayName = "Button"; | ||
|
||
export { Button, buttonVariants }; |
25 changes: 25 additions & 0 deletions
25
apps/large-file-upload/libs/shared/components/ui/input.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import * as React from "react"; | ||
|
||
import { cn } from "@/shared/utils"; | ||
|
||
export interface InputProps | ||
extends React.InputHTMLAttributes<HTMLInputElement> {} | ||
|
||
const Input = React.forwardRef<HTMLInputElement, InputProps>( | ||
({ className, type, ...props }, ref) => { | ||
return ( | ||
<input | ||
type={type} | ||
className={cn( | ||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", | ||
className | ||
)} | ||
ref={ref} | ||
{...props} | ||
/> | ||
); | ||
} | ||
); | ||
Input.displayName = "Input"; | ||
|
||
export { Input }; |
26 changes: 26 additions & 0 deletions
26
apps/large-file-upload/libs/shared/components/ui/label.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
"use client" | ||
|
||
import * as React from "react" | ||
import * as LabelPrimitive from "@radix-ui/react-label" | ||
import { cva, type VariantProps } from "class-variance-authority" | ||
|
||
import { cn } from "@/shared/utils" | ||
|
||
const labelVariants = cva( | ||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" | ||
) | ||
|
||
const Label = React.forwardRef< | ||
React.ElementRef<typeof LabelPrimitive.Root>, | ||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & | ||
VariantProps<typeof labelVariants> | ||
>(({ className, ...props }, ref) => ( | ||
<LabelPrimitive.Root | ||
ref={ref} | ||
className={cn(labelVariants(), className)} | ||
{...props} | ||
/> | ||
)) | ||
Label.displayName = LabelPrimitive.Root.displayName | ||
|
||
export { Label } |
31 changes: 31 additions & 0 deletions
31
apps/large-file-upload/libs/shared/components/ui/popover.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
"use client" | ||
|
||
import * as React from "react" | ||
import * as PopoverPrimitive from "@radix-ui/react-popover" | ||
|
||
import { cn } from "@/shared/utils" | ||
|
||
const Popover = PopoverPrimitive.Root | ||
|
||
const PopoverTrigger = PopoverPrimitive.Trigger | ||
|
||
const PopoverContent = React.forwardRef< | ||
React.ElementRef<typeof PopoverPrimitive.Content>, | ||
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> | ||
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( | ||
<PopoverPrimitive.Portal> | ||
<PopoverPrimitive.Content | ||
ref={ref} | ||
align={align} | ||
sideOffset={sideOffset} | ||
className={cn( | ||
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", | ||
className | ||
)} | ||
{...props} | ||
/> | ||
</PopoverPrimitive.Portal> | ||
)) | ||
PopoverContent.displayName = PopoverPrimitive.Content.displayName | ||
|
||
export { Popover, PopoverTrigger, PopoverContent } |
28 changes: 28 additions & 0 deletions
28
apps/large-file-upload/libs/shared/components/ui/progress.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
"use client"; | ||
|
||
import * as ProgressPrimitive from "@radix-ui/react-progress"; | ||
import * as React from "react"; | ||
|
||
import { cn } from "@/shared/utils"; | ||
|
||
const Progress = React.forwardRef< | ||
React.ElementRef<typeof ProgressPrimitive.Root>, | ||
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root> | ||
>(({ className, value, ...props }, ref) => ( | ||
<ProgressPrimitive.Root | ||
ref={ref} | ||
className={cn( | ||
"relative h-4 w-full overflow-hidden rounded-full bg-secondary", | ||
className | ||
)} | ||
{...props} | ||
> | ||
<ProgressPrimitive.Indicator | ||
className="h-full w-full flex-1 bg-primary transition-all" | ||
style={{ transform: `translateX(-${100 - (value || 0)}%)` }} | ||
/> | ||
</ProgressPrimitive.Root> | ||
)); | ||
Progress.displayName = ProgressPrimitive.Root.displayName; | ||
|
||
export { Progress }; |
28 changes: 28 additions & 0 deletions
28
apps/large-file-upload/libs/shared/components/ui/slider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
"use client" | ||
|
||
import * as React from "react" | ||
import * as SliderPrimitive from "@radix-ui/react-slider" | ||
|
||
import { cn } from "@/shared/utils" | ||
|
||
const Slider = React.forwardRef< | ||
React.ElementRef<typeof SliderPrimitive.Root>, | ||
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> | ||
>(({ className, ...props }, ref) => ( | ||
<SliderPrimitive.Root | ||
ref={ref} | ||
className={cn( | ||
"relative flex w-full touch-none select-none items-center", | ||
className | ||
)} | ||
{...props} | ||
> | ||
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary"> | ||
<SliderPrimitive.Range className="absolute h-full bg-primary" /> | ||
</SliderPrimitive.Track> | ||
<SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" /> | ||
</SliderPrimitive.Root> | ||
)) | ||
Slider.displayName = SliderPrimitive.Root.displayName | ||
|
||
export { Slider } |
Oops, something went wrong.