Create or delete pack

This commit is contained in:
Ajay Bura 2022-07-31 17:51:14 +05:30 committed by Ajay Bura
parent f646daa322
commit 42a8daa187
6 changed files with 165 additions and 23 deletions

View file

@ -201,7 +201,7 @@ function removeGlobalImagePack(mx, roomId, stateKey) {
return mx.setAccountData('im.ponies.emote_rooms', content); return mx.setAccountData('im.ponies.emote_rooms', content);
} }
function ImagePack({ roomId, stateKey }) { function ImagePack({ roomId, stateKey, handlePackDelete }) {
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId); const room = mx.getRoom(roomId);
const [viewMore, setViewMore] = useState(false); const [viewMore, setViewMore] = useState(false);
@ -228,6 +228,17 @@ function ImagePack({ roomId, stateKey }) {
const myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0; const myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0;
const canChange = room.currentState.hasSufficientPowerLevelFor('state_default', myPowerlevel); const canChange = room.currentState.hasSufficientPowerLevelFor('state_default', myPowerlevel);
const handleDeletePack = async () => {
const isConfirmed = await confirmDialog(
'Delete Pack',
`Are you sure that you want to delete "${pack.displayName}"?`,
'Delete',
'danger',
);
if (!isConfirmed) return;
handlePackDelete(stateKey);
};
const images = [...pack.images].slice(0, viewMore ? pack.images.size : 2); const images = [...pack.images].slice(0, viewMore ? pack.images.size : 2);
return ( return (
@ -264,15 +275,18 @@ function ImagePack({ roomId, stateKey }) {
))} ))}
</div> </div>
)} )}
{pack.images.size > 2 && ( {(pack.images.size > 2 || handlePackDelete) && (
<div className="image-pack__footer"> <div className="image-pack__footer">
<Button onClick={() => setViewMore(!viewMore)}> {pack.images.size > 2 && (
{ <Button onClick={() => setViewMore(!viewMore)}>
viewMore {
? 'View less' viewMore
: `View ${pack.images.size - 2} more` ? 'View less'
} : `View ${pack.images.size - 2} more`
</Button> }
</Button>
)}
{ handlePackDelete && <Button variant="danger" onClick={handleDeletePack}>Delete Pack</Button>}
</div> </div>
)} )}
<div className="image-pack__global"> <div className="image-pack__global">
@ -286,9 +300,13 @@ function ImagePack({ roomId, stateKey }) {
); );
} }
ImagePack.defaultProps = {
handlePackDelete: null,
};
ImagePack.propTypes = { ImagePack.propTypes = {
roomId: PropTypes.string.isRequired, roomId: PropTypes.string.isRequired,
stateKey: PropTypes.string.isRequired, stateKey: PropTypes.string.isRequired,
handlePackDelete: PropTypes.func,
}; };
export default ImagePack; export default ImagePack;

View file

@ -19,6 +19,7 @@
&__footer { &__footer {
padding: var(--sp-normal); padding: var(--sp-normal);
display: flex; display: flex;
justify-content: space-between;
gap: var(--sp-tight); gap: var(--sp-tight);
} }

View file

