Compare commits
No commits in common. "9122434a3649b8f07c06822e48b6f444ceac55e9" and "2574e7e0e64e6855b17033b6e78509abe59384f0" have entirely different histories.
9122434a36
...
2574e7e0e6
6 changed files with 39 additions and 78 deletions
|
@ -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>
|
|
|
@ -1,25 +1,27 @@
|
||||||
<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) {
|
||||||
scrollTarget.scrollTop = scrollTarget.scrollHeight - lastScrollHeight;
|
scrollTarget.scrollTop = scrollTarget.scrollHeight - lastScrollHeight;
|
||||||
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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue