diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx
index 6dfd746..b950f24 100644
--- a/src/components/Avatar.tsx
+++ b/src/components/Avatar.tsx
@@ -35,7 +35,7 @@ function Avatar(props: Props) {
contextMenu.open2(e, [ContextMenus.User(user)])}
+ onContextMenu={(e) => contextMenu.open2(e, [...ContextMenus.User(user)])}
>
diff --git a/src/components/messaging/Message.tsx b/src/components/messaging/Message.tsx
index be05ba6..73912e0 100644
--- a/src/components/messaging/Message.tsx
+++ b/src/components/messaging/Message.tsx
@@ -1,6 +1,7 @@
import { observer } from "mobx-react-lite";
import React, { memo } from "react";
import { ContextMenuContext } from "../../contexts/ContextMenuContext";
+import { useAppStore } from "../../stores/AppStore";
import { MessageLike } from "../../stores/objects/Message";
import { QueuedMessageStatus } from "../../stores/objects/QueuedMessage";
import ContextMenus from "../../utils/ContextMenus";
@@ -19,8 +20,11 @@ interface Props {
}
function Message({ message, header }: Props) {
+ const app = useAppStore();
const contextMenu = React.useContext(ContextMenuContext);
- const [contextMenuItems, setContextMenuItems] = React.useState([ContextMenus.Message(message)]);
+ const [contextMenuItems, setContextMenuItems] = React.useState([
+ ...ContextMenus.Message(app, message, app.account),
+ ]);
return (
contextMenu.open2(e, contextMenuItems)}>
diff --git a/src/components/messaging/MessageAttachment.tsx b/src/components/messaging/MessageAttachment.tsx
index 971762a..0ffae8a 100644
--- a/src/components/messaging/MessageAttachment.tsx
+++ b/src/components/messaging/MessageAttachment.tsx
@@ -64,7 +64,7 @@ export default function MessageAttachment({ attachment, contextMenuItems, maxWid
withPointer={attachment.content_type?.startsWith("image")}
key={attachment.id}
onContextMenu={(e) =>
- contextMenu.open2(e, [...(contextMenuItems ?? []), ContextMenus.MessageAttachment(attachment)])
+ contextMenu.open2(e, [...(contextMenuItems ?? []), ...ContextMenus.MessageAttachment(attachment)])
}
onClick={() => {
if (!attachment.content_type?.startsWith("image")) return;
diff --git a/src/components/messaging/MessageAuthor.tsx b/src/components/messaging/MessageAuthor.tsx
index 4cab019..5955385 100644
--- a/src/components/messaging/MessageAuthor.tsx
+++ b/src/components/messaging/MessageAuthor.tsx
@@ -46,7 +46,7 @@ function MessageAuthor({ message }: Props) {
style={{
color,
}}
- onContextMenu={(e) => contextMenu.open2(e, [ContextMenus.User(message.author)])}
+ onContextMenu={(e) => contextMenu.open2(e, [...ContextMenus.User(message.author)])}
>
{message.author.username}
diff --git a/src/stores/GuildMemberStore.ts b/src/stores/GuildMemberStore.ts
index 4649104..3a6a648 100644
--- a/src/stores/GuildMemberStore.ts
+++ b/src/stores/GuildMemberStore.ts
@@ -1,6 +1,6 @@
import type { Snowflake } from "@spacebarchat/spacebar-api-types/globals";
import type { APIGuildMember } from "@spacebarchat/spacebar-api-types/v9";
-import { action, makeObservable, observable, ObservableMap } from "mobx";
+import { action, computed, makeObservable, observable, ObservableMap } from "mobx";
import AppStore from "./AppStore";
import Guild from "./objects/Guild";
import GuildMember from "./objects/GuildMember";
@@ -64,4 +64,11 @@ export default class GuildMemberStore {
get size() {
return this.members.size;
}
+
+ @computed
+ get me() {
+ const meId = this.app.account?.id;
+ if (!meId) return null;
+ return this.members.get(meId);
+ }
}
diff --git a/src/stores/objects/Message.ts b/src/stores/objects/Message.ts
index 2cc6605..ad0eca3 100644
--- a/src/stores/objects/Message.ts
+++ b/src/stores/objects/Message.ts
@@ -1,22 +1,23 @@
-import type {
- APIActionRowComponent,
- APIApplication,
- APIAttachment,
- APIChannel,
- APIChannelMention,
- APIEmbed,
- APIMessage,
- APIMessageActionRowComponent,
- APIMessageActivity,
- APIMessageInteraction,
- APIMessageReference,
- APIReaction,
- APIRole,
- APISticker,
- APIStickerItem,
- APIUser,
- MessageFlags,
- Snowflake,
+import {
+ Routes,
+ type APIActionRowComponent,
+ type APIApplication,
+ type APIAttachment,
+ type APIChannel,
+ type APIChannelMention,
+ type APIEmbed,
+ type APIMessage,
+ type APIMessageActionRowComponent,
+ type APIMessageActivity,
+ type APIMessageInteraction,
+ type APIMessageReference,
+ type APIReaction,
+ type APIRole,
+ type APISticker,
+ type APIStickerItem,
+ type APIUser,
+ type MessageFlags,
+ type Snowflake,
} from "@spacebarchat/spacebar-api-types/v9";
import { action, makeObservable, observable } from "mobx";
import AppStore from "../AppStore";
@@ -247,4 +248,8 @@ export default class Message extends MessageBase {
this.timestamp = new Date(message.timestamp);
this.edited_timestamp = message.edited_timestamp ? new Date(message.edited_timestamp) : null;
}
+
+ async delete() {
+ await this.app.rest.delete(Routes.channelMessage(this.channel_id, this.id));
+ }
}
diff --git a/src/stores/objects/MessageBase.ts b/src/stores/objects/MessageBase.ts
index c96a681..5d26467 100644
--- a/src/stores/objects/MessageBase.ts
+++ b/src/stores/objects/MessageBase.ts
@@ -27,7 +27,7 @@ export default class MessageBase {
type: MessageType;
author: User;
- constructor(private readonly app: AppStore, data: MessageLikeData) {
+ constructor(public readonly app: AppStore, data: MessageLikeData) {
this.id = data.id;
this.content = data.content;
this.timestamp = new Date(data.timestamp);
diff --git a/src/stores/objects/QueuedMessage.ts b/src/stores/objects/QueuedMessage.ts
index 5ae3ac6..86b106c 100644
--- a/src/stores/objects/QueuedMessage.ts
+++ b/src/stores/objects/QueuedMessage.ts
@@ -60,4 +60,8 @@ export default class QueuedMessage extends MessageBase {
this.error = error;
this.status = QueuedMessageStatus.FAILED;
}
+
+ delete() {
+ //
+ }
}
diff --git a/src/utils/ContextMenus.ts b/src/utils/ContextMenus.ts
index 6dcc7a2..b1ac990 100644
--- a/src/utils/ContextMenus.ts
+++ b/src/utils/ContextMenus.ts
@@ -1,41 +1,73 @@
import { APIAttachment } from "@spacebarchat/spacebar-api-types/v9";
import { IContextMenuItem } from "../components/ContextMenuItem";
import AccountStore from "../stores/AccountStore";
+import AppStore from "../stores/AppStore";
import { MessageLike } from "../stores/objects/Message";
import User from "../stores/objects/User";
+import { Permissions } from "./Permissions";
export default {
- User: (user: User | AccountStore): IContextMenuItem => {
- return {
- label: "Copy User ID",
- onClick: () => {
- navigator.clipboard.writeText(user.id);
+ User: (user: User | AccountStore): IContextMenuItem[] => {
+ return [
+ {
+ label: "Copy User ID",
+ onClick: () => {
+ navigator.clipboard.writeText(user.id);
+ },
+ iconProps: {
+ icon: "mdiIdentifier",
+ },
},
- iconProps: {
- icon: "mdiIdentifier",
- },
- };
+ ];
},
- Message: (message: MessageLike): IContextMenuItem => {
- return {
- label: "Copy Message ID",
- onClick: () => {
- navigator.clipboard.writeText(message.id);
+ Message: (app: AppStore, message: MessageLike, account: AccountStore | null): IContextMenuItem[] => {
+ const channel = app.channels.get(message.channel_id);
+ const permissions = Permissions.getPermission(account?.id, channel?.guild, channel);
+ const canDeleteMessage = permissions.has("MANAGE_MESSAGES") || message.author.id === account?.id;
+
+ const items: IContextMenuItem[] = [
+ {
+ label: "Copy Message ID",
+ onClick: () => {
+ navigator.clipboard.writeText(message.id);
+ },
+ iconProps: {
+ icon: "mdiIdentifier",
+ },
},
- iconProps: {
- icon: "mdiIdentifier",
- },
- };
+ ];
+
+ if (canDeleteMessage) {
+ items.push({
+ label: "Delete Message",
+ onClick: () => {
+ message.delete();
+ },
+ iconProps: {
+ icon: "mdiTrashCanOutline",
+ color: "red",
+ },
+ color: "red",
+ hover: {
+ backgroundColor: "red",
+ color: "white",
+ },
+ });
+ }
+
+ return items;
},
- MessageAttachment: (attachment: APIAttachment): IContextMenuItem => {
- return {
- label: "Copy Attachment URL",
- onClick: () => {
- navigator.clipboard.writeText(attachment.url);
+ MessageAttachment: (attachment: APIAttachment): IContextMenuItem[] => {
+ return [
+ {
+ label: "Copy Attachment URL",
+ onClick: () => {
+ navigator.clipboard.writeText(attachment.url);
+ },
+ iconProps: {
+ icon: "mdiLink",
+ },
},
- iconProps: {
- icon: "mdiLink",
- },
- };
+ ];
},
};
diff --git a/src/utils/REST.ts b/src/utils/REST.ts
index 41d0328..f76404b 100644
--- a/src/utils/REST.ts
+++ b/src/utils/REST.ts
@@ -1,7 +1,3 @@
-// import {Globals} from '../constants/Globals';
-// import useLogger from '../hooks/useLogger';
-// import {DomainStore} from '../stores/DomainStore';
-
import AppStore from "../stores/AppStore";
import QueuedMessage from "../stores/objects/QueuedMessage";
import { Globals } from "./Globals";
@@ -190,7 +186,7 @@ export default class REST {
): Promise {
return new Promise((resolve, reject) => {
const url = REST.makeAPIUrl(path, queryParams);
- // this.logger.debug(`DELETE ${url}`);
+ this.logger.debug(`DELETE ${url}`);
return (
fetch(url, {
method: "DELETE",