diff --git a/src/lib/components/SphereBar.svelte b/src/lib/components/SphereBar.svelte
index a8060a6..272e2bd 100644
--- a/src/lib/components/SphereBar.svelte
+++ b/src/lib/components/SphereBar.svelte
@@ -1,16 +1,19 @@
@@ -60,17 +78,32 @@
{currentSphere.name ?? currentSphere.slug}
- {#each currentSphere.categories as category (category.id)}
- {#if category.id != currentSphere.id}
-
- > {category.name}
-
- {/if}
- {#each category.channels as channel (channel.id)}
-
- # {channel.name}
-
- {/each}
+ {#each currentSphere.categories[0].channels as channel (channel.id)}
+
+ # {channel.name}
+
+ {/each}
+ {#each currentSphere.categories.slice(1) as category (category.id)}
+ toggleCategory(e, category)}
+ >
+ {category.name}
+ {#if !category.collapsed}
+ {#each category.channels as channel (channel.id)}
+
+ # {channel.name}
+
+ {/each}
+ {/if}
+
{/each}
@@ -135,13 +168,43 @@
.category {
margin: 10px 0;
+ user-select: none;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .category summary {
+ margin: 0;
+ }
+
+ .category-name {
+ color: var(--color-text);
+ cursor: pointer;
+ padding: 5px;
+ border-radius: 5px;
+ }
+
+ .category-name:hover {
+ background-color: var(--purple-300);
}
.channel {
- padding-left: 5px;
+ padding: 5px;
+ margin: 2px;
+ border-radius: 5px;
text-decoration: none;
}
+ .channel:hover {
+ color: var(--gray-600);
+ background-color: var(--purple-300);
+ }
+
+ .channel.current {
+ color: var(--gray-600);
+ background-color: var(--purple-400);
+ }
+
#sphere-banner {
width: 100%;
height: 115px;
diff --git a/src/lib/types/category.ts b/src/lib/types/category.ts
index 3e04bea..fafa051 100644
--- a/src/lib/types/category.ts
+++ b/src/lib/types/category.ts
@@ -1,8 +1,9 @@
-import { SphereChannel } from "./channel";
+import type { SphereChannel } from './channel';
export interface Category {
- id: number;
- name: string;
- channels: SphereChannel[];
- position: number;
-}
\ No newline at end of file
+ id: number;
+ name: string;
+ channels: SphereChannel[];
+ position: number;
+ collapsed: boolean;
+}
diff --git a/src/lib/types/ui/config.ts b/src/lib/types/ui/config.ts
index af50716..725ee15 100644
--- a/src/lib/types/ui/config.ts
+++ b/src/lib/types/ui/config.ts
@@ -5,4 +5,5 @@ export interface UserConfig {
userList?: boolean;
recentEmojis?: string[];
lastChannel?: number;
+ hiddenCategories?: number[];
}
diff --git a/src/lib/ws.ts b/src/lib/ws.ts
index 304ca73..1e89841 100644
--- a/src/lib/ws.ts
+++ b/src/lib/ws.ts
@@ -15,13 +15,13 @@ const state = writable({
users: [],
spheres: [],
categories: [],
- channels: [],
+ channels: []
});
let ws: WebSocket | null = null;
let pingInterval: NodeJS.Timeout | null = null;
let lastAuthorID: { [name: number]: number } = {};
-let lastAuthorData: { [name: number]: { name: string, avatar: string | number | undefined } } = {};
+let lastAuthorData: { [name: number]: { name: string; avatar: string | number | undefined } } = {};
let notification: Notification;
let notification_opt: number;
let connected = false;
@@ -76,15 +76,13 @@ const connect = async (userData: UserData) => {
u.members.forEach((m) => {
state.users[m.user.id] = m.user;
});
- // u.channels.forEach((c) => {
- // state.channels[c.id] = c;
- // });
u.categories.forEach((c) => {
+ c.collapsed = false; // TODO: Maybe remember this between sessions?
state.categories[c.id] = c;
c.channels.forEach((c) => {
state.channels[c.id] = c;
- })
- })
+ });
+ });
state.spheres[u.id] = u;
});
state.users[payload.d.user.id] = payload.d.user;
@@ -140,27 +138,32 @@ const connect = async (userData: UserData) => {
const authorData = {
name:
payload.d._disguise?.name ??
- payload.d.author.display_name ?? payload.d.author.username,
- avatar:
- payload.d._disguise?.avatar ??
- payload.d.author.avatar
+ payload.d.author.display_name ??
+ payload.d.author.username,
+ avatar: payload.d._disguise?.avatar ?? payload.d.author.avatar
};
if (!lastAuthorData[channelID]) {
let lastMessage = get(state).messages[channelID].messages.at(-1);
if (lastMessage) {
lastAuthorData[channelID] = {
- name: lastMessage?._disguise?.name ??
- lastMessage.author.display_name ?? lastMessage.author.username,
+ name:
+ lastMessage?._disguise?.name ??
+ lastMessage.author.display_name ??
+ lastMessage.author.username,
avatar: lastMessage?._disguise?.avatar ?? lastMessage?.author.avatar
};
lastAuthorID[channelID] = lastMessage?.author.id;
}
}
- let sameData = authorData?.name == lastAuthorData[channelID]?.name && authorData?.avatar == lastAuthorData[channelID].avatar;
+ let sameData =
+ authorData?.name == lastAuthorData[channelID]?.name &&
+ authorData?.avatar == lastAuthorData[channelID].avatar;
const message = {
renderedContent: content,
showAuthor: !sameData || payload.d.author.id != lastAuthorID[channelID],
- mentioned: new RegExp(`(?`, 'gm').test(payload.d.content ?? ''),
+ mentioned: new RegExp(`(?`, 'gm').test(
+ payload.d.content ?? ''
+ ),
...payload.d
};
lastAuthorData[channelID] = authorData;
@@ -190,7 +193,7 @@ const connect = async (userData: UserData) => {
}
);
// new Audio('...').play();
- };
+ }
}
state.update((state) => {
if (state.messages[message.channel.id]) {