@ -1,12 +1,19 @@
import React from 'react'; import React, { useReducer, useEffect } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import './RoomEmojis.scss';
import initMatrix from '../../../client/initMatrix'; import initMatrix from '../../../client/initMatrix';
import { suffixRename } from '../../../util/common';
import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
import Text from '../../atoms/text/Text';
import Input from '../../atoms/input/Input';
import Button from '../../atoms/button/Button';
import ImagePack from '../image-pack/ImagePack'; import ImagePack from '../image-pack/ImagePack';
function RoomEmojis({ roomId }) { function useRoomPacks(room) {
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId); const [, forceUpdate] = useReducer((count) => count + 1, 0);
const packEvents = room.currentState.getStateEvents('im.ponies.room_emotes'); const packEvents = room.currentState.getStateEvents('im.ponies.room_emotes');
const unUsablePacks = []; const unUsablePacks = [];
@ -18,13 +25,102 @@ function RoomEmojis({ roomId }) {
return true; return true;
}); });
return usablePacks.reverse().map((mEvent) => ( useEffect(() => {
<ImagePack const handleEvent = (event, state, prevEvent) => {
key={mEvent.getId()} if (event.getRoomId() !== room.roomId) return;
roomId={roomId} if (event.getType() !== 'im.ponies.room_emotes') return;
stateKey={mEvent.getStateKey()} if (!prevEvent?.getContent()?.images || !event.getContent().images) {
/> forceUpdate();
)); }
};
mx.on('RoomState.events', handleEvent);
return () => {
mx.removeListener('RoomState.events', handleEvent);
};
}, [room, mx]);
const isStateKeyAvailable = (key) => !room.currentState.getStateEvents('im.ponies.room_emotes', key);
const createPack = async (name) => {
const packContent = {
pack: { display_name: name },
images: {},
};
let stateKey = '';
if (unUsablePacks.length > 0) {
const mEvent = unUsablePacks[0];
stateKey = mEvent.getStateKey();
} else {
stateKey = packContent.pack.display_name.replace(/\s/g, '-');
if (!isStateKeyAvailable(stateKey)) {
stateKey = suffixRename(
stateKey,
isStateKeyAvailable,
);
}
}
await mx.sendStateEvent(room.roomId, 'im.ponies.room_emotes', packContent, stateKey);
};
const deletePack = async (stateKey) => {
await mx.sendStateEvent(room.roomId, 'im.ponies.room_emotes', {}, stateKey);
};
return {
usablePacks,
createPack,
deletePack,
};
}
function RoomEmojis({ roomId }) {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const { usablePacks, createPack, deletePack } = useRoomPacks(room);
const myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0;
const canChange = room.currentState.hasSufficientPowerLevelFor('state_default', myPowerlevel);
const handlePackCreate = (e) => {
e.preventDefault();
const { nameInput } = e.target;
const name = nameInput.value.trim();
if (name === '') return;
nameInput.value = '';
createPack(name);
};
return (
<div className="room-emojis">
{ canChange && (
<div className="room-emojis__add-pack">
<MenuHeader>Create Pack</MenuHeader>
<form onSubmit={handlePackCreate}>
<Input name="nameInput" placeholder="Pack Name" required />
<Button variant="primary" type="submit">Create pack</Button>
</form>
</div>
)}
{
usablePacks.length > 0
? usablePacks.reverse().map((mEvent) => (
<ImagePack
key={mEvent.getId()}
roomId={roomId}
stateKey={mEvent.getStateKey()}
handlePackDelete={canChange ? deletePack : undefined}
/>
)) : (
<div className="room-emojis__empty">
<Text>No emojis or stickers pack yet.</Text>
</div>
)
}
</div>
);
} }
RoomEmojis.propTypes = { RoomEmojis.propTypes = {

View file

@ -0,0 +1,29 @@
.room-emojis {
.image-pack,
.room-emojis__add-pack,
.room-emojis__empty {
margin: var(--sp-normal) 0;
background-color: var(--bg-surface);
border-radius: var(--bo-radius);
box-shadow: var(--bs-surface-border);
overflow: hidden;
& > .context-menu__header:first-child {
margin-top: 2px;
}
}
&__add-pack {
& form {
margin: var(--sp-normal);
display: flex;
gap: var(--sp-normal);
& .input-container {
flex-grow: 1;
}
}
}
&__empty {
padding: var(--sp-extra-loose) var(--sp-normal);
text-align: center;
}
}

View file

@ -76,7 +76,6 @@
.room-settings .room-permissions__card, .room-settings .room-permissions__card,
.room-settings .room-search__form, .room-settings .room-search__form,
.room-settings .room-search__result-item , .room-settings .room-search__result-item ,
.room-settings .room-members, .room-settings .room-members {
.room-settings .image-pack {
@extend .room-settings__card; @extend .room-settings__card;
} }

View file

@ -32,7 +32,6 @@
} }
.space-settings .room-permissions__card, .space-settings .room-permissions__card,
.space-settings .room-members, .space-settings .room-members {
.space-settings .image-pack {
@extend .space-settings__card; @extend .space-settings__card;
} }