@weirdfingers/boards 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +23 -9
- package/dist/index.d.ts +23 -9
- package/dist/index.js +191 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +190 -65
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
- package/src/graphql/operations.ts +6 -0
- package/src/hooks/__tests__/useMultiUpload.test.ts +238 -0
- package/src/hooks/useGeneration.ts +44 -0
- package/src/hooks/useMultiUpload.ts +309 -0
- package/src/index.ts +7 -5
- package/src/hooks/useUpload.ts +0 -175
package/src/hooks/useUpload.ts
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hook for uploading artifacts (images, videos, audio, text).
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { useCallback, useState } from "react";
|
|
6
|
-
import { useMutation } from "urql";
|
|
7
|
-
import { UPLOAD_ARTIFACT_FROM_URL, ArtifactType } from "../graphql/operations";
|
|
8
|
-
import { useAuth } from "../auth/context";
|
|
9
|
-
import { useApiConfig } from "../config/ApiConfigContext";
|
|
10
|
-
|
|
11
|
-
export interface UploadRequest {
|
|
12
|
-
boardId: string;
|
|
13
|
-
artifactType: ArtifactType;
|
|
14
|
-
source: File | string; // File object or URL string
|
|
15
|
-
userDescription?: string;
|
|
16
|
-
parentGenerationId?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface UploadResult {
|
|
20
|
-
id: string;
|
|
21
|
-
storageUrl: string;
|
|
22
|
-
thumbnailUrl?: string;
|
|
23
|
-
status: "completed" | "failed";
|
|
24
|
-
artifactType: ArtifactType;
|
|
25
|
-
generatorName: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface UploadHook {
|
|
29
|
-
upload: (request: UploadRequest) => Promise<UploadResult>;
|
|
30
|
-
isUploading: boolean;
|
|
31
|
-
progress: number; // 0-100
|
|
32
|
-
error: Error | null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function useUpload(): UploadHook {
|
|
36
|
-
const [isUploading, setIsUploading] = useState(false);
|
|
37
|
-
const [progress, setProgress] = useState(0);
|
|
38
|
-
const [error, setError] = useState<Error | null>(null);
|
|
39
|
-
|
|
40
|
-
const { apiUrl } = useApiConfig();
|
|
41
|
-
const auth = useAuth();
|
|
42
|
-
|
|
43
|
-
const [, uploadFromUrlMutation] = useMutation(UPLOAD_ARTIFACT_FROM_URL);
|
|
44
|
-
|
|
45
|
-
const upload = useCallback(
|
|
46
|
-
async (request: UploadRequest): Promise<UploadResult> => {
|
|
47
|
-
setError(null);
|
|
48
|
-
setProgress(0);
|
|
49
|
-
setIsUploading(true);
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
// Handle URL upload via GraphQL
|
|
53
|
-
if (typeof request.source === "string") {
|
|
54
|
-
const result = await uploadFromUrlMutation({
|
|
55
|
-
input: {
|
|
56
|
-
boardId: request.boardId,
|
|
57
|
-
artifactType: request.artifactType,
|
|
58
|
-
fileUrl: request.source,
|
|
59
|
-
userDescription: request.userDescription,
|
|
60
|
-
parentGenerationId: request.parentGenerationId,
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
if (result.error) {
|
|
65
|
-
throw new Error(result.error.message);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (!result.data?.uploadArtifact) {
|
|
69
|
-
throw new Error("Upload failed");
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
setProgress(100);
|
|
73
|
-
setIsUploading(false);
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
id: result.data.uploadArtifact.id,
|
|
77
|
-
storageUrl: result.data.uploadArtifact.storageUrl,
|
|
78
|
-
thumbnailUrl: result.data.uploadArtifact.thumbnailUrl,
|
|
79
|
-
status: "completed",
|
|
80
|
-
artifactType: result.data.uploadArtifact.artifactType,
|
|
81
|
-
generatorName: result.data.uploadArtifact.generatorName,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Handle file upload via REST API
|
|
86
|
-
const formData = new FormData();
|
|
87
|
-
formData.append("board_id", request.boardId);
|
|
88
|
-
formData.append("artifact_type", request.artifactType.toLowerCase());
|
|
89
|
-
formData.append("file", request.source);
|
|
90
|
-
if (request.userDescription) {
|
|
91
|
-
formData.append("user_description", request.userDescription);
|
|
92
|
-
}
|
|
93
|
-
if (request.parentGenerationId) {
|
|
94
|
-
formData.append("parent_generation_id", request.parentGenerationId);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const token = await auth.getToken();
|
|
98
|
-
const headers: Record<string, string> = {};
|
|
99
|
-
if (token) {
|
|
100
|
-
headers.Authorization = `Bearer ${token}`;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Use XMLHttpRequest for progress tracking
|
|
104
|
-
const result = await new Promise<UploadResult>((resolve, reject) => {
|
|
105
|
-
const xhr = new XMLHttpRequest();
|
|
106
|
-
|
|
107
|
-
xhr.upload.addEventListener("progress", (e) => {
|
|
108
|
-
if (e.lengthComputable) {
|
|
109
|
-
const percentComplete = (e.loaded / e.total) * 100;
|
|
110
|
-
setProgress(percentComplete);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
xhr.addEventListener("load", () => {
|
|
115
|
-
if (xhr.status === 200) {
|
|
116
|
-
try {
|
|
117
|
-
const data = JSON.parse(xhr.responseText);
|
|
118
|
-
resolve({
|
|
119
|
-
id: data.id,
|
|
120
|
-
storageUrl: data.storageUrl,
|
|
121
|
-
thumbnailUrl: data.thumbnailUrl,
|
|
122
|
-
status: "completed",
|
|
123
|
-
artifactType: data.artifactType as ArtifactType,
|
|
124
|
-
generatorName: data.generatorName,
|
|
125
|
-
});
|
|
126
|
-
} catch (err) {
|
|
127
|
-
reject(new Error("Failed to parse response"));
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
try {
|
|
131
|
-
const errorData = JSON.parse(xhr.responseText);
|
|
132
|
-
reject(new Error(errorData.detail || `Upload failed: ${xhr.statusText}`));
|
|
133
|
-
} catch {
|
|
134
|
-
reject(new Error(`Upload failed: ${xhr.statusText}`));
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
xhr.addEventListener("error", () => {
|
|
140
|
-
reject(new Error("Upload failed: Network error"));
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
xhr.addEventListener("abort", () => {
|
|
144
|
-
reject(new Error("Upload cancelled"));
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
xhr.open("POST", `${apiUrl}/api/uploads/artifact`);
|
|
148
|
-
Object.entries(headers).forEach(([key, value]) => {
|
|
149
|
-
xhr.setRequestHeader(key, value);
|
|
150
|
-
});
|
|
151
|
-
xhr.send(formData);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
setProgress(100);
|
|
155
|
-
setIsUploading(false);
|
|
156
|
-
return result;
|
|
157
|
-
} catch (err) {
|
|
158
|
-
const uploadError =
|
|
159
|
-
err instanceof Error ? err : new Error("Upload failed");
|
|
160
|
-
setError(uploadError);
|
|
161
|
-
setIsUploading(false);
|
|
162
|
-
setProgress(0);
|
|
163
|
-
throw uploadError;
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
[uploadFromUrlMutation, apiUrl, auth]
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
return {
|
|
170
|
-
upload,
|
|
171
|
-
isUploading,
|
|
172
|
-
progress,
|
|
173
|
-
error,
|
|
174
|
-
};
|
|
175
|
-
}
|