diff --git a/app.vue b/app.vue index 72bffa2..8f0571f 100644 --- a/app.vue +++ b/app.vue @@ -12,20 +12,22 @@ import type { ContextMenuInterface } from './types/interfaces'; const banner = useState("banner", () => false); -const contextMenu = useState("contextMenu", () => ({ show: false, pointerX: 0, pointerY: 0, items: [] })); +const contextMenu = useState("contextMenu"); onMounted(() => { loadPreferredThemes() + document.removeEventListener("contextmenu", contextMenuHandler); + document.addEventListener("contextmenu", (e) => { + if (e.target instanceof Element && e.target.classList.contains("default-contextmenu")) return; + contextMenuHandler(e); + }); document.addEventListener("mousedown", (e) => { - if (e.target instanceof HTMLElement && e.target.classList.contains("context-menu-item")) return; + if (e.target instanceof HTMLElement && e.target.closest("#context-menu")) return; console.log("click"); console.log("target:", e.target); console.log(e.target instanceof HTMLDivElement); - if (contextMenu.value.show) { - console.log("context menu is shown, hiding"); - removeContextMenu(contextMenu); - } + removeContextMenu(contextMenu); if (e.target instanceof HTMLElement && e.target.classList.contains("message-text") && e.target.contentEditable) { e.target.contentEditable = "false"; } @@ -50,6 +52,14 @@ onMounted(() => { }); }); +function contextMenuHandler(e: MouseEvent) { + e.preventDefault(); + //console.log("Opened context menu"); + //createContextMenu(e, [ + // { name: "Wah", callback: () => { return } } + //]); +} + diff --git a/components/Message.vue b/components/Message.vue index 74b0bca..c6207a1 100644 --- a/components/Message.vue +++ b/components/Message.vue @@ -1,24 +1,22 @@ @@ -71,35 +69,37 @@ import MessageReply from './UserInterface/MessageReply.vue'; import type { ContextMenuInterface, ContextMenuItem } from '~/types/interfaces'; const { getDisplayName } = useProfile() - -const route = useRoute(); +const { getUser } = useAuth() const props = defineProps(); -const contextMenu = useState("contextMenu"); +const me = await getUser() + +const contextMenu = useState("contextMenu", () => ({ show: false, pointerX: 0, pointerY: 0, items: [] })); const messageElement = ref(); const dateHidden = ref(true); -const date = new Date(props.timestamp); +const date = uuidToDate(props.message.uuid); + const currentDate: Date = new Date() console.log("[MSG] message to render:", props.message); -console.log("author:", props.author); +console.log("author:", props.message.member); console.log("[MSG] reply message:", props.replyMessage); const linkRegex = /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)/g; const linkMatches = props.message.message.matchAll(linkRegex).map(link => link[0]); -const mediaLinks: string[] = []; +const mediaLinks = ref([]); console.log("link matches:", linkMatches); -const hasEmbed = ref(false); +const hideText = ref(false); const sanitized = ref(); onMounted(async () => { - const parsed = await parse(props.text, { gfm: true }); + const parsed = await parse(props.message.message, { gfm: true }); sanitized.value = DOMPurify.sanitize(parsed, { ALLOWED_TAGS: [ "strong", "em", "br", "blockquote", @@ -123,46 +123,56 @@ onMounted(async () => { console.log("added listeners"); } + const links: string[] = []; for (const link of linkMatches) { - console.log("link:", link); - try { - const res = await $fetch.raw(link); - if (res.ok && res.headers.get("content-type")?.match(/^image\/(apng|gif|jpeg|png|webp)$/)) { - console.log("link is image"); - mediaLinks.push(link); + console.log("link:", link); + try { + const res = await $fetch.raw(link); + if (res.ok && res.headers.get("content-type")?.match(/^image\/(apng|gif|jpeg|png|webp)$/)) { + console.log("link is image"); + links.push(link); + } + } catch (error) { + console.error(error); } - if (mediaLinks.length) { - hasEmbed.value = true - }; - } catch (error) { - console.error(error); - } -} -console.log("media links:", mediaLinks); + mediaLinks.value = [...links]; + } + + if (mediaLinks.value.length) { + const nonLinks = props.message.message.split(linkRegex); + let invalidContent = false; + for (const nonLink of nonLinks) { + if (nonLink != "" && nonLink != "\n" && nonLink != "
") { + invalidContent = true; + break; + } + } + hideText.value = !invalidContent; + }; + + console.log("media links:", mediaLinks); }); //function toggleTooltip(e: Event) { // showHover.value = !showHover.value; //} -const messageMenuItems: ContextMenuItem[] = [ +const menuItems: ContextMenuItem[] = [ { name: "Reply", icon: "lucide:reply", type: "normal", callback: () => { if (messageElement.value) replyToMessage(messageElement.value, props) } } ] -console.log("me:", props.me); -if (props.author.user.uuid == props.me.uuid) { +console.log("me:", me); +if (props.message.member.user.uuid == me!.uuid) { // Inserts "edit" option at index 1 (below the "reply" option) - messageMenuItems.splice(Math.min(1, messageMenuItems.length), 0, { name: "Edit (WIP)", icon: "lucide:square-pen", type: "normal", callback: () => { /* if (messageElement.value) editMessage(messageElement.value, props) */ } }); + menuItems.splice(1, 0, { name: "Edit (WIP)", icon: "lucide:square-pen", type: "normal", callback: () => { /* if (messageElement.value) editMessage(messageElement.value, props) */ } }); } -if (props.author.user.uuid == props.me.uuid /* || check message delete permission*/) { +if (props.message.member.user.uuid == me!.uuid /* || check message delete permission*/) { // Inserts "edit" option at index 2 (below the "edit" option) - messageMenuItems.splice(Math.min(2, messageMenuItems.length), 0, { name: "Delete (WIP)", icon: "lucide:trash", type: "danger", callback: () => {} }); + menuItems.splice(2, 0, { name: "Delete (WIP)", icon: "lucide:trash", type: "danger", callback: () => {} }); } -const memberMenuItems = await createMemberContextMenuItems(props.author, route.params.serverId as string); - function getDayDifference(date1: Date, date2: Date) { const midnight1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()); const midnight2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); @@ -178,14 +188,20 @@ function getDayDifference(date1: Date, date2: Date) { \ No newline at end of file diff --git a/components/Modal/Invite.vue b/components/Modal/Invite.vue index 232114c..de842a2 100644 --- a/components/Modal/Invite.vue +++ b/components/Modal/Invite.vue @@ -40,7 +40,8 @@ function copyInvite(type: "link" | "code") { if (!invite.value) return; if (type == "link") { - const inviteUrl = URL.parse(`invite/${invite.value}`, `${window.location.protocol}//${window.location.host}`); + const runtimeConfig = useRuntimeConfig(); + const inviteUrl = URL.parse(`invite/${invite.value}`, `${window.location.protocol}//${window.location.host}${runtimeConfig.app.baseURL}`); if (inviteUrl) { navigator.clipboard.writeText(inviteUrl.href); } diff --git a/components/Settings/AppSettings/Appearance.vue b/components/Settings/AppSettings/Appearance.vue index 98c41f9..f6f40f4 100644 --- a/components/Settings/AppSettings/Appearance.vue +++ b/components/Settings/AppSettings/Appearance.vue @@ -34,7 +34,8 @@ {{ layout.displayName }} - + + @@ -60,8 +61,8 @@ import { settingSave, settingsLoad } from '#imports'; const runtimeConfig = useRuntimeConfig() const baseURL = runtimeConfig.app.baseURL; -const styleFolder = `${baseURL}themes/style` -const layoutFolder = `${baseURL}themes/layout` +const styleFolder = `${baseURL}/themes/style` +const layoutFolder = `${baseURL}/themes/layout` const timeFormatTextStrings = ["Auto", "12-Hour", "24-Hour"] @@ -115,6 +116,7 @@ async function parseTheme(url: string): Promise { break case "previewImageUrl": previewImageUrl = `${layoutFolder}/${lineArray[1].trim()}` + console.log(previewImageUrl) break } } diff --git a/components/UserInterface/ContextMenu.vue b/components/UserInterface/ContextMenu.vue index 5d3a4be..1767657 100644 --- a/components/UserInterface/ContextMenu.vue +++ b/components/UserInterface/ContextMenu.vue @@ -18,10 +18,6 @@ onMounted(() => { if (contextMenu) { contextMenu.style.left = props.pointerX.toString() + "px"; contextMenu.style.top = props.pointerY.toString() + "px"; - const rect = contextMenu.getBoundingClientRect(); - if (rect.right > (window.innerWidth || document.documentElement.clientWidth)) { - contextMenu.style.left = (props.pointerX - contextMenu.clientWidth).toString() + "px"; - } } }); diff --git a/components/UserInterface/ResizableSidebar.vue b/components/UserInterface/ResizableSidebar.vue index e36c8a6..79e95bd 100644 --- a/components/UserInterface/ResizableSidebar.vue +++ b/components/UserInterface/ResizableSidebar.vue @@ -1,5 +1,5 @@