Compare commits

..

No commits in common. "9122434a3649b8f07c06822e48b6f444ceac55e9" and "2574e7e0e64e6855b17033b6e78509abe59384f0" have entirely different histories.

6 changed files with 39 additions and 78 deletions

View file

@ -1,28 +0,0 @@
<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>

View file

@ -1,16 +1,18 @@
<script> <script>
import { afterUpdate, beforeUpdate, onMount } from "svelte"; import { afterUpdate, beforeUpdate } from "svelte";
import { messagesStoreProvider } from "../../../stores.js"; import { messagesStoreProvider } from "../../../stores.js";
import Message from "./Message.svelte";
export let channelId; export let channelId;
let scrollTarget; let scrollTarget;
let scrollAnchor; let shouldAutoscroll = false;
let shouldAutoscroll = true;
let lastScrollHeight = null; let lastScrollHeight = null;
$: messages = messagesStoreProvider.getStore(channelId); $: messages = messagesStoreProvider.getStore(channelId);
beforeUpdate(() => {
shouldAutoscroll = scrollTarget && (scrollTarget.offsetHeight + scrollTarget.scrollTop) > (scrollTarget.scrollHeight - 20);
});
afterUpdate(() => { afterUpdate(() => {
// hacky way to preserve scroll position when messages are pushed back // hacky way to preserve scroll position when messages are pushed back
if (lastScrollHeight) { if (lastScrollHeight) {
@ -18,8 +20,8 @@
lastScrollHeight = null; lastScrollHeight = null;
return; return;
} }
if (shouldAutoscroll && scrollAnchor) { if (shouldAutoscroll && scrollTarget) {
scrollAnchor.scrollIntoView(false); scrollTarget.scrollTo(0, scrollTarget.scrollHeight);
} }
}); });
@ -27,9 +29,7 @@
const { scrollTop, offsetHeight, scrollHeight } = e.target; const { scrollTop, offsetHeight, scrollHeight } = e.target;
if ((scrollTop + offsetHeight) >= scrollHeight) { // user scrolled to bottom if ((scrollTop + offsetHeight) >= scrollHeight) { // user scrolled to bottom
messages.setIsCollectingOldMessages(true); messages.setIsCollectingOldMessages(true);
shouldAutoscroll = true;
} else { } else {
shouldAutoscroll = false;
if (scrollTop === 0) { if (scrollTop === 0) {
// load older messages if the user scrolls to the top. // load older messages if the user scrolls to the top.
// save the current scroll height if the server returned any messages, // save the current scroll height if the server returned any messages,
@ -57,11 +57,31 @@
overflow-x: hidden; overflow-x: hidden;
background-color: var(--background-color-1); 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> </style>
<div class="messages-container" on:scroll={ onScroll } bind:this={ scrollTarget }> <div class="messages-container" on:scroll={ onScroll } bind:this={ scrollTarget }>
{#each $messages as message (message.id)} {#each $messages as message (message.id)}
<Message message={message} /> <div class="message">
<span class="author">{ message.author_username }</span>
<span class="message-content" class:pending={ message._isPending }>{ message.content }</span>
</div>
{/each} {/each}
<div bind:this={ scrollAnchor } />
</div> </div>

View file

@ -1,4 +1,3 @@
import logging from "./logging";
import { getAuthToken, getItem } from "./storage"; import { getAuthToken, getItem } from "./storage";
export const GatewayPayloadType = { export const GatewayPayloadType = {
@ -23,8 +22,6 @@ export const GatewayEventType = {
Close: -4 Close: -4
} }
const log = logging.logger("Gateway");
export default { export default {
ws: null, ws: null,
authenticated: false, authenticated: false,
@ -36,6 +33,8 @@ export default {
reconnectTimeout: null, reconnectTimeout: null,
handlers: new Map(), handlers: new Map(),
init() { init() {
window.__WAFFLE_GATEWAY = this;
const token = getAuthToken(); const token = getAuthToken();
if (!token) { if (!token) {
return false; return false;
@ -47,7 +46,7 @@ export default {
} }
this.open = true; this.open = true;
this.dispatch(GatewayEventType.Open, null); this.dispatch(GatewayEventType.Open, null);
log("open"); console.log("[gateway] open");
}; };
this.ws.onmessage = (event) => { this.ws.onmessage = (event) => {
const payload = JSON.parse(event.data); const payload = JSON.parse(event.data);
@ -66,7 +65,7 @@ export default {
}); });
}, payload.d.pingInterval); }, payload.d.pingInterval);
log("hello"); console.log("[gateway] hello");
break; break;
} }
case GatewayPayloadType.Ready: { case GatewayPayloadType.Ready: {
@ -75,7 +74,7 @@ export default {
this.reconnectDelay = 400; this.reconnectDelay = 400;
log("ready"); console.log("[gateway] ready");
break; break;
} }
} }
@ -99,7 +98,7 @@ export default {
this.dispatch(GatewayEventType.Close, null); this.dispatch(GatewayEventType.Close, null);
log("close"); console.log("[gateway] close");
}; };
return true; return true;

View file

@ -1,21 +0,0 @@
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);
}
};

View file

@ -1,12 +1,6 @@
import App from './components/App.svelte'; import App from './components/App.svelte';
import gateway from './gateway'; import gateway from './gateway';
import { initStorageDefaults } from './storage'; import { initStorageDefaults } from './storage';
import logging from "./logging";
window.__waffle = {
logging,
gateway
};
initStorageDefaults(); initStorageDefaults();
gateway.init(); gateway.init();

View file

@ -1,11 +1,8 @@
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import gateway, { GatewayEventType } from "./gateway"; import gateway, { GatewayEventType } from "./gateway";
import logging from "./logging";
import request from "./request"; import request from "./request";
import { apiRoute } from "./storage"; import { apiRoute } from "./storage";
const storeLog = logging.logger("Store");
class Store { class Store {
constructor(value=null) { constructor(value=null) {
this._handlers = []; this._handlers = [];
@ -16,14 +13,14 @@ class Store {
const newLength = this._handlers.push(handler); const newLength = this._handlers.push(handler);
const handlerIndex = newLength - 1; const handlerIndex = newLength - 1;
handler(this.value); handler(this.value);
storeLog("Subscription initialized with value", this.value); console.log(this.value);
return () => { return () => {
this._handlers.splice(handlerIndex, 1); this._handlers.splice(handlerIndex, 1);
}; };
} }
updated() { updated() {
storeLog(`updated(): calling ${this._handlers.length} handlers - value changed`, this.value); console.log(this.value);
this._handlers.forEach(e => { this._handlers.forEach(e => {
e(this.value); e(this.value);
}); });