Change pack avatar, name & attribution

This commit is contained in:
Ajay Bura 2022-07-31 10:07:25 +05:30 committed by Ajay Bura
parent 6ae79e080f
commit 91b18cc5fd
6 changed files with 103 additions and 22 deletions

View file

@ -107,7 +107,17 @@ function useImagePackHandles(pack, sendPackContent) {
return newKey;
};
const handleEditProfile = () => false;
const handleAvatarChange = (url) => {
pack.setAvatarUrl(url);
sendPackContent(pack.getContent());
forceUpdate();
};
const handleEditProfile = (name, attribution) => {
pack.setDisplayName(name);
pack.setAttribution(attribution);
sendPackContent(pack.getContent());
forceUpdate();
};
const handleUsageChange = (newUsage) => {
const usage = [];
if (newUsage === 'emoticon' || newUsage === 'both') usage.push('emoticon');
@ -163,6 +173,7 @@ function useImagePackHandles(pack, sendPackContent) {
};
return {
handleAvatarChange,
handleEditProfile,
handleUsageChange,
handleRenameItem,
@ -180,6 +191,7 @@ function ImagePack({ roomId, stateKey }) {
const { pack, sendPackContent } = useRoomImagePack(roomId, stateKey);
const {
handleAvatarChange,
handleEditProfile,
handleUsageChange,
handleRenameItem,
@ -196,12 +208,13 @@ function ImagePack({ roomId, stateKey }) {
return (
<div className="image-pack">
<ImagePackProfile
avatarUrl={mx.mxcUrlToHttp(pack.avatarUrl)}
avatarUrl={pack.avatarUrl ? mx.mxcUrlToHttp(pack.avatarUrl, 42, 42, 'crop') : null}
displayName={pack.displayName ?? 'Unknown'}
attribution={pack.attribution}
usage={getUsage(pack.usage)}
onUsageChange={canChange ? handleUsageChange : undefined}
onEdit={canChange ? handleEditProfile : undefined}
onUsageChange={canChange ? handleUsageChange : null}
onAvatarChange={canChange ? handleAvatarChange : null}
onEditProfile={canChange ? handleEditProfile : null}
/>
{ canChange && (
<ImagePackUpload onUpload={handleAddItem} />

View file

@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import './ImagePackProfile.scss';
@ -9,14 +9,30 @@ import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar';
import Button from '../../atoms/button/Button';
import IconButton from '../../atoms/button/IconButton';
import Input from '../../atoms/input/Input';
import ImageUpload from '../image-upload/ImageUpload';
import ImagePackUsageSelector from './ImagePackUsageSelector';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import PencilIC from '../../../../public/res/ic/outlined/pencil.svg';
function ImagePackProfile({
avatarUrl, displayName, attribution, usage, onUsageChange, onEdit,
avatarUrl, displayName, attribution, usage,
onUsageChange, onAvatarChange, onEditProfile,
}) {
const [isEdit, setIsEdit] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
const { nameInput, attributionInput } = e.target;
const name = nameInput.value.trim() || undefined;
const att = attributionInput.value.trim() || undefined;
onEditProfile(name, att);
setIsEdit(false);
};
const handleUsageSelect = (event) => {
openReusableContextMenu(
'bottom',
@ -35,13 +51,42 @@ function ImagePackProfile({
return (
<div className="image-pack-profile">
{avatarUrl && <Avatar text={displayName} bgColor="blue" imageSrc={avatarUrl} size="normal" />}
{
onAvatarChange
? (
<ImageUpload
bgColor="#555"
text={displayName}
imageSrc={avatarUrl}
size="normal"
onUpload={onAvatarChange}
onRequestRemove={() => onAvatarChange(undefined)}
/>
)
: <Avatar bgColor="#555" text={displayName} imageSrc={avatarUrl} size="normal" />
}
<div className="image-pack-profile__content">
<div>
<Text>{displayName}</Text>
{onEdit && <IconButton size="extra-small" onClick={onEdit} src={PencilIC} tooltip="Edit" />}
</div>
{attribution && <Text variant="b3">{attribution}</Text>}
{
isEdit
? (
<form onSubmit={handleSubmit}>
<Input name="nameInput" label="Name" value={displayName} required />
<Input name="attributionInput" label="Attribution" value={attribution} resizable />
<div>
<Button variant="primary" type="submit">Save</Button>
<Button onClick={() => setIsEdit(false)}>Cancel</Button>
</div>
</form>
) : (
<>
<div>
<Text>{displayName}</Text>
{onEditProfile && <IconButton size="extra-small" onClick={() => setIsEdit(true)} src={PencilIC} tooltip="Edit" />}
</div>
{attribution && <Text variant="b3">{attribution}</Text>}
</>
)
}
</div>
<div className="image-pack-profile__usage">
<Text variant="b3">Pack usage</Text>
@ -64,7 +109,8 @@ ImagePackProfile.defaultProps = {
avatarUrl: null,
attribution: null,
onUsageChange: null,
onEdit: null,
onAvatarChange: null,
onEditProfile: null,
};
ImagePackProfile.propTypes = {
avatarUrl: PropTypes.string,
@ -72,7 +118,8 @@ ImagePackProfile.propTypes = {
attribution: PropTypes.string,
usage: PropTypes.oneOf(['emoticon', 'sticker', 'both']).isRequired,
onUsageChange: PropTypes.func,
onEdit: PropTypes.func,
onAvatarChange: PropTypes.func,
onEditProfile: PropTypes.func,
};
export default ImagePackProfile;

View file

@ -9,7 +9,7 @@
&__content {
@extend .cp-fx__item-one;
& div:first-child {
& > div:first-child {
display: flex;
align-items: center;
gap: var(--sp-extra-tight);
@ -18,6 +18,16 @@
padding: var(--sp-ultra-tight);
}
}
& > form {
display: flex;
flex-direction: column;
gap: var(--sp-extra-tight);
& > div:last-child {
margin: var(--sp-extra-tight) 0;
display: flex;
gap: var(--sp-tight);
}
}
}
&__usage {
& > *:first-child {

View file

@ -41,6 +41,7 @@ function ImagePackUpload({ onUpload }) {
const img = evt.target.files[0];
if (!img) return;
setImgFile(img);
shortcodeRef.current.focus();
};
const handleRemove = () => {
setImgFile(null);

View file

@ -7,9 +7,13 @@ import initMatrix from '../../../client/initMatrix';
import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar';
import Spinner from '../../atoms/spinner/Spinner';
import RawIcon from '../../atoms/system-icons/RawIcon';
import PlusIC from '../../../../public/res/ic/outlined/plus.svg';
function ImageUpload({
text, bgColor, imageSrc, onUpload, onRequestRemove,
size,
}) {
const [uploadPromise, setUploadPromise] = useState(null);
const uploadImageRef = useRef(null);
@ -50,10 +54,14 @@ function ImageUpload({
imageSrc={imageSrc}
text={text}
bgColor={bgColor}
size="large"
size={size}
/>
<div className={`img-upload__process ${uploadPromise === null ? ' img-upload__process--stopped' : ''}`}>
{uploadPromise === null && <Text variant="b3" weight="bold">Upload</Text>}
{uploadPromise === null && (
size === 'large'
? <Text variant="b3" weight="bold">Upload</Text>
: <RawIcon src={PlusIC} color="white" />
)}
{uploadPromise !== null && <Spinner size="small" />}
</div>
</button>
@ -75,6 +83,7 @@ ImageUpload.defaultProps = {
text: null,
bgColor: 'transparent',
imageSrc: null,
size: 'large',
};
ImageUpload.propTypes = {
@ -83,6 +92,7 @@ ImageUpload.propTypes = {
imageSrc: PropTypes.string,
onUpload: PropTypes.func.isRequired,
onRequestRemove: PropTypes.func.isRequired,
size: PropTypes.oneOf(['large', 'normal']),
};
export default ImageUpload;

View file

@ -15,18 +15,18 @@ class ImagePack {
this.id = eventId;
this.content = JSON.parse(JSON.stringify(content));
this.displayName = room?.name ?? undefined;
this.avatarUrl = room?.getMxcAvatarUrl() ?? undefined;
this.applyPack(content);
this.applyImages(content);
this.displayName ??= room?.name;
this.avatarUrl ??= room?.getMxcAvatarUrl();
}
applyPack(content) {
const pack = content.pack ?? {};
this.displayName = pack.display_name ?? this.displayName;
this.avatarUrl = pack.avatar_url ?? this.avatarUrl;
this.displayName = pack.display_name;
this.avatarUrl = pack.avatar_url;
this.usage = pack.usage ?? ['emoticon', 'sticker'];
this.attribution = pack.attribution;
}