Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
sable: minor
---

add button to save a sticker you see in the message timeline to your personal account sticker pack
32 changes: 32 additions & 0 deletions src/app/features/room/message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ import { MessageDeleteItem } from '$components/message/modals/MessageDelete';
import { MessageReportItem } from '$components/message/modals/MessageReport';
import { filterPronounsByLanguage } from '$utils/pronouns';
import { useMentionClickHandler } from '$hooks/useMentionClickHandler';
import {
addStickerToDefaultPack,
doesStickerExistInDefaultPack,
} from '$utils/addStickerToDefaultStickerPack';
import { MessageEditor } from './MessageEditor';
import * as css from './styles.css';

Expand Down Expand Up @@ -649,6 +653,7 @@ function MessageInternal(
});

const isThreadedMessage = mEvent.threadRootId !== undefined;
const isStickerMessage = mEvent.getType() === 'm.sticker';

return (
<MessageBase
Expand Down Expand Up @@ -792,6 +797,33 @@ function MessageInternal(
</Text>
</MenuItem>
)}
{isStickerMessage &&
!doesStickerExistInDefaultPack(mx, mEvent.getContent().url) && (
<MenuItem
size="300"
after={<Icon size="100" src={Icons.Star} />}
radii="300"
onClick={() => {
addStickerToDefaultPack(
mx,
`sticker-${mEvent.getId()}`,
mEvent.getContent().url,
mEvent.getContent().body,
mEvent.getContent().info
);
closeMenu();
}}
>
<Text
className={css.MessageMenuItemText}
as="span"
size="T300"
truncate
>
Add to User Sticker Pack
</Text>
</MenuItem>
)}
{relations && <MessageAllReactionItem room={room} relations={relations} />}
<MenuItem
size="300"
Expand Down
46 changes: 46 additions & 0 deletions src/app/utils/addStickerToDefaultStickerPack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { PackContent, ImageUsage } from '$plugins/custom-emoji';
import { AccountDataEvent } from '$types/matrix/accountData';
import { IImageInfo } from '$types/matrix/common';
import { MatrixClient } from 'matrix-js-sdk';

// Utility function to add a sticker to the default sticker pack
export async function addStickerToDefaultPack(
mx: MatrixClient,
shortcode: string,
mxc: string,
body?: string,
info?: IImageInfo
) {
// current content of the default sticker pack, which is stored in account data under the key 'PoniesUserEmotes'
const current =
mx.getAccountData(AccountDataEvent.PoniesUserEmotes)?.getContent<PackContent>() ?? {};

// modified content with the new sticker added.
// We add the new sticker under the "images" key, using the shortcode as the key for the sticker.
// The sticker content includes the mxc URL, body, info, and usage (which we set to "sticker").
const next: PackContent = {
...current,
images: {
...(current.images ?? {}),
[shortcode]: {
...(current.images?.[shortcode] ?? {}),
url: mxc,
body,
info,
usage: [ImageUsage.Sticker],
},
},
};

// update the account data with the modified content, which effectively adds the new sticker to the default sticker pack.
await mx.setAccountData(AccountDataEvent.PoniesUserEmotes, next);
}

// check if a sticker exists in the account sticker pack
export function doesStickerExistInDefaultPack(mx: MatrixClient, mxc: string) {
const imgs = mx
.getAccountData(AccountDataEvent.PoniesUserEmotes)
?.getContent<PackContent>().images;
if (imgs === undefined) return false;
return Object.values(imgs).some((image) => image.url === mxc) ?? false;
}
Loading