diff --git a/bun.lockb b/bun.lockb index 655da00..6193c42 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 81506f4..02ee751 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "sitemap": "^8.0.0", - "solar-js-sdk": "^0.0.1", + "solar-js-sdk": "./packages/sn", "unified": "^11.0.5", "zustand": "^5.0.3" }, diff --git a/packages/sn/src/attachment.ts b/packages/sn/src/attachment.ts index 2da9f95..7c02b75 100644 --- a/packages/sn/src/attachment.ts +++ b/packages/sn/src/attachment.ts @@ -47,19 +47,19 @@ export async function listAttachment(id: string[]): Promise { return resp.data.data } -type MultipartProgress = { +export type MultipartProgress = { value: number | null current: number total: number } -type MultipartInfo = { +export type MultipartInfo = { rid: string fileChunks: Record isUploaded: boolean } -class UploadAttachmentTask { +export class UploadAttachmentTask { private content: File private pool: string private multipartSize: number = 0 @@ -83,7 +83,7 @@ class UploadAttachmentTask { const limit = 3 try { - await this.createMultipartPlaceholder() + await this.createFragment() console.log(`[Paperclip] Multipart placeholder has been created with rid ${this.multipartInfo?.rid}`) this.multipartProgress.value = 0 @@ -124,7 +124,7 @@ class UploadAttachmentTask { } } - private async createMultipartPlaceholder(): Promise { + private async createFragment(): Promise { const mimetypeMap: Record = { mp4: 'video/mp4', mov: 'video/quicktime', @@ -139,7 +139,7 @@ class UploadAttachmentTask { const nameArray = this.content.name.split('.') nameArray.pop() - const resp = await sni.post('/cgi/uc/attachments/multipart', { + const resp = await sni.post('/cgi/uc/attachments/fragments', { pool: this.pool, size: this.content.size, name: this.content.name, @@ -162,7 +162,7 @@ class UploadAttachmentTask { const data = new FormData() data.set('file', chunk) - const resp = await sni.post(`/cgi/uc/attachments/multipart/${this.multipartInfo.rid}/${chunkId}`, data, { + const resp = await sni.post(`/cgi/uc/attachments/fragments/${this.multipartInfo.rid}/${chunkId}`, data, { timeout: 3 * 60 * 1000, }) diff --git a/src/pages/attachments/new.tsx b/src/pages/attachments/new.tsx new file mode 100644 index 0000000..967aaec --- /dev/null +++ b/src/pages/attachments/new.tsx @@ -0,0 +1,92 @@ +import { Alert, Box, Button, CircularProgress, Collapse, Container, styled, Typography } from '@mui/material' +import { useEffect, useState } from 'react' +import { checkAuthenticatedClient, redirectToLogin, UploadAttachmentTask } from 'solar-js-sdk' + +import ErrorIcon from '@mui/icons-material/Error' +import CloudUploadIcon from '@mui/icons-material/CloudUpload' + +export function getStaticProps() { + return { + props: { + title: 'New Attachment', + }, + } +} + +const VisuallyHiddenInput = styled('input')({ + clip: 'rect(0 0 0 0)', + clipPath: 'inset(50%)', + height: 1, + overflow: 'hidden', + position: 'absolute', + bottom: 0, + left: 0, + whiteSpace: 'nowrap', + width: 1, +}) + +export default function AttachmentNew() { + useEffect(() => { + if (!checkAuthenticatedClient()) redirectToLogin() + }, []) + + const [file, setFile] = useState() + const [busy, setBusy] = useState(false) + const [error, setError] = useState(null) + + async function submit() { + if (!file) return + + try { + setBusy(true) + const task = new UploadAttachmentTask(file, 'interactive') + await task.submit() + } catch (err: any) { + setError(err.toString()) + } finally { + setBusy(false) + } + } + + return ( + + + + } severity="error"> + {error} + + + + {busy ? ( + + ) : ( + + )} + + + + Pool: Interactive + + + + + ) +}