diff --git a/app/reports/page-content.tsx b/app/reports/page-content.tsx
index 186838f4..7161a7aa 100644
--- a/app/reports/page-content.tsx
+++ b/app/reports/page-content.tsx
@@ -1,5 +1,5 @@
'use client'
-import { useContext, useCallback, Suspense } from 'react'
+import { useContext, useCallback, Suspense, useEffect } from 'react'
import {
ReadonlyURLSearchParams,
usePathname,
@@ -22,6 +22,7 @@ import { AuthContext } from '@/shell/AuthContext'
import { ButtonGroup } from '@/common/buttons'
import { useFluentReportSearch } from '@/reports/useFluentReportSearch'
import { SubjectTable } from 'components/subject/table'
+import { useTitle } from 'react-use'
const TABS = [
{
@@ -48,6 +49,42 @@ const TABS = [
{ key: 'all', name: 'All', href: '/reports' },
]
+const buildPageTitle = ({
+ currentTab,
+ takendown,
+ includeMuted,
+ appealed,
+}: {
+ currentTab: string
+ takendown: boolean
+ includeMuted: boolean
+ appealed: boolean
+}) => {
+ const titleFromTab =
+ currentTab === 'all'
+ ? `All subjects`
+ : `${currentTab[0].toUpperCase()}${currentTab.slice(1)}`
+ const additionalFragments: string[] = []
+
+ if (takendown) {
+ additionalFragments.push('Taken Down')
+ }
+
+ if (includeMuted) {
+ additionalFragments.push('Include Muted')
+ }
+
+ if (appealed) {
+ additionalFragments.push('Appealed')
+ }
+
+ const additionalTitle = additionalFragments.length
+ ? ` (${additionalFragments.join(', ')})`
+ : ''
+ const title = `Queue - ${titleFromTab}${additionalTitle}`
+ return title
+}
+
const ResolvedFilters = () => {
const router = useRouter()
const pathname = usePathname()
@@ -197,6 +234,14 @@ export const ReportsPageContent = () => {
),
)
+ const pageTitle = buildPageTitle({
+ currentTab,
+ takendown,
+ includeMuted,
+ appealed,
+ })
+ useTitle(pageTitle)
+
return (
<>
diff --git a/app/repositories/[id]/[...record]/page.tsx b/app/repositories/[id]/[...record]/page.tsx
index 55ee3694..ad81ea5a 100644
--- a/app/repositories/[id]/[...record]/page.tsx
+++ b/app/repositories/[id]/[...record]/page.tsx
@@ -15,6 +15,36 @@ import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { ModActionPanelQuick } from 'app/actions/ModActionPanel/QuickAction'
import { emitEvent } from '@/mod-event/helpers/emitEvent'
import { useEffect } from 'react'
+import { useTitle } from 'react-use'
+
+const buildPageTitle = ({
+ handle,
+ collection,
+ rkey,
+}: {
+ handle?: string
+ collection?: string
+ rkey?: string
+}) => {
+ let title = `Record Details`
+
+ if (collection) {
+ const titleFromCollection = collection.split('.').pop()
+ if (titleFromCollection) {
+ title =
+ titleFromCollection[0].toUpperCase() + titleFromCollection.slice(1)
+ }
+ }
+
+ if (handle) {
+ title += ` - ${handle}`
+ }
+
+ if (rkey) {
+ title += ` - ${rkey}`
+ }
+ return title
+}
export default function Record({
params,
@@ -116,6 +146,13 @@ export default function Record({
}
}, [data, reportUri])
+ const pageTitle = buildPageTitle({
+ handle: data?.record?.repo.handle,
+ rkey,
+ collection,
+ })
+ useTitle(pageTitle)
+
if (error) {
return
}
diff --git a/app/repositories/[id]/page-content.tsx b/app/repositories/[id]/page-content.tsx
index abfe7c93..2a8f29b2 100644
--- a/app/repositories/[id]/page-content.tsx
+++ b/app/repositories/[id]/page-content.tsx
@@ -6,7 +6,29 @@ import { ComAtprotoAdminEmitModerationEvent } from '@atproto/api'
import { ModActionPanelQuick } from 'app/actions/ModActionPanel/QuickAction'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { emitEvent } from '@/mod-event/helpers/emitEvent'
+import { useTitle } from 'react-use'
+const buildPageTitle = ({
+ handle,
+ tab,
+}: {
+ handle: string
+ tab: string | null
+}) => {
+ let title = `Repository Details`
+ const titleFragments: string[] = [title]
+ const titleFromTab = tab ? tab[0].toUpperCase() + tab.slice(1) : ''
+
+ if (titleFromTab) {
+ titleFragments.unshift(titleFromTab)
+ }
+
+ if (handle) {
+ titleFragments.unshift(handle)
+ }
+
+ return titleFragments.join(' - ')
+}
export function RepositoryViewPageContent({ id }: { id: string }) {
const {
error,
@@ -27,6 +49,13 @@ export function RepositoryViewPageContent({ id }: { id: string }) {
}
router.push((pathname ?? '') + '?' + newParams.toString())
}
+ const tab = searchParams.get('tab')
+
+ const pageTitle = buildPageTitle({
+ handle: profile?.handle || repo?.handle || id,
+ tab,
+ })
+ useTitle(pageTitle)
return (
<>
diff --git a/app/repositories/page-content.tsx b/app/repositories/page-content.tsx
index 9de8d7cf..11d6bb39 100644
--- a/app/repositories/page-content.tsx
+++ b/app/repositories/page-content.tsx
@@ -3,6 +3,8 @@ import { RepositoriesTable } from '@/repositories/RepositoriesTable'
import { useSearchParams } from 'next/navigation'
import { useInfiniteQuery } from '@tanstack/react-query'
import client from '@/lib/client'
+import { useEffect } from 'react'
+import { useTitle } from 'react-use'
export default function RepositoriesListPage() {
const params = useSearchParams()
@@ -22,6 +24,14 @@ export default function RepositoriesListPage() {
},
getNextPageParam: (lastPage) => lastPage.cursor,
})
+
+ let pageTitle = `Repositories`
+ if (term) {
+ pageTitle += ` - ${term}`
+ }
+
+ useTitle(pageTitle)
+
const repos = data?.pages.flatMap((page) => page.repos) ?? []
return (
<>
diff --git a/app/subject-status/page.tsx b/app/subject-status/page.tsx
index 9c0ace5a..86247abe 100644
--- a/app/subject-status/page.tsx
+++ b/app/subject-status/page.tsx
@@ -4,6 +4,8 @@ import client from '@/lib/client'
import { Loading, LoadingFailed } from '@/common/Loader'
import { useSearchParams } from 'next/navigation'
import { SubjectStatusView } from '@/subject/StatusView'
+import { useEffect } from 'react'
+import { useTitle } from 'react-use'
export default function SubjectStatus() {
const params = useSearchParams()
@@ -21,6 +23,14 @@ export default function SubjectStatus() {
},
})
+ let pageTitle = `Subject Status`
+
+ if (data?.subjectStatuses[0]) {
+ pageTitle = `${data.subjectStatuses[0].subjectRepoHandle} - ${pageTitle}`
+ }
+
+ useTitle(pageTitle)
+
if (status === 'loading') {
return
}
diff --git a/app/surprise-me/page.tsx b/app/surprise-me/page.tsx
index cb74bc46..11892276 100644
--- a/app/surprise-me/page.tsx
+++ b/app/surprise-me/page.tsx
@@ -1,6 +1,6 @@
'use client'
-import { useState } from 'react'
-import { useInterval } from 'react-use'
+import { useEffect, useState } from 'react'
+import { useInterval, useTitle } from 'react-use'
import dynamic from 'next/dynamic'
// The game package uses some client only code so we can't really import and use it here because that breaks SSR for some reason
@@ -38,6 +38,8 @@ const Timer = () => {
// Right now, we only serve the tetris game here, in the future, we want to rotate
// between a few games/fun activities which is why it's named "surprise me"
export default function SurpriseMePage() {
+ useTitle(`Take a break!`)
+
return (
<>
{/* This is valid jsx but because of a known bug, typescript is confused */}
diff --git a/components/shell/LoginModal.tsx b/components/shell/LoginModal.tsx
index 92986d0e..d165b05e 100644
--- a/components/shell/LoginModal.tsx
+++ b/components/shell/LoginModal.tsx
@@ -43,6 +43,13 @@ export function LoginModal() {
}
}, [])
+ useEffect(() => {
+ const title = `Ozone - Authenticate`
+ if (!isLoggedIn) {
+ document.title = title
+ }
+ }, [isLoggedIn])
+
const onSubmit = async (e: FormEvent) => {
e.preventDefault()
e.stopPropagation()