feat: implement live channel sidebar
This commit is contained in:
parent
a1bd44ffb3
commit
38f926b32f
8
package-lock.json
generated
8
package-lock.json
generated
@ -13,7 +13,7 @@
|
|||||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/svelte-fontawesome": "^0.2.0",
|
"@fortawesome/svelte-fontawesome": "^0.2.0",
|
||||||
"detect-it": "^4.0.1",
|
"detect-it": "^4.0.1",
|
||||||
"fedwave-chat-client": "^0.0.1",
|
"fedwave-chat-client": "^0.0.2",
|
||||||
"jose": "^4.11.2",
|
"jose": "^4.11.2",
|
||||||
"svrollbar": "^0.12.0"
|
"svrollbar": "^0.12.0"
|
||||||
},
|
},
|
||||||
@ -1605,9 +1605,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fedwave-chat-client": {
|
"node_modules/fedwave-chat-client": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/fedwave-chat-client/-/fedwave-chat-client-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fedwave-chat-client/-/fedwave-chat-client-0.0.2.tgz",
|
||||||
"integrity": "sha512-VP7OJELCx1V0c26QbgF+mLoMq4EyPLbrjIylAvS12hv2XVlmGJRqnrh6kCVHqSr6ZwirjlM/eLSDgJ2jWXMiyw==",
|
"integrity": "sha512-r4rvOGVEvb09LrIrWOF4D1yEd/9duxameFlnJltOZxXagPkzS5RhJagIOKO0L+37moUHOVv/cMu3Gg+YFDA0Pg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"socket.io-client": "^3.1.3"
|
"socket.io-client": "^3.1.3"
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/svelte-fontawesome": "^0.2.0",
|
"@fortawesome/svelte-fontawesome": "^0.2.0",
|
||||||
"detect-it": "^4.0.1",
|
"detect-it": "^4.0.1",
|
||||||
"fedwave-chat-client": "^0.0.1",
|
"fedwave-chat-client": "^0.0.2",
|
||||||
"jose": "^4.11.2",
|
"jose": "^4.11.2",
|
||||||
"svrollbar": "^0.12.0"
|
"svrollbar": "^0.12.0"
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
export let size: string = 'var(--avatar-size)';
|
export let size: string = 'var(--avatar-size)';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button class="avatar pa-0 border-0" style:--color="{color}" style:--size="{size}" on:click>
|
<button class="avatar pa-0 border-0 shrink-0" style:--color="{color}" style:--size="{size}" on:click>
|
||||||
<img src="{avatar}" alt="{`${username}'s avatar`}">
|
<img src="{avatar}" alt="{`${username}'s avatar`}">
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -3,19 +3,54 @@
|
|||||||
export let mobile = false;
|
export let mobile = false;
|
||||||
|
|
||||||
import { FontAwesomeIcon as FA } from '@fortawesome/svelte-fontawesome';
|
import { FontAwesomeIcon as FA } from '@fortawesome/svelte-fontawesome';
|
||||||
import { faHome, faPerson } from '@fortawesome/free-solid-svg-icons';
|
import { faHome, faPerson, faCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
import { channels, room } from './chat';
|
||||||
|
import Avatar from './Avatar.svelte';
|
||||||
|
|
||||||
|
let selected = "channels";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="sidebar h-100vh d-flex" bind:clientWidth class:mobile="{mobile}">
|
<div class="sidebar h-100vh d-flex" bind:clientWidth class:mobile="{mobile}">
|
||||||
<div class="overlay" />
|
<div class="overlay" />
|
||||||
<div class="servers d-flex col">
|
<div class="servers shrink-0 d-flex col">
|
||||||
<button class="selected">
|
<button
|
||||||
|
class:selected="{selected === 'whispers'}"
|
||||||
|
on:click="{() => selected = 'whispers'}">
|
||||||
<FA size="2x" icon="{faPerson}" />
|
<FA size="2x" icon="{faPerson}" />
|
||||||
</button>
|
</button>
|
||||||
<button>
|
<button
|
||||||
|
class:selected="{selected === 'channels'}"
|
||||||
|
on:click="{() => selected = 'channels'}">
|
||||||
<FA size="2x" icon="{faHome}" />
|
<FA size="2x" icon="{faHome}" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{#if selected === 'whispers'}
|
||||||
|
<div class="whispers grow-1 mw-0"></div>
|
||||||
|
{:else if selected === 'channels'}
|
||||||
|
<div class="channels grow-1 d-flex col mw-0 py-8">
|
||||||
|
{#each $channels.sort((a, b) => b.viewCount - a.viewCount) as channel}
|
||||||
|
<a href="{channel.name}"
|
||||||
|
class="channel d-flex align-center mb-8 mx-8 pa-6 radius-12"
|
||||||
|
class:selected="{$room === channel.name.toLowerCase()}">
|
||||||
|
<Avatar username="{channel.name}"
|
||||||
|
avatar="{channel.avatar}" />
|
||||||
|
<div class="channel-name mw-0 ellipsis ml-8">
|
||||||
|
{channel.name}
|
||||||
|
</div>
|
||||||
|
{#if false && channel.live}
|
||||||
|
<div class="channel-live ml-2 mt-8 color-red">
|
||||||
|
<FA icon="{faCircle}" size="xs" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="spacer"/>
|
||||||
|
<div class="channel-viewers px-6 py-2 radius-pill">
|
||||||
|
{channel.viewCount + channel.viewCountRTC}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -48,6 +83,15 @@
|
|||||||
pointer-events: var(--should-display);
|
pointer-events: var(--should-display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.channel-live {
|
||||||
|
align-self: normal;
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channel-viewers {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
.servers {
|
.servers {
|
||||||
width: var(--sidebar-server-select-width);
|
width: var(--sidebar-server-select-width);
|
||||||
background-color: var(--base-500);
|
background-color: var(--base-500);
|
||||||
@ -75,6 +119,29 @@
|
|||||||
background-color: var(--base-700);
|
background-color: var(--base-700);
|
||||||
color: var(--base-300);
|
color: var(--base-300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: var(--base-400);
|
||||||
|
color: var(--base-700);
|
||||||
|
|
||||||
|
transition-property: background-color, color, border-radius;
|
||||||
|
transition-duration: 80ms;
|
||||||
|
transition-timing-function: ease-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--base-300);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: var(--base-700);
|
||||||
|
color: var(--base-300);
|
||||||
|
|
||||||
|
& .channel-viewers {
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -97,10 +97,46 @@ globalMode.subscribe((v) => {
|
|||||||
|
|
||||||
export const shouldTweet = writable(false);
|
export const shouldTweet = writable(false);
|
||||||
|
|
||||||
|
export type User = {
|
||||||
|
color: string;
|
||||||
|
page: string;
|
||||||
|
username: string;
|
||||||
|
unum: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Channel = Record<
|
||||||
|
| 'avatar'
|
||||||
|
| 'channel'
|
||||||
|
| 'cover'
|
||||||
|
| 'desc'
|
||||||
|
| 'name'
|
||||||
|
| 'src'
|
||||||
|
| 'thumbnail'
|
||||||
|
| 'title'
|
||||||
|
| 'type'
|
||||||
|
| 'url'
|
||||||
|
| 'user',
|
||||||
|
string
|
||||||
|
> &
|
||||||
|
Record<'live' | 'nsfw', boolean> &
|
||||||
|
Record<'viewCount' | 'viewCountRTC', number> & {
|
||||||
|
users: Record<string, { watching: string[]; data: User }>[];
|
||||||
|
};
|
||||||
|
|
||||||
|
let setChannels: Subscriber<any> | undefined;
|
||||||
|
export const channels = readable<Channel[]>(chat.channelViewers, (setf) => {
|
||||||
|
setChannels = setf;
|
||||||
|
return () => {
|
||||||
|
setChannels = undefined;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
chat.onUpdateUsernames = (vs) => setChannels?.(vs) as any;
|
||||||
|
|
||||||
// Essentially a shared_ptr idiom. When nobody is subscribed to this, the chat
|
// Essentially a shared_ptr idiom. When nobody is subscribed to this, the chat
|
||||||
// d/c's.
|
// d/c's.
|
||||||
export const chat_lock = readable(null, () => {
|
export const chat_lock = readable(null, () => {
|
||||||
const release_connected = connected.subscribe(() => {});
|
const release_connected = connected.subscribe(() => {});
|
||||||
|
const release_channels = channels.subscribe(() => {});
|
||||||
|
|
||||||
const creds = get(credentials);
|
const creds = get(credentials);
|
||||||
|
|
||||||
@ -111,6 +147,7 @@ export const chat_lock = readable(null, () => {
|
|||||||
setConnected?.(false);
|
setConnected?.(false);
|
||||||
|
|
||||||
release_connected();
|
release_connected();
|
||||||
|
release_channels();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user