Skip to content

Commit

Permalink
feat: add presence indicator (#1327)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe authored Nov 10, 2023
1 parent 78cc730 commit 6734a7b
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 8 deletions.
6 changes: 3 additions & 3 deletions budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
"resourceSizes": [
{
"resourceType": "document",
"budget": 7.8
"budget": 8
},
{
"resourceType": "script",
"budget": 57.5
"budget": 62
},
{
"resourceType": "stylesheet",
"budget": 7.8
"budget": 8.2
}
],
"resourceCounts": [
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"nuxt": "3.8.1",
"nuxt-time": "^0.1.1",
"partykit": "0.0.30",
"partysocket": "^0.0.12",
"pathe": "^1.1.1",
"postcss-nesting": "^12.0.1",
"remark": "^14.0.3",
Expand Down
12 changes: 8 additions & 4 deletions partykit/server.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import type { PartyKitServer, Party } from 'partykit/server'

export default {
async onConnect(ws, room) {
async onConnect(ws, party) {
// 1. Handle live voting in slide deck
const set = async (val: number) => {
await room.storage.put('count', val)
await party.storage.put('count', val)
ws.send(`count:${val}`)
}

ws.send(`count:${await get(room)}`)
ws.send(`count:${await get(party)}`)
ws.addEventListener('message', async ({ data }) => {
if (data === 'vote') {
await set((await get(room)) + 1)
await set((await get(party)) + 1)
}
if (data === 'clear') {
await set(0)
}
})

// 2. Tell connectees how many people are viewing the site
party.broadcast(`connections:${[...party.getConnections()].length}`)
},
async onRequest(request, room) {
if (request.method === 'GET') {
Expand Down
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
>
<LayoutTheSiteHeader />
<NuxtPage />
<LayoutThePresenceIndicator />
<LayoutTheSiteFooter />
</div>
</template>
Expand Down
70 changes: 70 additions & 0 deletions src/components/layout/ThePresenceIndicator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<template>
<div
class="fixed bottom-[1rem] right-[1rem] p-1 bg-background rounded-full overflow-hidden z-10"
>
<component
:is="status === 'live' ? 'a' : 'span'"
:href="status === 'live' ? 'https://twitch.tv/danielroe' : null"
:target="status === 'live' ? '_blank' : null"
class="pl-2 pr-2 py-1 rounded-full flex flex-row items-center shadow tracking-none border-1 text-xs transition-opacity"
:class="colorSet[status].badge"
:title="
status === 'live' ? 'Live now on Twitch' : `${count} viewers on website`
"
>
<span
class="rounded-full inline-block h-2 w-2 animate-pulse shadow"
:class="colorSet[status].block"
/>
<span
class="ml-2 tabular-nums flex flex-row items-center gap-1 font-bold uppercase tracking-wider"
>
<template v-if="status === 'live'"> live now </template>
<template v-else>
{{ count || '&nbsp;' }}
<span v-if="count" class="sr-only">viewers on website</span>
</template>
</span>
&ZeroWidthSpace;
</component>
</div>
</template>

<script setup lang="ts">
import PartySocket from 'partysocket'
const colorSet = {
live: {
badge:
'light:border-red-800 dark:border-red-400 light:shadow-red-400 dark:shadow-red-800 text-red-400 light:text-red-800',
block: 'light:bg-red-800 dark:bg-red dark:shadow-red-800',
},
default: {
badge:
'light:border-green-800 dark:border-green-400 light:shadow-green-400 dark:shadow-green-800 opacity-50 hover:opacity-100 focus:opacity-100',
block: 'light:bg-green-800 dark:bg-green dark:shadow-green-800',
},
}
const status = ref<keyof typeof colorSet>('default')
const count = ref<null | number>(null)
if (import.meta.client) {
const partySocket = new PartySocket({
host: import.meta.dev ? 'localhost:1999' : 'v.danielroe.partykit.dev',
room: 'site',
})
partySocket.onmessage = evt => {
const data = evt.data as string
const [type, value] = data.split(':')
if (type === 'connections') {
count.value = parseInt(value)
}
}
onBeforeUnmount(() => partySocket.close())
onDeactivated(() => partySocket.close())
onActivated(() => partySocket.reconnect())
}
</script>
2 changes: 1 addition & 1 deletion test/unit/bundle.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('project sizes', () => {
stats.client = await analyzeSizes('**/*.js', publicDir)
expect
.soft(roundToKilobytes(stats.client.totalBytes))
.toMatchInlineSnapshot('"197k"')
.toMatchInlineSnapshot('"208k"')
expect.soft(stats.client.files.map(f => f.replace(/\..*\.js/, '.js')))
.toMatchInlineSnapshot(`
[
Expand Down

1 comment on commit 6734a7b

@vercel
Copy link

@vercel vercel bot commented on 6734a7b Nov 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.