Change pack avatar, name & attribution

This commit is contained in:
Ajay Bura 2022-07-31 10:07:25 +05:30
parent 15e8412326
commit 458738f06a
6 changed files with 103 additions and 22 deletions

View file

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

View file

@ -1,4 +1,4 @@
import React from 'react'; import React, { useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import './ImagePackProfile.scss'; import './ImagePackProfile.scss';
@ -9,14 +9,30 @@ import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar'; import Avatar from '../../atoms/avatar/Avatar';
import Button from '../../atoms/button/Button'; import Button from '../../atoms/button/Button';
import IconButton from '../../atoms/button/IconButton'; import IconButton from '../../atoms/button/IconButton';
import Input from '../../atoms/input/Input';
import ImageUpload from '../image-upload/ImageUpload';
import ImagePackUsageSelector from './ImagePackUsageSelector'; import ImagePackUsageSelector from './ImagePackUsageSelector';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg'; import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import PencilIC from '../../../../public/res/ic/outlined/pencil.svg'; import PencilIC from '../../../../public/res/ic/outlined/pencil.svg';
function ImagePackProfile({ 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) => { const handleUsageSelect = (event) => {
openReusableContextMenu( openReusableContextMenu(
'bottom', 'bottom',
@ -35,13 +51,42 @@ function ImagePackProfile({
return ( return (
<div className="image-pack-profile"> <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 className="image-pack-profile__content">
{
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> <div>
<Text>{displayName}</Text> <Text>{displayName}</Text>
{onEdit && <IconButton size="extra-small" onClick={onEdit} src={PencilIC} tooltip="Edit" />} {onEditProfile && <IconButton size="extra-small" onClick={() => setIsEdit(true)} src={PencilIC} tooltip="Edit" />}
</div> </div>
{attribution && <Text variant="b3">{attribution}</Text>} {attribution && <Text variant="b3">{attribution}</Text>}
</>
)
}
</div> </div>
<div className="image-pack-profile__usage"> <div className="image-pack-profile__usage">
<Text variant="b3">Pack usage</Text> <Text variant="b3">Pack usage</Text>
@ -64,7 +109,8 @@ ImagePackProfile.defaultProps = {
avatarUrl: null, avatarUrl: null,
attribution: null, attribution: null,
onUsageChange: null, onUsageChange: null,
onEdit: null, onAvatarChange: null,
onEditProfile: null,
}; };
ImagePackProfile.propTypes = { ImagePackProfile.propTypes = {
avatarUrl: PropTypes.string, avatarUrl: PropTypes.string,
@ -72,7 +118,8 @@ ImagePackProfile.propTypes = {
attribution: PropTypes.string, attribution: PropTypes.string,
usage: PropTypes.oneOf(['emoticon', 'sticker', 'both']).isRequired, usage: PropTypes.oneOf(['emoticon', 'sticker', 'both']).isRequired,
onUsageChange: PropTypes.func, onUsageChange: PropTypes.func,
onEdit: PropTypes.func, onAvatarChange: PropTypes.func,
onEditProfile: PropTypes.func,
}; };
export default ImagePackProfile; export default ImagePackProfile;

View file

@ -9,7 +9,7 @@
&__content { &__content {
@extend .cp-fx__item-one; @extend .cp-fx__item-one;
& div:first-child { & > div:first-child {
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--sp-extra-tight); gap: var(--sp-extra-tight);
@ -18,6 +18,16 @@
padding: var(--sp-ultra-tight); 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 { &__usage {
& > *:first-child { & > *:first-child {

View file

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

View file

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

View file

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