From 13fc2612ae388dec682829ae2b6211bb3cb8ccb3 Mon Sep 17 00:00:00 2001
From: Wyatt Benno <wyattbenno@gmail.com>
Date: Thu, 5 Dec 2019 11:48:37 +0900
Subject: [PATCH] Change 403 messaging

---
 src/components/timeline/timeline.js           |  7 ++++++-
 src/components/timeline/timeline.vue          | 19 ++++++++++++++++---
 src/i18n/en.json                              |  2 ++
 src/modules/statuses.js                       |  7 +++++++
 src/services/api/api.service.js               | 10 ++++++++--
 .../timeline_fetcher.service.js               |  6 ++++++
 6 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js
index 27a9a55e..6086336c 100644
--- a/src/components/timeline/timeline.js
+++ b/src/components/timeline/timeline.js
@@ -36,7 +36,12 @@ const Timeline = {
     }
   },
   computed: {
-    timelineError () { return this.$store.state.statuses.error },
+    timelineError () {
+      return this.$store.state.statuses.error
+    },
+    error403 () {
+      return this.$store.state.statuses.error403
+    },
     newStatusCount () {
       return this.timeline.newStatusCount
     },
diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue
index 93f6f570..1c45d0f6 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -11,15 +11,22 @@
       >
         {{ $t('timeline.error_fetching') }}
       </div>
+      <div
+        v-else-if="error403"
+        class="loadmore-error alert error"
+        @click.prevent
+      >
+        {{ $t('timeline.error_403') }}
+      </div>
       <button
-        v-if="timeline.newStatusCount > 0 && !timelineError"
+        v-if="timeline.newStatusCount > 0 && !timelineError && !error403"
         class="loadmore-button"
         @click.prevent="showNewStatuses"
       >
         {{ $t('timeline.show_new') }}{{ newStatusCountStr }}
       </button>
       <div
-        v-if="!timeline.newStatusCount > 0 && !timelineError"
+        v-if="!timeline.newStatusCount > 0 && !timelineError && !error403"
         class="loadmore-text faint"
         @click.prevent
       >
@@ -67,12 +74,18 @@
         {{ $t('timeline.no_more_statuses') }}
       </div>
       <a
-        v-else-if="!timeline.loading"
+        v-else-if="!timeline.loading && !error403"
         href="#"
         @click.prevent="fetchOlderStatuses()"
       >
         <div class="new-status-notification text-center panel-footer">{{ $t('timeline.load_older') }}</div>
       </a>
+      <a
+        v-else-if="error403"
+        href="#"
+      >
+        <div class="new-status-notification text-center panel-footer">{{ $t('timeline.error_403_message') }}</div>
+      </a>
       <div
         v-else
         class="new-status-notification text-center panel-footer"
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 85146ef5..c203e156 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -535,6 +535,8 @@
     "collapse": "Collapse",
     "conversation": "Conversation",
     "error_fetching": "Error fetching updates",
+    "error_403": "This timeline is not public.",
+    "error_403_message": "Please sign in.",
     "load_older": "Load older statuses",
     "no_retweet_hint": "Post is marked as followers-only or direct and cannot be repeated",
     "repeated": "repeated",
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index f11ffdcd..d0e871c8 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -38,6 +38,7 @@ export const defaultState = () => ({
   notifications: emptyNotifications(),
   favorites: new Set(),
   error: false,
+  error403: false,
   timelines: {
     mentions: emptyTl(),
     public: emptyTl(),
@@ -479,6 +480,9 @@ export const mutations = {
   setError (state, { value }) {
     state.error = value
   },
+  set403Error (state, { value }) {
+    state.error403 = value
+  },
   setNotificationsLoading (state, { value }) {
     state.notifications.loading = value
   },
@@ -528,6 +532,9 @@ const statuses = {
     setError ({ rootState, commit }, { value }) {
       commit('setError', { value })
     },
+    set403Error ({ rootState, commit }, { value }) {
+      commit('set403Error', { value })
+    },
     setNotificationsLoading ({ rootState, commit }, { value }) {
       commit('setNotificationsLoading', { value })
     },
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 8f5eb416..a2aa802f 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -532,13 +532,19 @@ const fetchTimeline = ({
 
   return fetch(url, { headers: authHeaders(credentials) })
     .then((data) => {
-      if (data.ok) {
+      if (data.ok || data.status === 403) {
         return data
       }
       throw new Error('Error fetching timeline', data)
     })
     .then((data) => data.json())
-    .then((data) => data.map(isNotifications ? parseNotification : parseStatus))
+    .then((data) => {
+      if (!data.error) {
+        return data.map(isNotifications ? parseNotification : parseStatus)
+      } else {
+        return data
+      }
+    })
 }
 
 const fetchPinnedStatuses = ({ id, credentials }) => {
diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js
index 9eb30c2d..9352d73a 100644
--- a/src/services/timeline_fetcher/timeline_fetcher.service.js
+++ b/src/services/timeline_fetcher/timeline_fetcher.service.js
@@ -6,6 +6,7 @@ const update = ({ store, statuses, timeline, showImmediately, userId }) => {
   const ccTimeline = camelCase(timeline)
 
   store.dispatch('setError', { value: false })
+  store.dispatch('set403Error', { value: false })
 
   store.dispatch('addNewStatuses', {
     timeline: ccTimeline,
@@ -45,6 +46,11 @@ const fetchAndUpdate = ({
 
   return apiService.fetchTimeline(args)
     .then((statuses) => {
+      // Change messaging if not public
+      if (statuses.error) {
+        store.dispatch('set403Error', { value: true })
+        return
+      }
       if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) {
         store.dispatch('queueFlush', { timeline: timeline, id: timelineData.maxId })
       }