frontend: link up channel sidebar with gateway and fix channel button layout issue

This commit is contained in:
hippoz 2022-04-17 04:08:40 +03:00
parent 01649150a4
commit 381f1ae454
Signed by: hippoz
GPG key ID: 7C52899193467641
7 changed files with 163 additions and 39 deletions

View file

@ -1,6 +1,6 @@
<script> <script>
import ChannelView from "./Main.svelte"; import Main from "./pages/main/Main.svelte";
</script> </script>
<ChannelView /> <Main />

View file

@ -1,5 +1,7 @@
<script> <script>
import { HashIcon } from "svelte-feather-icons"; import { HashIcon } from "svelte-feather-icons";
export let channel;
</script> </script>
<style> <style>
@ -38,7 +40,7 @@
} }
.message-input { .message-input {
height: 3.4em; height: 3em;
width: 100%; width: 100%;
background-color : var(--background-color-2); background-color : var(--background-color-2);
border: none; border: none;
@ -51,7 +53,7 @@
<div class="main-container"> <div class="main-container">
<div class="top-bar"> <div class="top-bar">
<HashIcon /> <HashIcon />
<span class="h5 channel-heading">channel name</span> <span class="h5 channel-heading">{ channel.name }</span>
</div> </div>
<div class="messages-container"> <div class="messages-container">

View file

@ -15,5 +15,5 @@ import Sidebar from "./Sidebar.svelte";
<div class="flex-container"> <div class="flex-container">
<Sidebar /> <Sidebar />
<ChannelView /> <ChannelView channel={{ name: "channel name" }} />
</div> </div>

View file

@ -1,11 +1,24 @@
<script> <script>
import { HashIcon } from "svelte-feather-icons"; import { HashIcon } from "svelte-feather-icons";
import { channels } from "../../../stores";
</script> </script>
<div class="sidebar">
{#each $channels as channel}
<button class="sidebar-button">
<div>
<HashIcon />
</div>
<span>{ channel.name }</span>
</button>
{/each}
</div>
<style> <style>
.sidebar { .sidebar {
height: 100%; height: 100%;
width: 255px; width: 255px;
max-width: 255px;
padding: var(--space-sm); padding: var(--space-sm);
background-color: var(--background-color-1); background-color: var(--background-color-1);
} }
@ -13,39 +26,36 @@
.sidebar-button { .sidebar-button {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: left;
border: none; border: none;
background-color: var(--background-color-1); background-color: var(--background-color-1);
padding: var(--space-sm); padding: var(--space-sm);
margin-bottom: var(--space-xxs); margin-bottom: var(--space-xxs);
color: currentColor; color: currentColor;
font: inherit; font: inherit;
width: 100%;
border-radius: var(--radius-md); border-radius: var(--radius-md);
vertical-align: middle; width: 100%;
height: 3.4em;
text-align: center;
} }
.sidebar-button span { .sidebar-button span {
margin-left: var(--space-xxs); margin-left: var(--space-xxs);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sidebar-button div {
display: inline;
flex-shrink: 0;
/* TODO: HACK! */
width: 24px;
height: 24px;
} }
.sidebar-button:hover { .sidebar-button:hover {
background-color: var(--background-color-2); background-color: var(--background-color-2);
} }
</style> </style>
<div class="sidebar">
<button class="sidebar-button">
<HashIcon />
<span>channel name</span>
</button>
<button class="sidebar-button">
<HashIcon />
<span>channel name</span>
</button>
<button class="sidebar-button">
<HashIcon />
<span>channel name</span>
</button>
</div>

View file

@ -15,6 +15,13 @@ export const GatewayPayloadType = {
MessageDelete: 122, MessageDelete: 122,
} }
export const GatewayEventType = {
...GatewayPayloadType,
Open: -5,
Close: -4
}
export default { export default {
ws: null, ws: null,
authenticated: false, authenticated: false,
@ -23,7 +30,10 @@ export default {
channels: null, channels: null,
reconnectDelay: 400, reconnectDelay: 400,
reconnectTimeout: null, reconnectTimeout: null,
handlers: new Map(),
init() { init() {
window.__WAFFLE_GATEWAY = this;
const token = getAuthToken(); const token = getAuthToken();
if (!token) { if (!token) {
return false; return false;
@ -33,6 +43,7 @@ export default {
if (this.reconnectTimeout) { if (this.reconnectTimeout) {
clearTimeout(this.reconnectTimeout); clearTimeout(this.reconnectTimeout);
} }
this.dispatch(GatewayEventType.Open, null);
console.log("[gateway] open"); console.log("[gateway] open");
}; };
this.ws.onmessage = (event) => { this.ws.onmessage = (event) => {
@ -65,6 +76,8 @@ export default {
break; break;
} }
} }
this.dispatch(payload.t, payload.d);
}; };
this.ws.onclose = () => { this.ws.onclose = () => {
if (this.reconnectDelay < 60000) { if (this.reconnectDelay < 60000) {
@ -80,6 +93,8 @@ export default {
this.init(); this.init();
}, this.reconnectDelay); }, this.reconnectDelay);
this.dispatch(GatewayEventType.Close, null);
console.log("[gateway] close"); console.log("[gateway] close");
}; };
@ -87,5 +102,33 @@ export default {
}, },
send(data) { send(data) {
return this.ws.send(JSON.stringify(data)); return this.ws.send(JSON.stringify(data));
},
dispatch(event, payload) {
const eventHandlers = this.handlers.get(event);
if (!eventHandlers)
return;
eventHandlers.forEach((e) => {
e(payload);
});
},
subscribe(event, handler) {
if (!this.handlers.get(event)) {
this.handlers.set(event, new Set());
}
this.handlers.get(event).add(handler);
return handler; // can later be used for unsubscribe()
},
unsubscribe(event, handler) {
const eventHandlers = this.handlers.get(event);
if (!eventHandlers)
return;
eventHandlers.delete(handler);
if (eventHandlers.size < 1) {
this.handlers.delete(event);
}
} }
}; };

69
frontend/src/stores.js Normal file
View file

@ -0,0 +1,69 @@
import gateway, { GatewayEventType } from "./gateway";
export const channels = {
_handlers: [],
_value: [],
_didInit: false,
subscribe(handler) {
this._init();
const newLength = this._handlers.push(handler);
const handlerIndex = newLength - 1;
handler(this._value);
return () => {
this._handlers.splice(handlerIndex, 1);
};
},
_dispatchUpdate() {
this._handlers.forEach(e => {
e(this._value);
});
},
_init() {
window.__WAFFLE_CHANNELS_STORE = this;
if (this._didInit)
return;
this._didInit = true;
const channels = gateway.channels;
if (channels) {
this._value = channels;
}
gateway.subscribe(GatewayEventType.Ready, ({ channels }) => {
if (channels) {
this._value = channels;
}
this._dispatchUpdate();
});
gateway.subscribe(GatewayEventType.ChannelCreate, (channel) => {
this._value.push(channel);
this._dispatchUpdate();
});
gateway.subscribe(GatewayEventType.ChannelDelete, ({ id }) => {
const index = this._value.findIndex(e => e.id === id);
if (!index)
return;
this._value.splice(index);
this._dispatchUpdate();
});
gateway.subscribe(GatewayEventType.ChannelUpdate, (data) => {
const index = this._value.findIndex(e => e.id === data.id);
if (!index)
return;
if (!this._value[index])
return;
this._value[index] = data;
this._dispatchUpdate();
});
}
};

View file

@ -19,50 +19,50 @@ content-type: application/json
### ###
GET http://localhost:3000/api/v1/users/self HTTP/1.1 GET http://localhost:3000/api/v1/users/self HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
### ###
POST http://localhost:3000/api/v1/channels HTTP/1.1 POST http://localhost:3000/api/v1/channels HTTP/1.1
content-type: application/json content-type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
{ {
"name": "yet another channelllll" "name": "idk what to call these"
} }
### ###
PUT http://localhost:3000/api/v1/channels/8 HTTP/1.1 PUT http://localhost:3000/api/v1/channels/5 HTTP/1.1
content-type: application/json content-type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
#Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5MjU5NDUwLCJleHAiOjE2NDk0MzIyNTB9.JmF9NujFZnln7A-ynNpeyayGBqmR5poAyACYV6RnSQY #Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5MjU5NDUwLCJleHAiOjE2NDk0MzIyNTB9.JmF9NujFZnln7A-ynNpeyayGBqmR5poAyACYV6RnSQY
{ {
"name": "this is my channelaaaaaa" "name": "idk what to put here"
} }
### ###
DELETE http://localhost:3000/api/v1/channels/1 HTTP/1.1 DELETE http://localhost:3000/api/v1/channels/10 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
#Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5MjU5NDUwLCJleHAiOjE2NDk0MzIyNTB9.JmF9NujFZnln7A-ynNpeyayGBqmR5poAyACYV6RnSQY #Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5MjU5NDUwLCJleHAiOjE2NDk0MzIyNTB9.JmF9NujFZnln7A-ynNpeyayGBqmR5poAyACYV6RnSQY
### ###
GET http://localhost:3000/api/v1/channels/1 HTTP/1.1 GET http://localhost:3000/api/v1/channels/1 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
### ###
GET http://localhost:3000/api/v1/channels HTTP/1.1 GET http://localhost:3000/api/v1/channels HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
### ###
POST http://localhost:3000/api/v1/channels/5/messages HTTP/1.1 POST http://localhost:3000/api/v1/channels/5/messages HTTP/1.1
content-type: application/json content-type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
{ {
"content": "i hate cheese" "content": "i hate cheese"
@ -71,13 +71,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6M
### ###
GET http://localhost:3000/api/v1/channels/5/messages HTTP/1.1 GET http://localhost:3000/api/v1/channels/5/messages HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
### ###
PUT http://localhost:3000/api/v1/messages/3 HTTP/1.1 PUT http://localhost:3000/api/v1/messages/3 HTTP/1.1
content-type: application/json content-type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
{ {
"content": "hello again!" "content": "hello again!"
@ -86,9 +86,9 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6M
### ###
GET http://localhost:3000/api/v1/messages/3 GET http://localhost:3000/api/v1/messages/3
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk
### ###
DELETE http://localhost:3000/api/v1/messages/2 HTTP/1.1 DELETE http://localhost:3000/api/v1/messages/2 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5NzAwMTE0LCJleHAiOjE2NDk4NzI5MTR9.EOn8MBHZLCxfU5fHc0ZY2x9p3y-_RdD7X915L1B6Ftc Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjUwMTUyNjQ2LCJleHAiOjE2NTAzMjU0NDZ9.eFjOjJV3rIZWN0WrdRblflh2q8dYDGQv4qxugjbYNFk