{{ date.toLocaleTimeString(undefined, { timeStyle: "short" }) }}
@@ -33,18 +39,9 @@
+
+
\ No newline at end of file
diff --git a/types/hooks.ts b/types/hooks.ts
new file mode 100644
index 0000000..73a7894
--- /dev/null
+++ b/types/hooks.ts
@@ -0,0 +1,7 @@
+import type { RuntimeNuxtHooks } from 'nuxt/schema';
+
+declare module "nuxt/schema" {
+ interface RuntimeNuxtHooks {
+ "app:message:right-clicked": (payload: { messageId: string }) => void
+ }
+}
diff --git a/types/interfaces.ts b/types/interfaces.ts
index 7b9a97b..72cda88 100644
--- a/types/interfaces.ts
+++ b/types/interfaces.ts
@@ -44,7 +44,8 @@ export interface MessageResponse {
channel_uuid: string,
user_uuid: string,
message: string,
- user: UserResponse
+ reply_to: string | null,
+ user: UserResponse,
}
export interface InviteResponse {
@@ -84,3 +85,8 @@ export interface ScrollPosition {
offsetTop: number,
offsetLeft: number
}
+
+export interface ContextMenuItem {
+ name: string,
+ callback: (...args: any[]) => any;
+}
diff --git a/types/props.ts b/types/props.ts
new file mode 100644
index 0000000..aa6ff0c
--- /dev/null
+++ b/types/props.ts
@@ -0,0 +1,20 @@
+import type { MessageResponse, UserResponse } from "./interfaces";
+
+export interface MessageProps {
+ class?: string,
+ img?: string | null,
+ author?: UserResponse
+ text: string,
+ timestamp: number,
+ format: "12" | "24",
+ type: "normal" | "grouped",
+ marginBottom: boolean,
+ last: boolean,
+ messageId: string,
+ replyingTo?: boolean,
+ editing?: boolean,
+ me: UserResponse
+ message: MessageResponse,
+ replyMessage?: MessageResponse
+ isMentioned?: boolean,
+}
\ No newline at end of file
diff --git a/utils/createContextMenu.ts b/utils/createContextMenu.ts
new file mode 100644
index 0000000..f3c4aab
--- /dev/null
+++ b/utils/createContextMenu.ts
@@ -0,0 +1,17 @@
+import { render } from "vue";
+import ContextMenu from "~/components/ContextMenu.vue";
+import type { ContextMenuItem } from "~/types/interfaces";
+
+export default (e: MouseEvent, menuItems: ContextMenuItem[]) => {
+ console.log("Rendering new context menu");
+ const menuContainer = document.createElement("div");
+ menuContainer.id = "context-menu";
+ document.body.appendChild(menuContainer);
+ const contextMenu = h(ContextMenu, {
+ menuItems,
+ cursorX: e.clientX,
+ cursorY: e.clientY
+ });
+ render(contextMenu, menuContainer);
+ console.log("Rendered");
+}
diff --git a/utils/editMessage.ts b/utils/editMessage.ts
new file mode 100644
index 0000000..5cc3ce8
--- /dev/null
+++ b/utils/editMessage.ts
@@ -0,0 +1,24 @@
+import type { MessageProps } from "~/types/props";
+
+export default async (element: HTMLDivElement, props: MessageProps) => {
+ console.log("message:", element);
+ const me = await fetchWithApi("/me") as any;
+ if (props.author?.uuid == me.uuid) {
+ const text = element.getElementsByClassName("message-text")[0] as HTMLDivElement;
+ text.contentEditable = "true";
+ text.focus();
+ const range = document.createRange();
+ range.selectNodeContents(text);
+ range.collapse(false);
+ const selection = window.getSelection();
+ selection?.removeAllRanges();
+ selection?.addRange(range);
+ element.addEventListener("keyup", (e) => {
+ console.log("key released:", e.key);
+ if (e.key == "Escape") {
+ text.contentEditable = "false";
+ }
+ text.blur();
+ }, { once: true });
+ }
+}
diff --git a/utils/removeContextMenu.ts b/utils/removeContextMenu.ts
new file mode 100644
index 0000000..3b42c8b
--- /dev/null
+++ b/utils/removeContextMenu.ts
@@ -0,0 +1,6 @@
+export default () => {
+ const contextMenu = document.getElementById("context-menu");
+ if (contextMenu) {
+ contextMenu.remove();
+ }
+}
diff --git a/utils/replyToMessage.ts b/utils/replyToMessage.ts
new file mode 100644
index 0000000..bbb453b
--- /dev/null
+++ b/utils/replyToMessage.ts
@@ -0,0 +1,14 @@
+import { render } from "vue";
+import MessageReply from "~/components/MessageReply.vue";
+import type { MessageProps } from "~/types/props";
+
+export default (element: HTMLDivElement, props: MessageProps) => {
+ console.log("element:", element);
+ const messageBox = document.getElementById("message-box") as HTMLDivElement;
+ if (messageBox) {
+ const div = document.createElement("div");
+ const messageReply = h(MessageReply, { author: props.author?.display_name || props.author!.username, text: props.text || "", id: props.message.uuid, replyId: props.replyMessage?.uuid || element.dataset.messageId!, maxWidth: "full" });
+ messageBox.prepend(div);
+ render(messageReply, div);
+ }
+}