Skip to content

Commit

Permalink
work on channel list
Browse files Browse the repository at this point in the history
  • Loading branch information
loudar committed May 30, 2024
1 parent 6f97046 commit fff9149
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 16 deletions.
33 changes: 30 additions & 3 deletions ui/api/Hooks.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export class Hooks {
Api.getChannels().then((res) => {
if (res.status === 200) {
store().setSignalValue('channels', res.data);
for (const channel of res.data) {
Hooks.runActiveChannel(channel.id);
}
} else {
toast("Failed to fetch channels", "negative");
store().setSignalValue('channels', []);
Expand All @@ -35,7 +38,6 @@ export class Hooks {
setMessages(channel, res.data);
} else {
toast("Failed to fetch messages", "negative");
setMessages(channel, []);
}
});
}
Expand All @@ -48,7 +50,7 @@ export function setMessages(channel, messages) {

const ex = store().get('messages').value;
setChannel(ex, channel);
store().setSignalValue('messages', {...ex, [channel]: messages});
store().setSignalValue('messages', {...ex, [channel]: messages.sort((a, b) => a.id - b.id)});
}

export function addMessage(channel, message) {
Expand All @@ -58,7 +60,7 @@ export function addMessage(channel, message) {

const ex = store().get('messages').value;
setChannel(ex, channel);
store().setSignalValue('messages', {...ex, [channel]: [message, ...ex[channel]]});
store().setSignalValue('messages', {...ex, [channel]: [...ex[channel], message]});
}

export function removeMessage(channel, messageId) {
Expand All @@ -75,4 +77,29 @@ export function setChannel(ex, channel) {
if (!ex[channel]) {
ex[channel] = [];
}
}

export function addChannel(channel) {
if (!store().get('channels')) {
store().set('channels', signal([]));
}

if (store().get('channels').value.includes(channel)) {
return;
}

store().setSignalValue('channels', [channel, ...store().get('channels').value]);
}

export function removeChannel(channel) {
if (!store().get('channels')) {
store().set('channels', signal([]));
}

store().setSignalValue('channels', store().get('channels').value.filter((c) => c !== channel));
}

export function setActiveChannel(channel) {
store().set('activeChannel', signal(channel));
Hooks.runActiveChannel(channel);
}
25 changes: 25 additions & 0 deletions ui/classes.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
width: calc(var(--width) - 2 * var(--input-border-width));
}

.flex-pane {
flex-grow: 1;
border: var(--input-border-width) solid var(--bg-4);
}

.padded {
padding: var(--gap-h);
}
Expand Down Expand Up @@ -231,6 +236,7 @@

.message-content {
position: relative;
padding: 0.25em;
}

.message-menu {
Expand All @@ -250,4 +256,23 @@

.close-button {
align-self: end;
}

.resizable {
position: relative;
}

.resize-indicator {
position: absolute;
}

.resize-indicator.v {
height: 100%;
width: 10px;
right: 0;
cursor: ew-resize;
}

.resize-indicator:hover {
background: rgba(150, 150, 150, 0.2);
}
59 changes: 57 additions & 2 deletions ui/components/layout.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,67 @@ export class LayoutTemplates {
.build();
}

static pane(content, defaultWidth = "50%", minWidth = "300px") {
static pane(content, defaultWidth = "50%", minWidth = "300px", maxWidth = "100%") {
return create("div")
.classes("pane")
.styles("--width", defaultWidth)
.styles("width", defaultWidth)
.styles("min-width", minWidth)
.styles("max-width", maxWidth)
.children(content)
.build();
}

static flexPane(content, minWidth = "300px", maxWidth = "100%") {
return create("div")
.classes("flex-pane")
.styles("min-width", minWidth)
.styles("max-width", maxWidth)
.children(content)
.build();
}

static resizableFromRight(content, defaultWidth = "50%", minWidth = "300px", maxWidth = "100%") {
const uniqueId = Math.random().toString(36).substring(7);

return create("div")
.classes("pane", "resizable")
.styles("--width", defaultWidth)
.styles("min-width", minWidth)
.styles("max-width", maxWidth)
.id(uniqueId)
.children(
LayoutTemplates.resizeIndicator(uniqueId, "v"),
content
).build();
}

static resizeIndicator(refId, type = "v") {
const propertyToSet = type === "v" ? "width" : "height";
const clientProperty = type === "v" ? "clientX" : "clientY";

return create("div")
.classes("resize-indicator", type)
.onmousedown(e => {
const startPos = e[clientProperty];
const pane = document.getElementById(refId);
const startSize = parseInt(getComputedStyle(pane)[propertyToSet], 10);
document.body.style.userSelect = "none";

const onMouseMove = e => {
e.preventDefault();
const newSize = startSize + (e[clientProperty] - startPos);
pane.style.setProperty(propertyToSet, `${newSize}px`);
};

const onMouseUp = () => {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
document.body.style.userSelect = "";
};

document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
})
.build();
}
}
35 changes: 25 additions & 10 deletions ui/components/pages/chat.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ export class ChatComponent {
activeChannel.value = newChannels[0]?.id || null;
}
});
const updateChannels = () => {
displayChannels.value = channels.value.sort((a, b) => {
const aLastMsg = messages.value[a.id]?.at(-1);
const bLastMsg = messages.value[b.id]?.at(-1);
if (!aLastMsg || !bLastMsg) {
return 0;
}

return new Date(bLastMsg.createdAt).getTime() - new Date(aLastMsg.createdAt).getTime();
});
};
const displayChannels = signal(channels.value);
messages.subscribe(updateChannels);
channels.subscribe(updateChannels);

activeChannel.subscribe(channel => {
Store.set("currentChannelId", channel);
Hooks.runActiveChannel(channel);
Expand All @@ -36,22 +51,22 @@ export class ChatComponent {
create("div")
.classes("panes", "full-width", "flex-grow")
.children(
LayoutTemplates.pane(ChatComponent.channelList(channels, activeChannel), "25%", "200px"),
ifjs(activeChannel, LayoutTemplates.pane(ChatComponent.chat(activeChannel, messages), "75%", "300px")),
ifjs(activeChannel, LayoutTemplates.pane(create("span").text("No channel selected").build(), "75%", "300px"), true)
LayoutTemplates.resizableFromRight(ChatComponent.channelList(displayChannels, messages, activeChannel), "50%", "200px", "50%"),
ifjs(activeChannel, LayoutTemplates.flexPane(ChatComponent.chat(activeChannel, messages), "300px", "100%")),
ifjs(activeChannel, LayoutTemplates.flexPane(create("span").text("No channel selected").build(), "300px", "100%"), true)
).build()
).build();
}

static channelList(channels, activeChannel) {
static channelList(channels, messages, activeChannel) {
return signalMap(channels,
create("div")
.classes("flex-v", "no-gap")
, channel => {
if (channel.type === "gr") {
return ChatComponent.groupChannel(channel, activeChannel);
return ChatComponent.groupChannel(channel, messages, activeChannel);
} else {
return ChatComponent.dmChannel(channel, activeChannel);
return ChatComponent.dmChannel(channel, messages, activeChannel);
}
});
}
Expand All @@ -73,7 +88,7 @@ export class ChatComponent {
.classes("chat-content", "flex-v", "no-gap")
.children(
signalMap(messages, create("div")
.classes("chat-messages", "flex-v", "flex-grow"),
.classes("chat-messages", "flex-v", "flex-grow", "no-gap"),
message => ChatComponent.message(message, messages)),
create("div")
.classes("background-2", "chat-input", "flex", "align-center")
Expand Down Expand Up @@ -176,7 +191,7 @@ export class ChatComponent {
).build();
}

static groupChannel(channel, activeChannel) {
static groupChannel(channel, messages, activeChannel) {
const activeClass = computedSignal(activeChannel, (id) => id === channel.id ? "active" : "_");
const editing = signal(false);

Expand Down Expand Up @@ -275,7 +290,7 @@ export class ChatComponent {
).build();
}

static dmChannel(channel, activeChannel) {
static dmChannel(channel, messages, activeChannel) {
const activeClass = computedSignal(activeChannel, (id) => id === channel.id ? "active" : "_");

return create("div")
Expand All @@ -289,7 +304,7 @@ export class ChatComponent {
.build(),
create("span")
.classes("text-small")
.text("DM")
.text(messages.value[channel.id]?.at(-1)?.text || "No messages")
.build(),
).build();
}
Expand Down
6 changes: 5 additions & 1 deletion ui/live/LiveInstance.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {addMessage, removeMessage} from "../api/Hooks.mjs";
import {addChannel, addMessage, removeMessage} from "../api/Hooks.mjs";
import {toast} from "../actions.mjs";
import {Api} from "../api/Api.mjs";

Expand Down Expand Up @@ -44,13 +44,17 @@ export class LiveInstance {

this.server.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(data);
switch (data.type) {
case "message":
addMessage(data.message.channelId, data.message);
break;
case "removeMessage":
removeMessage(data.channelId, data.messageId);
break;
case "newChannel":
addChannel(data.channel);
break;
}
};
}
Expand Down

0 comments on commit fff9149

Please sign in to comment.