Compare commits
2 commits
2574e7e0e6
...
9122434a36
Author | SHA1 | Date | |
---|---|---|---|
|
9122434a36 | ||
|
15e57c2372 |
6 changed files with 78 additions and 39 deletions
28
frontend/src/components/pages/main/Message.svelte
Normal file
28
frontend/src/components/pages/main/Message.svelte
Normal file
|
@ -0,0 +1,28 @@
|
|||
<script>
|
||||
export let message;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.message {
|
||||
overflow-x: none;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
color: var(--foreground-color-2);
|
||||
}
|
||||
|
||||
.pending {
|
||||
color: var(--foreground-color-3);
|
||||
}
|
||||
|
||||
.author {
|
||||
font-weight: bold;
|
||||
margin-right: var(--space-xxs);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="message">
|
||||
<span class="author">{ message.author_username }</span>
|
||||
<span class="message-content" class:pending={ message._isPending }>{ message.content }</span>
|
||||
</div>
|
|
@ -1,27 +1,25 @@
|
|||
<script>
|
||||
import { afterUpdate, beforeUpdate } from "svelte";
|
||||
import { afterUpdate, beforeUpdate, onMount } from "svelte";
|
||||
import { messagesStoreProvider } from "../../../stores.js";
|
||||
import Message from "./Message.svelte";
|
||||
|
||||
export let channelId;
|
||||
let scrollTarget;
|
||||
let shouldAutoscroll = false;
|
||||
let scrollAnchor;
|
||||
let shouldAutoscroll = true;
|
||||
let lastScrollHeight = null;
|
||||
|
||||
$: messages = messagesStoreProvider.getStore(channelId);
|
||||
|
||||
beforeUpdate(() => {
|
||||
shouldAutoscroll = scrollTarget && (scrollTarget.offsetHeight + scrollTarget.scrollTop) > (scrollTarget.scrollHeight - 20);
|
||||
});
|
||||
|
||||
afterUpdate(() => {
|
||||
// hacky way to preserve scroll position when messages are pushed back
|
||||
if (lastScrollHeight) {
|
||||
scrollTarget.scrollTop = scrollTarget.scrollHeight - lastScrollHeight;
|
||||
scrollTarget.scrollTop = scrollTarget.scrollHeight - lastScrollHeight;
|
||||
lastScrollHeight = null;
|
||||
return;
|
||||
}
|
||||
if (shouldAutoscroll && scrollTarget) {
|
||||
scrollTarget.scrollTo(0, scrollTarget.scrollHeight);
|
||||
if (shouldAutoscroll && scrollAnchor) {
|
||||
scrollAnchor.scrollIntoView(false);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -29,7 +27,9 @@
|
|||
const { scrollTop, offsetHeight, scrollHeight } = e.target;
|
||||
if ((scrollTop + offsetHeight) >= scrollHeight) { // user scrolled to bottom
|
||||
messages.setIsCollectingOldMessages(true);
|
||||
shouldAutoscroll = true;
|
||||
} else {
|
||||
shouldAutoscroll = false;
|
||||
if (scrollTop === 0) {
|
||||
// load older messages if the user scrolls to the top.
|
||||
// save the current scroll height if the server returned any messages,
|
||||
|
@ -57,31 +57,11 @@
|
|||
overflow-x: hidden;
|
||||
background-color: var(--background-color-1);
|
||||
}
|
||||
|
||||
.message {
|
||||
overflow-x: none;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
color: var(--foreground-color-2);
|
||||
}
|
||||
|
||||
.pending {
|
||||
color: var(--foreground-color-3);
|
||||
}
|
||||
|
||||
.author {
|
||||
font-weight: bold;
|
||||
margin-right: var(--space-xxs);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="messages-container" on:scroll={ onScroll } bind:this={ scrollTarget }>
|
||||
{#each $messages as message (message.id)}
|
||||
<div class="message">
|
||||
<span class="author">{ message.author_username }</span>
|
||||
<span class="message-content" class:pending={ message._isPending }>{ message.content }</span>
|
||||
</div>
|
||||
<Message message={message} />
|
||||
{/each}
|
||||
<div bind:this={ scrollAnchor } />
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import logging from "./logging";
|
||||
import { getAuthToken, getItem } from "./storage";
|
||||
|
||||
export const GatewayPayloadType = {
|
||||
|
@ -22,6 +23,8 @@ export const GatewayEventType = {
|
|||
Close: -4
|
||||
}
|
||||
|
||||
const log = logging.logger("Gateway");
|
||||
|
||||
export default {
|
||||
ws: null,
|
||||
authenticated: false,
|
||||
|
@ -33,8 +36,6 @@ export default {
|
|||
reconnectTimeout: null,
|
||||
handlers: new Map(),
|
||||
init() {
|
||||
window.__WAFFLE_GATEWAY = this;
|
||||
|
||||
const token = getAuthToken();
|
||||
if (!token) {
|
||||
return false;
|
||||
|
@ -46,7 +47,7 @@ export default {
|
|||
}
|
||||
this.open = true;
|
||||
this.dispatch(GatewayEventType.Open, null);
|
||||
console.log("[gateway] open");
|
||||
log("open");
|
||||
};
|
||||
this.ws.onmessage = (event) => {
|
||||
const payload = JSON.parse(event.data);
|
||||
|
@ -65,7 +66,7 @@ export default {
|
|||
});
|
||||
}, payload.d.pingInterval);
|
||||
|
||||
console.log("[gateway] hello");
|
||||
log("hello");
|
||||
break;
|
||||
}
|
||||
case GatewayPayloadType.Ready: {
|
||||
|
@ -74,7 +75,7 @@ export default {
|
|||
|
||||
this.reconnectDelay = 400;
|
||||
|
||||
console.log("[gateway] ready");
|
||||
log("ready");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +99,7 @@ export default {
|
|||
|
||||
this.dispatch(GatewayEventType.Close, null);
|
||||
|
||||
console.log("[gateway] close");
|
||||
log("close");
|
||||
};
|
||||
|
||||
return true;
|
||||
|
|
21
frontend/src/logging.js
Normal file
21
frontend/src/logging.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
export default {
|
||||
sinks: new Map(),
|
||||
logger(sink, enabled=false) {
|
||||
this.sinks.set(sink, enabled);
|
||||
return (...args) => {
|
||||
if (this.sinks.get(sink)) {
|
||||
console.log(
|
||||
`%c[${sink}]`,
|
||||
"color: #8f3f71; font-weight: bold;",
|
||||
...args
|
||||
);
|
||||
}
|
||||
};
|
||||
},
|
||||
enableSink(sink) {
|
||||
this.sinks.set(sink, true);
|
||||
},
|
||||
disableSink(sink) {
|
||||
this.sinks.set(sink, false);
|
||||
}
|
||||
};
|
|
@ -1,6 +1,12 @@
|
|||
import App from './components/App.svelte';
|
||||
import gateway from './gateway';
|
||||
import { initStorageDefaults } from './storage';
|
||||
import logging from "./logging";
|
||||
|
||||
window.__waffle = {
|
||||
logging,
|
||||
gateway
|
||||
};
|
||||
|
||||
initStorageDefaults();
|
||||
gateway.init();
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import { writable } from "svelte/store";
|
||||
import gateway, { GatewayEventType } from "./gateway";
|
||||
import logging from "./logging";
|
||||
import request from "./request";
|
||||
import { apiRoute } from "./storage";
|
||||
|
||||
const storeLog = logging.logger("Store");
|
||||
|
||||
class Store {
|
||||
constructor(value=null) {
|
||||
this._handlers = [];
|
||||
|
@ -13,14 +16,14 @@ class Store {
|
|||
const newLength = this._handlers.push(handler);
|
||||
const handlerIndex = newLength - 1;
|
||||
handler(this.value);
|
||||
console.log(this.value);
|
||||
storeLog("Subscription initialized with value", this.value);
|
||||
return () => {
|
||||
this._handlers.splice(handlerIndex, 1);
|
||||
};
|
||||
}
|
||||
|
||||
updated() {
|
||||
console.log(this.value);
|
||||
storeLog(`updated(): calling ${this._handlers.length} handlers - value changed`, this.value);
|
||||
this._handlers.forEach(e => {
|
||||
e(this.value);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue