From 64c6276153e8d361ed4d89a7ebe2b9ed2650b0d0 Mon Sep 17 00:00:00 2001 From: SauceyRed Date: Sat, 7 Jun 2025 06:25:51 +0200 Subject: [PATCH 001/188] feat: add dropdown for guild settings and invite --- components/GuildOptionsMenu.vue | 58 +++++++++++++++++++ .../[serverId]/channels/[channelId].vue | 48 ++++++++++----- 2 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 components/GuildOptionsMenu.vue diff --git a/components/GuildOptionsMenu.vue b/components/GuildOptionsMenu.vue new file mode 100644 index 0000000..d024ec8 --- /dev/null +++ b/components/GuildOptionsMenu.vue @@ -0,0 +1,58 @@ + + + + + \ No newline at end of file diff --git a/pages/servers/[serverId]/channels/[channelId].vue b/pages/servers/[serverId]/channels/[channelId].vue index c9aa8d2..b3d492a 100644 --- a/pages/servers/[serverId]/channels/[channelId].vue +++ b/pages/servers/[serverId]/channels/[channelId].vue @@ -1,21 +1,13 @@ \ No newline at end of file From 1e0b8e2ba18c680ee626ba274de3df97b076f797 Mon Sep 17 00:00:00 2001 From: SauceyRed Date: Mon, 7 Jul 2025 21:07:33 +0200 Subject: [PATCH 008/188] feat: add Dropdown component --- components/Dropdown.vue | 46 +++++++++++++++++++++++++++++++++++++++++ types/interfaces.ts | 6 ++++++ 2 files changed, 52 insertions(+) create mode 100644 components/Dropdown.vue diff --git a/components/Dropdown.vue b/components/Dropdown.vue new file mode 100644 index 0000000..ff03799 --- /dev/null +++ b/components/Dropdown.vue @@ -0,0 +1,46 @@ + + + + + \ No newline at end of file diff --git a/types/interfaces.ts b/types/interfaces.ts index 1aba1bc..fe58dd2 100644 --- a/types/interfaces.ts +++ b/types/interfaces.ts @@ -81,3 +81,9 @@ export interface ScrollPosition { offsetTop: number, offsetLeft: number } + +export interface DropdownOption { + name: string, + value: string | number, + callback: () => void +} From 7ddc2acb02aaa4c5d4bd4b3bd27903a299208d0c Mon Sep 17 00:00:00 2001 From: SauceyRed Date: Wed, 9 Jul 2025 07:37:05 +0200 Subject: [PATCH 009/188] feat: add message id as data field of Message component --- components/Message.vue | 7 ++++--- components/MessageArea.vue | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/components/Message.vue b/components/Message.vue index 5cd7773..188960a 100644 --- a/components/Message.vue +++ b/components/Message.vue @@ -1,5 +1,5 @@ \ No newline at end of file From b1a3ce9b00977c4bf74af610f944c885eb2ef719 Mon Sep 17 00:00:00 2001 From: JustTemmie <47639983+JustTemmie@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:18:28 +0200 Subject: [PATCH 014/188] feat: update interface to include friends_since --- types/interfaces.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/types/interfaces.ts b/types/interfaces.ts index 610d007..7b9a97b 100644 --- a/types/interfaces.ts +++ b/types/interfaces.ts @@ -61,7 +61,8 @@ export interface UserResponse { pronouns: string | null, about: string | null, email?: string, - email_verified?: boolean + email_verified?: boolean, + friends_since: string | null, } export interface StatsResponse { From 8a9ecaa2e2ead30576367a2bd275c70edeb1da19 Mon Sep 17 00:00:00 2001 From: JustTemmie <47639983+JustTemmie@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:44:18 +0200 Subject: [PATCH 015/188] refactor: move spacer into it's own component --- components/VerticalSpacer.vue | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 components/VerticalSpacer.vue diff --git a/components/VerticalSpacer.vue b/components/VerticalSpacer.vue new file mode 100644 index 0000000..293e9f0 --- /dev/null +++ b/components/VerticalSpacer.vue @@ -0,0 +1,21 @@ + + + + + From 5dbf21b0abb975d98ae1e825fd6edaf01fab36dc Mon Sep 17 00:00:00 2001 From: JustTemmie <47639983+JustTemmie@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:44:46 +0200 Subject: [PATCH 016/188] feat: implement friends list --- components/DirectMessagesSidebar.vue | 38 ++++++++++++++++++++++++++++ components/UserEntry.vue | 35 +++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 components/DirectMessagesSidebar.vue create mode 100644 components/UserEntry.vue diff --git a/components/DirectMessagesSidebar.vue b/components/DirectMessagesSidebar.vue new file mode 100644 index 0000000..d9f677d --- /dev/null +++ b/components/DirectMessagesSidebar.vue @@ -0,0 +1,38 @@ + + + + + \ No newline at end of file diff --git a/components/UserEntry.vue b/components/UserEntry.vue new file mode 100644 index 0000000..dcea368 --- /dev/null +++ b/components/UserEntry.vue @@ -0,0 +1,35 @@ + + + + + From 15e5a21277f487174f66dcc6113edf2aae2265bd Mon Sep 17 00:00:00 2001 From: JustTemmie <47639983+JustTemmie@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:47:52 +0200 Subject: [PATCH 017/188] refactor: try sorting components into sub-folders --- components/{ => Guild}/Channel.vue | 0 components/{ => Member}/MemberEntry.vue | 0 components/{ => Popups}/CropPopup.vue | 0 components/{ => Popups}/InvitePopup.vue | 0 components/{ => Popups}/Loading.vue | 0 components/{ => User}/UserEntry.vue | 0 components/{ => User}/UserPopup.vue | 0 components/UserArea.vue | 20 ------------------- components/{ => UserInterface}/Button.vue | 0 .../{ => UserInterface}/VerticalSpacer.vue | 0 10 files changed, 20 deletions(-) rename components/{ => Guild}/Channel.vue (100%) rename components/{ => Member}/MemberEntry.vue (100%) rename components/{ => Popups}/CropPopup.vue (100%) rename components/{ => Popups}/InvitePopup.vue (100%) rename components/{ => Popups}/Loading.vue (100%) rename components/{ => User}/UserEntry.vue (100%) rename components/{ => User}/UserPopup.vue (100%) delete mode 100644 components/UserArea.vue rename components/{ => UserInterface}/Button.vue (100%) rename components/{ => UserInterface}/VerticalSpacer.vue (100%) diff --git a/components/Channel.vue b/components/Guild/Channel.vue similarity index 100% rename from components/Channel.vue rename to components/Guild/Channel.vue diff --git a/components/MemberEntry.vue b/components/Member/MemberEntry.vue similarity index 100% rename from components/MemberEntry.vue rename to components/Member/MemberEntry.vue diff --git a/components/CropPopup.vue b/components/Popups/CropPopup.vue similarity index 100% rename from components/CropPopup.vue rename to components/Popups/CropPopup.vue diff --git a/components/InvitePopup.vue b/components/Popups/InvitePopup.vue similarity index 100% rename from components/InvitePopup.vue rename to components/Popups/InvitePopup.vue diff --git a/components/Loading.vue b/components/Popups/Loading.vue similarity index 100% rename from components/Loading.vue rename to components/Popups/Loading.vue diff --git a/components/UserEntry.vue b/components/User/UserEntry.vue similarity index 100% rename from components/UserEntry.vue rename to components/User/UserEntry.vue diff --git a/components/UserPopup.vue b/components/User/UserPopup.vue similarity index 100% rename from components/UserPopup.vue rename to components/User/UserPopup.vue diff --git a/components/UserArea.vue b/components/UserArea.vue deleted file mode 100644 index d922c3f..0000000 --- a/components/UserArea.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - - - \ No newline at end of file diff --git a/components/Button.vue b/components/UserInterface/Button.vue similarity index 100% rename from components/Button.vue rename to components/UserInterface/Button.vue diff --git a/components/VerticalSpacer.vue b/components/UserInterface/VerticalSpacer.vue similarity index 100% rename from components/VerticalSpacer.vue rename to components/UserInterface/VerticalSpacer.vue From 59000709fe5f3ae0c3b7f3254870481094e90da2 Mon Sep 17 00:00:00 2001 From: JustTemmie <47639983+JustTemmie@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:51:14 +0200 Subject: [PATCH 018/188] feat: update api --- composables/api.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/composables/api.ts b/composables/api.ts index d2ca7a0..8a37a8e 100644 --- a/composables/api.ts +++ b/composables/api.ts @@ -1,4 +1,4 @@ -import type { ChannelResponse, GuildMemberResponse, GuildResponse, MessageResponse, StatsResponse } from "~/types/interfaces"; +import type { ChannelResponse, GuildMemberResponse, GuildResponse, MessageResponse, StatsResponse, UserResponse } from "~/types/interfaces"; export const useApi = () => { async function fetchGuilds(): Promise { @@ -24,14 +24,18 @@ export const useApi = () => { async function fetchMember(guildId: string, memberId: string): Promise { return await fetchWithApi(`/guilds/${guildId}/members/${memberId}`); } - + async function fetchUsers() { return await fetchWithApi(`/users`); } - + async function fetchUser(userId: string) { return await fetchWithApi(`/users/${userId}`); } + + async function fetchFriends(): Promise { + return await fetchWithApi('/me/friends') + } async function fetchMessages(channelId: string, options?: { amount?: number, offset?: number }): Promise { return await fetchWithApi(`/channels/${channelId}/messages`, { query: { amount: options?.amount ?? 100, offset: options?.offset ?? 0 } }); @@ -59,6 +63,7 @@ export const useApi = () => { fetchMember, fetchUsers, fetchUser, + fetchFriends, fetchMessages, fetchMessage, fetchInstanceStats, From 8e69dc805e20e5feab0493b9b9aafac5a23f3c57 Mon Sep 17 00:00:00 2001 From: JustTemmie <47639983+JustTemmie@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:51:56 +0200 Subject: [PATCH 019/188] chore: remove unused popups --- components/Member/MemberEntry.vue | 1 - components/Settings/UserSettings/Account.vue | 1 - components/Settings/UserSettings/Privacy.vue | 1 - pages/servers/[serverId]/channels/[channelId].vue | 1 - 4 files changed, 4 deletions(-) diff --git a/components/Member/MemberEntry.vue b/components/Member/MemberEntry.vue index ed4cd48..1ea4170 100644 --- a/components/Member/MemberEntry.vue +++ b/components/Member/MemberEntry.vue @@ -10,7 +10,6 @@ \ No newline at end of file diff --git a/components/User/UserEntry.vue b/components/User/UserEntry.vue index dcea368..b463759 100644 --- a/components/User/UserEntry.vue +++ b/components/User/UserEntry.vue @@ -24,7 +24,12 @@ const props = defineProps<{ margin-bottom: .5em; gap: .5em; - cursor: pointer; + text-decoration: none; + color: inherit; +} + +.user-item:hover { + background-color: #00000020 } .user-avatar { diff --git a/components/UserInterface/VerticalSpacer.vue b/components/UserInterface/VerticalSpacer.vue index 293e9f0..8ac1bd6 100644 --- a/components/UserInterface/VerticalSpacer.vue +++ b/components/UserInterface/VerticalSpacer.vue @@ -2,15 +2,6 @@ - - \ No newline at end of file diff --git a/components/DirectMessagesSidebar.vue b/components/Me/DirectMessagesSidebar.vue similarity index 73% rename from components/DirectMessagesSidebar.vue rename to components/Me/DirectMessagesSidebar.vue index dece975..5a0e99d 100644 --- a/components/DirectMessagesSidebar.vue +++ b/components/Me/DirectMessagesSidebar.vue @@ -5,24 +5,24 @@

Direct Messages

+ Friends +
- + :href="`/me/${user.uuid}`"/>
+ + \ No newline at end of file diff --git a/composables/api.ts b/composables/api.ts index 8a37a8e..0cd6db0 100644 --- a/composables/api.ts +++ b/composables/api.ts @@ -37,6 +37,14 @@ export const useApi = () => { return await fetchWithApi('/me/friends') } + async function addFriend(username: string): Promise { + await fetchWithApi('/me/friends', { method: "POST", body: { username } }); + } + + async function removeFriend(userId: string): Promise { + await fetchWithApi(`/me/friends/${userId}`, { method: "DELETE" }); + } + async function fetchMessages(channelId: string, options?: { amount?: number, offset?: number }): Promise { return await fetchWithApi(`/channels/${channelId}/messages`, { query: { amount: options?.amount ?? 100, offset: options?.offset ?? 0 } }); } @@ -64,6 +72,8 @@ export const useApi = () => { fetchUsers, fetchUser, fetchFriends, + addFriend, + removeFriend, fetchMessages, fetchMessage, fetchInstanceStats, diff --git a/pages/me/[userId].vue b/pages/me/[userId].vue new file mode 100644 index 0000000..d466938 --- /dev/null +++ b/pages/me/[userId].vue @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/pages/me/friends.vue b/pages/me/friends.vue new file mode 100644 index 0000000..b284658 --- /dev/null +++ b/pages/me/friends.vue @@ -0,0 +1,82 @@ + + + + + \ No newline at end of file diff --git a/pages/me/index.vue b/pages/me/index.vue index 701481d..b075668 100644 --- a/pages/me/index.vue +++ b/pages/me/index.vue @@ -5,6 +5,8 @@ \ No newline at end of file From 2ff892b0da73a9d0e1ad5522e2dece2f74c7a16f Mon Sep 17 00:00:00 2001 From: SauceyRed Date: Fri, 11 Jul 2025 03:31:25 +0200 Subject: [PATCH 039/188] feat: add util to create MessageReply instance --- utils/replyToMessage.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/utils/replyToMessage.ts b/utils/replyToMessage.ts index 03253d2..bbb453b 100644 --- a/utils/replyToMessage.ts +++ b/utils/replyToMessage.ts @@ -1,5 +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); + } } From a8ee8122ee0f7d03a0e3abc65a9595d041684d56 Mon Sep 17 00:00:00 2001 From: SauceyRed Date: Fri, 11 Jul 2025 03:33:24 +0200 Subject: [PATCH 040/188] feat: implement message replies --- components/Message.vue | 27 ++++++++++++++++++++++++--- components/MessageArea.vue | 29 ++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/components/Message.vue b/components/Message.vue index d3d4086..d86f0ad 100644 --- a/components/Message.vue +++ b/components/Message.vue @@ -1,5 +1,9 @@ + + \ No newline at end of file diff --git a/components/Settings/AppSettings/Appearance.vue b/components/Settings/AppSettings/Appearance.vue index a35e719..39e7410 100644 --- a/components/Settings/AppSettings/Appearance.vue +++ b/components/Settings/AppSettings/Appearance.vue @@ -17,11 +17,15 @@ -

