significantly improve unread system

This commit is contained in:
hippoz 2022-09-02 22:07:08 +03:00
parent 81e9de6cd8
commit 7b9379732e
No known key found for this signature in database
GPG key ID: 7C52899193467641
3 changed files with 74 additions and 31 deletions

View file

@ -348,7 +348,7 @@ body {
text-overflow: ellipsis;
}
.sidebar-button div {
.sidebar-button .sidebar-button-icon {
display: inline;
flex-shrink: 0;

View file

@ -2,7 +2,7 @@
import { HashIcon, PlusIcon, MoreVerticalIcon, SettingsIcon, CloudIcon } from "svelte-feather-icons";
import { quadInOut } from "svelte/easing";
import { maybeFly, maybeFlyIf } from "../animations";
import { channels, gatewayStatus, overlayStore, selectedChannel, showSidebar, smallViewport, userInfoStore } from "../stores";
import { channels, gatewayStatus, overlayStore, selectedChannel, showSidebar, smallViewport, userInfoStore, unreadStore } from "../stores";
import UserTopBar from "./UserTopBar.svelte";
const selectChannel = (channel) => {
@ -19,30 +19,32 @@
<div class="sidebar">
{#each $channels as channel (channel.id)}
<button on:click="{ selectChannel(channel) }" class="sidebar-button" class:selected={ channel.id === $selectedChannel.id }>
<div>
<div class="sidebar-button-icon">
<HashIcon />
</div>
<span>{ channel.name }</span>
{#if channel._hasUnreads}
<span class="unread-indicator"></span>
{/if}
{#if $userInfoStore && (channel.owner_id === $userInfoStore.id || $userInfoStore.is_superuser)}
<button class="icon-button icon-button-auto" on:click|stopPropagation="{ () => overlayStore.open('editChannel', { channel }) }" aria-label="Edit Channel">
<MoreVerticalIcon />
</button>
{/if}
<div class="sidebar-channel-buttons">
{#if $unreadStore.get(channel.id)}
<div class="unread-indicator">{ $unreadStore.get(channel.id) }</div>
{/if}
{#if $userInfoStore && (channel.owner_id === $userInfoStore.id || $userInfoStore.is_superuser)}
<button class="icon-button" on:click|stopPropagation="{ () => overlayStore.open('editChannel', { channel }) }" aria-label="Edit Channel">
<MoreVerticalIcon />
</button>
{/if}
</div>
</button>
{/each}
{#if $userInfoStore && $userInfoStore.permissions.create_channel}
<button on:click="{ () => overlayStore.open('createChannel') }" class="sidebar-button">
<div>
<div class="sidebar-button-icon">
<PlusIcon />
</div>
<span>Create Channel</span>
</button>
{/if}
<button on:click="{ () => overlayStore.open('settings') }" class="sidebar-button">
<div>
<div class="sidebar-button-icon">
<SettingsIcon />
</div>
<span>Settings</span>
@ -58,7 +60,24 @@
<style>
.unread-indicator {
color: var(--purple-2);
display: inline-flex;
justify-content: center;
align-items: center;
background-color: var(--red-2);
padding-top: 1px;
padding-bottom: 1px;
padding-left: 0.375rem;
padding-right: 0.375rem;
border-radius: 9999px;
font-size: x-small;
}
.sidebar-channel-buttons {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
flex-shrink: 0;
margin-left: auto;
}
</style>

View file

@ -103,22 +103,6 @@ class ChannelsStore extends Store {
this.value[index] = data;
this.updated();
});
gateway.subscribe(GatewayEventType.MessageCreate, ({ channel_id }) => {
const index = this.value.findIndex(e => e.id === channel_id);
if (index === -1 || !this.value[index] || selectedChannel.value.id === channel_id)
return;
this.value[index]._hasUnreads = true;
this.updated();
});
selectedChannel.subscribe(({ id }) => {
const index = this.value.findIndex(e => e.id === id);
if (index === -1 || !this.value[index] || !this.value[index]._hasUnreads)
return;
this.value[index]._hasUnreads = false;
this.updated();
});
}
}
@ -448,6 +432,31 @@ class PresenceStore extends Store {
}
}
class UnreadStore extends Store {
constructor() {
super(new Map(), "UnreadStore");
gateway.subscribe(GatewayEventType.MessageCreate, ({ channel_id: channelId }) => {
if (selectedChannel.value.id !== channelId || window.document.visibilityState !== "visible") {
this.value.set(channelId, (this.value.get(channelId) || 0) + 1);
this.updated();
}
});
selectedChannel.subscribe(({ id }) => {
this.value.delete(id);
this.updated();
});
window.document.addEventListener("visibilitychange", () => {
if (window.document.visibilityState === "visible" && selectedChannel.value) {
this.value.delete(selectedChannel.value.id);
this.updated();
}
});
}
}
export const selectedChannel = new Store({ id: -1, name: "none", creator_id: -1 }, "selectedChannel");
export const showSidebar = new Store(true, "showSidebar");
export const showPresenceSidebar = new Store(false, "showPresenceSidebar");
@ -462,14 +471,15 @@ export const userInfoStore = new UserInfoStore();
export const overlayStore = new OverlayStore();
export const typingStore = new TypingStore();
export const presenceStore = new PresenceStore();
export const unreadStore = new UnreadStore();
export const setMessageInputEvent = new Store(null, "event:setMessageInput");
export const allStores = {
selectedChannel,
showSidebar,
showPresenceSidebar,
showChannelView,
smallViewport,
showChannelView,
theme,
doAnimations,
channels,
@ -478,6 +488,9 @@ export const allStores = {
userInfoStore,
overlayStore,
typingStore,
presenceStore,
unreadStore,
setMessageInputEvent,
};
selectedChannel.watch((newSelectedChannel) => {
@ -485,3 +498,14 @@ selectedChannel.watch((newSelectedChannel) => {
setItem("state:openChannelId", newSelectedChannel.id);
}
});
unreadStore.subscribe(() => {
let totalUnreads = 0;
unreadStore.value.forEach(count => totalUnreads += count);
if (totalUnreads > 0) {
window.document.title = `(${totalUnreads}) waffle`;
} else {
window.document.title = "waffle";
}
});