From 2e59ab738b6991a0e6b0a0b9a6dafba41e16c929 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 7 Mar 2019 19:49:41 +0200
Subject: [PATCH 01/13] updates normalizer for proper user handling and adds
 support for friends tl via mastoapi

---
 src/services/api/api.service.js                   |  4 ++--
 .../entity_normalizer.service.js                  | 15 ++++++++++++---
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 2de87026..fe2cb1c8 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1,6 +1,5 @@
 /* eslint-env browser */
 const LOGIN_URL = '/api/account/verify_credentials.json'
-const FRIENDS_TIMELINE_URL = '/api/statuses/friends_timeline.json'
 const ALL_FOLLOWING_URL = '/api/qvitter/allfollowing'
 const PUBLIC_TIMELINE_URL = '/api/statuses/public_timeline.json'
 const PUBLIC_AND_EXTERNAL_TIMELINE_URL = '/api/statuses/public_and_external_timeline.json'
@@ -43,6 +42,7 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny'
 const SUGGESTIONS_URL = '/api/v1/suggestions'
 
 const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
+const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home'
 
 import { each, map } from 'lodash'
 import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
@@ -342,7 +342,7 @@ const setUserMute = ({id, credentials, muted = true}) => {
 const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false}) => {
   const timelineUrls = {
     public: PUBLIC_TIMELINE_URL,
-    friends: FRIENDS_TIMELINE_URL,
+    friends: MASTODON_USER_HOME_TIMELINE_URL,
     mentions: MENTIONS_URL,
     dms: DM_TIMELINE_URL,
     notifications: QVITTER_USER_NOTIFICATIONS_URL,
diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js
index d20ce77f..70f6d693 100644
--- a/src/services/entity_normalizer/entity_normalizer.service.js
+++ b/src/services/entity_normalizer/entity_normalizer.service.js
@@ -60,9 +60,18 @@ export const parseUser = (data) => {
 
     if (data.pleroma) {
       const pleroma = data.pleroma
-      output.follows_you = pleroma.follows_you
-      output.statusnet_blocking = pleroma.statusnet_blocking
-      output.muted = pleroma.muted
+      const relationship = pleroma.relationship
+      output.follows_you = relationship.followed_by
+      output.statusnet_blocking = relationship.blocking
+      output.muted = relationship.muting
+      output.following = relationship.following
+
+      // Unused:
+      // domain_blocking
+      // endorsed
+      // muting_notifications
+      // requested
+      // showing_reblogs
     }
 
     // Missing, trying to recover

From c038d0c12a8cc2af9fd3d3c6f9e338ee0d7c4765 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 7 Mar 2019 20:04:29 +0200
Subject: [PATCH 02/13] undo this change since BE returns empty object for
 relationship, add in a separate MR

---
 .../entity_normalizer.service.js                  | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js
index 70f6d693..d20ce77f 100644
--- a/src/services/entity_normalizer/entity_normalizer.service.js
+++ b/src/services/entity_normalizer/entity_normalizer.service.js
@@ -60,18 +60,9 @@ export const parseUser = (data) => {
 
     if (data.pleroma) {
       const pleroma = data.pleroma
-      const relationship = pleroma.relationship
-      output.follows_you = relationship.followed_by
-      output.statusnet_blocking = relationship.blocking
-      output.muted = relationship.muting
-      output.following = relationship.following
-
-      // Unused:
-      // domain_blocking
-      // endorsed
-      // muting_notifications
-      // requested
-      // showing_reblogs
+      output.follows_you = pleroma.follows_you
+      output.statusnet_blocking = pleroma.statusnet_blocking
+      output.muted = pleroma.muted
     }
 
     // Missing, trying to recover

From 8522063b2c4a35f0926517a3b75376c81131dd79 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 7 Mar 2019 20:16:35 +0200
Subject: [PATCH 03/13] switch public and TWKN to MastoAPI

---
 src/services/api/api.service.js | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 2de87026..f9b556c0 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -2,8 +2,6 @@
 const LOGIN_URL = '/api/account/verify_credentials.json'
 const FRIENDS_TIMELINE_URL = '/api/statuses/friends_timeline.json'
 const ALL_FOLLOWING_URL = '/api/qvitter/allfollowing'
-const PUBLIC_TIMELINE_URL = '/api/statuses/public_timeline.json'
-const PUBLIC_AND_EXTERNAL_TIMELINE_URL = '/api/statuses/public_and_external_timeline.json'
 const TAG_TIMELINE_URL = '/api/statusnet/tags/timeline'
 const FAVORITE_URL = '/api/favorites/create'
 const UNFAVORITE_URL = '/api/favorites/destroy'
@@ -43,6 +41,7 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny'
 const SUGGESTIONS_URL = '/api/v1/suggestions'
 
 const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
+const MASTODON_PUBLIC_TIMELINE = '/api/v1/timelines/public'
 
 import { each, map } from 'lodash'
 import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
@@ -341,12 +340,12 @@ const setUserMute = ({id, credentials, muted = true}) => {
 
 const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false}) => {
   const timelineUrls = {
-    public: PUBLIC_TIMELINE_URL,
+    public: MASTODON_PUBLIC_TIMELINE,
     friends: FRIENDS_TIMELINE_URL,
     mentions: MENTIONS_URL,
     dms: DM_TIMELINE_URL,
     notifications: QVITTER_USER_NOTIFICATIONS_URL,
-    'publicAndExternal': PUBLIC_AND_EXTERNAL_TIMELINE_URL,
+    'publicAndExternal': MASTODON_PUBLIC_TIMELINE,
     user: QVITTER_USER_TIMELINE_URL,
     media: QVITTER_USER_TIMELINE_URL,
     favorites: MASTODON_USER_FAVORITES_TIMELINE_URL,
@@ -372,6 +371,12 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use
   if (timeline === 'media') {
     params.push(['only_media', 1])
   }
+  if (timeline === 'public') {
+    params.push(['local', true])
+  }
+  if (timeline === 'public' || timeline === 'publicAndExternal') {
+    params.push(['only_media', false])
+  }
 
   params.push(['count', 20])
 

From 6e2946f35290380cbd9e2147a570469f1be18ab6 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 7 Mar 2019 20:21:07 +0200
Subject: [PATCH 04/13] switch direct messages to mastoapi

---
 src/services/api/api.service.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 2de87026..65d0916f 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -15,7 +15,6 @@ const STATUS_URL = '/api/statuses/show'
 const MEDIA_UPLOAD_URL = '/api/statusnet/media/upload'
 const CONVERSATION_URL = '/api/statusnet/conversation'
 const MENTIONS_URL = '/api/statuses/mentions.json'
-const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json'
 const FOLLOWERS_URL = '/api/statuses/followers.json'
 const FRIENDS_URL = '/api/statuses/friends.json'
 const BLOCKS_URL = '/api/statuses/blocks.json'
@@ -43,6 +42,7 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny'
 const SUGGESTIONS_URL = '/api/v1/suggestions'
 
 const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
+const MASTODON_DIRECT_MESSAGES_TIMELINE_URL = '/api/v1/timelines/direct'
 
 import { each, map } from 'lodash'
 import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
@@ -344,7 +344,7 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use
     public: PUBLIC_TIMELINE_URL,
     friends: FRIENDS_TIMELINE_URL,
     mentions: MENTIONS_URL,
-    dms: DM_TIMELINE_URL,
+    dms: MASTODON_DIRECT_MESSAGES_TIMELINE_URL,
     notifications: QVITTER_USER_NOTIFICATIONS_URL,
     'publicAndExternal': PUBLIC_AND_EXTERNAL_TIMELINE_URL,
     user: QVITTER_USER_TIMELINE_URL,

From 0b1506a4c00c1482dd31ee43b17ee673e9f57bde Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sun, 10 Mar 2019 18:05:51 +0200
Subject: [PATCH 05/13] wip support for follower/following, a bit broken and
 with regression

---
 src/services/api/api.service.js | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 2de87026..9cee75b9 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -16,8 +16,6 @@ const MEDIA_UPLOAD_URL = '/api/statusnet/media/upload'
 const CONVERSATION_URL = '/api/statusnet/conversation'
 const MENTIONS_URL = '/api/statuses/mentions.json'
 const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json'
-const FOLLOWERS_URL = '/api/statuses/followers.json'
-const FRIENDS_URL = '/api/statuses/friends.json'
 const BLOCKS_URL = '/api/statuses/blocks.json'
 const FOLLOWING_URL = '/api/friendships/create.json'
 const UNFOLLOWING_URL = '/api/friendships/destroy.json'
@@ -43,6 +41,8 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny'
 const SUGGESTIONS_URL = '/api/v1/suggestions'
 
 const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
+const MASTODON_FOLLOWING_URL = id => `/api/v1/accounts/${id}/following`
+const MASTODON_FOLLOWERS_URL = id => `/api/v1/accounts/${id}/followers`
 
 import { each, map } from 'lodash'
 import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
@@ -258,9 +258,9 @@ const fetchUser = ({id, credentials}) => {
 }
 
 const fetchFriends = ({id, page, credentials}) => {
-  let url = `${FRIENDS_URL}?user_id=${id}`
+  let url = MASTODON_FOLLOWING_URL(id)
   if (page) {
-    url = url + `&page=${page}`
+    url = url + `?page=${page}`
   }
   return fetch(url, { headers: authHeaders(credentials) })
     .then((data) => data.json())
@@ -268,16 +268,16 @@ const fetchFriends = ({id, page, credentials}) => {
 }
 
 const exportFriends = ({id, credentials}) => {
-  let url = `${FRIENDS_URL}?user_id=${id}&all=true`
+  let url = MASTODON_FOLLOWING_URL(id) + `?all=true`
   return fetch(url, { headers: authHeaders(credentials) })
     .then((data) => data.json())
     .then((data) => data.map(parseUser))
 }
 
 const fetchFollowers = ({id, page, credentials}) => {
-  let url = `${FOLLOWERS_URL}?user_id=${id}`
+  let url = MASTODON_FOLLOWERS_URL(id)
   if (page) {
-    url = url + `&page=${page}`
+    url = url + `?page=${page}`
   }
   return fetch(url, { headers: authHeaders(credentials) })
     .then((data) => data.json())

From 543cc0d285246c3353a05ca0fdda9d511af46276 Mon Sep 17 00:00:00 2001
From: dave <starpumadev@gmail.com>
Date: Sun, 17 Mar 2019 16:59:08 -0400
Subject: [PATCH 06/13] #442 - clean up Bio placeholder text

---
 src/i18n/en.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/i18n/en.json b/src/i18n/en.json
index 01fe2fba..0bf8b4e9 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -97,7 +97,7 @@
     "new_captcha": "Click the image to get a new captcha",
     "username_placeholder": "e.g. lain",
     "fullname_placeholder": "e.g. Lain Iwakura",
-    "bio_placeholder": "e.g.\nHi, I'm Lain\nI’m an anime girl living in suburban Japan. You may know me from the Wired.",
+    "bio_placeholder": "e.g. \nHi, I'm Lain. \nI’m an anime girl living in suburban Japan. You may know me from the Wired.",
     "validations": {
       "username_required": "cannot be left blank",
       "fullname_required": "cannot be left blank",

From 5717d971829c54e4387b05725658e652b69a8b17 Mon Sep 17 00:00:00 2001
From: dave <starpumadev@gmail.com>
Date: Mon, 18 Mar 2019 10:35:13 -0400
Subject: [PATCH 07/13] #442 - update placeholder linebreak

---
 src/components/registration/registration.js  | 3 +++
 src/components/registration/registration.vue | 2 +-
 src/i18n/en.json                             | 2 +-
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/components/registration/registration.js b/src/components/registration/registration.js
index ab6cd64d..8dc00420 100644
--- a/src/components/registration/registration.js
+++ b/src/components/registration/registration.js
@@ -35,6 +35,9 @@ const registration = {
   },
   computed: {
     token () { return this.$route.params.token },
+    bioPlaceholder () {
+      return this.$t('registration.bio_placeholder').replace(/\s*\n\s*/g, ' \n')
+    },
     ...mapState({
       registrationOpen: (state) => state.instance.registrationOpen,
       signedIn: (state) => !!state.users.currentUser,
diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue
index e22b308d..110b27bf 100644
--- a/src/components/registration/registration.vue
+++ b/src/components/registration/registration.vue
@@ -45,7 +45,7 @@
 
             <div class='form-group'>
               <label class='form--label' for='bio'>{{$t('registration.bio')}} ({{$t('general.optional')}})</label>
-              <textarea :disabled="isPending" v-model='user.bio' class='form-control' id='bio' :placeholder="$t('registration.bio_placeholder')"></textarea>
+              <textarea :disabled="isPending" v-model='user.bio' class='form-control' id='bio' :placeholder="bioPlaceholder"></textarea>
             </div>
 
             <div class='form-group' :class="{ 'form-group--error': $v.user.password.$error }">
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 0bf8b4e9..e5139a4e 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -97,7 +97,7 @@
     "new_captcha": "Click the image to get a new captcha",
     "username_placeholder": "e.g. lain",
     "fullname_placeholder": "e.g. Lain Iwakura",
-    "bio_placeholder": "e.g. \nHi, I'm Lain. \nI’m an anime girl living in suburban Japan. You may know me from the Wired.",
+    "bio_placeholder": "e.g.\nHi, I'm Lain.\nI’m an anime girl living in suburban Japan. You may know me from the Wired.",
     "validations": {
       "username_required": "cannot be left blank",
       "fullname_required": "cannot be left blank",

From 968e6c7fe8392970ddb93751cd8df551ac99c5f1 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 25 Mar 2019 21:04:52 +0200
Subject: [PATCH 08/13] correctly paginate on MastoAPI

---
 src/modules/users.js                          | 24 +++++++++----------
 src/services/api/api.service.js               | 24 ++++++++++++-------
 .../backend_interactor_service.js             |  8 +++----
 3 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/src/modules/users.js b/src/modules/users.js
index 5cfa128e..61d05462 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -52,23 +52,23 @@ export const mutations = {
     state.loggingIn = false
   },
   // TODO Clean after ourselves?
-  addFriends (state, { id, friends, page }) {
+  addFriends (state, { id, friends }) {
     const user = state.usersObject[id]
     each(friends, friend => {
       if (!find(user.friends, { id: friend.id })) {
         user.friends.push(friend)
       }
     })
-    user.friendsPage = page + 1
+    user.lastFriendId = friends.slice(-1)[0].id
   },
-  addFollowers (state, { id, followers, page }) {
+  addFollowers (state, { id, followers }) {
     const user = state.usersObject[id]
     each(followers, follower => {
       if (!find(user.followers, { id: follower.id })) {
         user.followers.push(follower)
       }
     })
-    user.followersPage = page + 1
+    user.lastFollowerId = followers.slice(-1)[0].id
   },
   // Because frontend doesn't have a reason to keep these stuff in memory
   // outside of viewing someones user profile.
@@ -78,7 +78,7 @@ export const mutations = {
       return
     }
     user.friends = []
-    user.friendsPage = 0
+    user.lastFriendId = null
   },
   clearFollowers (state, userId) {
     const user = state.usersObject[userId]
@@ -86,7 +86,7 @@ export const mutations = {
       return
     }
     user.followers = []
-    user.followersPage = 0
+    user.lastFollowerId = null
   },
   addNewUsers (state, users) {
     each(users, (user) => mergeOrAdd(state.users, state.usersObject, user))
@@ -219,10 +219,10 @@ const users = {
     addFriends ({ rootState, commit }, fetchBy) {
       return new Promise((resolve, reject) => {
         const user = rootState.users.usersObject[fetchBy]
-        const page = user.friendsPage || 1
-        rootState.api.backendInteractor.fetchFriends({ id: user.id, page })
+        const sinceId = user.lastFriendId
+        rootState.api.backendInteractor.fetchFriends({ id: user.id, sinceId })
           .then((friends) => {
-            commit('addFriends', { id: user.id, friends, page })
+            commit('addFriends', { id: user.id, friends })
             resolve(friends)
           }).catch(() => {
             reject()
@@ -231,10 +231,10 @@ const users = {
     },
     addFollowers ({ rootState, commit }, fetchBy) {
       const user = rootState.users.usersObject[fetchBy]
-      const page = user.followersPage || 1
-      return rootState.api.backendInteractor.fetchFollowers({ id: user.id, page })
+      const sinceId = user.lastFollowerId
+      return rootState.api.backendInteractor.fetchFollowers({ id: user.id, sinceId })
         .then((followers) => {
-          commit('addFollowers', { id: user.id, followers, page })
+          commit('addFollowers', { id: user.id, followers })
           return followers
         })
     },
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 2c5e9d60..a8de736c 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -276,11 +276,15 @@ const fetchUserRelationship = ({id, credentials}) => {
     })
 }
 
-const fetchFriends = ({id, page, credentials}) => {
+const fetchFriends = ({id, maxId, sinceId, limit = 20, credentials}) => {
   let url = MASTODON_FOLLOWING_URL(id)
-  if (page) {
-    url = url + `?page=${page}`
-  }
+  const args = [
+    maxId && `max_id=${maxId}`,
+    sinceId && `max_id=${sinceId}`,
+    limit && `limit=${limit}`
+  ].filter(_ => _).join('&')
+
+  url = url + (args ? '?' + args : '')
   return fetch(url, { headers: authHeaders(credentials) })
     .then((data) => data.json())
     .then((data) => data.map(parseUser))
@@ -293,11 +297,15 @@ const exportFriends = ({id, credentials}) => {
     .then((data) => data.map(parseUser))
 }
 
-const fetchFollowers = ({id, page, credentials}) => {
+const fetchFollowers = ({id, maxId, sinceId, limit = 20, credentials}) => {
   let url = MASTODON_FOLLOWERS_URL(id)
-  if (page) {
-    url = url + `?page=${page}`
-  }
+  const args = [
+    maxId && `max_id=${maxId}`,
+    sinceId && `max_id=${sinceId}`,
+    limit && `limit=${limit}`
+  ].filter(_ => _).join('&')
+
+  url = url + (args ? '?' + args : '')
   return fetch(url, { headers: authHeaders(credentials) })
     .then((data) => data.json())
     .then((data) => data.map(parseUser))
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 0f0bcddc..71e78d2f 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -10,16 +10,16 @@ const backendInteractorService = (credentials) => {
     return apiService.fetchConversation({id, credentials})
   }
 
-  const fetchFriends = ({id, page}) => {
-    return apiService.fetchFriends({id, page, credentials})
+  const fetchFriends = ({id, maxId, sinceId, limit}) => {
+    return apiService.fetchFriends({id, maxId, sinceId, limit, credentials})
   }
 
   const exportFriends = ({id}) => {
     return apiService.exportFriends({id, credentials})
   }
 
-  const fetchFollowers = ({id, page}) => {
-    return apiService.fetchFollowers({id, page, credentials})
+  const fetchFollowers = ({id, maxId, sinceId, limit}) => {
+    return apiService.fetchFollowers({id, maxId, sinceId, limit, credentials})
   }
 
   const fetchAllFollowing = ({username}) => {

From 2d05aef24b36d1c8be5cdad13ae69a2f0514c713 Mon Sep 17 00:00:00 2001
From: jasper <jasper92341@hotmail.com>
Date: Tue, 26 Mar 2019 14:26:26 -0700
Subject: [PATCH 09/13] Add await to login action'

---
 src/boot/after_store.js    | 2 +-
 src/lib/persisted_state.js | 3 ---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index f5e84cbc..f5add8ad 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -241,7 +241,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
 
   // Now we have the server settings and can try logging in
   if (store.state.oauth.token) {
-    store.dispatch('loginUser', store.state.oauth.token)
+    await store.dispatch('loginUser', store.state.oauth.token)
   }
 
   const router = new VueRouter({
diff --git a/src/lib/persisted_state.js b/src/lib/persisted_state.js
index 720ff706..7ab89c12 100644
--- a/src/lib/persisted_state.js
+++ b/src/lib/persisted_state.js
@@ -60,9 +60,6 @@ export default function createPersistedState ({
             merge({}, store.state, savedState)
           )
         }
-        if (store.state.oauth.token) {
-          store.dispatch('loginUser', store.state.oauth.token)
-        }
         loaded = true
       } catch (e) {
         console.log("Couldn't load state")

From 95459ff0bca7f095f0fdc01b38dd89626fe5c189 Mon Sep 17 00:00:00 2001
From: HJ <30-hj@users.noreply.git.pleroma.social>
Date: Wed, 27 Mar 2019 08:47:54 +0000
Subject: [PATCH 10/13] Revert "Merge branch 'mastoapi/friends-tl' into
 'develop'"

This reverts merge request !647
---
 src/services/api/api.service.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 4ebfb7b7..3a4f21a6 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1,5 +1,6 @@
 /* eslint-env browser */
 const LOGIN_URL = '/api/account/verify_credentials.json'
+const FRIENDS_TIMELINE_URL = '/api/statuses/friends_timeline.json'
 const ALL_FOLLOWING_URL = '/api/qvitter/allfollowing'
 const PUBLIC_TIMELINE_URL = '/api/statuses/public_timeline.json'
 const PUBLIC_AND_EXTERNAL_TIMELINE_URL = '/api/statuses/public_and_external_timeline.json'
@@ -32,7 +33,6 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny'
 const SUGGESTIONS_URL = '/api/v1/suggestions'
 
 const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
-const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home'
 const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}`
 const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
 const MASTODON_USER_URL = '/api/v1/accounts'
@@ -348,7 +348,7 @@ const fetchStatus = ({id, credentials}) => {
 const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false, withMuted = false}) => {
   const timelineUrls = {
     public: PUBLIC_TIMELINE_URL,
-    friends: MASTODON_USER_HOME_TIMELINE_URL,
+    friends: FRIENDS_TIMELINE_URL,
     mentions: MENTIONS_URL,
     dms: DM_TIMELINE_URL,
     notifications: QVITTER_USER_NOTIFICATIONS_URL,

From b3a6bec17b18f554caa12d35e9e875adddc206db Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 27 Mar 2019 11:15:57 +0200
Subject: [PATCH 11/13] Revert "Merge branch 'revert-987b5162' into 'develop'"

This reverts commit 96753e6a5febff60e0c2cb6fac13d5e7865f0a94, reversing
changes made to 987b5162a7530979e9fa887a24311eb1cd480fc5.
---
 src/services/api/api.service.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 8d7f9e5d..aabbe80f 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1,6 +1,5 @@
 /* eslint-env browser */
 const LOGIN_URL = '/api/account/verify_credentials.json'
-const FRIENDS_TIMELINE_URL = '/api/statuses/friends_timeline.json'
 const ALL_FOLLOWING_URL = '/api/qvitter/allfollowing'
 const TAG_TIMELINE_URL = '/api/statusnet/tags/timeline'
 const FAVORITE_URL = '/api/favorites/create'
@@ -32,6 +31,7 @@ const SUGGESTIONS_URL = '/api/v1/suggestions'
 
 const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
 const MASTODON_PUBLIC_TIMELINE = '/api/v1/timelines/public'
+const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home'
 const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}`
 const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
 const MASTODON_USER_URL = '/api/v1/accounts'
@@ -347,7 +347,7 @@ const fetchStatus = ({id, credentials}) => {
 const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false, withMuted = false}) => {
   const timelineUrls = {
     public: MASTODON_PUBLIC_TIMELINE,
-    friends: FRIENDS_TIMELINE_URL,
+    friends: MASTODON_USER_HOME_TIMELINE_URL,
     mentions: MENTIONS_URL,
     dms: DM_TIMELINE_URL,
     notifications: QVITTER_USER_NOTIFICATIONS_URL,

From fb2aca06de230a1d52ab5ac50e8916c9d4a8decb Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 27 Mar 2019 22:02:46 +0200
Subject: [PATCH 12/13] review

---
 src/modules/users.js            | 6 +++---
 src/services/api/api.service.js | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/modules/users.js b/src/modules/users.js
index 61d05462..cc10b89d 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -1,5 +1,5 @@
 import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
-import { compact, map, each, merge, find } from 'lodash'
+import { compact, map, each, merge, find, last } from 'lodash'
 import { set } from 'vue'
 import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js'
 import oauthApi from '../services/new_api/oauth'
@@ -59,7 +59,7 @@ export const mutations = {
         user.friends.push(friend)
       }
     })
-    user.lastFriendId = friends.slice(-1)[0].id
+    user.lastFriendId = last(friends).id
   },
   addFollowers (state, { id, followers }) {
     const user = state.usersObject[id]
@@ -68,7 +68,7 @@ export const mutations = {
         user.followers.push(follower)
       }
     })
-    user.lastFollowerId = followers.slice(-1)[0].id
+    user.lastFollowerId = last(followers).id
   },
   // Because frontend doesn't have a reason to keep these stuff in memory
   // outside of viewing someones user profile.
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index a8de736c..cf4acdf7 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -280,7 +280,7 @@ const fetchFriends = ({id, maxId, sinceId, limit = 20, credentials}) => {
   let url = MASTODON_FOLLOWING_URL(id)
   const args = [
     maxId && `max_id=${maxId}`,
-    sinceId && `max_id=${sinceId}`,
+    sinceId && `since_id=${sinceId}`,
     limit && `limit=${limit}`
   ].filter(_ => _).join('&')
 
@@ -301,11 +301,11 @@ const fetchFollowers = ({id, maxId, sinceId, limit = 20, credentials}) => {
   let url = MASTODON_FOLLOWERS_URL(id)
   const args = [
     maxId && `max_id=${maxId}`,
-    sinceId && `max_id=${sinceId}`,
+    sinceId && `since_id=${sinceId}`,
     limit && `limit=${limit}`
   ].filter(_ => _).join('&')
 
-  url = url + (args ? '?' + args : '')
+  url += args ? '?' + args : ''
   return fetch(url, { headers: authHeaders(credentials) })
     .then((data) => data.json())
     .then((data) => data.map(parseUser))

From 0a031aae20bf1dc3bc0b15af0b794798d179aafa Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 27 Mar 2019 22:04:59 +0200
Subject: [PATCH 13/13] errata

---
 src/modules/users.js | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/modules/users.js b/src/modules/users.js
index cc10b89d..1a507d31 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -219,8 +219,8 @@ const users = {
     addFriends ({ rootState, commit }, fetchBy) {
       return new Promise((resolve, reject) => {
         const user = rootState.users.usersObject[fetchBy]
-        const sinceId = user.lastFriendId
-        rootState.api.backendInteractor.fetchFriends({ id: user.id, sinceId })
+        const maxId = user.lastFriendId
+        rootState.api.backendInteractor.fetchFriends({ id: user.id, maxId })
           .then((friends) => {
             commit('addFriends', { id: user.id, friends })
             resolve(friends)
@@ -231,8 +231,8 @@ const users = {
     },
     addFollowers ({ rootState, commit }, fetchBy) {
       const user = rootState.users.usersObject[fetchBy]
-      const sinceId = user.lastFollowerId
-      return rootState.api.backendInteractor.fetchFollowers({ id: user.id, sinceId })
+      const maxId = user.lastFollowerId
+      return rootState.api.backendInteractor.fetchFollowers({ id: user.id, maxId })
         .then((followers) => {
           commit('addFollowers', { id: user.id, followers })
           return followers