Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions app/components/LeaveRoomButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import { Button } from './Button'
import { Icon } from './Icon/Icon'
import { Tooltip } from './Tooltip'

interface LeaveRoomButtonProps {}
interface LeaveRoomButtonProps {
navigateToFeedbackPage: boolean
}

export const LeaveRoomButton: FC<LeaveRoomButtonProps> = () => {
export const LeaveRoomButton: FC<LeaveRoomButtonProps> = ({
navigateToFeedbackPage,
}) => {
const navigate = useNavigate()
return (
<Tooltip content="Leave">
<Button
displayType="danger"
onClick={() => {
navigate('/')
navigate(navigateToFeedbackPage ? '/call-quality-feedback' : '/')
}}
>
<VisuallyHidden>Leave</VisuallyHidden>
Expand Down
24 changes: 22 additions & 2 deletions app/routes/_room.$roomName._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,29 @@ import { useRoomContext } from '~/hooks/useRoomContext'
import { errorMessageMap } from '~/hooks/useUserMedia'
import getUsername from '~/utils/getUsername.server'

export const loader = async ({ request }: LoaderFunctionArgs) => {
export const loader = async ({ request, context }: LoaderFunctionArgs) => {
const username = await getUsername(request)
invariant(username)
return json({ username })
return json({ username, callsAppId: context.env.CALLS_APP_ID })
}

let refreshCheckDone = false
function trackRefreshes() {
if (refreshCheckDone) return
if (typeof document === 'undefined') return

const key = `previously loaded`
const initialValue = sessionStorage.getItem(key)
const refreshed = initialValue !== null
sessionStorage.setItem(key, Date.now().toString())

if (refreshed) {
fetch(`/api/reportRefresh`, {
method: 'POST',
})
}

refreshCheckDone = true
}

export default function Lobby() {
Expand All @@ -33,6 +52,7 @@ export default function Lobby() {
const { videoStreamTrack, audioStreamTrack, audioEnabled } = userMedia
const session = useSubscribedState(peer.session$)
const sessionError = useSubscribedState(peer.sessionError$)
trackRefreshes()

const joinedUsers = new Set(
room.otherUsers.filter((u) => u.tracks.audio).map((u) => u.name)
Expand Down
4 changes: 3 additions & 1 deletion app/routes/_room.$roomName.room.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const loader = async ({ request, context }: LoaderFunctionArgs) => {
context.env.FEEDBACK_STORAGE
),
mode: context.mode,
hasDb: Boolean(context.env.DB),
})
}

Expand Down Expand Up @@ -123,6 +124,7 @@ export default function Room() {
}

function JoinedRoom({ bugReportsEnabled }: { bugReportsEnabled: boolean }) {
const { hasDb } = useLoaderData<typeof loader>()
const {
userMedia,
peer,
Expand Down Expand Up @@ -324,7 +326,7 @@ function JoinedRoom({ bugReportsEnabled }: { bugReportsEnabled: boolean }) {
className="hidden md:block"
></ParticipantsButton>
<OverflowMenu bugReportsEnabled={bugReportsEnabled} />
<LeaveRoomButton />
<LeaveRoomButton navigateToFeedbackPage={hasDb} />
</div>
</div>
<HighPacketLossWarningsToast />
Expand Down
16 changes: 16 additions & 0 deletions app/routes/api.reportRefresh.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { ActionFunctionArgs } from '@remix-run/cloudflare'
import { AnalyticsRefreshes, getDb } from 'schema'
import { RELEASE } from '~/utils/constants'
import { mode } from '~/utils/mode'

export const action = async ({ context }: ActionFunctionArgs) => {
const db = getDb(context)
if (db === null || mode === 'development')
return new Response(null, { status: 200 })

await db.insert(AnalyticsRefreshes).values({
version: RELEASE ?? 'dev',
})

return new Response(null, { status: 201 })
}
42 changes: 42 additions & 0 deletions app/routes/call-quality-feedback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { type ActionFunctionArgs } from '@remix-run/cloudflare'
import { Form } from '@remix-run/react'
import { AnalyticsSimpleCallFeedback, getDb } from 'schema'
import { Button } from '~/components/Button'
import { RELEASE } from '~/utils/constants'

const redirectToHome = new Response(null, {
status: 302,
headers: {
Location: '/',
},
})

export const action = async ({ request, context }: ActionFunctionArgs) => {
const db = getDb(context)
if (!db) return redirectToHome

const formData = await request.formData()
const experiencedIssues = formData.get('experiencedIssues') === 'true'
await db.insert(AnalyticsSimpleCallFeedback).values({
experiencedIssues: Number(experiencedIssues),
version: RELEASE ?? 'dev',
})

return redirectToHome
}

export default function SetUsername() {
return (
<div className="grid h-full gap-4 place-content-center">
<h1 className="text-3xl font-bold">Experience any issues?</h1>
<Form className="flex items-end gap-4" method="post">
<Button displayType="secondary" value="true" name="experiencedIssues">
Yes
</Button>
<Button displayType="secondary" value="false" name="experiencedIssues">
No
</Button>
</Form>
</div>
)
}
1 change: 1 addition & 0 deletions app/types/Env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export type Env = {
MAX_WEBCAM_BITRATE?: string
MAX_WEBCAM_QUALITY_LEVEL?: string
MAX_API_HISTORY?: string
DB?: D1Database
}
24 changes: 24 additions & 0 deletions drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { Config } from 'drizzle-kit'

const { LOCAL_DB_PATH, DB_ID, D1_TOKEN, CF_ACCOUNT_ID } = process.env

// Use better-sqlite driver for local development
export default LOCAL_DB_PATH
? ({
schema: './schema.ts',
dialect: 'sqlite',
dbCredentials: {
url: LOCAL_DB_PATH,
},
} satisfies Config)
: ({
schema: './schema.ts',
out: './migrations',
dialect: 'sqlite',
driver: 'd1-http',
dbCredentials: {
databaseId: DB_ID!,
token: D1_TOKEN!,
accountId: CF_ACCOUNT_ID!,
},
} satisfies Config)
16 changes: 16 additions & 0 deletions migrations/0000_warm_siren.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
CREATE TABLE `AnalyticsRefreshes` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`created` text DEFAULT CURRENT_TIMESTAMP NOT NULL,
`modified` text DEFAULT CURRENT_TIMESTAMP NOT NULL,
`deleted` text,
`version` text NOT NULL
);
--> statement-breakpoint
CREATE TABLE `AnalyticsSimpleCallFeedback` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`created` text DEFAULT CURRENT_TIMESTAMP NOT NULL,
`modified` text DEFAULT CURRENT_TIMESTAMP NOT NULL,
`deleted` text,
`version` text NOT NULL,
`experiencedIssues` integer NOT NULL
);
116 changes: 116 additions & 0 deletions migrations/meta/0000_snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"version": "6",
"dialect": "sqlite",
"id": "fe0342f9-5cae-44a5-86d3-368c43bf7869",
"prevId": "00000000-0000-0000-0000-000000000000",
"tables": {
"AnalyticsRefreshes": {
"name": "AnalyticsRefreshes",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"created": {
"name": "created",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP"
},
"modified": {
"name": "modified",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP"
},
"deleted": {
"name": "deleted",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"version": {
"name": "version",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"AnalyticsSimpleCallFeedback": {
"name": "AnalyticsSimpleCallFeedback",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"created": {
"name": "created",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP"
},
"modified": {
"name": "modified",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP"
},
"deleted": {
"name": "deleted",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"version": {
"name": "version",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"experiencedIssues": {
"name": "experiencedIssues",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}
13 changes: 13 additions & 0 deletions migrations/meta/_journal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "sqlite",
"entries": [
{
"idx": 0,
"version": "6",
"when": 1726697068248,
"tag": "0000_warm_siren",
"breakpoints": true
}
]
}
Loading