Commit 6c8fd192fb8c
tarball1 file changed+38-6
@@ -28,6 +28,7 @@
2828
sendMessage,2929
uploadAttachment,3030
uploadAvatar,31
+ uploadRoomAvatar,3132
editMessage3233
} from './lib/api';3334
import { isKnownCommand, parseCommand, splitTarget, unescapeCommand } from './lib/commands';@@ -601,11 +602,21 @@
601602
return;602603
}603604
if (attachments.length > 0 && uploadBusy) return;604
- const command = attachments.length === 0 ? parseCommand(body) : null;605
+ const command = parseCommand(body);605606
if (command && !isKnownCommand(command.name)) {606607
pushBanner(`Unknown command /${command.name}`);607608
return;608609
}610
+ if (command && attachments.length > 0) {611
+ if (command.name !== 'roomavatar' && command.name !== 'globalavatar') {612
+ pushBanner(`/${command.name} doesn't take attachments`);613
+ return;614
+ }615
+ if (command.args || attachments.length !== 1 || !attachments[0].file.type.startsWith('image/')) {616
+ pushBanner(`/${command.name} takes a single attached image`);617
+ return;618
+ }619
+ }609620
composer = '';610621
if (roomId in drafts) delete drafts[roomId];611622
stickToBottom = true;@@ -616,7 +627,14 @@
616627
pickedMentions = { ...pickedMentions, [roomId]: [] };617628
mentionQuery = null;618629
if (command) {619
- void execute(roomId, command, reply, mentions);630
+ const image = attachments[0] ?? null;631
+ if (image) {632
+ const { [roomId]: _used, ...rest } = staged;633
+ staged = rest;634
+ }635
+ void execute(roomId, command, reply, mentions, image?.file ?? null).finally(() => {636
+ if (image?.previewUrl) URL.revokeObjectURL(image.previewUrl);637
+ });620638
} else if (attachments.length === 0) {621639
queueSend(roomId, text, reply, mentions, $markdownEnabled);622640
} else {@@ -637,7 +655,13 @@
637655
return null;638656
}639657
640
- async function execute(roomId: string, command: ParsedCommand, reply: ReplyReference | null, mentions: Mention[]): Promise<void> {658
+ async function execute(659
+ roomId: string,660
+ command: ParsedCommand,661
+ reply: ReplyReference | null,662
+ mentions: Mention[],663
+ image: File | null664
+ ): Promise<void> {641665
const { name, args } = command;642666
const target = () => {643667
const found = splitTarget(args, Object.values(people));@@ -699,8 +723,13 @@
699723
await runCommand({ op: 'set_room_display_name', room_id: roomId, name: args || null });700724
break;701725
case 'roomavatar':702
- if (args && !args.startsWith('mxc://')) throw new Error('/roomavatar takes an mxc:// link, or nothing to drop the override');703
- await runCommand({ op: 'set_room_avatar', room_id: roomId, mxc: args || null });726
+ if (image) {727
+ await uploadRoomAvatar(roomId, image);728
+ } else if (args && !args.startsWith('mxc://')) {729
+ throw new Error('/roomavatar takes an mxc:// link, an attached image, or nothing to drop the override');730
+ } else {731
+ await runCommand({ op: 'set_room_avatar', room_id: roomId, mxc: args || null });732
+ }704733
break;705734
case 'delete': {706735
const eventId = reply?.event_id ?? lastOwnEventId();@@ -713,7 +742,10 @@
713742
await loadProfile();714743
break;715744
case 'globalavatar':716
- if (!args) {745
+ if (image) {746
+ await uploadAvatar(image);747
+ await loadProfile();748
+ } else if (!args) {717749
avatarInput?.click();718750
} else if (args.startsWith('mxc://')) {719751
await runCommand({ op: 'set_avatar', mxc: args });