feat: avatars for humans (#273)
* implement avatar backend functionality * add avatar endpoints * typo * implement client side avatar upload and handling * fixes * Update go/internal/handler/handler.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update js/desktop/src/lib/avatar-image.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * bug in order * remove unused component * fix invalid migration * fix syntax errors --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit was merged in pull request #273.
This commit is contained in:
co-authored by
coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
parent
ca3bbf204e
commit
4facc6b371
@@ -42,16 +42,12 @@ class ApiClient {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
private async fetch(
|
||||
private async send(
|
||||
method: string,
|
||||
path: string,
|
||||
body?: unknown,
|
||||
init: { headers?: Record<string, string>; body?: BodyInit } = {},
|
||||
): Promise<Response> {
|
||||
const headers: Record<string, string> = {};
|
||||
|
||||
if (body) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
const headers: Record<string, string> = { ...init.headers };
|
||||
|
||||
const token = this.config.getToken();
|
||||
if (token) {
|
||||
@@ -61,7 +57,7 @@ class ApiClient {
|
||||
const response = await fetch(`${this.config.baseUrl}${path}`, {
|
||||
method,
|
||||
headers,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
body: init.body,
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
@@ -77,6 +73,17 @@ class ApiClient {
|
||||
return response;
|
||||
}
|
||||
|
||||
private async fetch(
|
||||
method: string,
|
||||
path: string,
|
||||
body?: unknown,
|
||||
): Promise<Response> {
|
||||
return this.send(method, path, {
|
||||
headers: body ? { 'Content-Type': 'application/json' } : undefined,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
private async request<T>(
|
||||
schema: z.ZodType<T>,
|
||||
method: string,
|
||||
@@ -137,6 +144,25 @@ class ApiClient {
|
||||
await this.requestVoid('PATCH', '/humans/me/settings', data);
|
||||
}
|
||||
|
||||
// --- Avatar ---
|
||||
|
||||
async updateAvatar(blob: Blob): Promise<void> {
|
||||
await this.send('PUT', '/humans/me/avatar', {
|
||||
headers: { 'Content-Type': blob.type || 'image/jpeg' },
|
||||
body: blob,
|
||||
});
|
||||
}
|
||||
|
||||
async deleteAvatar(): Promise<void> {
|
||||
await this.requestVoid('DELETE', '/humans/me/avatar');
|
||||
}
|
||||
|
||||
async getAvatarDownloadUrl(objectId: string): Promise<string> {
|
||||
const response = await this.fetch('GET', `/humans/avatar/${objectId}`);
|
||||
const data = await response.json();
|
||||
return data.url;
|
||||
}
|
||||
|
||||
// --- Depot ---
|
||||
|
||||
async prepareUpload(data: PrepareUploadRequest) {
|
||||
|
||||
@@ -6,6 +6,7 @@ export const HumanSchema = z.object({
|
||||
email: z.string().email(),
|
||||
email_prefix: z.string(),
|
||||
email_notifications_enabled: z.boolean(),
|
||||
avatar_object_id: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
export type Human = z.infer<typeof HumanSchema>;
|
||||
|
||||
Reference in New Issue
Block a user