From e9d8a7b26eec733c6910233d2018f271e38b9af4 Mon Sep 17 00:00:00 2001 From: Ajay Bura <32841439+ajbura@users.noreply.github.com> Date: Sun, 12 Jan 2025 13:43:52 +0530 Subject: [PATCH] add option to edit pack meta --- .../image-pack-view/ImagePackContent.tsx | 409 +++++++++++++++--- .../image-pack-view/ImagePackView.tsx | 12 +- .../components/image-pack-view/ImageTile.tsx | 73 +--- .../image-pack-view/UsageSelector.tsx | 51 --- .../image-pack-view/UsageSwitcher.tsx | 115 +++++ .../components/image-pack-view/style.css.ts | 12 +- .../plugins/custom-emoji/PackMetaReader.ts | 4 + src/app/plugins/custom-emoji/utils.ts | 11 + 8 files changed, 524 insertions(+), 163 deletions(-) delete mode 100644 src/app/components/image-pack-view/UsageSelector.tsx create mode 100644 src/app/components/image-pack-view/UsageSwitcher.tsx diff --git a/src/app/components/image-pack-view/ImagePackContent.tsx b/src/app/components/image-pack-view/ImagePackContent.tsx index a8dd530e..1ef538d7 100644 --- a/src/app/components/image-pack-view/ImagePackContent.tsx +++ b/src/app/components/image-pack-view/ImagePackContent.tsx @@ -1,7 +1,22 @@ -import React, { useMemo } from 'react'; -import { as, Box, Text, config, Avatar, AvatarImage, AvatarFallback, Button } from 'folds'; +import React, { FormEventHandler, useCallback, useMemo, useState } from 'react'; +import { + as, + Box, + Text, + config, + Avatar, + AvatarImage, + AvatarFallback, + Button, + Icon, + Icons, + Input, + TextArea, + Chip, + Menu, +} from 'folds'; import Linkify from 'linkify-react'; -import { ImagePack, PackMetaReader } from '../../plugins/custom-emoji'; +import { ImagePack, ImageUsage, packMetaEqual, PackMetaReader } from '../../plugins/custom-emoji'; import { mxcUrlToHttp } from '../../utils/matrix'; import { useMediaAuthentication } from '../../hooks/useMediaAuthentication'; import { useMatrixClient } from '../../hooks/useMatrixClient'; @@ -11,28 +26,219 @@ import { BreakWord } from '../../styles/Text.css'; import { LINKIFY_OPTS } from '../../plugins/react-custom-html-parser'; import { ContainerColor } from '../../styles/ContainerColor.css'; import { ImageTile } from './ImageTile'; +import { SettingTile } from '../setting-tile'; +import { UsageSwitcher } from './UsageSwitcher'; +import { useFilePicker } from '../../hooks/useFilePicker'; +import { useObjectURL } from '../../hooks/useObjectURL'; +import { createUploadAtom, UploadSuccess } from '../../state/upload'; +import { CompactUploadCardRenderer } from '../upload-card'; +import * as css from './style.css'; type ImagePackAvatarProps = { - meta: PackMetaReader; + url?: string; + name?: string; }; -function ImagePackAvatar({ meta }: ImagePackAvatarProps) { - const mx = useMatrixClient(); - const useAuthentication = useMediaAuthentication(); - const packAvatar = meta.avatar ? mxcUrlToHttp(mx, meta.avatar, useAuthentication) : undefined; - +function ImagePackAvatar({ url, name }: ImagePackAvatarProps) { return ( - - {packAvatar ? ( - + + {url ? ( + ) : ( - {nameInitials(meta.name ?? 'Unknown')} + {nameInitials(name ?? 'Unknown')} )} ); } +type ImagePackProfileProps = { + meta: PackMetaReader; + canEdit?: boolean; + onEdit?: () => void; +}; +function ImagePackProfile({ meta, canEdit, onEdit }: ImagePackProfileProps) { + const mx = useMatrixClient(); + const useAuthentication = useMediaAuthentication(); + const avatarUrl = meta.avatar + ? mxcUrlToHttp(mx, meta.avatar, useAuthentication) ?? undefined + : undefined; + + return ( + + + + + {meta.name ?? 'Unknown'} + + {meta.attribution && ( + + {meta.attribution} + + )} + + {canEdit && ( + + } + onClick={onEdit} + outlined + > + Edit + + + )} + + + + + + ); +} + +type ImagePackProfileEditProps = { + meta: PackMetaReader; + onCancel: () => void; + onSave: (meta: PackMetaReader) => void; +}; +function ImagePackProfileEdit({ meta, onCancel, onSave }: ImagePackProfileEditProps) { + const mx = useMatrixClient(); + const useAuthentication = useMediaAuthentication(); + const [avatar, setAvatar] = useState(meta.avatar); + + const avatarUrl = avatar ? mxcUrlToHttp(mx, avatar, useAuthentication) ?? undefined : undefined; + + const [imageFile, setImageFile] = useState(); + const avatarFileUrl = useObjectURL(imageFile); + const uploadingAvatar = avatarFileUrl ? avatar === meta.avatar : false; + const uploadAtom = useMemo(() => { + if (imageFile) return createUploadAtom(imageFile); + return undefined; + }, [imageFile]); + + const pickFile = useFilePicker(setImageFile, false); + + const handleRemoveUpload = useCallback(() => { + setImageFile(undefined); + setAvatar(meta.avatar); + }, [meta.avatar]); + + const handleUploaded = useCallback((upload: UploadSuccess) => { + setAvatar(upload.mxc); + }, []); + + const handleSubmit: FormEventHandler = (evt) => { + evt.preventDefault(); + if (uploadingAvatar) return; + + const target = evt.target as HTMLFormElement | undefined; + const nameInput = target?.nameInput as HTMLInputElement | undefined; + const attributionTextArea = target?.attributionTextArea as HTMLTextAreaElement | undefined; + if (!nameInput || !attributionTextArea) return; + + const name = nameInput.value.trim(); + const attribution = attributionTextArea.value.trim(); + if (!name) return; + + const metaReader = new PackMetaReader({ + avatar_url: avatar, + display_name: name, + attribution, + }); + onSave(metaReader); + }; + + return ( + + + + Pack Avatar + {uploadAtom ? ( + + + + ) : ( + + + {!avatar && meta.avatar && ( + + )} + {avatar && ( + + )} + + )} + + + + + + + Name + + + + Attribution +