From 62ac7330fcd94c6a80baf1820ce15ef6dc4ba4b6 Mon Sep 17 00:00:00 2001
From: Nolan Lawson <nolan@nolanlawson.com>
Date: Mon, 12 Nov 2018 18:28:43 -0800
Subject: [PATCH] feat(title): add dynamic document title (#645)

* feat(title): add dynamic document title

fixes #490 and #643

* fix code style
---
 routes/_components/Title.html                 | 24 +++++++++++++++++++
 routes/accounts/[accountId].html              |  6 ++---
 routes/accounts/[accountId]/followers.html    |  6 ++---
 routes/accounts/[accountId]/follows.html      |  6 ++---
 routes/blocked.html                           |  6 ++---
 routes/community/index.html                   |  6 ++---
 routes/favorites.html                         |  6 ++---
 routes/federated.html                         |  6 ++---
 routes/index.html                             |  6 ++---
 routes/lists/[listId].html                    |  6 ++---
 routes/local.html                             |  6 ++---
 routes/muted.html                             |  6 ++---
 routes/notifications.html                     |  6 ++---
 routes/pinned.html                            |  6 ++---
 routes/requests.html                          |  6 ++---
 routes/search.html                            |  6 ++---
 routes/settings/about.html                    |  6 ++---
 routes/settings/general.html                  |  6 ++---
 routes/settings/index.html                    |  6 ++---
 routes/settings/instances/[instanceName].html |  6 ++---
 routes/settings/instances/add.html            |  6 ++---
 routes/settings/instances/index.html          |  6 ++---
 routes/statuses/[statusId]/favorites.html     |  6 ++---
 routes/statuses/[statusId]/index.html         |  6 ++---
 routes/statuses/[statusId]/reblogs.html       |  6 ++---
 routes/tags/[tagName].html                    |  6 ++---
 tests/spec/102-notifications.js               |  6 ++++-
 tests/utils.js                                |  2 ++
 28 files changed, 106 insertions(+), 76 deletions(-)
 create mode 100644 routes/_components/Title.html

diff --git a/routes/_components/Title.html b/routes/_components/Title.html
new file mode 100644
index 0000000..5d6104f
--- /dev/null
+++ b/routes/_components/Title.html
@@ -0,0 +1,24 @@
+<svelte:head>
+  <title>{instanceIndicator} · {name}{notificationsIndicator}</title>
+</svelte:head>
+<script>
+  import { store } from '../_store/store'
+
+  export default {
+    data: () => ({
+      settingsPage: false
+    }),
+    store: () => store,
+    computed: {
+      instanceIndicator: ({ $isUserLoggedIn, $currentInstance, settingsPage }) => (
+        // If the user is not logged in, or if they're on a settings page (which
+        // is more general than instance-specific), of if this is server-rendered, then
+        // show "Pinafore". Otherwise show the instance name.
+        `${($isUserLoggedIn && !settingsPage && $currentInstance) ? $currentInstance : 'Pinafore'}`
+      ),
+      notificationsIndicator: ({ $hasNotifications, $numberOfNotifications }) => (
+        $hasNotifications ? ` (${$numberOfNotifications})` : ''
+      )
+    }
+  }
+</script>
\ No newline at end of file
diff --git a/routes/accounts/[accountId].html b/routes/accounts/[accountId].html
index 4838ffc..ac63c04 100644
--- a/routes/accounts/[accountId].html
+++ b/routes/accounts/[accountId].html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Profile</title>
-</svelte:head>
+<Title name="Profile" />
 <Layout page='tags'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../_components/Layout.html'
+  import Title from '../_components/Title.html'
   import LazyPage from '../_components/LazyPage.html'
   import pageComponent from '../_pages/accounts/[accountId].html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/accounts/[accountId]/followers.html b/routes/accounts/[accountId]/followers.html
index 7fd5dd2..2f8b3cb 100644
--- a/routes/accounts/[accountId]/followers.html
+++ b/routes/accounts/[accountId]/followers.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Followers</title>
-</svelte:head>
+<Title name="Followers" />
 <Layout page='tags'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../../_components/Layout.html'
+  import Title from '../../_components/Title.html'
   import LazyPage from '../../_components/LazyPage.html'
   import pageComponent from '../../_pages/accounts/[accountId]/followers.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/accounts/[accountId]/follows.html b/routes/accounts/[accountId]/follows.html
index 058040b..a218965 100644
--- a/routes/accounts/[accountId]/follows.html
+++ b/routes/accounts/[accountId]/follows.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Follows</title>
-</svelte:head>
+<Title name="Follows" />
 <Layout page='tags'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../../_components/Layout.html'
+  import Title from '../../_components/Title.html'
   import LazyPage from '../../_components/LazyPage.html'
   import pageComponent from '../../_pages/accounts/[accountId]/follows.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/blocked.html b/routes/blocked.html
index b309409..8e0d8ea 100644
--- a/routes/blocked.html
+++ b/routes/blocked.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Blocked users</title>
-</svelte:head>
+<Title name="Blocked users" />
 <Layout page='blocked'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/blocked.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/community/index.html b/routes/community/index.html
index 44df7e5..c4dd49e 100644
--- a/routes/community/index.html
+++ b/routes/community/index.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Community</title>
-</svelte:head>
+<Title name="Community" />
 <Layout page='community'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../_components/Layout.html'
+  import Title from '../_components/Title.html'
   import LazyPage from '../_components/LazyPage.html'
   import pageComponent from '../_pages/community/index.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/favorites.html b/routes/favorites.html
index f0fceac..d81220c 100644
--- a/routes/favorites.html
+++ b/routes/favorites.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Favorites</title>
-</svelte:head>
+<Title name="Favorites" />
 <Layout page='favorites'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/favorites.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/federated.html b/routes/federated.html
index e280465..efd2d81 100644
--- a/routes/federated.html
+++ b/routes/federated.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Federated</title>
-</svelte:head>
+<Title name="Federated" />
 <Layout page='federated'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/federated.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/index.html b/routes/index.html
index 2767b48..c5b5b25 100644
--- a/routes/index.html
+++ b/routes/index.html
@@ -1,17 +1,17 @@
-<svelte:head>
-	<title>Pinafore – Home</title>
-</svelte:head>
+<Title name="Home" />
 <Layout page='home'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/index.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/lists/[listId].html b/routes/lists/[listId].html
index 3511a93..28b371c 100644
--- a/routes/lists/[listId].html
+++ b/routes/lists/[listId].html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – List</title>
-</svelte:head>
+<Title name="List" />
 <Layout page='lists/{params.listId}'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../_components/Layout.html'
+  import Title from '../_components/Title.html'
   import LazyPage from '../_components/LazyPage.html'
   import pageComponent from '../_pages/lists/[listId].html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/local.html b/routes/local.html
index 97c817e..31fa392 100644
--- a/routes/local.html
+++ b/routes/local.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Local</title>
-</svelte:head>
+<Title name="Local" />
 <Layout page='local'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/local.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/muted.html b/routes/muted.html
index 84a3f55..45f78f1 100644
--- a/routes/muted.html
+++ b/routes/muted.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Muted users</title>
-</svelte:head>
+<Title name="Muted users" />
 <Layout page='muted'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/muted.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/notifications.html b/routes/notifications.html
index ace6751..bed5cd0 100644
--- a/routes/notifications.html
+++ b/routes/notifications.html
@@ -1,17 +1,17 @@
-<svelte:head>
-	<title>Pinafore – Notifications</title>
-</svelte:head>
+<Title name="Notifications" />
 <Layout page='notifications'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/notifications.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/pinned.html b/routes/pinned.html
index 20ddffa..268e1a2 100644
--- a/routes/pinned.html
+++ b/routes/pinned.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Pinned toots</title>
-</svelte:head>
+<Title name="Pinned toots" />
 <Layout page='pinned'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/pinned.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/requests.html b/routes/requests.html
index 0736dc5..c400588 100644
--- a/routes/requests.html
+++ b/routes/requests.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Follow requests</title>
-</svelte:head>
+<Title name="Follow requests" />
 <Layout page='muted'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/requests.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/search.html b/routes/search.html
index 843d7d1..f17de71 100644
--- a/routes/search.html
+++ b/routes/search.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Search</title>
-</svelte:head>
+<Title name="Search" />
 <Layout page='search'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from './_components/Layout.html'
+  import Title from './_components/Title.html'
   import LazyPage from './_components/LazyPage.html'
   import pageComponent from './_pages/search.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/settings/about.html b/routes/settings/about.html
index 6bef90b..0524874 100644
--- a/routes/settings/about.html
+++ b/routes/settings/about.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – About</title>
-</svelte:head>
+<Title name="About" settingsPage={true} />
 <Layout page='settings'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../_components/Layout.html'
+  import Title from '../_components/Title.html'
   import LazyPage from '../_components/LazyPage.html'
   import pageComponent from '../_pages/settings/about.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/settings/general.html b/routes/settings/general.html
index d2036e0..e75e099 100644
--- a/routes/settings/general.html
+++ b/routes/settings/general.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – General Settings</title>
-</svelte:head>
+<Title name="General Settings" settingsPage={true} />
 <Layout page='settings'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../_components/Layout.html'
+  import Title from '../_components/Title.html'
   import LazyPage from '../_components/LazyPage.html'
   import pageComponent from '../_pages/settings/general.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/settings/index.html b/routes/settings/index.html
index 4a9cc30..9cbdaa8 100644
--- a/routes/settings/index.html
+++ b/routes/settings/index.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Settings</title>
-</svelte:head>
+<Title name="Settings" settingsPage={true} />
 <Layout page='settings'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../_components/Layout.html'
+  import Title from '../_components/Title.html'
   import LazyPage from '../_components/LazyPage.html'
   import pageComponent from '../_pages/settings/index.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/settings/instances/[instanceName].html b/routes/settings/instances/[instanceName].html
index 4207e1d..ea9d035 100644
--- a/routes/settings/instances/[instanceName].html
+++ b/routes/settings/instances/[instanceName].html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Instance</title>
-</svelte:head>
+<Title name="{params.instanceName}" settingsPage={true} />
 <Layout page='settings'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../../_components/Layout.html'
+  import Title from '../../_components/Title.html'
   import LazyPage from '../../_components/LazyPage.html'
   import pageComponent from '../../_pages/settings/instances/[instanceName].html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/settings/instances/add.html b/routes/settings/instances/add.html
index a786a15..376b5e2 100644
--- a/routes/settings/instances/add.html
+++ b/routes/settings/instances/add.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Add instance</title>
-</svelte:head>
+<Title name="Add instance" settingsPage={true} />
 <Layout page='settings'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../../_components/Layout.html'
+  import Title from '../../_components/Title.html'
   import LazyPage from '../../_components/LazyPage.html'
   import pageComponent from '../../_pages/settings/instances/add.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/settings/instances/index.html b/routes/settings/instances/index.html
index 1584745..ea8b5a3 100644
--- a/routes/settings/instances/index.html
+++ b/routes/settings/instances/index.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Instances</title>
-</svelte:head>
+<Title name="Instances" settingsPage={true} />
 <Layout page='settings'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../../_components/Layout.html'
+  import Title from '../../_components/Title.html'
   import LazyPage from '../../_components/LazyPage.html'
   import pageComponent from '../../_pages/settings/instances/index.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/statuses/[statusId]/favorites.html b/routes/statuses/[statusId]/favorites.html
index 7ce3f41..7d717e2 100644
--- a/routes/statuses/[statusId]/favorites.html
+++ b/routes/statuses/[statusId]/favorites.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Favorites</title>
-</svelte:head>
+<Title name="Favorites" />
 <Layout page='favorites'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../../_components/Layout.html'
+  import Title from '../../_components/Title.html'
   import LazyPage from '../../_components/LazyPage.html'
   import pageComponent from '../../_pages/statuses/[statusId]/favorites.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/statuses/[statusId]/index.html b/routes/statuses/[statusId]/index.html
index 28824f4..172e94e 100644
--- a/routes/statuses/[statusId]/index.html
+++ b/routes/statuses/[statusId]/index.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Status</title>
-</svelte:head>
+<Title name="Status" />
 <Layout page='statuses' >
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../../_components/Layout.html'
+  import Title from '../../_components/Title.html'
   import LazyPage from '../../_components/LazyPage.html'
   import pageComponent from '../../_pages/statuses/[statusId]/index.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/statuses/[statusId]/reblogs.html b/routes/statuses/[statusId]/reblogs.html
index 31f87b0..cae3729 100644
--- a/routes/statuses/[statusId]/reblogs.html
+++ b/routes/statuses/[statusId]/reblogs.html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Reblogs</title>
-</svelte:head>
+<Title name="Reblogs" />
 <Layout page='reblogs'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../../_components/Layout.html'
+  import Title from '../../_components/Title.html'
   import LazyPage from '../../_components/LazyPage.html'
   import pageComponent from '../../_pages/statuses/[statusId]/reblogs.html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/routes/tags/[tagName].html b/routes/tags/[tagName].html
index bbecaf0..10002db 100644
--- a/routes/tags/[tagName].html
+++ b/routes/tags/[tagName].html
@@ -1,17 +1,17 @@
-<svelte:head>
-  <title>Pinafore – Hashtag</title>
-</svelte:head>
+<Title name="Hashtag" />
 <Layout page='tags'>
   <LazyPage {pageComponent} {params} />
 </Layout>
 <script>
   import Layout from '../_components/Layout.html'
+  import Title from '../_components/Title.html'
   import LazyPage from '../_components/LazyPage.html'
   import pageComponent from '../_pages/tags/[tagName].html'
 
   export default {
     components: {
       Layout,
+      Title,
       LazyPage
     },
     data: () => ({
diff --git a/tests/spec/102-notifications.js b/tests/spec/102-notifications.js
index 2921135..18719c8 100644
--- a/tests/spec/102-notifications.js
+++ b/tests/spec/102-notifications.js
@@ -1,6 +1,6 @@
 import { loginAsFoobar } from '../roles'
 import {
-  getNthStatus, getUrl, homeNavButton, notificationsNavButton
+  getNthStatus, getTitleText, getUrl, homeNavButton, notificationsNavButton
 } from '../utils'
 import { favoriteStatusAs, postAs } from '../serverActions'
 
@@ -12,15 +12,19 @@ test('shows unread notifications', async t => {
   await loginAsFoobar(t)
   await t
     .expect(notificationsNavButton.getAttribute('aria-label')).eql('Notifications')
+    .expect(getTitleText()).eql('localhost:3000 · Home')
   await favoriteStatusAs('admin', id)
   await t
     .expect(notificationsNavButton.getAttribute('aria-label')).eql('Notifications (1)')
+    .expect(getTitleText()).eql('localhost:3000 · Home (1)')
     .click(notificationsNavButton)
     .expect(getUrl()).contains('/notifications')
     .expect(notificationsNavButton.getAttribute('aria-label')).eql('Notifications (current page)')
+    .expect(getTitleText()).eql('localhost:3000 · Notifications')
     .expect(getNthStatus(0).innerText).contains('somebody please favorite this to validate me')
     .expect(getNthStatus(0).innerText).match(/admin\s+favorited your status/)
   await t
     .click(homeNavButton)
     .expect(notificationsNavButton.getAttribute('aria-label')).eql('Notifications')
+    .expect(getTitleText()).eql('localhost:3000 · Home')
 })
diff --git a/tests/utils.js b/tests/utils.js
index ef863cf..dad5872 100644
--- a/tests/utils.js
+++ b/tests/utils.js
@@ -79,6 +79,8 @@ export const getActiveElementInsideNthStatus = exec(() => {
   return ''
 })
 
+export const getTitleText = exec(() => document.head.querySelector('title').innerHTML)
+
 export const goBack = exec(() => window.history.back())
 
 export const forceOffline = exec(() => window.__forceOnline(false))