ICONS

-
+ + +

TIME FORMAT

+
+
- -
@@ -70,6 +74,11 @@ async function fetchThemes() { } await fetchThemes() + + +async function onTimeFormatClicked(index: number) { + console.log(index) +} \ No newline at end of file From 890fbebbe9f3dd91d37ff605b1fc95aeaee1a2cc Mon Sep 17 00:00:00 2001 From: SauceyRed Date: Sat, 12 Jul 2025 18:58:09 +0200 Subject: [PATCH 056/188] feat: use \ No newline at end of file From eb4945075646eb595404ad743b6d39be418dc728 Mon Sep 17 00:00:00 2001 From: JustTemmie <47639983+JustTemmie@users.noreply.github.com> Date: Sat, 12 Jul 2025 20:43:25 +0200 Subject: [PATCH 065/188] feat: support 12 and 24 hour formats --- components/Message.vue | 3 ++- components/MessageArea.vue | 2 +- utils/getPreferredTimeFormat.ts | 11 +++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 utils/getPreferredTimeFormat.ts diff --git a/components/Message.vue b/components/Message.vue index a8329dd..db08258 100644 --- a/components/Message.vue +++ b/components/Message.vue @@ -46,7 +46,8 @@ Yesterday at {{ date.toLocaleDateString(undefined) }}, - {{ date.toLocaleTimeString(undefined, { timeStyle: "short" }) }} + + {{ date.toLocaleTimeString(undefined, { hour12: props.format=="12", timeStyle: "short" }) }}
diff --git a/components/MessageArea.vue b/components/MessageArea.vue index b2338f5..d59b862 100644 --- a/components/MessageArea.vue +++ b/components/MessageArea.vue @@ -49,7 +49,7 @@ const me = await fetchWithApi("/me") as UserResponse; const messageTimestamps = ref>({}); const messagesType = ref>({}); const messageGroupingMaxDifference = useRuntimeConfig().public.messageGroupingMaxDifference -const timeFormat = settingLoad("timeFormat") ?? "24" +const timeFormat = getPreferredTimeFormat() const messagesRes: MessageResponse[] | undefined = await fetchWithApi( `${props.channelUrl}/messages`, diff --git a/utils/getPreferredTimeFormat.ts b/utils/getPreferredTimeFormat.ts new file mode 100644 index 0000000..4cf03e0 --- /dev/null +++ b/utils/getPreferredTimeFormat.ts @@ -0,0 +1,11 @@ +export default (): "12" | "24" => { + const format = settingLoad("timeFormat").timeFormat ?? "auto" + + if (format == "12-hour") { + return "12" + } else if (format == "24-hour") { + return "24" + } + + return "24" +} \ No newline at end of file From 6221359a156f27e292dee3d1bcd65313d15fa89d Mon Sep 17 00:00:00 2001 From: SauceyRed Date: Sat, 12 Jul 2025 22:20:28 +0200 Subject: [PATCH 066/188] style(ui): move homebar to app.vue outside to avoid it being rerendered on route change --- app.vue | 7 +++++++ layouts/client.vue | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app.vue b/app.vue index c4fd0dc..850f19a 100644 --- a/app.vue +++ b/app.vue @@ -1,5 +1,12 @@