From 621ac0bdc76ef1f38b227ede9200a947bbbc8073 Mon Sep 17 00:00:00 2001
From: Ariadne Conill <ariadne@dereferenced.org>
Date: Sat, 9 Nov 2019 19:49:50 -0600
Subject: [PATCH 01/62] docs: document FE interaction with the BE private
 setting

---
 docs/CONFIGURATION.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md
index 35363537..f7397a55 100644
--- a/docs/CONFIGURATION.md
+++ b/docs/CONFIGURATION.md
@@ -96,3 +96,6 @@ Setting this will change the warning text that is displayed for direct messages.
 ATTENTION: If you actually want the behavior to change. You will need to set the appropriate option at the backend. See the backend documentation for information about that.
 
 DO NOT activate this without checking the backend configuration first!
+
+### Private Mode
+If the `private` instance setting is enabled in the backend, features that are not accessible without authentication, such as the timelines and search will be disabled for unauthenticated users.

From 99fd096ddd1cc657a86c41e7e96344b8bb1dc4de Mon Sep 17 00:00:00 2001
From: Ariadne Conill <ariadne@dereferenced.org>
Date: Sat, 9 Nov 2019 19:53:03 -0600
Subject: [PATCH 02/62] boot: track whether private mode is enabled or not

---
 src/boot/after_store.js | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index 226b67d8..cbe0c330 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -218,6 +218,9 @@ const getNodeInfo = async ({ store }) => {
       store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
       store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: software.name === 'pleroma' })
 
+      const priv = metadata.private
+      store.dispatch('setInstanceOption', { name: 'private', value: priv })
+
       const frontendVersion = window.___pleromafe_commit_hash
       store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion })
       store.dispatch('setInstanceOption', { name: 'tagPolicyAvailable', value: metadata.federation.mrf_policies.includes('TagPolicy') })

From 21f1637e437398ec56b6078cf28b58bd4a0299ba Mon Sep 17 00:00:00 2001
From: Ariadne Conill <ariadne@dereferenced.org>
Date: Mon, 11 Nov 2019 14:14:44 -0600
Subject: [PATCH 03/62] nav panel: refactor to use vuex mapState

---
 src/components/nav_panel/nav_panel.js | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index aa3f7605..bfcab62e 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -1,4 +1,5 @@
 import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
+import { mapState } from 'vuex'
 
 const NavPanel = {
   created () {
@@ -9,17 +10,11 @@ const NavPanel = {
       followRequestFetcher.startFetching({ store, credentials })
     }
   },
-  computed: {
-    currentUser () {
-      return this.$store.state.users.currentUser
-    },
-    chat () {
-      return this.$store.state.chat.channel
-    },
-    followRequestCount () {
-      return this.$store.state.api.followRequests.length
-    }
-  }
+  computed: mapState({
+    currentUser: state => state.users.currentUser,
+    chat: state => state.chat.channel,
+    followRequestCount: state => state.api.followRequests.length
+  })
 }
 
 export default NavPanel

From 1f9674350cdf7455fe5540d377eb327edf1336ce Mon Sep 17 00:00:00 2001
From: Ariadne Conill <ariadne@dereferenced.org>
Date: Mon, 11 Nov 2019 14:18:36 -0600
Subject: [PATCH 04/62] nav panel: disable TWKN if federation disabled, disable
 Public and TWKN if privateMode is enabled

---
 src/components/nav_panel/nav_panel.js  | 4 +++-
 src/components/nav_panel/nav_panel.vue | 4 ++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index bfcab62e..a6426d13 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -13,7 +13,9 @@ const NavPanel = {
   computed: mapState({
     currentUser: state => state.users.currentUser,
     chat: state => state.chat.channel,
-    followRequestCount: state => state.api.followRequests.length
+    followRequestCount: state => state.api.followRequests.length,
+    privateMode: state => state.instance.private,
+    federating: state => state.instance.federationPolicy.federating || true
   })
 }
 
diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue
index 28589bb1..d85c28bd 100644
--- a/src/components/nav_panel/nav_panel.vue
+++ b/src/components/nav_panel/nav_panel.vue
@@ -28,12 +28,12 @@
             </span>
           </router-link>
         </li>
-        <li>
+        <li v-if="currentUser || !privateMode">
           <router-link :to="{ name: 'public-timeline' }">
             {{ $t("nav.public_tl") }}
           </router-link>
         </li>
-        <li>
+        <li v-if="(currentUser || !privateMode) && federating">
           <router-link :to="{ name: 'public-external-timeline' }">
             {{ $t("nav.twkn") }}
           </router-link>

From cb5f73148a2dc9341d16326ed606d74e818fb61d Mon Sep 17 00:00:00 2001
From: Ariadne Conill <ariadne@dereferenced.org>
Date: Mon, 11 Nov 2019 14:25:38 -0600
Subject: [PATCH 05/62] app: search API is not available in private mode so
 disable it

---
 src/App.js  | 3 ++-
 src/App.vue | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/App.js b/src/App.js
index 04a40e30..e2b0e6db 100644
--- a/src/App.js
+++ b/src/App.js
@@ -97,7 +97,8 @@ export default {
         this.$store.state.instance.instanceSpecificPanelContent
     },
     showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
-    isMobileLayout () { return this.$store.state.interface.mobileLayout }
+    isMobileLayout () { return this.$store.state.interface.mobileLayout },
+    privateMode () { return this.$store.state.instance.private }
   },
   methods: {
     scrollToTop () {
diff --git a/src/App.vue b/src/App.vue
index dbe842ec..1f244b56 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -43,6 +43,7 @@
             class="nav-icon mobile-hidden"
             @toggled="onSearchBarToggled"
             @click.stop.native
+            v-if="currentUser || !privateMode"
           />
           <router-link
             class="mobile-hidden"

From 43d4d17b41863dd5784f1d611857a9064759946b Mon Sep 17 00:00:00 2001
From: Ariadne Conill <ariadne@dereferenced.org>
Date: Mon, 11 Nov 2019 14:37:14 -0600
Subject: [PATCH 06/62] side drawer: same treatment

---
 src/components/side_drawer/side_drawer.js  | 6 ++++++
 src/components/side_drawer/side_drawer.vue | 6 +++---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js
index 567d2e5e..2725d43a 100644
--- a/src/components/side_drawer/side_drawer.js
+++ b/src/components/side_drawer/side_drawer.js
@@ -34,6 +34,12 @@ const SideDrawer = {
     },
     followRequestCount () {
       return this.$store.state.api.followRequests.length
+    },
+    privateMode () {
+      return this.$store.state.instance.private
+    },
+    federating () {
+      return this.$store.state.instance.federationPolicy.federating || true
     }
   },
   methods: {
diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue
index 214b8e0c..be18a5d7 100644
--- a/src/components/side_drawer/side_drawer.vue
+++ b/src/components/side_drawer/side_drawer.vue
@@ -79,12 +79,12 @@
             </span>
           </router-link>
         </li>
-        <li @click="toggleDrawer">
+        <li @click="toggleDrawer" v-if="currentUser || !privateMode">
           <router-link to="/main/public">
             {{ $t("nav.public_tl") }}
           </router-link>
         </li>
-        <li @click="toggleDrawer">
+        <li @click="toggleDrawer" v-if="(currentUser || !privateMode) && federating">
           <router-link to="/main/all">
             {{ $t("nav.twkn") }}
           </router-link>
@@ -99,7 +99,7 @@
         </li>
       </ul>
       <ul>
-        <li @click="toggleDrawer">
+        <li @click="toggleDrawer" v-if="currentUser || !privateMode">
           <router-link :to="{ name: 'search' }">
             {{ $t("nav.search") }}
           </router-link>

From ddb6fb9217789e90490a4ec1ce7a2dd9ced67631 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sun, 24 Nov 2019 13:57:46 +0200
Subject: [PATCH 07/62] Backend Interactor service overhaul, removed the need
 for copypasting

---
 .../follow_request_card.js                    |   4 +-
 .../moderation_tools/moderation_tools.js      |  16 +-
 .../user_reporting_modal.js                   |   2 +-
 src/components/user_settings/user_settings.js |   8 +-
 src/modules/oauth_tokens.js                   |   2 +-
 src/modules/polls.js                          |   4 +-
 src/modules/statuses.js                       |  26 +-
 src/modules/users.js                          |  16 +-
 .../backend_interactor_service.js             | 231 ++----------------
 .../follow_manipulate/follow_manipulate.js    |   2 +-
 10 files changed, 55 insertions(+), 256 deletions(-)

diff --git a/src/components/follow_request_card/follow_request_card.js b/src/components/follow_request_card/follow_request_card.js
index 1a00a1c1..a8931787 100644
--- a/src/components/follow_request_card/follow_request_card.js
+++ b/src/components/follow_request_card/follow_request_card.js
@@ -7,11 +7,11 @@ const FollowRequestCard = {
   },
   methods: {
     approveUser () {
-      this.$store.state.api.backendInteractor.approveUser(this.user.id)
+      this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
       this.$store.dispatch('removeFollowRequest', this.user)
     },
     denyUser () {
-      this.$store.state.api.backendInteractor.denyUser(this.user.id)
+      this.$store.state.api.backendInteractor.denyUser({ id: this.user.id })
       this.$store.dispatch('removeFollowRequest', this.user)
     }
   }
diff --git a/src/components/moderation_tools/moderation_tools.js b/src/components/moderation_tools/moderation_tools.js
index 8aadc8c5..5bb76497 100644
--- a/src/components/moderation_tools/moderation_tools.js
+++ b/src/components/moderation_tools/moderation_tools.js
@@ -45,12 +45,12 @@ const ModerationTools = {
     toggleTag (tag) {
       const store = this.$store
       if (this.tagsSet.has(tag)) {
-        store.state.api.backendInteractor.untagUser(this.user, tag).then(response => {
+        store.state.api.backendInteractor.untagUser({ user: this.user, tag }).then(response => {
           if (!response.ok) { return }
           store.commit('untagUser', { user: this.user, tag })
         })
       } else {
-        store.state.api.backendInteractor.tagUser(this.user, tag).then(response => {
+        store.state.api.backendInteractor.tagUser({ user: this.user, tag }).then(response => {
           if (!response.ok) { return }
           store.commit('tagUser', { user: this.user, tag })
         })
@@ -59,21 +59,21 @@ const ModerationTools = {
     toggleRight (right) {
       const store = this.$store
       if (this.user.rights[right]) {
-        store.state.api.backendInteractor.deleteRight(this.user, right).then(response => {
+        store.state.api.backendInteractor.deleteRight({ user: this.user, right }).then(response => {
           if (!response.ok) { return }
-          store.commit('updateRight', { user: this.user, right: right, value: false })
+          store.commit('updateRight', { user: this.user, right, value: false })
         })
       } else {
-        store.state.api.backendInteractor.addRight(this.user, right).then(response => {
+        store.state.api.backendInteractor.addRight({ user: this.user, right }).then(response => {
           if (!response.ok) { return }
-          store.commit('updateRight', { user: this.user, right: right, value: true })
+          store.commit('updateRight', { user: this.user, right, value: true })
         })
       }
     },
     toggleActivationStatus () {
       const store = this.$store
       const status = !!this.user.deactivated
-      store.state.api.backendInteractor.setActivationStatus(this.user, status).then(response => {
+      store.state.api.backendInteractor.setActivationStatus({ user: this.user, status }).then(response => {
         if (!response.ok) { return }
         store.commit('updateActivationStatus', { user: this.user, status: status })
       })
@@ -85,7 +85,7 @@ const ModerationTools = {
       const store = this.$store
       const user = this.user
       const { id, name } = user
-      store.state.api.backendInteractor.deleteUser(user)
+      store.state.api.backendInteractor.deleteUser({ user })
         .then(e => {
           this.$store.dispatch('markStatusesAsDeleted', status => user.id === status.user.id)
           const isProfile = this.$route.name === 'external-user-profile' || this.$route.name === 'user-profile'
diff --git a/src/components/user_reporting_modal/user_reporting_modal.js b/src/components/user_reporting_modal/user_reporting_modal.js
index 833fa98a..38cf117b 100644
--- a/src/components/user_reporting_modal/user_reporting_modal.js
+++ b/src/components/user_reporting_modal/user_reporting_modal.js
@@ -64,7 +64,7 @@ const UserReportingModal = {
         forward: this.forward,
         statusIds: this.statusIdsToReport
       }
-      this.$store.state.api.backendInteractor.reportUser(params)
+      this.$store.state.api.backendInteractor.reportUser({ ...params })
         .then(() => {
           this.processing = false
           this.resetState()
diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js
index 3fdc5340..d5d671e4 100644
--- a/src/components/user_settings/user_settings.js
+++ b/src/components/user_settings/user_settings.js
@@ -242,7 +242,7 @@ const UserSettings = {
       })
     },
     importFollows (file) {
-      return this.$store.state.api.backendInteractor.importFollows(file)
+      return this.$store.state.api.backendInteractor.importFollows({ file })
         .then((status) => {
           if (!status) {
             throw new Error('failed')
@@ -250,7 +250,7 @@ const UserSettings = {
         })
     },
     importBlocks (file) {
-      return this.$store.state.api.backendInteractor.importBlocks(file)
+      return this.$store.state.api.backendInteractor.importBlocks({ file })
         .then((status) => {
           if (!status) {
             throw new Error('failed')
@@ -297,7 +297,7 @@ const UserSettings = {
         newPassword: this.changePasswordInputs[1],
         newPasswordConfirmation: this.changePasswordInputs[2]
       }
-      this.$store.state.api.backendInteractor.changePassword(params)
+      this.$store.state.api.backendInteractor.changePassword({ params })
         .then((res) => {
           if (res.status === 'success') {
             this.changedPassword = true
@@ -314,7 +314,7 @@ const UserSettings = {
         email: this.newEmail,
         password: this.changeEmailPassword
       }
-      this.$store.state.api.backendInteractor.changeEmail(params)
+      this.$store.state.api.backendInteractor.changeEmail({ params })
         .then((res) => {
           if (res.status === 'success') {
             this.changedEmail = true
diff --git a/src/modules/oauth_tokens.js b/src/modules/oauth_tokens.js
index 0159a3f1..907cae4a 100644
--- a/src/modules/oauth_tokens.js
+++ b/src/modules/oauth_tokens.js
@@ -9,7 +9,7 @@ const oauthTokens = {
       })
     },
     revokeToken ({ rootState, commit, state }, id) {
-      rootState.api.backendInteractor.revokeOAuthToken(id).then((response) => {
+      rootState.api.backendInteractor.revokeOAuthToken({ id }).then((response) => {
         if (response.status === 201) {
           commit('swapTokens', state.tokens.filter(token => token.id !== id))
         }
diff --git a/src/modules/polls.js b/src/modules/polls.js
index e6158b63..92b89a06 100644
--- a/src/modules/polls.js
+++ b/src/modules/polls.js
@@ -40,7 +40,7 @@ const polls = {
       commit('mergeOrAddPoll', poll)
     },
     updateTrackedPoll ({ rootState, dispatch, commit }, pollId) {
-      rootState.api.backendInteractor.fetchPoll(pollId).then(poll => {
+      rootState.api.backendInteractor.fetchPoll({ pollId }).then(poll => {
         setTimeout(() => {
           if (rootState.polls.trackedPolls[pollId]) {
             dispatch('updateTrackedPoll', pollId)
@@ -59,7 +59,7 @@ const polls = {
       commit('untrackPoll', pollId)
     },
     votePoll ({ rootState, commit }, { id, pollId, choices }) {
-      return rootState.api.backendInteractor.vote(pollId, choices).then(poll => {
+      return rootState.api.backendInteractor.vote({ pollId, choices }).then(poll => {
         commit('mergeOrAddPoll', poll)
         return poll
       })
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index f11ffdcd..6a743a4a 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -551,45 +551,45 @@ const statuses = {
     favorite ({ rootState, commit }, status) {
       // Optimistic favoriting...
       commit('setFavorited', { status, value: true })
-      rootState.api.backendInteractor.favorite(status.id)
+      rootState.api.backendInteractor.favorite({ id: status.id })
         .then(status => commit('setFavoritedConfirm', { status, user: rootState.users.currentUser }))
     },
     unfavorite ({ rootState, commit }, status) {
       // Optimistic unfavoriting...
       commit('setFavorited', { status, value: false })
-      rootState.api.backendInteractor.unfavorite(status.id)
+      rootState.api.backendInteractor.unfavorite({ id: status.id })
         .then(status => commit('setFavoritedConfirm', { status, user: rootState.users.currentUser }))
     },
     fetchPinnedStatuses ({ rootState, dispatch }, userId) {
-      rootState.api.backendInteractor.fetchPinnedStatuses(userId)
+      rootState.api.backendInteractor.fetchPinnedStatuses({ id: userId })
         .then(statuses => dispatch('addNewStatuses', { statuses, timeline: 'user', userId, showImmediately: true, noIdUpdate: true }))
     },
     pinStatus ({ rootState, dispatch }, statusId) {
-      return rootState.api.backendInteractor.pinOwnStatus(statusId)
+      return rootState.api.backendInteractor.pinOwnStatus({ id: statusId })
         .then((status) => dispatch('addNewStatuses', { statuses: [status] }))
     },
     unpinStatus ({ rootState, dispatch }, statusId) {
-      rootState.api.backendInteractor.unpinOwnStatus(statusId)
+      rootState.api.backendInteractor.unpinOwnStatus({ id: statusId })
         .then((status) => dispatch('addNewStatuses', { statuses: [status] }))
     },
     muteConversation ({ rootState, commit }, statusId) {
-      return rootState.api.backendInteractor.muteConversation(statusId)
+      return rootState.api.backendInteractor.muteConversation({ id: statusId })
         .then((status) => commit('setMutedStatus', status))
     },
     unmuteConversation ({ rootState, commit }, statusId) {
-      return rootState.api.backendInteractor.unmuteConversation(statusId)
+      return rootState.api.backendInteractor.unmuteConversation({ id: statusId })
         .then((status) => commit('setMutedStatus', status))
     },
     retweet ({ rootState, commit }, status) {
       // Optimistic retweeting...
       commit('setRetweeted', { status, value: true })
-      rootState.api.backendInteractor.retweet(status.id)
+      rootState.api.backendInteractor.retweet({ id: status.id })
         .then(status => commit('setRetweetedConfirm', { status: status.retweeted_status, user: rootState.users.currentUser }))
     },
     unretweet ({ rootState, commit }, status) {
       // Optimistic unretweeting...
       commit('setRetweeted', { status, value: false })
-      rootState.api.backendInteractor.unretweet(status.id)
+      rootState.api.backendInteractor.unretweet({ id: status.id })
         .then(status => commit('setRetweetedConfirm', { status, user: rootState.users.currentUser }))
     },
     queueFlush ({ rootState, commit }, { timeline, id }) {
@@ -604,19 +604,19 @@ const statuses = {
     },
     fetchFavsAndRepeats ({ rootState, commit }, id) {
       Promise.all([
-        rootState.api.backendInteractor.fetchFavoritedByUsers(id),
-        rootState.api.backendInteractor.fetchRebloggedByUsers(id)
+        rootState.api.backendInteractor.fetchFavoritedByUsers({ id }),
+        rootState.api.backendInteractor.fetchRebloggedByUsers({ id })
       ]).then(([favoritedByUsers, rebloggedByUsers]) => {
         commit('addFavs', { id, favoritedByUsers, currentUser: rootState.users.currentUser })
         commit('addRepeats', { id, rebloggedByUsers, currentUser: rootState.users.currentUser })
       })
     },
     fetchFavs ({ rootState, commit }, id) {
-      rootState.api.backendInteractor.fetchFavoritedByUsers(id)
+      rootState.api.backendInteractor.fetchFavoritedByUsers({ id })
         .then(favoritedByUsers => commit('addFavs', { id, favoritedByUsers, currentUser: rootState.users.currentUser }))
     },
     fetchRepeats ({ rootState, commit }, id) {
-      rootState.api.backendInteractor.fetchRebloggedByUsers(id)
+      rootState.api.backendInteractor.fetchRebloggedByUsers({ id })
         .then(rebloggedByUsers => commit('addRepeats', { id, rebloggedByUsers, currentUser: rootState.users.currentUser }))
     },
     search (store, { q, resolve, limit, offset, following }) {
diff --git a/src/modules/users.js b/src/modules/users.js
index 14b2d8b5..e1373220 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -32,7 +32,7 @@ const getNotificationPermission = () => {
 }
 
 const blockUser = (store, id) => {
-  return store.rootState.api.backendInteractor.blockUser(id)
+  return store.rootState.api.backendInteractor.blockUser({ id })
     .then((relationship) => {
       store.commit('updateUserRelationship', [relationship])
       store.commit('addBlockId', id)
@@ -43,12 +43,12 @@ const blockUser = (store, id) => {
 }
 
 const unblockUser = (store, id) => {
-  return store.rootState.api.backendInteractor.unblockUser(id)
+  return store.rootState.api.backendInteractor.unblockUser({ id })
     .then((relationship) => store.commit('updateUserRelationship', [relationship]))
 }
 
 const muteUser = (store, id) => {
-  return store.rootState.api.backendInteractor.muteUser(id)
+  return store.rootState.api.backendInteractor.muteUser({ id })
     .then((relationship) => {
       store.commit('updateUserRelationship', [relationship])
       store.commit('addMuteId', id)
@@ -56,7 +56,7 @@ const muteUser = (store, id) => {
 }
 
 const unmuteUser = (store, id) => {
-  return store.rootState.api.backendInteractor.unmuteUser(id)
+  return store.rootState.api.backendInteractor.unmuteUser({ id })
     .then((relationship) => store.commit('updateUserRelationship', [relationship]))
 }
 
@@ -324,11 +324,11 @@ const users = {
       commit('clearFollowers', userId)
     },
     subscribeUser ({ rootState, commit }, id) {
-      return rootState.api.backendInteractor.subscribeUser(id)
+      return rootState.api.backendInteractor.subscribeUser({ id })
         .then((relationship) => commit('updateUserRelationship', [relationship]))
     },
     unsubscribeUser ({ rootState, commit }, id) {
-      return rootState.api.backendInteractor.unsubscribeUser(id)
+      return rootState.api.backendInteractor.unsubscribeUser({ id })
         .then((relationship) => commit('updateUserRelationship', [relationship]))
     },
     registerPushNotifications (store) {
@@ -382,7 +382,7 @@ const users = {
       })
     },
     searchUsers (store, query) {
-      return store.rootState.api.backendInteractor.searchUsers(query)
+      return store.rootState.api.backendInteractor.searchUsers({ query })
         .then((users) => {
           store.commit('addNewUsers', users)
           return users
@@ -394,7 +394,7 @@ const users = {
       let rootState = store.rootState
 
       try {
-        let data = await rootState.api.backendInteractor.register(userInfo)
+        let data = await rootState.api.backendInteractor.register({ ...userInfo })
         store.commit('signUpSuccess')
         store.commit('setToken', data.access_token)
         store.dispatch('loginUser', data.access_token)
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index c16bd1f1..57fdccde 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -3,228 +3,27 @@ import timelineFetcherService from '../timeline_fetcher/timeline_fetcher.service
 import notificationsFetcher from '../notifications_fetcher/notifications_fetcher.service.js'
 import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
 
-const backendInteractorService = credentials => {
-  const fetchStatus = ({ id }) => {
-    return apiService.fetchStatus({ id, credentials })
-  }
-
-  const fetchConversation = ({ id }) => {
-    return apiService.fetchConversation({ id, 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, maxId, sinceId, limit }) => {
-    return apiService.fetchFollowers({ id, maxId, sinceId, limit, credentials })
-  }
-
-  const fetchUser = ({ id }) => {
-    return apiService.fetchUser({ id, credentials })
-  }
-
-  const fetchUserRelationship = ({ id }) => {
-    return apiService.fetchUserRelationship({ id, credentials })
-  }
-
-  const followUser = ({ id, reblogs }) => {
-    return apiService.followUser({ credentials, id, reblogs })
-  }
-
-  const unfollowUser = (id) => {
-    return apiService.unfollowUser({ credentials, id })
-  }
-
-  const blockUser = (id) => {
-    return apiService.blockUser({ credentials, id })
-  }
-
-  const unblockUser = (id) => {
-    return apiService.unblockUser({ credentials, id })
-  }
-
-  const approveUser = (id) => {
-    return apiService.approveUser({ credentials, id })
-  }
-
-  const denyUser = (id) => {
-    return apiService.denyUser({ credentials, id })
-  }
-
-  const startFetchingTimeline = ({ timeline, store, userId = false, tag }) => {
+const backendInteractorService = credentials => ({
+  startFetchingTimeline ({ timeline, store, userId = false, tag }) {
     return timelineFetcherService.startFetching({ timeline, store, credentials, userId, tag })
-  }
+  },
 
-  const startFetchingNotifications = ({ store }) => {
+  startFetchingNotifications ({ store }) {
     return notificationsFetcher.startFetching({ store, credentials })
-  }
+  },
 
-  const startFetchingFollowRequest = ({ store }) => {
+  startFetchingFollowRequest ({ store }) {
     return followRequestFetcher.startFetching({ store, credentials })
-  }
+  },
 
-  // eslint-disable-next-line camelcase
-  const tagUser = ({ screen_name }, tag) => {
-    return apiService.tagUser({ screen_name, tag, credentials })
-  }
+  ...Object.entries(apiService).reduce((acc, [key, func]) => {
+    return {
+      ...acc,
+      [key]: (args) => func({ credentials, ...args })
+    }
+  }, {}),
 
-  // eslint-disable-next-line camelcase
-  const untagUser = ({ screen_name }, tag) => {
-    return apiService.untagUser({ screen_name, tag, credentials })
-  }
-
-  // eslint-disable-next-line camelcase
-  const addRight = ({ screen_name }, right) => {
-    return apiService.addRight({ screen_name, right, credentials })
-  }
-
-  // eslint-disable-next-line camelcase
-  const deleteRight = ({ screen_name }, right) => {
-    return apiService.deleteRight({ screen_name, right, credentials })
-  }
-
-  // eslint-disable-next-line camelcase
-  const setActivationStatus = ({ screen_name }, status) => {
-    return apiService.setActivationStatus({ screen_name, status, credentials })
-  }
-
-  // eslint-disable-next-line camelcase
-  const deleteUser = ({ screen_name }) => {
-    return apiService.deleteUser({ screen_name, credentials })
-  }
-
-  const vote = (pollId, choices) => {
-    return apiService.vote({ credentials, pollId, choices })
-  }
-
-  const fetchPoll = (pollId) => {
-    return apiService.fetchPoll({ credentials, pollId })
-  }
-
-  const updateNotificationSettings = ({ settings }) => {
-    return apiService.updateNotificationSettings({ credentials, settings })
-  }
-
-  const fetchMutes = () => apiService.fetchMutes({ credentials })
-  const muteUser = (id) => apiService.muteUser({ credentials, id })
-  const unmuteUser = (id) => apiService.unmuteUser({ credentials, id })
-  const subscribeUser = (id) => apiService.subscribeUser({ credentials, id })
-  const unsubscribeUser = (id) => apiService.unsubscribeUser({ credentials, id })
-  const fetchBlocks = () => apiService.fetchBlocks({ credentials })
-  const fetchOAuthTokens = () => apiService.fetchOAuthTokens({ credentials })
-  const revokeOAuthToken = (id) => apiService.revokeOAuthToken({ id, credentials })
-  const fetchPinnedStatuses = (id) => apiService.fetchPinnedStatuses({ credentials, id })
-  const pinOwnStatus = (id) => apiService.pinOwnStatus({ credentials, id })
-  const unpinOwnStatus = (id) => apiService.unpinOwnStatus({ credentials, id })
-  const muteConversation = (id) => apiService.muteConversation({ credentials, id })
-  const unmuteConversation = (id) => apiService.unmuteConversation({ credentials, id })
-
-  const getCaptcha = () => apiService.getCaptcha()
-  const register = (params) => apiService.register({ credentials, params })
-  const updateAvatar = ({ avatar }) => apiService.updateAvatar({ credentials, avatar })
-  const updateBg = ({ background }) => apiService.updateBg({ credentials, background })
-  const updateBanner = ({ banner }) => apiService.updateBanner({ credentials, banner })
-  const updateProfile = ({ params }) => apiService.updateProfile({ credentials, params })
-
-  const importBlocks = (file) => apiService.importBlocks({ file, credentials })
-  const importFollows = (file) => apiService.importFollows({ file, credentials })
-
-  const deleteAccount = ({ password }) => apiService.deleteAccount({ credentials, password })
-  const changeEmail = ({ email, password }) => apiService.changeEmail({ credentials, email, password })
-  const changePassword = ({ password, newPassword, newPasswordConfirmation }) =>
-    apiService.changePassword({ credentials, password, newPassword, newPasswordConfirmation })
-
-  const fetchSettingsMFA = () => apiService.settingsMFA({ credentials })
-  const generateMfaBackupCodes = () => apiService.generateMfaBackupCodes({ credentials })
-  const mfaSetupOTP = () => apiService.mfaSetupOTP({ credentials })
-  const mfaConfirmOTP = ({ password, token }) => apiService.mfaConfirmOTP({ credentials, password, token })
-  const mfaDisableOTP = ({ password }) => apiService.mfaDisableOTP({ credentials, password })
-
-  const fetchFavoritedByUsers = (id) => apiService.fetchFavoritedByUsers({ id })
-  const fetchRebloggedByUsers = (id) => apiService.fetchRebloggedByUsers({ id })
-  const reportUser = (params) => apiService.reportUser({ credentials, ...params })
-
-  const favorite = (id) => apiService.favorite({ id, credentials })
-  const unfavorite = (id) => apiService.unfavorite({ id, credentials })
-  const retweet = (id) => apiService.retweet({ id, credentials })
-  const unretweet = (id) => apiService.unretweet({ id, credentials })
-  const search2 = ({ q, resolve, limit, offset, following }) =>
-    apiService.search2({ credentials, q, resolve, limit, offset, following })
-  const searchUsers = (query) => apiService.searchUsers({ query, credentials })
-
-  const backendInteractorServiceInstance = {
-    fetchStatus,
-    fetchConversation,
-    fetchFriends,
-    exportFriends,
-    fetchFollowers,
-    followUser,
-    unfollowUser,
-    blockUser,
-    unblockUser,
-    fetchUser,
-    fetchUserRelationship,
-    verifyCredentials: apiService.verifyCredentials,
-    startFetchingTimeline,
-    startFetchingNotifications,
-    startFetchingFollowRequest,
-    fetchMutes,
-    muteUser,
-    unmuteUser,
-    subscribeUser,
-    unsubscribeUser,
-    fetchBlocks,
-    fetchOAuthTokens,
-    revokeOAuthToken,
-    fetchPinnedStatuses,
-    pinOwnStatus,
-    unpinOwnStatus,
-    muteConversation,
-    unmuteConversation,
-    tagUser,
-    untagUser,
-    addRight,
-    deleteRight,
-    deleteUser,
-    setActivationStatus,
-    register,
-    getCaptcha,
-    updateAvatar,
-    updateBg,
-    updateBanner,
-    updateProfile,
-    importBlocks,
-    importFollows,
-    deleteAccount,
-    changeEmail,
-    changePassword,
-    fetchSettingsMFA,
-    generateMfaBackupCodes,
-    mfaSetupOTP,
-    mfaConfirmOTP,
-    mfaDisableOTP,
-    approveUser,
-    denyUser,
-    vote,
-    fetchPoll,
-    fetchFavoritedByUsers,
-    fetchRebloggedByUsers,
-    reportUser,
-    favorite,
-    unfavorite,
-    retweet,
-    unretweet,
-    updateNotificationSettings,
-    search2,
-    searchUsers
-  }
-
-  return backendInteractorServiceInstance
-}
+  verifyCredentials: apiService.verifyCredentials
+})
 
 export default backendInteractorService
diff --git a/src/services/follow_manipulate/follow_manipulate.js b/src/services/follow_manipulate/follow_manipulate.js
index 598cb5f7..29b38a0f 100644
--- a/src/services/follow_manipulate/follow_manipulate.js
+++ b/src/services/follow_manipulate/follow_manipulate.js
@@ -39,7 +39,7 @@ export const requestFollow = (user, store) => new Promise((resolve, reject) => {
 })
 
 export const requestUnfollow = (user, store) => new Promise((resolve, reject) => {
-  store.state.api.backendInteractor.unfollowUser(user.id)
+  store.state.api.backendInteractor.unfollowUser({ id: user.id })
     .then((updated) => {
       store.commit('updateUserRelationship', [updated])
       resolve({

From 319bb4ac2895b8eb62da42e3f95addc9bb67b1a0 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sun, 24 Nov 2019 18:50:28 +0200
Subject: [PATCH 08/62] initial streaming work

---
 src/modules/api.js                            | 15 +++++++
 src/modules/users.js                          | 11 +++--
 src/services/api/api.service.js               | 40 +++++++++++++++++++
 .../backend_interactor_service.js             | 15 ++++++-
 4 files changed, 76 insertions(+), 5 deletions(-)

diff --git a/src/modules/api.js b/src/modules/api.js
index 1293e3c8..1bf65db5 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -6,6 +6,7 @@ const api = {
     backendInteractor: backendInteractorService(),
     fetchers: {},
     socket: null,
+    mastoSocket: null,
     followRequests: []
   },
   mutations: {
@@ -29,6 +30,20 @@ const api = {
     }
   },
   actions: {
+    startMastoSocket (store) {
+      store.state.mastoSocket = store.state.backendInteractor
+        .startUserSocket({
+          store,
+          onMessage: (message) => {
+            if (!message) return
+            if (message.event === 'notification') {
+              store.dispatch('addNewNotifications', { notifications: [message.notification], older: false })
+            } else if (message.event === 'update') {
+              store.dispatch('addNewStatuses', { statuses: [message.status], userId: false, showImmediately: false, timeline: 'friends' })
+            }
+          }
+        })
+    },
     startFetchingTimeline (store, { timeline = 'friends', tag = false, userId = false }) {
       // Don't start fetching if we already are.
       if (store.state.fetchers[timeline]) return
diff --git a/src/modules/users.js b/src/modules/users.js
index e1373220..861a2f4f 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -469,11 +469,14 @@ const users = {
                 store.dispatch('initializeSocket')
               }
 
-              // Start getting fresh posts.
-              store.dispatch('startFetchingTimeline', { timeline: 'friends' })
+              store.dispatch('startMastoSocket').catch((error) => {
+                console.error(error)
+                // Start getting fresh posts.
+                store.dispatch('startFetchingTimeline', { timeline: 'friends' })
 
-              // Start fetching notifications
-              store.dispatch('startFetchingNotifications')
+                // Start fetching notifications
+                store.dispatch('startFetchingNotifications')
+              })
 
               // Get user mutes
               store.dispatch('fetchMutes')
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 8f5eb416..7f27564f 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -71,6 +71,7 @@ const MASTODON_MUTE_CONVERSATION = id => `/api/v1/statuses/${id}/mute`
 const MASTODON_UNMUTE_CONVERSATION = id => `/api/v1/statuses/${id}/unmute`
 const MASTODON_SEARCH_2 = `/api/v2/search`
 const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
+const MASTODON_STREAMING = '/api/v1/streaming'
 
 const oldfetch = window.fetch
 
@@ -932,6 +933,45 @@ const search2 = ({ credentials, q, resolve, limit, offset, following }) => {
     })
 }
 
+export const getMastodonSocketURI = ({ credentials, stream, args = {} }) => {
+  return Object.entries({
+    ...(credentials
+      ? { access_token: credentials }
+      : {}
+    ),
+    stream,
+    ...args
+  }).reduce((acc, [key, val]) => {
+    return acc + `${key}=${val}&`
+  }, MASTODON_STREAMING + '?')
+}
+
+const MASTODON_STREAMING_EVENTS = new Set([
+  'update',
+  'notification',
+  'delete',
+  'filters_changed'
+])
+
+export const handleMastoWS = (wsEvent) => {
+  console.debug('Event', wsEvent)
+  const { data } = wsEvent
+  if (!data) return
+  const parsedEvent = JSON.parse(data)
+  const { event, payload } = parsedEvent
+  if (MASTODON_STREAMING_EVENTS.has(event)) {
+    const data = payload ? JSON.parse(payload) : null
+    if (event === 'update') {
+      return { event, status: parseStatus(data) }
+    } else if (event === 'notification') {
+      return { event, notification: parseNotification(data) }
+    }
+  } else {
+    console.warn('Unknown event', wsEvent)
+    return null
+  }
+}
+
 const apiService = {
   verifyCredentials,
   fetchTimeline,
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 57fdccde..0cef4640 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -1,4 +1,4 @@
-import apiService from '../api/api.service.js'
+import apiService, { getMastodonSocketURI, handleMastoWS } from '../api/api.service.js'
 import timelineFetcherService from '../timeline_fetcher/timeline_fetcher.service.js'
 import notificationsFetcher from '../notifications_fetcher/notifications_fetcher.service.js'
 import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
@@ -16,6 +16,19 @@ const backendInteractorService = credentials => ({
     return followRequestFetcher.startFetching({ store, credentials })
   },
 
+  startUserSocket ({ store, onMessage }) {
+    const serv = store.rootState.instance.server.replace('https', 'wss')
+    // const serb = 'ws://localhost:8080/'
+    const url = serv + getMastodonSocketURI({ credentials, stream: 'user' })
+    const socket = new WebSocket(url)
+    console.log(socket)
+    if (socket) {
+      socket.addEventListener('message', (wsEvent) => onMessage(handleMastoWS(wsEvent)))
+    } else {
+      throw new Error('failed to connect to socket')
+    }
+  },
+
   ...Object.entries(apiService).reduce((acc, [key, func]) => {
     return {
       ...acc,

From 172ebaf4e67358852bfaafd8f069763ca5e602b1 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sun, 24 Nov 2019 22:01:12 +0200
Subject: [PATCH 09/62] improved initial notifications fetching

---
 src/components/notifications/notifications.js |  5 ++++
 src/modules/api.js                            | 23 ++++++++++++++++---
 src/modules/users.js                          |  2 +-
 .../backend_interactor_service.js             |  9 ++++++--
 4 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js
index 6c4054fd..a89c0cdc 100644
--- a/src/components/notifications/notifications.js
+++ b/src/components/notifications/notifications.js
@@ -47,6 +47,11 @@ const Notifications = {
   components: {
     Notification
   },
+  created () {
+    const { dispatch } = this.$store
+
+    dispatch('fetchAndUpdateNotifications')
+  },
   watch: {
     unseenCount (count) {
       if (count > 0) {
diff --git a/src/modules/api.js b/src/modules/api.js
index 1bf65db5..0e7e5e19 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -31,18 +31,32 @@ const api = {
   },
   actions: {
     startMastoSocket (store) {
-      store.state.mastoSocket = store.state.backendInteractor
+      const { state, dispatch } = store
+      state.mastoSocket = state.backendInteractor
         .startUserSocket({
           store,
           onMessage: (message) => {
             if (!message) return
             if (message.event === 'notification') {
-              store.dispatch('addNewNotifications', { notifications: [message.notification], older: false })
+              dispatch('addNewNotifications', {
+                notifications: [message.notification],
+                older: false
+              })
             } else if (message.event === 'update') {
-              store.dispatch('addNewStatuses', { statuses: [message.status], userId: false, showImmediately: false, timeline: 'friends' })
+              dispatch('addNewStatuses', {
+                statuses: [message.status],
+                userId: false,
+                showImmediately: false,
+                timeline: 'friends'
+              })
             }
           }
         })
+      state.mastoSocket.addEventListener('error', error => {
+        console.error('Error with MastoAPI websocket:', error)
+        dispatch('startFetchingTimeline', { timeline: 'friends' })
+        dispatch('startFetchingNotifications')
+      })
     },
     startFetchingTimeline (store, { timeline = 'friends', tag = false, userId = false }) {
       // Don't start fetching if we already are.
@@ -58,6 +72,9 @@ const api = {
       const fetcher = store.state.backendInteractor.startFetchingNotifications({ store })
       store.commit('addFetcher', { fetcherName: 'notifications', fetcher })
     },
+    fetchAndUpdateNotifications (store) {
+      store.state.backendInteractor.fetchAndUpdateNotifications({ store })
+    },
     startFetchingFollowRequest (store) {
       // Don't start fetching if we already are.
       if (store.state.fetchers['followRequest']) return
diff --git a/src/modules/users.js b/src/modules/users.js
index 861a2f4f..eff0c5d5 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -470,7 +470,7 @@ const users = {
               }
 
               store.dispatch('startMastoSocket').catch((error) => {
-                console.error(error)
+                console.error('Failed initializing MastoAPI Streaming socket', error)
                 // Start getting fresh posts.
                 store.dispatch('startFetchingTimeline', { timeline: 'friends' })
 
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 0cef4640..850b7867 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -12,18 +12,23 @@ const backendInteractorService = credentials => ({
     return notificationsFetcher.startFetching({ store, credentials })
   },
 
+  fetchAndUpdateNotifications ({ store }) {
+    return notificationsFetcher.fetchAndUpdate({ store, credentials })
+  },
+
   startFetchingFollowRequest ({ store }) {
     return followRequestFetcher.startFetching({ store, credentials })
   },
 
   startUserSocket ({ store, onMessage }) {
-    const serv = store.rootState.instance.server.replace('https', 'wss')
-    // const serb = 'ws://localhost:8080/'
+    const serv = store.rootState.instance.server.replace('http', 'ws')
     const url = serv + getMastodonSocketURI({ credentials, stream: 'user' })
     const socket = new WebSocket(url)
     console.log(socket)
     if (socket) {
       socket.addEventListener('message', (wsEvent) => onMessage(handleMastoWS(wsEvent)))
+      socket.addEventListener('error', (error) => console.error('WebSocket Error:', error))
+      return socket
     } else {
       throw new Error('failed to connect to socket')
     }

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 10/62] 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 })
       }

From 01855f315c7db813d7bbf2f3683017819d2fb70c Mon Sep 17 00:00:00 2001
From: Wyatt Benno <wyattbenno@gmail.com>
Date: Fri, 6 Dec 2019 09:38:55 +0900
Subject: [PATCH 11/62] Wording updates

---
 src/components/timeline/timeline.vue                      | 2 +-
 src/i18n/en.json                                          | 3 +--
 src/services/timeline_fetcher/timeline_fetcher.service.js | 2 +-
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue
index 1c45d0f6..e4d453b8 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -84,7 +84,7 @@
         v-else-if="error403"
         href="#"
       >
-        <div class="new-status-notification text-center panel-footer">{{ $t('timeline.error_403_message') }}</div>
+        <div class="new-status-notification text-center panel-footer">{{ error403 }}</div>
       </a>
       <div
         v-else
diff --git a/src/i18n/en.json b/src/i18n/en.json
index c203e156..1dd99062 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -535,8 +535,7 @@
     "collapse": "Collapse",
     "conversation": "Conversation",
     "error_fetching": "Error fetching updates",
-    "error_403": "This timeline is not public.",
-    "error_403_message": "Please sign in.",
+    "error_403": "Access denied",
     "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/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js
index 9352d73a..b7952050 100644
--- a/src/services/timeline_fetcher/timeline_fetcher.service.js
+++ b/src/services/timeline_fetcher/timeline_fetcher.service.js
@@ -48,7 +48,7 @@ const fetchAndUpdate = ({
     .then((statuses) => {
       // Change messaging if not public
       if (statuses.error) {
-        store.dispatch('set403Error', { value: true })
+        store.dispatch('set403Error', { value: statuses.error })
         return
       }
       if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) {

From 914c78398469988f549930bd35d044082d155277 Mon Sep 17 00:00:00 2001
From: Absturztaube <me@absturztau.be>
Date: Sat, 7 Dec 2019 10:29:53 +0100
Subject: [PATCH 12/62] fix sticker picker height in emojo picker

---
 src/components/emoji_picker/emoji_picker.scss | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/components/emoji_picker/emoji_picker.scss b/src/components/emoji_picker/emoji_picker.scss
index 6608f393..29010c5b 100644
--- a/src/components/emoji_picker/emoji_picker.scss
+++ b/src/components/emoji_picker/emoji_picker.scss
@@ -101,6 +101,10 @@
     }
   }
 
+  .stickers-content {
+    min-height: 269px;
+  }
+
   .emoji {
     &-search {
       padding: 5px;

From a06705d9390b738ccace9fb6a0c213306f753f42 Mon Sep 17 00:00:00 2001
From: Ivan Tashkinov <ivantashkinov@gmail.com>
Date: Sun, 8 Dec 2019 13:52:26 +0300
Subject: [PATCH 13/62] Added OAuth 'push' and 'admin' scopes.

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

diff --git a/src/services/new_api/oauth.js b/src/services/new_api/oauth.js
index d0d18c03..3c8e64bd 100644
--- a/src/services/new_api/oauth.js
+++ b/src/services/new_api/oauth.js
@@ -12,7 +12,7 @@ export const getOrCreateApp = ({ clientId, clientSecret, instance, commit }) =>
 
   form.append('client_name', `PleromaFE_${window.___pleromafe_commit_hash}_${(new Date()).toISOString()}`)
   form.append('redirect_uris', REDIRECT_URI)
-  form.append('scopes', 'read write follow')
+  form.append('scopes', 'read write follow push admin')
 
   return window.fetch(url, {
     method: 'POST',
@@ -28,7 +28,7 @@ const login = ({ instance, clientId }) => {
     response_type: 'code',
     client_id: clientId,
     redirect_uri: REDIRECT_URI,
-    scope: 'read write follow'
+    scope: 'read write follow push admin'
   }
 
   const dataString = reduce(data, (acc, v, k) => {

From ff95d865d223fed5bab2a4d72ff3a22f014d3c56 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sun, 8 Dec 2019 16:05:41 +0200
Subject: [PATCH 14/62] Updated streaming and improved error-handling, some
 more refactoring to api

---
 .../public_and_external_timeline.js           |  2 +-
 .../public_timeline/public_timeline.js        |  2 +-
 src/components/tag_timeline/tag_timeline.js   |  2 +-
 src/components/user_profile/user_profile.js   |  6 +-
 src/modules/api.js                            | 99 +++++++++++++------
 src/modules/users.js                          |  8 +-
 .../backend_interactor_service.js             |  5 +-
 7 files changed, 84 insertions(+), 40 deletions(-)

diff --git a/src/components/public_and_external_timeline/public_and_external_timeline.js b/src/components/public_and_external_timeline/public_and_external_timeline.js
index f614c13b..cbd4491b 100644
--- a/src/components/public_and_external_timeline/public_and_external_timeline.js
+++ b/src/components/public_and_external_timeline/public_and_external_timeline.js
@@ -10,7 +10,7 @@ const PublicAndExternalTimeline = {
     this.$store.dispatch('startFetchingTimeline', { timeline: 'publicAndExternal' })
   },
   destroyed () {
-    this.$store.dispatch('stopFetching', 'publicAndExternal')
+    this.$store.dispatch('stopFetchingTimeline', 'publicAndExternal')
   }
 }
 
diff --git a/src/components/public_timeline/public_timeline.js b/src/components/public_timeline/public_timeline.js
index 8976a99c..66c40d3a 100644
--- a/src/components/public_timeline/public_timeline.js
+++ b/src/components/public_timeline/public_timeline.js
@@ -10,7 +10,7 @@ const PublicTimeline = {
     this.$store.dispatch('startFetchingTimeline', { timeline: 'public' })
   },
   destroyed () {
-    this.$store.dispatch('stopFetching', 'public')
+    this.$store.dispatch('stopFetchingTimeline', 'public')
   }
 
 }
diff --git a/src/components/tag_timeline/tag_timeline.js b/src/components/tag_timeline/tag_timeline.js
index 458eb1c5..400c6a4b 100644
--- a/src/components/tag_timeline/tag_timeline.js
+++ b/src/components/tag_timeline/tag_timeline.js
@@ -19,7 +19,7 @@ const TagTimeline = {
     }
   },
   destroyed () {
-    this.$store.dispatch('stopFetching', 'tag')
+    this.$store.dispatch('stopFetchingTimeline', 'tag')
   }
 }
 
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
index 00055707..9558a0bd 100644
--- a/src/components/user_profile/user_profile.js
+++ b/src/components/user_profile/user_profile.js
@@ -112,9 +112,9 @@ const UserProfile = {
       }
     },
     stopFetching () {
-      this.$store.dispatch('stopFetching', 'user')
-      this.$store.dispatch('stopFetching', 'favorites')
-      this.$store.dispatch('stopFetching', 'media')
+      this.$store.dispatch('stopFetchingTimeline', 'user')
+      this.$store.dispatch('stopFetchingTimeline', 'favorites')
+      this.$store.dispatch('stopFetchingTimeline', 'media')
     },
     switchUser (userNameOrId) {
       this.stopFetching()
diff --git a/src/modules/api.js b/src/modules/api.js
index 0e7e5e19..185c9db6 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -6,7 +6,7 @@ const api = {
     backendInteractor: backendInteractorService(),
     fetchers: {},
     socket: null,
-    mastoSocket: null,
+    mastoUserSocket: null,
     followRequests: []
   },
   mutations: {
@@ -16,7 +16,8 @@ const api = {
     addFetcher (state, { fetcherName, fetcher }) {
       state.fetchers[fetcherName] = fetcher
     },
-    removeFetcher (state, { fetcherName }) {
+    removeFetcher (state, { fetcherName, fetcher }) {
+      window.clearInterval(fetcher)
       delete state.fetchers[fetcherName]
     },
     setWsToken (state, token) {
@@ -30,13 +31,14 @@ const api = {
     }
   },
   actions: {
-    startMastoSocket (store) {
+    // MastoAPI 'User' sockets
+    startMastoUserSocket (store) {
       const { state, dispatch } = store
-      state.mastoSocket = state.backendInteractor
+      state.mastoUserSocket = state.backendInteractor
         .startUserSocket({
           store,
           onMessage: (message) => {
-            if (!message) return
+            if (!message) return // pings
             if (message.event === 'notification') {
               dispatch('addNewNotifications', {
                 notifications: [message.notification],
@@ -52,41 +54,86 @@ const api = {
             }
           }
         })
-      state.mastoSocket.addEventListener('error', error => {
-        console.error('Error with MastoAPI websocket:', error)
-        dispatch('startFetchingTimeline', { timeline: 'friends' })
-        dispatch('startFetchingNotifications')
+      state.mastoUserSocket.addEventListener('error', error => {
+        console.error('Error in MastoAPI websocket:', error)
+      })
+      state.mastoUserSocket.addEventListener('close', closeEvent => {
+        const ignoreCodes = new Set([
+          1000, // Normal (intended) closure
+          1001 // Going away
+        ])
+        const { code } = closeEvent
+        console.debug('Socket closure event:', closeEvent)
+        if (ignoreCodes.has(code)) {
+          console.debug(`Not restarting socket becasue of closure code ${code} is in ignore list`)
+        } else {
+          console.warn(`MastoAPI websocket disconnected, restarting. CloseEvent code: ${code}`)
+          dispatch('startFetchingTimeline', { timeline: 'friends' })
+          dispatch('startFetchingNotifications')
+          dispatch('restartMastoUserSocket')
+        }
       })
     },
-    startFetchingTimeline (store, { timeline = 'friends', tag = false, userId = false }) {
-      // Don't start fetching if we already are.
+    restartMastoUserSocket ({ dispatch }) {
+      // This basically starts MastoAPI user socket and stops conventional
+      // fetchers when connection reestablished
+      dispatch('startMastoUserSocket').then(() => {
+        dispatch('stopFetchingTimeline', { timeline: 'friends' })
+        dispatch('stopFetchingNotifications')
+      })
+    },
+
+    // Timelines
+    startFetchingTimeline (store, {
+      timeline = 'friends',
+      tag = false,
+      userId = false
+    }) {
       if (store.state.fetchers[timeline]) return
 
-      const fetcher = store.state.backendInteractor.startFetchingTimeline({ timeline, store, userId, tag })
+      const fetcher = store.state.backendInteractor.startFetchingTimeline({
+        timeline, store, userId, tag
+      })
       store.commit('addFetcher', { fetcherName: timeline, fetcher })
     },
-    startFetchingNotifications (store) {
-      // Don't start fetching if we already are.
-      if (store.state.fetchers['notifications']) return
+    stopFetchingTimeline (store, timeline) {
+      const fetcher = store.state.fetchers[timeline]
+      if (!fetcher) return
+      store.commit('removeFetcher', { fetcherName: timeline, fetcher })
+    },
 
+    // Notifications
+    startFetchingNotifications (store) {
+      if (store.state.fetchers.notifications) return
       const fetcher = store.state.backendInteractor.startFetchingNotifications({ store })
       store.commit('addFetcher', { fetcherName: 'notifications', fetcher })
     },
+    stopFetchingNotifications (store) {
+      const fetcher = store.state.fetchers.notifications
+      if (!fetcher) return
+      store.commit('removeFetcher', { fetcherName: 'notifications', fetcher })
+    },
     fetchAndUpdateNotifications (store) {
       store.state.backendInteractor.fetchAndUpdateNotifications({ store })
     },
-    startFetchingFollowRequest (store) {
-      // Don't start fetching if we already are.
-      if (store.state.fetchers['followRequest']) return
 
-      const fetcher = store.state.backendInteractor.startFetchingFollowRequest({ store })
-      store.commit('addFetcher', { fetcherName: 'followRequest', fetcher })
+    // Follow requests
+    startFetchingFollowRequests (store) {
+      if (store.state.fetchers['followRequests']) return
+      const fetcher = store.state.backendInteractor.startFetchingFollowRequests({ store })
+      store.commit('addFetcher', { fetcherName: 'followRequests', fetcher })
     },
-    stopFetching (store, fetcherName) {
-      const fetcher = store.state.fetchers[fetcherName]
-      window.clearInterval(fetcher)
-      store.commit('removeFetcher', { fetcherName })
+    stopFetchingFollowRequests (store) {
+      const fetcher = store.state.fetchers.followRequests
+      if (!fetcher) return
+      store.commit('removeFetcher', { fetcherName: 'followRequests', fetcher })
     },
+    removeFollowRequest (store, request) {
+      let requests = store.state.followRequests.filter((it) => it !== request)
+      store.commit('setFollowRequests', requests)
+    },
+
+    // Pleroma websocket
     setWsToken (store, token) {
       store.commit('setWsToken', token)
     },
@@ -104,10 +151,6 @@ const api = {
     disconnectFromSocket ({ commit, state }) {
       state.socket && state.socket.disconnect()
       commit('setSocket', null)
-    },
-    removeFollowRequest (store, request) {
-      let requests = store.state.followRequests.filter((it) => it !== request)
-      store.commit('setFollowRequests', requests)
     }
   }
 }
diff --git a/src/modules/users.js b/src/modules/users.js
index eff0c5d5..6bdaf193 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -431,10 +431,10 @@ const users = {
           store.commit('clearCurrentUser')
           store.dispatch('disconnectFromSocket')
           store.commit('clearToken')
-          store.dispatch('stopFetching', 'friends')
+          store.dispatch('stopFetchingTimeline', 'friends')
           store.commit('setBackendInteractor', backendInteractorService(store.getters.getToken()))
-          store.dispatch('stopFetching', 'notifications')
-          store.dispatch('stopFetching', 'followRequest')
+          store.dispatch('stopFetchingNotifications')
+          store.dispatch('stopFetchingFollowRequests')
           store.commit('clearNotifications')
           store.commit('resetStatuses')
         })
@@ -469,7 +469,7 @@ const users = {
                 store.dispatch('initializeSocket')
               }
 
-              store.dispatch('startMastoSocket').catch((error) => {
+              store.dispatch('startMastoUserSocket').catch((error) => {
                 console.error('Failed initializing MastoAPI Streaming socket', error)
                 // Start getting fresh posts.
                 store.dispatch('startFetchingTimeline', { timeline: 'friends' })
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 850b7867..33b79a40 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -24,10 +24,11 @@ const backendInteractorService = credentials => ({
     const serv = store.rootState.instance.server.replace('http', 'ws')
     const url = serv + getMastodonSocketURI({ credentials, stream: 'user' })
     const socket = new WebSocket(url)
-    console.log(socket)
+    console.debug('Socket created:', socket)
     if (socket) {
+      socket.addEventListener('open', (wsEvent) => console.debug('MastoAPI User WebSocket connection established'))
       socket.addEventListener('message', (wsEvent) => onMessage(handleMastoWS(wsEvent)))
-      socket.addEventListener('error', (error) => console.error('WebSocket Error:', error))
+      socket.addEventListener('error', (error) => console.error('MastoApi User WebSocket Error:', error))
       return socket
     } else {
       throw new Error('failed to connect to socket')

From 505fb260610e557e27bbc5d27515337ea07e0e3e Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sun, 8 Dec 2019 19:18:38 +0200
Subject: [PATCH 15/62] better wrapper for websocket

---
 src/modules/api.js                            | 43 +++++++++--------
 src/services/api/api.service.js               | 46 ++++++++++++++++++-
 .../backend_interactor_service.js             | 15 ++----
 3 files changed, 69 insertions(+), 35 deletions(-)

diff --git a/src/modules/api.js b/src/modules/api.js
index 185c9db6..593f8498 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -34,36 +34,35 @@ const api = {
     // MastoAPI 'User' sockets
     startMastoUserSocket (store) {
       const { state, dispatch } = store
-      state.mastoUserSocket = state.backendInteractor
-        .startUserSocket({
-          store,
-          onMessage: (message) => {
-            if (!message) return // pings
-            if (message.event === 'notification') {
-              dispatch('addNewNotifications', {
-                notifications: [message.notification],
-                older: false
-              })
-            } else if (message.event === 'update') {
-              dispatch('addNewStatuses', {
-                statuses: [message.status],
-                userId: false,
-                showImmediately: false,
-                timeline: 'friends'
-              })
-            }
+      state.mastoUserSocket = state.backendInteractor.startUserSocket({ store })
+      state.mastoUserSocket.addEventListener(
+        'message',
+        ({ detail: message }) => {
+          if (!message) return // pings
+          if (message.event === 'notification') {
+            dispatch('addNewNotifications', {
+              notifications: [message.notification],
+              older: false
+            })
+          } else if (message.event === 'update') {
+            dispatch('addNewStatuses', {
+              statuses: [message.status],
+              userId: false,
+              showImmediately: false,
+              timeline: 'friends'
+            })
           }
-        })
-      state.mastoUserSocket.addEventListener('error', error => {
+        }
+      )
+      state.mastoUserSocket.addEventListener('error', ({ detail: error }) => {
         console.error('Error in MastoAPI websocket:', error)
       })
-      state.mastoUserSocket.addEventListener('close', closeEvent => {
+      state.mastoUserSocket.addEventListener('close', ({ detail: closeEvent }) => {
         const ignoreCodes = new Set([
           1000, // Normal (intended) closure
           1001 // Going away
         ])
         const { code } = closeEvent
-        console.debug('Socket closure event:', closeEvent)
         if (ignoreCodes.has(code)) {
           console.debug(`Not restarting socket becasue of closure code ${code} is in ignore list`)
         } else {
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 7f27564f..c6818df4 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -953,8 +953,52 @@ const MASTODON_STREAMING_EVENTS = new Set([
   'filters_changed'
 ])
 
+// A thin wrapper around WebSocket API that allows adding a pre-processor to it
+// Uses EventTarget and a CustomEvent to proxy events
+export const ProcessedWS = ({
+  url,
+  preprocessor = handleMastoWS,
+  id = 'Unknown'
+}) => {
+  const eventTarget = new EventTarget()
+  const socket = new WebSocket(url)
+  if (!socket) throw new Error(`Failed to create socket ${id}`)
+  const proxy = (original, eventName, processor = a => a) => {
+    original.addEventListener(eventName, (eventData) => {
+      eventTarget.dispatchEvent(new CustomEvent(
+        eventName,
+        { detail: processor(eventData) }
+      ))
+    })
+  }
+  socket.addEventListener('open', (wsEvent) => {
+    console.debug(`[WS][${id}] Socket connected`, wsEvent)
+  })
+  socket.addEventListener('error', (wsEvent) => {
+    console.debug(`[WS][${id}] Socket errored`, wsEvent)
+  })
+  socket.addEventListener('close', (wsEvent) => {
+    console.debug(
+      `[WS][${id}] Socket disconnected with code ${wsEvent.code}`,
+      wsEvent
+    )
+  })
+  socket.addEventListener('message', (wsEvent) => {
+    console.debug(
+      `[WS][${id}] Message received`,
+      wsEvent
+    )
+  })
+
+  proxy(socket, 'open')
+  proxy(socket, 'close')
+  proxy(socket, 'message', preprocessor)
+  proxy(socket, 'error')
+
+  return eventTarget
+}
+
 export const handleMastoWS = (wsEvent) => {
-  console.debug('Event', wsEvent)
   const { data } = wsEvent
   if (!data) return
   const parsedEvent = JSON.parse(data)
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 33b79a40..b7372ed0 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -1,4 +1,4 @@
-import apiService, { getMastodonSocketURI, handleMastoWS } from '../api/api.service.js'
+import apiService, { getMastodonSocketURI, ProcessedWS } from '../api/api.service.js'
 import timelineFetcherService from '../timeline_fetcher/timeline_fetcher.service.js'
 import notificationsFetcher from '../notifications_fetcher/notifications_fetcher.service.js'
 import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
@@ -20,19 +20,10 @@ const backendInteractorService = credentials => ({
     return followRequestFetcher.startFetching({ store, credentials })
   },
 
-  startUserSocket ({ store, onMessage }) {
+  startUserSocket ({ store }) {
     const serv = store.rootState.instance.server.replace('http', 'ws')
     const url = serv + getMastodonSocketURI({ credentials, stream: 'user' })
-    const socket = new WebSocket(url)
-    console.debug('Socket created:', socket)
-    if (socket) {
-      socket.addEventListener('open', (wsEvent) => console.debug('MastoAPI User WebSocket connection established'))
-      socket.addEventListener('message', (wsEvent) => onMessage(handleMastoWS(wsEvent)))
-      socket.addEventListener('error', (error) => console.error('MastoApi User WebSocket Error:', error))
-      return socket
-    } else {
-      throw new Error('failed to connect to socket')
-    }
+    return ProcessedWS({ url, id: 'User' })
   },
 
   ...Object.entries(apiService).reduce((acc, [key, func]) => {

From e86af0c965d459d016d638c0822bc9af6a6c0ee1 Mon Sep 17 00:00:00 2001
From: Wyatt Benno <wyattbenno@gmail.com>
Date: Mon, 9 Dec 2019 09:02:34 +0900
Subject: [PATCH 16/62] Change naming, make more general

---
 src/components/timeline/timeline.js                  |  4 ++--
 src/components/timeline/timeline.vue                 | 12 ++++++------
 src/modules/statuses.js                              | 10 +++++-----
 src/services/api/api.service.js                      |  5 +----
 .../timeline_fetcher/timeline_fetcher.service.js     |  6 +++---
 5 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js
index 6086336c..9a53acd6 100644
--- a/src/components/timeline/timeline.js
+++ b/src/components/timeline/timeline.js
@@ -39,8 +39,8 @@ const Timeline = {
     timelineError () {
       return this.$store.state.statuses.error
     },
-    error403 () {
-      return this.$store.state.statuses.error403
+    errorData () {
+      return this.$store.state.statuses.errorData
     },
     newStatusCount () {
       return this.timeline.newStatusCount
diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue
index e4d453b8..d9f4025d 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -12,21 +12,21 @@
         {{ $t('timeline.error_fetching') }}
       </div>
       <div
-        v-else-if="error403"
+        v-else-if="errorData"
         class="loadmore-error alert error"
         @click.prevent
       >
         {{ $t('timeline.error_403') }}
       </div>
       <button
-        v-if="timeline.newStatusCount > 0 && !timelineError && !error403"
+        v-if="timeline.newStatusCount > 0 && !timelineError && !errorData"
         class="loadmore-button"
         @click.prevent="showNewStatuses"
       >
         {{ $t('timeline.show_new') }}{{ newStatusCountStr }}
       </button>
       <div
-        v-if="!timeline.newStatusCount > 0 && !timelineError && !error403"
+        v-if="!timeline.newStatusCount > 0 && !timelineError && !errorData"
         class="loadmore-text faint"
         @click.prevent
       >
@@ -74,17 +74,17 @@
         {{ $t('timeline.no_more_statuses') }}
       </div>
       <a
-        v-else-if="!timeline.loading && !error403"
+        v-else-if="!timeline.loading && !errorData"
         href="#"
         @click.prevent="fetchOlderStatuses()"
       >
         <div class="new-status-notification text-center panel-footer">{{ $t('timeline.load_older') }}</div>
       </a>
       <a
-        v-else-if="error403"
+        v-else-if="errorData"
         href="#"
       >
-        <div class="new-status-notification text-center panel-footer">{{ error403 }}</div>
+        <div class="new-status-notification text-center panel-footer">{{ errorData }}</div>
       </a>
       <div
         v-else
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index d0e871c8..4068aa02 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -38,7 +38,7 @@ export const defaultState = () => ({
   notifications: emptyNotifications(),
   favorites: new Set(),
   error: false,
-  error403: false,
+  errorData: '',
   timelines: {
     mentions: emptyTl(),
     public: emptyTl(),
@@ -480,8 +480,8 @@ export const mutations = {
   setError (state, { value }) {
     state.error = value
   },
-  set403Error (state, { value }) {
-    state.error403 = value
+  setErrorData (state, { value }) {
+    state.errorData = value
   },
   setNotificationsLoading (state, { value }) {
     state.notifications.loading = value
@@ -532,8 +532,8 @@ const statuses = {
     setError ({ rootState, commit }, { value }) {
       commit('setError', { value })
     },
-    set403Error ({ rootState, commit }, { value }) {
-      commit('set403Error', { value })
+    setErrorData ({ rootState, commit }, { value }) {
+      commit('setErrorData', { 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 a2aa802f..45b63caf 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -532,10 +532,7 @@ const fetchTimeline = ({
 
   return fetch(url, { headers: authHeaders(credentials) })
     .then((data) => {
-      if (data.ok || data.status === 403) {
-        return data
-      }
-      throw new Error('Error fetching timeline', data)
+      return data
     })
     .then((data) => data.json())
     .then((data) => {
diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js
index b7952050..1aaae563 100644
--- a/src/services/timeline_fetcher/timeline_fetcher.service.js
+++ b/src/services/timeline_fetcher/timeline_fetcher.service.js
@@ -6,7 +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('setErrorData', { value: false })
 
   store.dispatch('addNewStatuses', {
     timeline: ccTimeline,
@@ -46,9 +46,9 @@ const fetchAndUpdate = ({
 
   return apiService.fetchTimeline(args)
     .then((statuses) => {
-      // Change messaging if not public
       if (statuses.error) {
-        store.dispatch('set403Error', { value: statuses.error })
+        console.log(statuses)
+        store.dispatch('setErrorData', { value: statuses.error })
         return
       }
       if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) {

From 1a043d4350c1cab2a56c5197ee8fb31e68593567 Mon Sep 17 00:00:00 2001
From: Wyatt Benno <wyattbenno@gmail.com>
Date: Mon, 9 Dec 2019 09:11:31 +0900
Subject: [PATCH 17/62] remove console

---
 src/services/timeline_fetcher/timeline_fetcher.service.js | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js
index 1aaae563..68644261 100644
--- a/src/services/timeline_fetcher/timeline_fetcher.service.js
+++ b/src/services/timeline_fetcher/timeline_fetcher.service.js
@@ -47,7 +47,6 @@ const fetchAndUpdate = ({
   return apiService.fetchTimeline(args)
     .then((statuses) => {
       if (statuses.error) {
-        console.log(statuses)
         store.dispatch('setErrorData', { value: statuses.error })
         return
       }

From 8ee80339555c53d45602f40fdbe6b487a6992515 Mon Sep 17 00:00:00 2001
From: Wyatt Benno <wyattbenno@gmail.com>
Date: Mon, 9 Dec 2019 10:31:57 +0900
Subject: [PATCH 18/62] Set error data

---
 src/components/timeline/timeline.vue                      | 4 ++--
 src/i18n/en.json                                          | 1 -
 src/modules/statuses.js                                   | 2 +-
 src/services/api/api.service.js                           | 7 ++++++-
 src/services/timeline_fetcher/timeline_fetcher.service.js | 4 ++--
 5 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue
index d9f4025d..bb4ab379 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -16,7 +16,7 @@
         class="loadmore-error alert error"
         @click.prevent
       >
-        {{ $t('timeline.error_403') }}
+        {{ errorData.statusText }}
       </div>
       <button
         v-if="timeline.newStatusCount > 0 && !timelineError && !errorData"
@@ -84,7 +84,7 @@
         v-else-if="errorData"
         href="#"
       >
-        <div class="new-status-notification text-center panel-footer">{{ errorData }}</div>
+        <div class="new-status-notification text-center panel-footer">{{ errorData.error }}</div>
       </a>
       <div
         v-else
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 1dd99062..85146ef5 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -535,7 +535,6 @@
     "collapse": "Collapse",
     "conversation": "Conversation",
     "error_fetching": "Error fetching updates",
-    "error_403": "Access denied",
     "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 4068aa02..e3a1f293 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -38,7 +38,7 @@ export const defaultState = () => ({
   notifications: emptyNotifications(),
   favorites: new Set(),
   error: false,
-  errorData: '',
+  errorData: null,
   timelines: {
     mentions: emptyTl(),
     public: emptyTl(),
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 45b63caf..63e72e30 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -529,9 +529,12 @@ const fetchTimeline = ({
 
   const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
   url += `?${queryString}`
-
+  let status = ''
+  let statusText = ''
   return fetch(url, { headers: authHeaders(credentials) })
     .then((data) => {
+      status = data.status
+      statusText = data.statusText
       return data
     })
     .then((data) => data.json())
@@ -539,6 +542,8 @@ const fetchTimeline = ({
       if (!data.error) {
         return data.map(isNotifications ? parseNotification : parseStatus)
       } else {
+        data.status = status
+        data.statusText = statusText
         return data
       }
     })
diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js
index 68644261..c6b28ad5 100644
--- a/src/services/timeline_fetcher/timeline_fetcher.service.js
+++ b/src/services/timeline_fetcher/timeline_fetcher.service.js
@@ -6,7 +6,7 @@ const update = ({ store, statuses, timeline, showImmediately, userId }) => {
   const ccTimeline = camelCase(timeline)
 
   store.dispatch('setError', { value: false })
-  store.dispatch('setErrorData', { value: false })
+  store.dispatch('setErrorData', { value: null })
 
   store.dispatch('addNewStatuses', {
     timeline: ccTimeline,
@@ -47,7 +47,7 @@ const fetchAndUpdate = ({
   return apiService.fetchTimeline(args)
     .then((statuses) => {
       if (statuses.error) {
-        store.dispatch('setErrorData', { value: statuses.error })
+        store.dispatch('setErrorData', { value: statuses })
         return
       }
       if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) {

From f6d8f245e68c8a1f747af527f59670d88bde5c08 Mon Sep 17 00:00:00 2001
From: Absturztaube <me@absturztaube.ch>
Date: Mon, 9 Dec 2019 22:15:38 +0100
Subject: [PATCH 19/62] Revert "fix sticker picker height in emojo picker"

This reverts commit 914c78398469988f549930bd35d044082d155277.
---
 src/components/emoji_picker/emoji_picker.scss | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/components/emoji_picker/emoji_picker.scss b/src/components/emoji_picker/emoji_picker.scss
index 29010c5b..6608f393 100644
--- a/src/components/emoji_picker/emoji_picker.scss
+++ b/src/components/emoji_picker/emoji_picker.scss
@@ -101,10 +101,6 @@
     }
   }
 
-  .stickers-content {
-    min-height: 269px;
-  }
-
   .emoji {
     &-search {
       padding: 5px;

From 7e3a4fa8ec183f8e04804938d713953aed6bec66 Mon Sep 17 00:00:00 2001
From: Absturztaube <me@absturztaube.ch>
Date: Mon, 9 Dec 2019 22:16:51 +0100
Subject: [PATCH 20/62] fix invisible tab-switcher in emoji picker

---
 .../sticker_picker/sticker_picker.vue         | 28 ++++++++-----------
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/src/components/sticker_picker/sticker_picker.vue b/src/components/sticker_picker/sticker_picker.vue
index 323855b9..7d6fdc24 100644
--- a/src/components/sticker_picker/sticker_picker.vue
+++ b/src/components/sticker_picker/sticker_picker.vue
@@ -37,22 +37,18 @@
 .sticker-picker {
   width: 100%;
   position: relative;
-  .tab-switcher {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    right: 0;
-  }
-  .sticker-picker-content {
-    .sticker {
-      display: inline-block;
-      width: 20%;
-      height: 20%;
-      img {
-        width: 100%;
-        &:hover {
-          filter: drop-shadow(0 0 5px var(--link, $fallback--link));
+  .contents {
+    min-height: 250px;
+    .sticker-picker-content {
+      .sticker {
+        display: inline-block;
+        width: 20%;
+        height: 20%;
+        img {
+          width: 100%;
+          &:hover {
+            filter: drop-shadow(0 0 5px var(--link, $fallback--link));
+          }
         }
       }
     }

From 6acd889589e46b18491d96b5fa992154b4e58d88 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 10 Dec 2019 21:30:27 +0200
Subject: [PATCH 21/62] Option to enable streaming

---
 src/components/settings/settings.js  | 14 +++++++++++++-
 src/components/settings/settings.vue |  9 +++++++++
 src/i18n/en.json                     |  2 ++
 src/i18n/ru.json                     |  2 ++
 src/modules/api.js                   | 18 ++++++++++++++++++
 src/modules/config.js                |  1 +
 src/modules/users.js                 | 14 +++++++++++---
 src/services/api/api.service.js      |  6 ++++++
 8 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index c49083f9..2d7723cc 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -84,7 +84,7 @@ const settings = {
         }
       }])
       .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
-    // Special cases (need to transform values)
+    // Special cases (need to transform values or perform actions first)
     muteWordsString: {
       get () { return this.$store.getters.mergedConfig.muteWords.join('\n') },
       set (value) {
@@ -93,6 +93,18 @@ const settings = {
           value: filter(value.split('\n'), (word) => trim(word).length > 0)
         })
       }
+    },
+    useStreamingApi: {
+      get () { return this.$store.getters.mergedConfig.useStreamingApi },
+      set (value) {
+        const promise = value
+          ? this.$store.dispatch('enableMastoSockets')
+          : this.$store.dispatch('disableMastoSockets')
+
+        promise.then(() => {
+          this.$store.dispatch('setOption', { name: 'useStreamingApi', value })
+        })
+      }
     }
   },
   // Updating nested properties
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index c4021137..b40c85dd 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -73,6 +73,15 @@
                     </li>
                   </ul>
                 </li>
+                <li>
+                  <Checkbox v-model="useStreamingApi">
+                    {{ $t('settings.useStreamingApi') }}
+                    <br/>
+                    <small>
+                    {{ $t('settings.useStreamingApiWarning') }}
+                    </small>
+                  </Checkbox>
+                </li>
                 <li>
                   <Checkbox v-model="autoLoad">
                     {{ $t('settings.autoload') }}
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 85146ef5..60fc792f 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -358,6 +358,8 @@
     "post_status_content_type": "Post status content type",
     "stop_gifs": "Play-on-hover GIFs",
     "streaming": "Enable automatic streaming of new posts when scrolled to the top",
+    "useStreamingApi": "Receive posts and notifications real-time",
+    "useStreamingApiWarning": "(Not recommended, experimental, known to skip posts)",
     "text": "Text",
     "theme": "Theme",
     "theme_help": "Use hex color codes (#rrggbb) to customize your color theme.",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index 19e10f1e..4cb2d497 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -219,6 +219,8 @@
     "subject_input_always_show": "Всегда показывать поле ввода темы",
     "stop_gifs": "Проигрывать GIF анимации только при наведении",
     "streaming": "Включить автоматическую загрузку новых сообщений при прокрутке вверх",
+    "useStreamingApi": "Получать сообщения и уведомления в реальном времени",
+    "useStreamingApiWarning": "(Не рекомендуется, экспериментально, сообщения могут пропадать)",
     "text": "Текст",
     "theme": "Тема",
     "theme_help": "Используйте шестнадцатеричные коды цветов (#rrggbb) для настройки темы.",
diff --git a/src/modules/api.js b/src/modules/api.js
index 593f8498..dc91d00e 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -31,6 +31,18 @@ const api = {
     }
   },
   actions: {
+    // Global MastoAPI socket control, in future should disable ALL sockets/(re)start relevant sockets
+    enableMastoSockets (store) {
+      const { state, dispatch } = store
+      if (state.mastoUserSocket) return
+      dispatch('startMastoUserSocket')
+    },
+    disableMastoSockets (store) {
+      const { state, dispatch } = store
+      if (!state.mastoUserSocket) return
+      dispatch('stopMastoUserSocket')
+    },
+
     // MastoAPI 'User' sockets
     startMastoUserSocket (store) {
       const { state, dispatch } = store
@@ -81,6 +93,12 @@ const api = {
         dispatch('stopFetchingNotifications')
       })
     },
+    stopMastoUserSocket ({ state, dispatch }) {
+      dispatch('startFetchingTimeline', { timeline: 'friends' })
+      dispatch('startFetchingNotifications')
+      console.log(state.mastoUserSocket)
+      state.mastoUserSocket.close()
+    },
 
     // Timelines
     startFetchingTimeline (store, {
diff --git a/src/modules/config.js b/src/modules/config.js
index 329b4091..74025db1 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -35,6 +35,7 @@ export const defaultState = {
   highlight: {},
   interfaceLanguage: browserLocale,
   hideScopeNotice: false,
+  useStreamingApi: false,
   scopeCopy: undefined, // instance default
   subjectLineBehavior: undefined, // instance default
   alwaysShowSubjectInput: undefined, // instance default
diff --git a/src/modules/users.js b/src/modules/users.js
index 6bdaf193..cbec6063 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -469,14 +469,22 @@ const users = {
                 store.dispatch('initializeSocket')
               }
 
-              store.dispatch('startMastoUserSocket').catch((error) => {
-                console.error('Failed initializing MastoAPI Streaming socket', error)
+              const startPolling = () => {
                 // Start getting fresh posts.
                 store.dispatch('startFetchingTimeline', { timeline: 'friends' })
 
                 // Start fetching notifications
                 store.dispatch('startFetchingNotifications')
-              })
+              }
+
+              if (store.getters.mergedConfig.useStreamingApi) {
+                store.dispatch('enableMastoSockets').catch((error) => {
+                  console.error('Failed initializing MastoAPI Streaming socket', error)
+                  startPolling()
+                })
+              } else {
+                startPolling()
+              }
 
               // Get user mutes
               store.dispatch('fetchMutes')
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index c6818df4..517b953e 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -983,18 +983,24 @@ export const ProcessedWS = ({
       wsEvent
     )
   })
+  // Commented code reason: very spammy, uncomment to enable message debug logging
+  /*
   socket.addEventListener('message', (wsEvent) => {
     console.debug(
       `[WS][${id}] Message received`,
       wsEvent
     )
   })
+  /**/
 
   proxy(socket, 'open')
   proxy(socket, 'close')
   proxy(socket, 'message', preprocessor)
   proxy(socket, 'error')
 
+  // 1000 = Normal Closure
+  eventTarget.close = () => { socket.close(1000, 'Shutting down socket') }
+
   return eventTarget
 }
 

From 1af536d68f8e457904400bf2019c6755f849d790 Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Wed, 11 Dec 2019 13:52:03 +0500
Subject: [PATCH 22/62] upgrade Babel core to v7

---
 package.json |   4 +-
 yarn.lock    | 171 +++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 153 insertions(+), 22 deletions(-)

diff --git a/package.json b/package.json
index 3c9598eb..88790ec6 100644
--- a/package.json
+++ b/package.json
@@ -40,13 +40,13 @@
     "whatwg-fetch": "^2.0.3"
   },
   "devDependencies": {
+    "@babel/core": "^7.7.5",
     "@babel/polyfill": "^7.0.0",
     "@vue/test-utils": "^1.0.0-beta.26",
     "autoprefixer": "^6.4.0",
-    "babel-core": "^6.0.0",
     "babel-eslint": "^7.0.0",
     "babel-helper-vue-jsx-merge-props": "^2.0.3",
-    "babel-loader": "^7.0.0",
+    "babel-loader": "^8.0.6",
     "babel-plugin-syntax-jsx": "^6.18.0",
     "babel-plugin-transform-runtime": "^6.0.0",
     "babel-plugin-transform-vue-jsx": "3",
diff --git a/yarn.lock b/yarn.lock
index 44473c94..a3cc6e2a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8,12 +8,81 @@
   dependencies:
     "@babel/highlight" "^7.0.0"
 
+"@babel/code-frame@^7.5.5":
+  version "7.5.5"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
+  integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
+  dependencies:
+    "@babel/highlight" "^7.0.0"
+
+"@babel/core@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.5.tgz#ae1323cd035b5160293307f50647e83f8ba62f7e"
+  integrity sha512-M42+ScN4+1S9iB6f+TL7QBpoQETxbclx+KNoKJABghnKYE+fMzSGqst0BZJc8CpI625bwPwYgUyRvxZ+0mZzpw==
+  dependencies:
+    "@babel/code-frame" "^7.5.5"
+    "@babel/generator" "^7.7.4"
+    "@babel/helpers" "^7.7.4"
+    "@babel/parser" "^7.7.5"
+    "@babel/template" "^7.7.4"
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+    convert-source-map "^1.7.0"
+    debug "^4.1.0"
+    json5 "^2.1.0"
+    lodash "^4.17.13"
+    resolve "^1.3.2"
+    semver "^5.4.1"
+    source-map "^0.5.0"
+
+"@babel/generator@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369"
+  integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==
+  dependencies:
+    "@babel/types" "^7.7.4"
+    jsesc "^2.5.1"
+    lodash "^4.17.13"
+    source-map "^0.5.0"
+
+"@babel/helper-function-name@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e"
+  integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==
+  dependencies:
+    "@babel/helper-get-function-arity" "^7.7.4"
+    "@babel/template" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-get-function-arity@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0"
+  integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
 "@babel/helper-module-imports@^7.0.0-beta.49":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
   dependencies:
     "@babel/types" "^7.0.0"
 
+"@babel/helper-split-export-declaration@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8"
+  integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helpers@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302"
+  integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==
+  dependencies:
+    "@babel/template" "^7.7.4"
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
 "@babel/highlight@^7.0.0":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4"
@@ -22,6 +91,11 @@
     esutils "^2.0.2"
     js-tokens "^4.0.0"
 
+"@babel/parser@^7.7.4", "@babel/parser@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71"
+  integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==
+
 "@babel/polyfill@^7.0.0":
   version "7.2.5"
   resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.2.5.tgz#6c54b964f71ad27edddc567d065e57e87ed7fa7d"
@@ -29,6 +103,30 @@
     core-js "^2.5.7"
     regenerator-runtime "^0.12.0"
 
+"@babel/template@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
+  integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "@babel/parser" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
+"@babel/traverse@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558"
+  integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==
+  dependencies:
+    "@babel/code-frame" "^7.5.5"
+    "@babel/generator" "^7.7.4"
+    "@babel/helper-function-name" "^7.7.4"
+    "@babel/helper-split-export-declaration" "^7.7.4"
+    "@babel/parser" "^7.7.4"
+    "@babel/types" "^7.7.4"
+    debug "^4.1.0"
+    globals "^11.1.0"
+    lodash "^4.17.13"
+
 "@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49":
   version "7.2.2"
   resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.2.2.tgz#44e10fc24e33af524488b716cdaee5360ea8ed1e"
@@ -37,6 +135,15 @@
     lodash "^4.17.10"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193"
+  integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==
+  dependencies:
+    esutils "^2.0.2"
+    lodash "^4.17.13"
+    to-fast-properties "^2.0.0"
+
 "@chenfengyuan/vue-qrcode@^1.0.0":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@chenfengyuan/vue-qrcode/-/vue-qrcode-1.0.0.tgz#07103fe2048ce0160cddde836fb5378cc7951d6f"
@@ -492,7 +599,7 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
     esutils "^2.0.2"
     js-tokens "^3.0.2"
 
-babel-core@^6.0.0, babel-core@^6.1.4, babel-core@^6.26.0:
+babel-core@^6.1.4, babel-core@^6.26.0:
   version "6.26.3"
   resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
   dependencies:
@@ -660,13 +767,15 @@ babel-helpers@^6.24.1:
     babel-runtime "^6.22.0"
     babel-template "^6.24.1"
 
-babel-loader@^7.0.0:
-  version "7.1.5"
-  resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68"
+babel-loader@^8.0.6:
+  version "8.0.6"
+  resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb"
+  integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==
   dependencies:
-    find-cache-dir "^1.0.0"
+    find-cache-dir "^2.0.0"
     loader-utils "^1.0.2"
     mkdirp "^0.5.1"
+    pify "^4.0.1"
 
 babel-messages@^6.23.0:
   version "6.23.0"
@@ -1840,6 +1949,13 @@ convert-source-map@^1.5.1:
   dependencies:
     safe-buffer "~5.1.1"
 
+convert-source-map@^1.7.0:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
+  integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
+  dependencies:
+    safe-buffer "~5.1.1"
+
 cookie-signature@1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
@@ -3014,14 +3130,6 @@ find-cache-dir@^0.1.1:
     mkdirp "^0.5.1"
     pkg-dir "^1.0.0"
 
-find-cache-dir@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
-  dependencies:
-    commondir "^1.0.1"
-    make-dir "^1.0.0"
-    pkg-dir "^2.0.0"
-
 find-cache-dir@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
@@ -3321,7 +3429,7 @@ glob@^7.1.2:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-globals@^11.7.0:
+globals@^11.1.0, globals@^11.7.0:
   version "11.12.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
 
@@ -4144,6 +4252,11 @@ jsesc@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
 
+jsesc@^2.5.1:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+  integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
 jsesc@~0.5.0:
   version "0.5.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
@@ -4186,6 +4299,13 @@ json5@^1.0.1:
   dependencies:
     minimist "^1.2.0"
 
+json5@^2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6"
+  integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==
+  dependencies:
+    minimist "^1.2.0"
+
 jsprim@^1.2.2:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -4647,6 +4767,11 @@ lodash@^4.16.4, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.2
   version "4.17.11"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
 
+lodash@^4.17.13:
+  version "4.17.15"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
+  integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+
 log-symbols@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
@@ -4707,12 +4832,6 @@ lru-cache@~2.6.5:
   version "2.6.5"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.5.tgz#e56d6354148ede8d7707b58d143220fd08df0fd5"
 
-make-dir@^1.0.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
-  dependencies:
-    pify "^3.0.0"
-
 make-dir@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
@@ -6447,6 +6566,13 @@ resolve@^1.10.0, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1:
   dependencies:
     path-parse "^1.0.6"
 
+resolve@^1.3.2:
+  version "1.13.1"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16"
+  integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==
+  dependencies:
+    path-parse "^1.0.6"
+
 restore-cursor@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
@@ -6577,6 +6703,11 @@ selenium-server@2.53.1:
   version "5.6.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
 
+semver@^5.4.1:
+  version "5.7.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+  integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
 semver@^5.5.1:
   version "5.7.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"

From 4f9aba1a7c20a5dadec7ba4960445a0d5876c41e Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Wed, 11 Dec 2019 13:56:08 +0500
Subject: [PATCH 23/62] upgrade babel preset

---
 package.json |    5 +-
 yarn.lock    | 1145 ++++++++++++++++++++++++++++----------------------
 2 files changed, 650 insertions(+), 500 deletions(-)

diff --git a/package.json b/package.json
index 88790ec6..9bf498e1 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
   },
   "devDependencies": {
     "@babel/core": "^7.7.5",
-    "@babel/polyfill": "^7.0.0",
+    "@babel/preset-env": "^7.7.6",
     "@vue/test-utils": "^1.0.0-beta.26",
     "autoprefixer": "^6.4.0",
     "babel-eslint": "^7.0.0",
@@ -50,9 +50,6 @@
     "babel-plugin-syntax-jsx": "^6.18.0",
     "babel-plugin-transform-runtime": "^6.0.0",
     "babel-plugin-transform-vue-jsx": "3",
-    "babel-preset-env": "^1.7.0",
-    "babel-preset-es2015": "^6.0.0",
-    "babel-preset-stage-2": "^6.0.0",
     "babel-register": "^6.0.0",
     "chai": "^3.5.0",
     "chalk": "^1.1.3",
diff --git a/yarn.lock b/yarn.lock
index a3cc6e2a..b5017997 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -45,6 +45,55 @@
     lodash "^4.17.13"
     source-map "^0.5.0"
 
+"@babel/helper-annotate-as-pure@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz#bb3faf1e74b74bd547e867e48f551fa6b098b6ce"
+  integrity sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz#5f73f2b28580e224b5b9bd03146a4015d6217f5f"
+  integrity sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ==
+  dependencies:
+    "@babel/helper-explode-assignable-expression" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-call-delegate@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz#621b83e596722b50c0066f9dc37d3232e461b801"
+  integrity sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA==
+  dependencies:
+    "@babel/helper-hoist-variables" "^7.7.4"
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-create-regexp-features-plugin@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59"
+  integrity sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A==
+  dependencies:
+    "@babel/helper-regex" "^7.4.4"
+    regexpu-core "^4.6.0"
+
+"@babel/helper-define-map@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz#2841bf92eb8bd9c906851546fe6b9d45e162f176"
+  integrity sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg==
+  dependencies:
+    "@babel/helper-function-name" "^7.7.4"
+    "@babel/types" "^7.7.4"
+    lodash "^4.17.13"
+
+"@babel/helper-explode-assignable-expression@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz#fa700878e008d85dc51ba43e9fb835cddfe05c84"
+  integrity sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg==
+  dependencies:
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
 "@babel/helper-function-name@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e"
@@ -61,12 +110,93 @@
   dependencies:
     "@babel/types" "^7.7.4"
 
+"@babel/helper-hoist-variables@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz#612384e3d823fdfaaf9fce31550fe5d4db0f3d12"
+  integrity sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-member-expression-to-functions@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74"
+  integrity sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
 "@babel/helper-module-imports@^7.0.0-beta.49":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
   dependencies:
     "@babel/types" "^7.0.0"
 
+"@babel/helper-module-imports@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91"
+  integrity sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835"
+  integrity sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw==
+  dependencies:
+    "@babel/helper-module-imports" "^7.7.4"
+    "@babel/helper-simple-access" "^7.7.4"
+    "@babel/helper-split-export-declaration" "^7.7.4"
+    "@babel/template" "^7.7.4"
+    "@babel/types" "^7.7.4"
+    lodash "^4.17.13"
+
+"@babel/helper-optimise-call-expression@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2"
+  integrity sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg==
+  dependencies:
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-plugin-utils@^7.0.0":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
+  integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==
+
+"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4":
+  version "7.5.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351"
+  integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==
+  dependencies:
+    lodash "^4.17.13"
+
+"@babel/helper-remap-async-to-generator@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234"
+  integrity sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.7.4"
+    "@babel/helper-wrap-function" "^7.7.4"
+    "@babel/template" "^7.7.4"
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-replace-supers@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2"
+  integrity sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg==
+  dependencies:
+    "@babel/helper-member-expression-to-functions" "^7.7.4"
+    "@babel/helper-optimise-call-expression" "^7.7.4"
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
+"@babel/helper-simple-access@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294"
+  integrity sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A==
+  dependencies:
+    "@babel/template" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
 "@babel/helper-split-export-declaration@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8"
@@ -74,6 +204,16 @@
   dependencies:
     "@babel/types" "^7.7.4"
 
+"@babel/helper-wrap-function@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace"
+  integrity sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg==
+  dependencies:
+    "@babel/helper-function-name" "^7.7.4"
+    "@babel/template" "^7.7.4"
+    "@babel/traverse" "^7.7.4"
+    "@babel/types" "^7.7.4"
+
 "@babel/helpers@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302"
@@ -96,12 +236,397 @@
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71"
   integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==
 
-"@babel/polyfill@^7.0.0":
-  version "7.2.5"
-  resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.2.5.tgz#6c54b964f71ad27edddc567d065e57e87ed7fa7d"
+"@babel/plugin-proposal-async-generator-functions@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d"
+  integrity sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw==
   dependencies:
-    core-js "^2.5.7"
-    regenerator-runtime "^0.12.0"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-remap-async-to-generator" "^7.7.4"
+    "@babel/plugin-syntax-async-generators" "^7.7.4"
+
+"@babel/plugin-proposal-dynamic-import@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz#dde64a7f127691758cbfed6cf70de0fa5879d52d"
+  integrity sha512-StH+nGAdO6qDB1l8sZ5UBV8AC3F2VW2I8Vfld73TMKyptMU9DY5YsJAS8U81+vEtxcH3Y/La0wG0btDrhpnhjQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-dynamic-import" "^7.7.4"
+
+"@babel/plugin-proposal-json-strings@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz#7700a6bfda771d8dc81973249eac416c6b4c697d"
+  integrity sha512-wQvt3akcBTfLU/wYoqm/ws7YOAQKu8EVJEvHip/mzkNtjaclQoCCIqKXFP5/eyfnfbQCDV3OLRIK3mIVyXuZlw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-json-strings" "^7.7.4"
+
+"@babel/plugin-proposal-object-rest-spread@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.4.tgz#cc57849894a5c774214178c8ab64f6334ec8af71"
+  integrity sha512-rnpnZR3/iWKmiQyJ3LKJpSwLDcX/nSXhdLk4Aq/tXOApIvyu7qoabrige0ylsAJffaUC51WiBu209Q0U+86OWQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-object-rest-spread" "^7.7.4"
+
+"@babel/plugin-proposal-optional-catch-binding@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz#ec21e8aeb09ec6711bc0a39ca49520abee1de379"
+  integrity sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-syntax-optional-catch-binding" "^7.7.4"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.4.tgz#7c239ccaf09470dbe1d453d50057460e84517ebb"
+  integrity sha512-cHgqHgYvffluZk85dJ02vloErm3Y6xtH+2noOBOJ2kXOJH3aVCDnj5eR/lVNlTnYu4hndAPJD3rTFjW3qee0PA==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-async-generators@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz#331aaf310a10c80c44a66b238b6e49132bd3c889"
+  integrity sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-dynamic-import@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec"
+  integrity sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-json-strings@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz#86e63f7d2e22f9e27129ac4e83ea989a382e86cc"
+  integrity sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-object-rest-spread@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46"
+  integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz#a3e38f59f4b6233867b4a92dcb0ee05b2c334aa6"
+  integrity sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-top-level-await@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz#bd7d8fa7b9fee793a36e4027fd6dd1aa32f946da"
+  integrity sha512-wdsOw0MvkL1UIgiQ/IFr3ETcfv1xb8RMM0H9wbiDyLaJFyiDg5oZvDLCXosIXmFeIlweML5iOBXAkqddkYNizg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-arrow-functions@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12"
+  integrity sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-async-to-generator@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba"
+  integrity sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg==
+  dependencies:
+    "@babel/helper-module-imports" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-remap-async-to-generator" "^7.7.4"
+
+"@babel/plugin-transform-block-scoped-functions@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b"
+  integrity sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-block-scoping@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224"
+  integrity sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    lodash "^4.17.13"
+
+"@babel/plugin-transform-classes@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec"
+  integrity sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.7.4"
+    "@babel/helper-define-map" "^7.7.4"
+    "@babel/helper-function-name" "^7.7.4"
+    "@babel/helper-optimise-call-expression" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-replace-supers" "^7.7.4"
+    "@babel/helper-split-export-declaration" "^7.7.4"
+    globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d"
+  integrity sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-destructuring@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267"
+  integrity sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-dotall-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.4.tgz#f7ccda61118c5b7a2599a72d5e3210884a021e96"
+  integrity sha512-mk0cH1zyMa/XHeb6LOTXTbG7uIJ8Rrjlzu91pUx/KS3JpcgaTDwMS8kM+ar8SLOvlL2Lofi4CGBAjCo3a2x+lw==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-duplicate-keys@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz#3d21731a42e3f598a73835299dd0169c3b90ac91"
+  integrity sha512-g1y4/G6xGWMD85Tlft5XedGaZBCIVN+/P0bs6eabmcPP9egFleMAo65OOjlhcz1njpwagyY3t0nsQC9oTFegJA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-exponentiation-operator@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz#dd30c0191e3a1ba19bcc7e389bdfddc0729d5db9"
+  integrity sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ==
+  dependencies:
+    "@babel/helper-builder-binary-assignment-operator-visitor" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-for-of@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc"
+  integrity sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-function-name@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1"
+  integrity sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g==
+  dependencies:
+    "@babel/helper-function-name" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-literals@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e"
+  integrity sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-member-expression-literals@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a"
+  integrity sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-modules-amd@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz#39e0fb717224b59475b306402bb8eedab01e729c"
+  integrity sha512-CT57FG4A2ZUNU1v+HdvDSDrjNWBrtCmSH6YbbgN3Lrf0Di/q/lWRxZrE72p3+HCCz9UjfZOEBdphgC0nzOS6DQ==
+  dependencies:
+    "@babel/helper-module-transforms" "^7.7.5"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    babel-plugin-dynamic-import-node "^2.3.0"
+
+"@babel/plugin-transform-modules-commonjs@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz#1d27f5eb0bcf7543e774950e5b2fa782e637b345"
+  integrity sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q==
+  dependencies:
+    "@babel/helper-module-transforms" "^7.7.5"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-simple-access" "^7.7.4"
+    babel-plugin-dynamic-import-node "^2.3.0"
+
+"@babel/plugin-transform-modules-systemjs@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz#cd98152339d3e763dfe838b7d4273edaf520bb30"
+  integrity sha512-y2c96hmcsUi6LrMqvmNDPBBiGCiQu0aYqpHatVVu6kD4mFEXKjyNxd/drc18XXAf9dv7UXjrZwBVmTTGaGP8iw==
+  dependencies:
+    "@babel/helper-hoist-variables" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    babel-plugin-dynamic-import-node "^2.3.0"
+
+"@babel/plugin-transform-modules-umd@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz#1027c355a118de0aae9fee00ad7813c584d9061f"
+  integrity sha512-u2B8TIi0qZI4j8q4C51ktfO7E3cQ0qnaXFI1/OXITordD40tt17g/sXqgNNCcMTcBFKrUPcGDx+TBJuZxLx7tw==
+  dependencies:
+    "@babel/helper-module-transforms" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-named-capturing-groups-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz#fb3bcc4ee4198e7385805007373d6b6f42c98220"
+  integrity sha512-jBUkiqLKvUWpv9GLSuHUFYdmHg0ujC1JEYoZUfeOOfNydZXp1sXObgyPatpcwjWgsdBGsagWW0cdJpX/DO2jMw==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.7.4"
+
+"@babel/plugin-transform-new-target@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz#4a0753d2d60639437be07b592a9e58ee00720167"
+  integrity sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-object-super@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262"
+  integrity sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-replace-supers" "^7.7.4"
+
+"@babel/plugin-transform-parameters@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.4.tgz#da4555c97f39b51ac089d31c7380f03bca4075ce"
+  integrity sha512-VJwhVePWPa0DqE9vcfptaJSzNDKrWU/4FbYCjZERtmqEs05g3UMXnYMZoXja7JAJ7Y7sPZipwm/pGApZt7wHlw==
+  dependencies:
+    "@babel/helper-call-delegate" "^7.7.4"
+    "@babel/helper-get-function-arity" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-property-literals@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2"
+  integrity sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-regenerator@^7.7.5":
+  version "7.7.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz#3a8757ee1a2780f390e89f246065ecf59c26fce9"
+  integrity sha512-/8I8tPvX2FkuEyWbjRCt4qTAgZK0DVy8QRguhA524UH48RfGJy94On2ri+dCuwOpcerPRl9O4ebQkRcVzIaGBw==
+  dependencies:
+    regenerator-transform "^0.14.0"
+
+"@babel/plugin-transform-reserved-words@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz#6a7cf123ad175bb5c69aec8f6f0770387ed3f1eb"
+  integrity sha512-OrPiUB5s5XvkCO1lS7D8ZtHcswIC57j62acAnJZKqGGnHP+TIc/ljQSrgdX/QyOTdEK5COAhuc820Hi1q2UgLQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-shorthand-properties@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e"
+  integrity sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-spread@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578"
+  integrity sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-sticky-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c"
+  integrity sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-regex" "^7.0.0"
+
+"@babel/plugin-transform-template-literals@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604"
+  integrity sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-typeof-symbol@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz#3174626214f2d6de322882e498a38e8371b2140e"
+  integrity sha512-KQPUQ/7mqe2m0B8VecdyaW5XcQYaePyl9R7IsKd+irzj6jvbhoGnRE+M0aNkyAzI07VfUQ9266L5xMARitV3wg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-unicode-regex@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz#a3c0f65b117c4c81c5b6484f2a5e7b95346b83ae"
+  integrity sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/preset-env@^7.7.6":
+  version "7.7.6"
+  resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.6.tgz#39ac600427bbb94eec6b27953f1dfa1d64d457b2"
+  integrity sha512-k5hO17iF/Q7tR9Jv8PdNBZWYW6RofxhnxKjBMc0nG4JTaWvOTiPoO/RLFwAKcA4FpmuBFm6jkoqaRJLGi0zdaQ==
+  dependencies:
+    "@babel/helper-module-imports" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/plugin-proposal-async-generator-functions" "^7.7.4"
+    "@babel/plugin-proposal-dynamic-import" "^7.7.4"
+    "@babel/plugin-proposal-json-strings" "^7.7.4"
+    "@babel/plugin-proposal-object-rest-spread" "^7.7.4"
+    "@babel/plugin-proposal-optional-catch-binding" "^7.7.4"
+    "@babel/plugin-proposal-unicode-property-regex" "^7.7.4"
+    "@babel/plugin-syntax-async-generators" "^7.7.4"
+    "@babel/plugin-syntax-dynamic-import" "^7.7.4"
+    "@babel/plugin-syntax-json-strings" "^7.7.4"
+    "@babel/plugin-syntax-object-rest-spread" "^7.7.4"
+    "@babel/plugin-syntax-optional-catch-binding" "^7.7.4"
+    "@babel/plugin-syntax-top-level-await" "^7.7.4"
+    "@babel/plugin-transform-arrow-functions" "^7.7.4"
+    "@babel/plugin-transform-async-to-generator" "^7.7.4"
+    "@babel/plugin-transform-block-scoped-functions" "^7.7.4"
+    "@babel/plugin-transform-block-scoping" "^7.7.4"
+    "@babel/plugin-transform-classes" "^7.7.4"
+    "@babel/plugin-transform-computed-properties" "^7.7.4"
+    "@babel/plugin-transform-destructuring" "^7.7.4"
+    "@babel/plugin-transform-dotall-regex" "^7.7.4"
+    "@babel/plugin-transform-duplicate-keys" "^7.7.4"
+    "@babel/plugin-transform-exponentiation-operator" "^7.7.4"
+    "@babel/plugin-transform-for-of" "^7.7.4"
+    "@babel/plugin-transform-function-name" "^7.7.4"
+    "@babel/plugin-transform-literals" "^7.7.4"
+    "@babel/plugin-transform-member-expression-literals" "^7.7.4"
+    "@babel/plugin-transform-modules-amd" "^7.7.5"
+    "@babel/plugin-transform-modules-commonjs" "^7.7.5"
+    "@babel/plugin-transform-modules-systemjs" "^7.7.4"
+    "@babel/plugin-transform-modules-umd" "^7.7.4"
+    "@babel/plugin-transform-named-capturing-groups-regex" "^7.7.4"
+    "@babel/plugin-transform-new-target" "^7.7.4"
+    "@babel/plugin-transform-object-super" "^7.7.4"
+    "@babel/plugin-transform-parameters" "^7.7.4"
+    "@babel/plugin-transform-property-literals" "^7.7.4"
+    "@babel/plugin-transform-regenerator" "^7.7.5"
+    "@babel/plugin-transform-reserved-words" "^7.7.4"
+    "@babel/plugin-transform-shorthand-properties" "^7.7.4"
+    "@babel/plugin-transform-spread" "^7.7.4"
+    "@babel/plugin-transform-sticky-regex" "^7.7.4"
+    "@babel/plugin-transform-template-literals" "^7.7.4"
+    "@babel/plugin-transform-typeof-symbol" "^7.7.4"
+    "@babel/plugin-transform-unicode-regex" "^7.7.4"
+    "@babel/types" "^7.7.4"
+    browserslist "^4.6.0"
+    core-js-compat "^3.4.7"
+    invariant "^2.2.2"
+    js-levenshtein "^1.1.3"
+    semver "^5.5.0"
 
 "@babel/template@^7.7.4":
   version "7.7.4"
@@ -645,117 +1170,6 @@ babel-generator@^6.26.0:
     source-map "^0.5.7"
     trim-right "^1.0.1"
 
-babel-helper-bindify-decorators@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330"
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
-  dependencies:
-    babel-helper-explode-assignable-expression "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-helper-call-delegate@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d"
-  dependencies:
-    babel-helper-hoist-variables "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-define-map@^6.24.1:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f"
-  dependencies:
-    babel-helper-function-name "^6.24.1"
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    lodash "^4.17.4"
-
-babel-helper-explode-assignable-expression@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa"
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-explode-class@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb"
-  dependencies:
-    babel-helper-bindify-decorators "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-function-name@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
-  dependencies:
-    babel-helper-get-function-arity "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-get-function-arity@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d"
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-helper-hoist-variables@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76"
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-helper-optimise-call-expression@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-helper-regex@^6.24.1:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72"
-  dependencies:
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    lodash "^4.17.4"
-
-babel-helper-remap-async-to-generator@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
-  dependencies:
-    babel-helper-function-name "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-helper-replace-supers@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
-  dependencies:
-    babel-helper-optimise-call-expression "^6.24.1"
-    babel-messages "^6.23.0"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
 babel-helper-vue-jsx-merge-props@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
@@ -787,11 +1201,12 @@ babel-plugin-add-module-exports@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25"
 
-babel-plugin-check-es2015-constants@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
+babel-plugin-dynamic-import-node@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f"
+  integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==
   dependencies:
-    babel-runtime "^6.22.0"
+    object.assign "^4.1.0"
 
 babel-plugin-lodash@^3.2.11:
   version "3.3.4"
@@ -803,368 +1218,22 @@ babel-plugin-lodash@^3.2.11:
     lodash "^4.17.10"
     require-package-name "^2.0.1"
 
-babel-plugin-syntax-async-functions@^6.8.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
-
-babel-plugin-syntax-async-generators@^6.5.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a"
-
-babel-plugin-syntax-class-properties@^6.8.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
-
-babel-plugin-syntax-decorators@^6.13.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
-
-babel-plugin-syntax-dynamic-import@^6.18.0:
-  version "6.18.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
-
-babel-plugin-syntax-exponentiation-operator@^6.8.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
-
 babel-plugin-syntax-jsx@^6.18.0:
   version "6.18.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
 
-babel-plugin-syntax-object-rest-spread@^6.8.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
-
-babel-plugin-syntax-trailing-function-commas@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
-
-babel-plugin-transform-async-generator-functions@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db"
-  dependencies:
-    babel-helper-remap-async-to-generator "^6.24.1"
-    babel-plugin-syntax-async-generators "^6.5.0"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
-  dependencies:
-    babel-helper-remap-async-to-generator "^6.24.1"
-    babel-plugin-syntax-async-functions "^6.8.0"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-class-properties@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
-  dependencies:
-    babel-helper-function-name "^6.24.1"
-    babel-plugin-syntax-class-properties "^6.8.0"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-decorators@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d"
-  dependencies:
-    babel-helper-explode-class "^6.24.1"
-    babel-plugin-syntax-decorators "^6.13.0"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-arrow-functions@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
-  dependencies:
-    babel-runtime "^6.26.0"
-    babel-template "^6.26.0"
-    babel-traverse "^6.26.0"
-    babel-types "^6.26.0"
-    lodash "^4.17.4"
-
-babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
-  dependencies:
-    babel-helper-define-map "^6.24.1"
-    babel-helper-function-name "^6.24.1"
-    babel-helper-optimise-call-expression "^6.24.1"
-    babel-helper-replace-supers "^6.24.1"
-    babel-messages "^6.23.0"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
-  dependencies:
-    babel-helper-function-name "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-literals@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
-  dependencies:
-    babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
-  version "6.26.2"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3"
-  dependencies:
-    babel-plugin-transform-strict-mode "^6.24.1"
-    babel-runtime "^6.26.0"
-    babel-template "^6.26.0"
-    babel-types "^6.26.0"
-
-babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
-  dependencies:
-    babel-helper-hoist-variables "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
-  dependencies:
-    babel-plugin-transform-es2015-modules-amd "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
-  dependencies:
-    babel-helper-replace-supers "^6.24.1"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
-  dependencies:
-    babel-helper-call-delegate "^6.24.1"
-    babel-helper-get-function-arity "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-    babel-traverse "^6.24.1"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-spread@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
-  dependencies:
-    babel-helper-regex "^6.24.1"
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-template-literals@^6.22.0:
-  version "6.22.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
-  dependencies:
-    babel-helper-regex "^6.24.1"
-    babel-runtime "^6.22.0"
-    regexpu-core "^2.0.0"
-
-babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
-  dependencies:
-    babel-helper-builder-binary-assignment-operator-visitor "^6.24.1"
-    babel-plugin-syntax-exponentiation-operator "^6.8.0"
-    babel-runtime "^6.22.0"
-
-babel-plugin-transform-object-rest-spread@^6.22.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06"
-  dependencies:
-    babel-plugin-syntax-object-rest-spread "^6.8.0"
-    babel-runtime "^6.26.0"
-
-babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
-  dependencies:
-    regenerator-transform "^0.10.0"
-
 babel-plugin-transform-runtime@^6.0.0:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee"
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-strict-mode@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-types "^6.24.1"
-
 babel-plugin-transform-vue-jsx@3:
   version "3.7.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-3.7.0.tgz#d40492e6692a36b594f7e9a1928f43e969740960"
   dependencies:
     esutils "^2.0.2"
 
-babel-preset-env@^1.7.0:
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a"
-  dependencies:
-    babel-plugin-check-es2015-constants "^6.22.0"
-    babel-plugin-syntax-trailing-function-commas "^6.22.0"
-    babel-plugin-transform-async-to-generator "^6.22.0"
-    babel-plugin-transform-es2015-arrow-functions "^6.22.0"
-    babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
-    babel-plugin-transform-es2015-block-scoping "^6.23.0"
-    babel-plugin-transform-es2015-classes "^6.23.0"
-    babel-plugin-transform-es2015-computed-properties "^6.22.0"
-    babel-plugin-transform-es2015-destructuring "^6.23.0"
-    babel-plugin-transform-es2015-duplicate-keys "^6.22.0"
-    babel-plugin-transform-es2015-for-of "^6.23.0"
-    babel-plugin-transform-es2015-function-name "^6.22.0"
-    babel-plugin-transform-es2015-literals "^6.22.0"
-    babel-plugin-transform-es2015-modules-amd "^6.22.0"
-    babel-plugin-transform-es2015-modules-commonjs "^6.23.0"
-    babel-plugin-transform-es2015-modules-systemjs "^6.23.0"
-    babel-plugin-transform-es2015-modules-umd "^6.23.0"
-    babel-plugin-transform-es2015-object-super "^6.22.0"
-    babel-plugin-transform-es2015-parameters "^6.23.0"
-    babel-plugin-transform-es2015-shorthand-properties "^6.22.0"
-    babel-plugin-transform-es2015-spread "^6.22.0"
-    babel-plugin-transform-es2015-sticky-regex "^6.22.0"
-    babel-plugin-transform-es2015-template-literals "^6.22.0"
-    babel-plugin-transform-es2015-typeof-symbol "^6.23.0"
-    babel-plugin-transform-es2015-unicode-regex "^6.22.0"
-    babel-plugin-transform-exponentiation-operator "^6.22.0"
-    babel-plugin-transform-regenerator "^6.22.0"
-    browserslist "^3.2.6"
-    invariant "^2.2.2"
-    semver "^5.3.0"
-
-babel-preset-es2015@^6.0.0:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
-  dependencies:
-    babel-plugin-check-es2015-constants "^6.22.0"
-    babel-plugin-transform-es2015-arrow-functions "^6.22.0"
-    babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
-    babel-plugin-transform-es2015-block-scoping "^6.24.1"
-    babel-plugin-transform-es2015-classes "^6.24.1"
-    babel-plugin-transform-es2015-computed-properties "^6.24.1"
-    babel-plugin-transform-es2015-destructuring "^6.22.0"
-    babel-plugin-transform-es2015-duplicate-keys "^6.24.1"
-    babel-plugin-transform-es2015-for-of "^6.22.0"
-    babel-plugin-transform-es2015-function-name "^6.24.1"
-    babel-plugin-transform-es2015-literals "^6.22.0"
-    babel-plugin-transform-es2015-modules-amd "^6.24.1"
-    babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
-    babel-plugin-transform-es2015-modules-systemjs "^6.24.1"
-    babel-plugin-transform-es2015-modules-umd "^6.24.1"
-    babel-plugin-transform-es2015-object-super "^6.24.1"
-    babel-plugin-transform-es2015-parameters "^6.24.1"
-    babel-plugin-transform-es2015-shorthand-properties "^6.24.1"
-    babel-plugin-transform-es2015-spread "^6.22.0"
-    babel-plugin-transform-es2015-sticky-regex "^6.24.1"
-    babel-plugin-transform-es2015-template-literals "^6.22.0"
-    babel-plugin-transform-es2015-typeof-symbol "^6.22.0"
-    babel-plugin-transform-es2015-unicode-regex "^6.24.1"
-    babel-plugin-transform-regenerator "^6.24.1"
-
-babel-preset-stage-2@^6.0.0:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1"
-  dependencies:
-    babel-plugin-syntax-dynamic-import "^6.18.0"
-    babel-plugin-transform-class-properties "^6.24.1"
-    babel-plugin-transform-decorators "^6.24.1"
-    babel-preset-stage-3 "^6.24.1"
-
-babel-preset-stage-3@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395"
-  dependencies:
-    babel-plugin-syntax-trailing-function-commas "^6.22.0"
-    babel-plugin-transform-async-generator-functions "^6.24.1"
-    babel-plugin-transform-async-to-generator "^6.24.1"
-    babel-plugin-transform-exponentiation-operator "^6.24.1"
-    babel-plugin-transform-object-rest-spread "^6.22.0"
-
 babel-register@^6.0.0, babel-register@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
@@ -1177,7 +1246,7 @@ babel-register@^6.0.0, babel-register@^6.26.0:
     mkdirp "^0.5.1"
     source-map-support "^0.4.15"
 
-babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+babel-runtime@^6.22.0, babel-runtime@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
   dependencies:
@@ -1194,7 +1263,7 @@ babel-template@^6.24.1, babel-template@^6.26.0:
     babylon "^6.18.0"
     lodash "^4.17.4"
 
-babel-traverse@^6.23.1, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
+babel-traverse@^6.23.1, babel-traverse@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
   dependencies:
@@ -1208,7 +1277,7 @@ babel-traverse@^6.23.1, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
     invariant "^2.2.2"
     lodash "^4.17.4"
 
-babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24.1, babel-types@^6.26.0:
+babel-types@^6.23.0, babel-types@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
   dependencies:
@@ -1443,12 +1512,14 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
     caniuse-db "^1.0.30000639"
     electron-to-chromium "^1.2.7"
 
-browserslist@^3.2.6:
-  version "3.2.8"
-  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6"
+browserslist@^4.6.0, browserslist@^4.8.2:
+  version "4.8.2"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.2.tgz#b45720ad5fbc8713b7253c20766f701c9a694289"
+  integrity sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA==
   dependencies:
-    caniuse-lite "^1.0.30000844"
-    electron-to-chromium "^1.3.47"
+    caniuse-lite "^1.0.30001015"
+    electron-to-chromium "^1.3.322"
+    node-releases "^1.1.42"
 
 buffer-alloc-unsafe@^1.1.0:
   version "1.1.0"
@@ -1604,9 +1675,10 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
   version "1.0.30000928"
   resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000928.tgz#2e83d2b14276442da239511615eb7c62fed0cfa7"
 
-caniuse-lite@^1.0.30000844:
-  version "1.0.30000928"
-  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000928.tgz#805e828dc72b06498e3683a32e61c7507fd67b88"
+caniuse-lite@^1.0.30001015:
+  version "1.0.30001015"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz#15a7ddf66aba786a71d99626bc8f2b91c6f0f5f0"
+  integrity sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ==
 
 caseless@~0.12.0:
   version "0.12.0"
@@ -1979,7 +2051,15 @@ copy-descriptor@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
 
-core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.7:
+core-js-compat@^3.4.7:
+  version "3.4.8"
+  resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.4.8.tgz#f72e6a4ed76437ea710928f44615f926a81607d5"
+  integrity sha512-l3WTmnXHV2Sfu5VuD7EHE2w7y+K68+kULKt5RJg8ZJk3YhHF1qLD4O8v8AmNq+8vbOwnPFFDvds25/AoEvMqlQ==
+  dependencies:
+    browserslist "^4.8.2"
+    semver "^6.3.0"
+
+core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0:
   version "2.6.2"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.2.tgz#267988d7268323b349e20b4588211655f0e83944"
 
@@ -2496,10 +2576,15 @@ ejs@2.5.7:
   version "2.5.7"
   resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a"
 
-electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.47:
+electron-to-chromium@^1.2.7:
   version "1.3.100"
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.100.tgz#899fb088def210aee6b838a47655bbb299190e13"
 
+electron-to-chromium@^1.3.322:
+  version "1.3.322"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8"
+  integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA==
+
 elliptic@^6.0.0:
   version "6.4.1"
   resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a"
@@ -4215,6 +4300,11 @@ js-base64@^2.1.9:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.0.tgz#42255ba183ab67ce59a0dee640afdc00ab5ae93e"
 
+js-levenshtein@^1.1.3:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
+  integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
+
 "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
@@ -5265,6 +5355,13 @@ node-pre-gyp@^0.12.0:
     semver "^5.3.0"
     tar "^4"
 
+node-releases@^1.1.42:
+  version "1.1.42"
+  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.42.tgz#a999f6a62f8746981f6da90627a8d2fc090bbad7"
+  integrity sha512-OQ/ESmUqGawI2PRX+XIRao44qWYBBfN54ImQYdWVTQqUckuejOg76ysSqDBK8NG3zwySRVnX36JwDQ6x+9GxzA==
+  dependencies:
+    semver "^6.3.0"
+
 nomnomnomnom@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/nomnomnomnom/-/nomnomnomnom-2.0.1.tgz#b2239f031c8d04da67e32836e1e3199e12f7a8e2"
@@ -5381,7 +5478,7 @@ object-hash@^1.1.4:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df"
 
-object-keys@^1.0.12:
+object-keys@^1.0.11, object-keys@^1.0.12:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
 
@@ -5395,6 +5492,16 @@ object-visit@^1.0.0:
   dependencies:
     isobject "^3.0.0"
 
+object.assign@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
+  integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
+  dependencies:
+    define-properties "^1.1.2"
+    function-bind "^1.1.1"
+    has-symbols "^1.0.0"
+    object-keys "^1.0.11"
+
 object.getownpropertydescriptors@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
@@ -6399,7 +6506,14 @@ reduce-function-call@^1.0.1:
   dependencies:
     balanced-match "^0.4.2"
 
-regenerate@^1.2.1:
+regenerate-unicode-properties@^8.1.0:
+  version "8.1.0"
+  resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e"
+  integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==
+  dependencies:
+    regenerate "^1.4.0"
+
+regenerate@^1.2.1, regenerate@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
 
@@ -6407,16 +6521,11 @@ regenerator-runtime@^0.11.0:
   version "0.11.1"
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
 
-regenerator-runtime@^0.12.0:
-  version "0.12.1"
-  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
-
-regenerator-transform@^0.10.0:
-  version "0.10.1"
-  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
+regenerator-transform@^0.14.0:
+  version "0.14.1"
+  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"
+  integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==
   dependencies:
-    babel-runtime "^6.18.0"
-    babel-types "^6.19.0"
     private "^0.1.6"
 
 regex-cache@^0.4.2:
@@ -6444,24 +6553,40 @@ regexpu-core@^1.0.0:
     regjsgen "^0.2.0"
     regjsparser "^0.1.4"
 
-regexpu-core@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
+regexpu-core@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6"
+  integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==
   dependencies:
-    regenerate "^1.2.1"
-    regjsgen "^0.2.0"
-    regjsparser "^0.1.4"
+    regenerate "^1.4.0"
+    regenerate-unicode-properties "^8.1.0"
+    regjsgen "^0.5.0"
+    regjsparser "^0.6.0"
+    unicode-match-property-ecmascript "^1.0.4"
+    unicode-match-property-value-ecmascript "^1.1.0"
 
 regjsgen@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
 
+regjsgen@^0.5.0:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c"
+  integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==
+
 regjsparser@^0.1.4:
   version "0.1.5"
   resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
   dependencies:
     jsesc "~0.5.0"
 
+regjsparser@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c"
+  integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==
+  dependencies:
+    jsesc "~0.5.0"
+
 relateurl@0.2.x:
   version "0.2.7"
   resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
@@ -6712,6 +6837,11 @@ semver@^5.5.1:
   version "5.7.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
 
+semver@^6.3.0:
+  version "6.3.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+  integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
 semver@~5.0.1:
   version "5.0.3"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a"
@@ -7451,6 +7581,29 @@ underscore@~1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
 
+unicode-canonical-property-names-ecmascript@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
+  integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==
+
+unicode-match-property-ecmascript@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c"
+  integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==
+  dependencies:
+    unicode-canonical-property-names-ecmascript "^1.0.4"
+    unicode-property-aliases-ecmascript "^1.0.4"
+
+unicode-match-property-value-ecmascript@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277"
+  integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==
+
+unicode-property-aliases-ecmascript@^1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57"
+  integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==
+
 union-value@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"

From a5cce10a7d1369af64c62024f0e9c388e3c17bac Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Wed, 11 Dec 2019 13:56:53 +0500
Subject: [PATCH 24/62] update babelrc presets config

---
 .babelrc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.babelrc b/.babelrc
index bc2b0e31..0fd2cc39 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,5 +1,5 @@
 {
-  "presets": ["es2015", "stage-2", "env"],
+  "presets": ["@babel/preset-env"],
   "plugins": ["transform-runtime", "lodash", "transform-vue-jsx"],
   "comments": false
 }

From d79dfb94950fff9f99a14ae38891a11d4c5aa373 Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Wed, 11 Dec 2019 14:00:36 +0500
Subject: [PATCH 25/62] upgrade babel-plugin-transform-vue-jsx

---
 package.json |  5 ++--
 yarn.lock    | 67 ++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 48 insertions(+), 24 deletions(-)

diff --git a/package.json b/package.json
index 9bf498e1..299eb5df 100644
--- a/package.json
+++ b/package.json
@@ -42,14 +42,13 @@
   "devDependencies": {
     "@babel/core": "^7.7.5",
     "@babel/preset-env": "^7.7.6",
+    "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
+    "@vue/babel-plugin-transform-vue-jsx": "^1.1.2",
     "@vue/test-utils": "^1.0.0-beta.26",
     "autoprefixer": "^6.4.0",
     "babel-eslint": "^7.0.0",
-    "babel-helper-vue-jsx-merge-props": "^2.0.3",
     "babel-loader": "^8.0.6",
-    "babel-plugin-syntax-jsx": "^6.18.0",
     "babel-plugin-transform-runtime": "^6.0.0",
-    "babel-plugin-transform-vue-jsx": "3",
     "babel-register": "^6.0.0",
     "chai": "^3.5.0",
     "chalk": "^1.1.3",
diff --git a/yarn.lock b/yarn.lock
index b5017997..ed35517a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -124,19 +124,19 @@
   dependencies:
     "@babel/types" "^7.7.4"
 
-"@babel/helper-module-imports@^7.0.0-beta.49":
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
-  dependencies:
-    "@babel/types" "^7.0.0"
-
-"@babel/helper-module-imports@^7.7.4":
+"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91"
   integrity sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==
   dependencies:
     "@babel/types" "^7.7.4"
 
+"@babel/helper-module-imports@^7.0.0-beta.49":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
+  dependencies:
+    "@babel/types" "^7.0.0"
+
 "@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.7.5":
   version "7.7.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835"
@@ -306,6 +306,13 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.0.0"
 
+"@babel/plugin-syntax-jsx@^7.2.0":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec"
+  integrity sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
 "@babel/plugin-syntax-object-rest-spread@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46"
@@ -675,6 +682,23 @@
   dependencies:
     qrcode "^1.3.0"
 
+"@vue/babel-helper-vue-jsx-merge-props@^1.0.0":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz#048fe579958da408fb7a8b2a3ec050b50a661040"
+  integrity sha512-6tyf5Cqm4m6v7buITuwS+jHzPlIPxbFzEhXR5JGZpbrvOcp1hiQKckd305/3C7C36wFekNTQSxAtgeM0j0yoUw==
+
+"@vue/babel-plugin-transform-vue-jsx@^1.1.2":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.1.2.tgz#c0a3e6efc022e75e4247b448a8fc6b86f03e91c0"
+  integrity sha512-YfdaoSMvD1nj7+DsrwfTvTnhDXI7bsuh+Y5qWwvQXlD24uLgnsoww3qbiZvWf/EoviZMrvqkqN4CBw0W3BWUTQ==
+  dependencies:
+    "@babel/helper-module-imports" "^7.0.0"
+    "@babel/plugin-syntax-jsx" "^7.2.0"
+    "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0"
+    html-tags "^2.0.0"
+    lodash.kebabcase "^4.1.1"
+    svg-tags "^1.0.0"
+
 "@vue/test-utils@^1.0.0-beta.26":
   version "1.0.0-beta.28"
   resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.28.tgz#767c43413df8cde86128735e58923803e444b9a5"
@@ -1170,10 +1194,6 @@ babel-generator@^6.26.0:
     source-map "^0.5.7"
     trim-right "^1.0.1"
 
-babel-helper-vue-jsx-merge-props@^2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
-
 babel-helpers@^6.24.1:
   version "6.24.1"
   resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
@@ -1218,22 +1238,12 @@ babel-plugin-lodash@^3.2.11:
     lodash "^4.17.10"
     require-package-name "^2.0.1"
 
-babel-plugin-syntax-jsx@^6.18.0:
-  version "6.18.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
-
 babel-plugin-transform-runtime@^6.0.0:
   version "6.23.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee"
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-transform-vue-jsx@3:
-  version "3.7.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-3.7.0.tgz#d40492e6692a36b594f7e9a1928f43e969740960"
-  dependencies:
-    esutils "^2.0.2"
-
 babel-register@^6.0.0, babel-register@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
@@ -3704,6 +3714,11 @@ html-minifier@^3.2.3:
     relateurl "0.2.x"
     uglify-js "3.4.x"
 
+html-tags@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b"
+  integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=
+
 html-webpack-plugin@^3.0.0, html-webpack-plugin@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b"
@@ -4781,6 +4796,11 @@ lodash.istypedarray@^3.0.0:
   version "3.0.6"
   resolved "https://registry.yarnpkg.com/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz#c9a477498607501d8e8494d283b87c39281cef62"
 
+lodash.kebabcase@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
+  integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY=
+
 lodash.keys@^3.0.0:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
@@ -7350,6 +7370,11 @@ supports-color@^6.0.0, supports-color@^6.1.0:
   dependencies:
     has-flag "^3.0.0"
 
+svg-tags@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
+  integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
+
 svgo@^0.7.0:
   version "0.7.2"
   resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"

From c141c7a753673705be89c056c1ed99126f786c7d Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Wed, 11 Dec 2019 14:01:53 +0500
Subject: [PATCH 26/62] babel-plugin-add-module-exports is not necessary for
 babel v7

---
 package.json | 1 -
 yarn.lock    | 4 ----
 2 files changed, 5 deletions(-)

diff --git a/package.json b/package.json
index 299eb5df..b920a3ab 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,6 @@
   },
   "dependencies": {
     "@chenfengyuan/vue-qrcode": "^1.0.0",
-    "babel-plugin-add-module-exports": "^0.2.1",
     "babel-plugin-lodash": "^3.2.11",
     "body-scroll-lock": "^2.6.4",
     "chromatism": "^3.0.0",
diff --git a/yarn.lock b/yarn.lock
index ed35517a..acc52ac8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1217,10 +1217,6 @@ babel-messages@^6.23.0:
   dependencies:
     babel-runtime "^6.22.0"
 
-babel-plugin-add-module-exports@^0.2.1:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25"
-
 babel-plugin-dynamic-import-node@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f"

From 773fa454bef87db9bfb3c08e4ba25ea38096c415 Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Wed, 11 Dec 2019 14:02:51 +0500
Subject: [PATCH 27/62] upgrade babel-plugin-lodash

---
 package.json | 2 +-
 yarn.lock    | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index b920a3ab..d941e501 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,6 @@
   },
   "dependencies": {
     "@chenfengyuan/vue-qrcode": "^1.0.0",
-    "babel-plugin-lodash": "^3.2.11",
     "body-scroll-lock": "^2.6.4",
     "chromatism": "^3.0.0",
     "cropperjs": "^1.4.3",
@@ -47,6 +46,7 @@
     "autoprefixer": "^6.4.0",
     "babel-eslint": "^7.0.0",
     "babel-loader": "^8.0.6",
+    "babel-plugin-lodash": "^3.3.4",
     "babel-plugin-transform-runtime": "^6.0.0",
     "babel-register": "^6.0.0",
     "chai": "^3.5.0",
diff --git a/yarn.lock b/yarn.lock
index acc52ac8..2dec375a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1224,9 +1224,10 @@ babel-plugin-dynamic-import-node@^2.3.0:
   dependencies:
     object.assign "^4.1.0"
 
-babel-plugin-lodash@^3.2.11:
+babel-plugin-lodash@^3.3.4:
   version "3.3.4"
   resolved "https://registry.yarnpkg.com/babel-plugin-lodash/-/babel-plugin-lodash-3.3.4.tgz#4f6844358a1340baed182adbeffa8df9967bc196"
+  integrity sha512-yDZLjK7TCkWl1gpBeBGmuaDIFhZKmkoL+Cu2MUUjv5VxUZx/z7tBGBCBcQs5RI1Bkz5LLmNdjx7paOyQtMovyg==
   dependencies:
     "@babel/helper-module-imports" "^7.0.0-beta.49"
     "@babel/types" "^7.0.0-beta.49"

From 424e78891afa7f76ed58191187c3e65a7727eaee Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Wed, 11 Dec 2019 14:19:56 +0500
Subject: [PATCH 28/62] upgrade babel-plugin-transform-runtime

---
 package.json |  3 ++-
 yarn.lock    | 28 ++++++++++++++++++++++------
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/package.json b/package.json
index d941e501..c1da6ded 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
     "lint-fix": "eslint --fix --ext .js,.vue src test/unit/specs test/e2e/specs"
   },
   "dependencies": {
+    "@babel/runtime": "^7.7.6",
     "@chenfengyuan/vue-qrcode": "^1.0.0",
     "body-scroll-lock": "^2.6.4",
     "chromatism": "^3.0.0",
@@ -39,6 +40,7 @@
   },
   "devDependencies": {
     "@babel/core": "^7.7.5",
+    "@babel/plugin-transform-runtime": "^7.7.6",
     "@babel/preset-env": "^7.7.6",
     "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
     "@vue/babel-plugin-transform-vue-jsx": "^1.1.2",
@@ -47,7 +49,6 @@
     "babel-eslint": "^7.0.0",
     "babel-loader": "^8.0.6",
     "babel-plugin-lodash": "^3.3.4",
-    "babel-plugin-transform-runtime": "^6.0.0",
     "babel-register": "^6.0.0",
     "chai": "^3.5.0",
     "chalk": "^1.1.3",
diff --git a/yarn.lock b/yarn.lock
index 2dec375a..99ddd096 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -533,6 +533,16 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.0.0"
 
+"@babel/plugin-transform-runtime@^7.7.6":
+  version "7.7.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.7.6.tgz#4f2b548c88922fb98ec1c242afd4733ee3e12f61"
+  integrity sha512-tajQY+YmXR7JjTwRvwL4HePqoL3DYxpYXIHKVvrOIvJmeHe2y1w4tz5qz9ObUDC9m76rCzIMPyn4eERuwA4a4A==
+  dependencies:
+    "@babel/helper-module-imports" "^7.7.4"
+    "@babel/helper-plugin-utils" "^7.0.0"
+    resolve "^1.8.1"
+    semver "^5.5.1"
+
 "@babel/plugin-transform-shorthand-properties@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e"
@@ -635,6 +645,13 @@
     js-levenshtein "^1.1.3"
     semver "^5.5.0"
 
+"@babel/runtime@^7.7.6":
+  version "7.7.6"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f"
+  integrity sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw==
+  dependencies:
+    regenerator-runtime "^0.13.2"
+
 "@babel/template@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
@@ -1235,12 +1252,6 @@ babel-plugin-lodash@^3.3.4:
     lodash "^4.17.10"
     require-package-name "^2.0.1"
 
-babel-plugin-transform-runtime@^6.0.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee"
-  dependencies:
-    babel-runtime "^6.22.0"
-
 babel-register@^6.0.0, babel-register@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
@@ -6538,6 +6549,11 @@ regenerator-runtime@^0.11.0:
   version "0.11.1"
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
 
+regenerator-runtime@^0.13.2:
+  version "0.13.3"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
+  integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==
+
 regenerator-transform@^0.14.0:
   version "0.14.1"
   resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"

From e6d5b9c0bba7410044d0ad2fe7e3670a5026d0d4 Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Wed, 11 Dec 2019 14:21:06 +0500
Subject: [PATCH 29/62] update babelrc

---
 .babelrc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.babelrc b/.babelrc
index 0fd2cc39..3019976f 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,5 +1,5 @@
 {
   "presets": ["@babel/preset-env"],
-  "plugins": ["transform-runtime", "lodash", "transform-vue-jsx"],
+  "plugins": ["@babel/plugin-transform-runtime", "lodash", "transform-vue-jsx"],
   "comments": false
 }

From cb92865dac3c8d961be01d506726b1692ce50d03 Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Wed, 11 Dec 2019 14:22:11 +0500
Subject: [PATCH 30/62] upgrade babel-register

---
 package.json                |  2 +-
 test/e2e/nightwatch.conf.js |  2 +-
 yarn.lock                   | 35 +++++++++++++++++++++++++++++++++--
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index c1da6ded..38936b23 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
     "@babel/core": "^7.7.5",
     "@babel/plugin-transform-runtime": "^7.7.6",
     "@babel/preset-env": "^7.7.6",
+    "@babel/register": "^7.7.4",
     "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
     "@vue/babel-plugin-transform-vue-jsx": "^1.1.2",
     "@vue/test-utils": "^1.0.0-beta.26",
@@ -49,7 +50,6 @@
     "babel-eslint": "^7.0.0",
     "babel-loader": "^8.0.6",
     "babel-plugin-lodash": "^3.3.4",
-    "babel-register": "^6.0.0",
     "chai": "^3.5.0",
     "chalk": "^1.1.3",
     "chromedriver": "^2.21.2",
diff --git a/test/e2e/nightwatch.conf.js b/test/e2e/nightwatch.conf.js
index 2fc3af0b..07d974df 100644
--- a/test/e2e/nightwatch.conf.js
+++ b/test/e2e/nightwatch.conf.js
@@ -1,4 +1,4 @@
-require('babel-register')
+require('@babel/register')
 var config = require('../../config')
 
 // http://nightwatchjs.org/guide#settings-file
diff --git a/yarn.lock b/yarn.lock
index 99ddd096..4b20a6a1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -645,6 +645,17 @@
     js-levenshtein "^1.1.3"
     semver "^5.5.0"
 
+"@babel/register@^7.7.4":
+  version "7.7.4"
+  resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.7.4.tgz#45a4956471a9df3b012b747f5781cc084ee8f128"
+  integrity sha512-/fmONZqL6ZMl9KJUYajetCrID6m0xmL4odX7v+Xvoxcv0DdbP/oO0TWIeLUCHqczQ6L6njDMqmqHFy2cp3FFsA==
+  dependencies:
+    find-cache-dir "^2.0.0"
+    lodash "^4.17.13"
+    make-dir "^2.1.0"
+    pirates "^4.0.0"
+    source-map-support "^0.5.16"
+
 "@babel/runtime@^7.7.6":
   version "7.7.6"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f"
@@ -1252,7 +1263,7 @@ babel-plugin-lodash@^3.3.4:
     lodash "^4.17.10"
     require-package-name "^2.0.1"
 
-babel-register@^6.0.0, babel-register@^6.26.0:
+babel-register@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
   dependencies:
@@ -4950,7 +4961,7 @@ lru-cache@~2.6.5:
   version "2.6.5"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.5.tgz#e56d6354148ede8d7707b58d143220fd08df0fd5"
 
-make-dir@^2.0.0:
+make-dir@^2.0.0, make-dir@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
   dependencies:
@@ -5368,6 +5379,11 @@ node-libs-browser@^2.0.0:
     util "^0.11.0"
     vm-browserify "0.0.4"
 
+node-modules-regexp@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
+  integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
+
 node-pre-gyp@^0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149"
@@ -5885,6 +5901,13 @@ pinkie@^2.0.0:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
 
+pirates@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
+  integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==
+  dependencies:
+    node-modules-regexp "^1.0.0"
+
 pkg-dir@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
@@ -7130,6 +7153,14 @@ source-map-support@^0.4.15:
   dependencies:
     source-map "^0.5.6"
 
+source-map-support@^0.5.16:
+  version "0.5.16"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
+  integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
+  dependencies:
+    buffer-from "^1.0.0"
+    source-map "^0.6.0"
+
 source-map-support@~0.5.10:
   version "0.5.12"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"

From d6dc2bad1f2175f9a9eb0dfd4c04fafab410632b Mon Sep 17 00:00:00 2001
From: Maksim Pechnikov <parallel588@gmail.com>
Date: Wed, 11 Dec 2019 15:59:29 +0300
Subject: [PATCH 31/62] fixed typo

---
 src/services/api/api.service.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 8f5eb416..68be0d50 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -22,7 +22,7 @@ const MFA_BACKUP_CODES_URL = '/api/pleroma/accounts/mfa/backup_codes'
 
 const MFA_SETUP_OTP_URL = '/api/pleroma/accounts/mfa/setup/totp'
 const MFA_CONFIRM_OTP_URL = '/api/pleroma/accounts/mfa/confirm/totp'
-const MFA_DISABLE_OTP_URL = '/api/pleroma/account/mfa/totp'
+const MFA_DISABLE_OTP_URL = '/api/pleroma/accounts/mfa/totp'
 
 const MASTODON_LOGIN_URL = '/api/v1/accounts/verify_credentials'
 const MASTODON_REGISTRATION_URL = '/api/v1/accounts'

From d0c78989aa9e5f5142dbc09a8935c004a2050257 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sun, 1 Dec 2019 19:34:01 -0500
Subject: [PATCH 32/62] hide instance url/link/text in header using
 hideSitename option

---
 src/App.js                                 | 1 +
 src/App.vue                                | 1 +
 src/boot/after_store.js                    | 1 +
 src/components/mobile_nav/mobile_nav.js    | 1 +
 src/components/mobile_nav/mobile_nav.vue   | 1 +
 src/components/side_drawer/side_drawer.js  | 3 +++
 src/components/side_drawer/side_drawer.vue | 2 +-
 src/modules/instance.js                    | 1 +
 8 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/App.js b/src/App.js
index 04a40e30..78ff29da 100644
--- a/src/App.js
+++ b/src/App.js
@@ -90,6 +90,7 @@ export default {
     },
     sitename () { return this.$store.state.instance.name },
     chat () { return this.$store.state.chat.channel.state === 'joined' },
+    hideSitename () { return this.$store.state.instance.hideSitename },
     suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
     showInstanceSpecificPanel () {
       return this.$store.state.instance.showInstanceSpecificPanel &&
diff --git a/src/App.vue b/src/App.vue
index dbe842ec..c66df843 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -31,6 +31,7 @@
         </div>
         <div class="item">
           <router-link
+            v-if="!hideSitename"
             class="site-name"
             :to="{ name: 'root' }"
             active-class="home"
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index 226b67d8..e18cd657 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -108,6 +108,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
   copyInstanceOption('alwaysShowSubjectInput')
   copyInstanceOption('noAttachmentLinks')
   copyInstanceOption('showFeaturesPanel')
+  copyInstanceOption('hideSitename')
 
   return store.dispatch('setTheme', config['theme'])
 }
diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js
index 5a90c31f..c1166a0c 100644
--- a/src/components/mobile_nav/mobile_nav.js
+++ b/src/components/mobile_nav/mobile_nav.js
@@ -29,6 +29,7 @@ const MobileNav = {
     unseenNotificationsCount () {
       return this.unseenNotifications.length
     },
+    hideSitename () { return this.$store.state.instance.hideSitename },
     sitename () { return this.$store.state.instance.name }
   },
   methods: {
diff --git a/src/components/mobile_nav/mobile_nav.vue b/src/components/mobile_nav/mobile_nav.vue
index d1c24e56..51f1d636 100644
--- a/src/components/mobile_nav/mobile_nav.vue
+++ b/src/components/mobile_nav/mobile_nav.vue
@@ -17,6 +17,7 @@
             <i class="button-icon icon-menu" />
           </a>
           <router-link
+            v-if="!hideSitename"
             class="site-name"
             :to="{ name: 'root' }"
             active-class="home"
diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js
index 0188cf3e..65c96e47 100644
--- a/src/components/side_drawer/side_drawer.js
+++ b/src/components/side_drawer/side_drawer.js
@@ -33,6 +33,9 @@ const SideDrawer = {
     logo () {
       return this.$store.state.instance.logo
     },
+    hideSitename () {
+      return this.$store.state.instance.hideSitename
+    },
     sitename () {
       return this.$store.state.instance.name
     },
diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue
index 214b8e0c..eb429f29 100644
--- a/src/components/side_drawer/side_drawer.vue
+++ b/src/components/side_drawer/side_drawer.vue
@@ -27,7 +27,7 @@
           class="side-drawer-logo-wrapper"
         >
           <img :src="logo">
-          <span>{{ sitename }}</span>
+          <span v-if="!hideSitename">{{ sitename }}</span>
         </div>
       </div>
       <ul>
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 96f14ed5..625323b9 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -27,6 +27,7 @@ const defaultState = {
   scopeCopy: true,
   subjectLineBehavior: 'email',
   postContentType: 'text/plain',
+  hideSitename: false,
   nsfwCensorImage: undefined,
   vapidPublicKey: undefined,
   noAttachmentLinks: false,

From fee3226705beb4b6eddb8e64f8c53b2651ca89fa Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Mon, 9 Dec 2019 15:21:33 -0500
Subject: [PATCH 33/62] add documentation for new instance option

---
 docs/CONFIGURATION.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md
index 35363537..3a21828b 100644
--- a/docs/CONFIGURATION.md
+++ b/docs/CONFIGURATION.md
@@ -77,6 +77,9 @@ Use custom image for NSFW'd images
 ### `showFeaturesPanel`
 Show panel showcasing instance features/settings to logged-out visitors
 
+### `hideSitename`
+Hide instance name in header
+
 ## Indirect configuration
 Some features are configured depending on how backend is configured. In general the approach is "if backend allows it there's no need to hide it, if backend doesn't allow it there's no need to show it.
 

From 63a5f50e7c4acfc7676a1093990d0377dcb1a39f Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 11 Dec 2019 18:20:43 +0200
Subject: [PATCH 34/62] fix deletes causing errors

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

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 517b953e..5f706dc0 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1010,6 +1010,10 @@ export const handleMastoWS = (wsEvent) => {
   const parsedEvent = JSON.parse(data)
   const { event, payload } = parsedEvent
   if (MASTODON_STREAMING_EVENTS.has(event)) {
+    // MastoBE and PleromaBE both send payload for delete as a PLAIN string
+    if (event === 'delete') {
+      return { event, id: payload }
+    }
     const data = payload ? JSON.parse(payload) : null
     if (event === 'update') {
       return { event, status: parseStatus(data) }

From d7bc1aff1d4c52c038457fe7650ffb793dfc4618 Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Thu, 12 Dec 2019 06:35:48 +0500
Subject: [PATCH 35/62] fix babelrc plugin config

---
 .babelrc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.babelrc b/.babelrc
index 3019976f..3c732dd1 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,5 +1,5 @@
 {
   "presets": ["@babel/preset-env"],
-  "plugins": ["@babel/plugin-transform-runtime", "lodash", "transform-vue-jsx"],
+  "plugins": ["@babel/plugin-transform-runtime", "lodash", "@vue/babel-plugin-transform-vue-jsx"],
   "comments": false
 }

From 386719b0d03475fb5cab667ce28a5aff354fbc4d Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Thu, 12 Dec 2019 08:33:40 +0500
Subject: [PATCH 36/62] fix css runtime loading issue

---
 src/App.scss                         | 13 +++++++++++++
 src/components/timeline/timeline.vue | 13 -------------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/App.scss b/src/App.scss
index 925913f2..754ca62e 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -870,3 +870,16 @@ nav {
     transform: rotate(359deg);
   }
 }
+
+.new-status-notification {
+  position:relative;
+  margin-top: -1px;
+  font-size: 1.1em;
+  border-width: 1px 0 0 0;
+  border-style: solid;
+  border-color: var(--border, $fallback--border);
+  padding: 10px;
+  z-index: 1;
+  background-color: $fallback--fg;
+  background-color: var(--panel, $fallback--fg);
+}
diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue
index 93f6f570..a6fba452 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -93,17 +93,4 @@
     opacity: 1;
   }
 }
-
-.new-status-notification {
-  position:relative;
-  margin-top: -1px;
-  font-size: 1.1em;
-  border-width: 1px 0 0 0;
-  border-style: solid;
-  border-color: var(--border, $fallback--border);
-  padding: 10px;
-  z-index: 1;
-  background-color: $fallback--fg;
-  background-color: var(--panel, $fallback--fg);
-}
 </style>

From f70fe28f644c037326a1d2c1fdffbf6d365e0a02 Mon Sep 17 00:00:00 2001
From: Maksim Pechnikov <parallel588@gmail.com>
Date: Thu, 12 Dec 2019 08:42:21 +0300
Subject: [PATCH 37/62] mfa: fix login and recovery form

---
 src/components/mfa_form/recovery_form.js | 11 ++++++++---
 src/components/mfa_form/totp_form.js     | 10 ++++++++--
 src/services/new_api/mfa.js              | 12 ++++++------
 3 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/src/components/mfa_form/recovery_form.js b/src/components/mfa_form/recovery_form.js
index 7a3cc22d..b25c65dd 100644
--- a/src/components/mfa_form/recovery_form.js
+++ b/src/components/mfa_form/recovery_form.js
@@ -8,18 +8,23 @@ export default {
   }),
   computed: {
     ...mapGetters({
-      authApp: 'authFlow/app',
       authSettings: 'authFlow/settings'
     }),
-    ...mapState({ instance: 'instance' })
+    ...mapState({
+      instance: 'instance',
+      oauth: 'oauth'
+    })
   },
   methods: {
     ...mapMutations('authFlow', ['requireTOTP', 'abortMFA']),
     ...mapActions({ login: 'authFlow/login' }),
     clearError () { this.error = false },
     submit () {
+      const { clientId, clientSecret } = this.oauth
+
       const data = {
-        app: this.authApp,
+        clientId,
+        clientSecret,
         instance: this.instance.server,
         mfaToken: this.authSettings.mfa_token,
         code: this.code
diff --git a/src/components/mfa_form/totp_form.js b/src/components/mfa_form/totp_form.js
index 778bf8dc..1ec7576b 100644
--- a/src/components/mfa_form/totp_form.js
+++ b/src/components/mfa_form/totp_form.js
@@ -10,15 +10,21 @@ export default {
       authApp: 'authFlow/app',
       authSettings: 'authFlow/settings'
     }),
-    ...mapState({ instance: 'instance' })
+    ...mapState({
+      instance: 'instance',
+      oauth: 'oauth'
+    })
   },
   methods: {
     ...mapMutations('authFlow', ['requireRecovery', 'abortMFA']),
     ...mapActions({ login: 'authFlow/login' }),
     clearError () { this.error = false },
     submit () {
+      const { clientId, clientSecret } = this.oauth
+
       const data = {
-        app: this.authApp,
+        clientId,
+        clientSecret,
         instance: this.instance.server,
         mfaToken: this.authSettings.mfa_token,
         code: this.code
diff --git a/src/services/new_api/mfa.js b/src/services/new_api/mfa.js
index cbba06d5..c944667c 100644
--- a/src/services/new_api/mfa.js
+++ b/src/services/new_api/mfa.js
@@ -1,9 +1,9 @@
-const verifyOTPCode = ({ app, instance, mfaToken, code }) => {
+const verifyOTPCode = ({ clientId, clientSecret, instance, mfaToken, code }) => {
   const url = `${instance}/oauth/mfa/challenge`
   const form = new window.FormData()
 
-  form.append('client_id', app.client_id)
-  form.append('client_secret', app.client_secret)
+  form.append('client_id', clientId)
+  form.append('client_secret', clientSecret)
   form.append('mfa_token', mfaToken)
   form.append('code', code)
   form.append('challenge_type', 'totp')
@@ -14,12 +14,12 @@ const verifyOTPCode = ({ app, instance, mfaToken, code }) => {
   }).then((data) => data.json())
 }
 
-const verifyRecoveryCode = ({ app, instance, mfaToken, code }) => {
+const verifyRecoveryCode = ({ clientId, clientSecret, instance, mfaToken, code }) => {
   const url = `${instance}/oauth/mfa/challenge`
   const form = new window.FormData()
 
-  form.append('client_id', app.client_id)
-  form.append('client_secret', app.client_secret)
+  form.append('client_id', clientId)
+  form.append('client_secret', clientSecret)
   form.append('mfa_token', mfaToken)
   form.append('code', code)
   form.append('challenge_type', 'recovery')

From b973ee5915ca9a2c79d9523286f42aee4b1a7db7 Mon Sep 17 00:00:00 2001
From: seven <sjang8762@outlook.com>
Date: Thu, 12 Dec 2019 12:13:31 +0500
Subject: [PATCH 38/62] must use h in higher babel-plugin-transform-vue-jsx

---
 src/hocs/with_load_more/with_load_more.js       | 4 ++--
 src/hocs/with_subscription/with_subscription.js | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/hocs/with_load_more/with_load_more.js b/src/hocs/with_load_more/with_load_more.js
index 1e1b2a74..6142f513 100644
--- a/src/hocs/with_load_more/with_load_more.js
+++ b/src/hocs/with_load_more/with_load_more.js
@@ -65,7 +65,7 @@ const withLoadMore = ({
         }
       }
     },
-    render (createElement) {
+    render (h) {
       const props = {
         props: {
           ...this.$props,
@@ -74,7 +74,7 @@ const withLoadMore = ({
         on: this.$listeners,
         scopedSlots: this.$scopedSlots
       }
-      const children = Object.entries(this.$slots).map(([key, value]) => createElement('template', { slot: key }, value))
+      const children = Object.entries(this.$slots).map(([key, value]) => h('template', { slot: key }, value))
       return (
         <div class="with-load-more">
           <WrappedComponent {...props}>
diff --git a/src/hocs/with_subscription/with_subscription.js b/src/hocs/with_subscription/with_subscription.js
index 91fc4cca..1775adcb 100644
--- a/src/hocs/with_subscription/with_subscription.js
+++ b/src/hocs/with_subscription/with_subscription.js
@@ -49,7 +49,7 @@ const withSubscription = ({
         }
       }
     },
-    render (createElement) {
+    render (h) {
       if (!this.error && !this.loading) {
         const props = {
           props: {
@@ -59,7 +59,7 @@ const withSubscription = ({
           on: this.$listeners,
           scopedSlots: this.$scopedSlots
         }
-        const children = Object.entries(this.$slots).map(([key, value]) => createElement('template', { slot: key }, value))
+        const children = Object.entries(this.$slots).map(([key, value]) => h('template', { slot: key }, value))
         return (
           <div class="with-subscription">
             <WrappedComponent {...props}>

From b3992358487d5afa7499759a90d6447a2b0bfe20 Mon Sep 17 00:00:00 2001
From: lain <lain@soykaf.club>
Date: Thu, 12 Dec 2019 09:38:24 +0000
Subject: [PATCH 39/62] Revert "Merge branch 'oauth-extra-scopes' into
 'develop'"

This reverts merge request !1024
---
 src/services/new_api/oauth.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/services/new_api/oauth.js b/src/services/new_api/oauth.js
index 3c8e64bd..d0d18c03 100644
--- a/src/services/new_api/oauth.js
+++ b/src/services/new_api/oauth.js
@@ -12,7 +12,7 @@ export const getOrCreateApp = ({ clientId, clientSecret, instance, commit }) =>
 
   form.append('client_name', `PleromaFE_${window.___pleromafe_commit_hash}_${(new Date()).toISOString()}`)
   form.append('redirect_uris', REDIRECT_URI)
-  form.append('scopes', 'read write follow push admin')
+  form.append('scopes', 'read write follow')
 
   return window.fetch(url, {
     method: 'POST',
@@ -28,7 +28,7 @@ const login = ({ instance, clientId }) => {
     response_type: 'code',
     client_id: clientId,
     redirect_uri: REDIRECT_URI,
-    scope: 'read write follow push admin'
+    scope: 'read write follow'
   }
 
   const dataString = reduce(data, (acc, v, k) => {

From ed3144eb1168ece5fcd3eed2867c653f785039d8 Mon Sep 17 00:00:00 2001
From: Egor Kislitsyn <egor@kislitsyn.com>
Date: Thu, 12 Dec 2019 18:19:46 +0700
Subject: [PATCH 40/62] Support "native" captcha

---
 src/components/registration/registration.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue
index 5bb06a4f..222b67a8 100644
--- a/src/components/registration/registration.vue
+++ b/src/components/registration/registration.vue
@@ -172,7 +172,7 @@
                 for="captcha-label"
               >{{ $t('captcha') }}</label>
 
-              <template v-if="captcha.type == 'kocaptcha'">
+              <template v-if="['kocaptcha', 'native'].includes(captcha.type)">
                 <img
                   :src="captcha.url"
                   @click="setCaptcha"

From 341416b0e0102b20d9b8ee317218ee55d0402452 Mon Sep 17 00:00:00 2001
From: Ivan Tashkinov <ivantbusiness@gmail.com>
Date: Thu, 12 Dec 2019 14:43:48 +0000
Subject: [PATCH 41/62] Revert "Merge branch 'revert-96cab6d8' into 'develop'"

This reverts merge request !1032
---
 src/services/new_api/oauth.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/services/new_api/oauth.js b/src/services/new_api/oauth.js
index d0d18c03..3c8e64bd 100644
--- a/src/services/new_api/oauth.js
+++ b/src/services/new_api/oauth.js
@@ -12,7 +12,7 @@ export const getOrCreateApp = ({ clientId, clientSecret, instance, commit }) =>
 
   form.append('client_name', `PleromaFE_${window.___pleromafe_commit_hash}_${(new Date()).toISOString()}`)
   form.append('redirect_uris', REDIRECT_URI)
-  form.append('scopes', 'read write follow')
+  form.append('scopes', 'read write follow push admin')
 
   return window.fetch(url, {
     method: 'POST',
@@ -28,7 +28,7 @@ const login = ({ instance, clientId }) => {
     response_type: 'code',
     client_id: clientId,
     redirect_uri: REDIRECT_URI,
-    scope: 'read write follow'
+    scope: 'read write follow push admin'
   }
 
   const dataString = reduce(data, (acc, v, k) => {

From 7fa294f11c9ea3912b134a16225b3fc0c2ad29cc Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sat, 30 Nov 2019 12:30:25 -0500
Subject: [PATCH 42/62] add icons to nav panel

---
 src/components/nav_panel/nav_panel.vue     | 14 +++++-----
 src/components/side_drawer/side_drawer.vue | 28 ++++++++++----------
 static/fontello.json                       | 30 ++++++++++++++++++++++
 3 files changed, 51 insertions(+), 21 deletions(-)

diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue
index 28589bb1..d660f189 100644
--- a/src/components/nav_panel/nav_panel.vue
+++ b/src/components/nav_panel/nav_panel.vue
@@ -4,22 +4,22 @@
       <ul>
         <li v-if="currentUser">
           <router-link :to="{ name: 'friends' }">
-            {{ $t("nav.timeline") }}
+            <i class="button-icon icon-home-2" /> {{ $t("nav.timeline") }}
           </router-link>
         </li>
         <li v-if="currentUser">
           <router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }">
-            {{ $t("nav.interactions") }}
+            <i class="button-icon icon-bell-alt" /> {{ $t("nav.interactions") }}
           </router-link>
         </li>
         <li v-if="currentUser">
           <router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
-            {{ $t("nav.dms") }}
+            <i class="button-icon icon-mail-alt" /> {{ $t("nav.dms") }}
           </router-link>
         </li>
         <li v-if="currentUser && currentUser.locked">
           <router-link :to="{ name: 'friend-requests' }">
-            {{ $t("nav.friend_requests") }}
+            <i class="button-icon icon-user-plus" /> {{ $t("nav.friend_requests") }}
             <span
               v-if="followRequestCount > 0"
               class="badge follow-request-count"
@@ -30,17 +30,17 @@
         </li>
         <li>
           <router-link :to="{ name: 'public-timeline' }">
-            {{ $t("nav.public_tl") }}
+            <i class="button-icon icon-users" /> {{ $t("nav.public_tl") }}
           </router-link>
         </li>
         <li>
           <router-link :to="{ name: 'public-external-timeline' }">
-            {{ $t("nav.twkn") }}
+            <i class="button-icon icon-globe" /> {{ $t("nav.twkn") }}
           </router-link>
         </li>
         <li>
           <router-link :to="{ name: 'about' }">
-            {{ $t("nav.about") }}
+            <i class="button-icon icon-info-circled" /> {{ $t("nav.about") }}
           </router-link>
         </li>
       </ul>
diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue
index eb429f29..1c65c173 100644
--- a/src/components/side_drawer/side_drawer.vue
+++ b/src/components/side_drawer/side_drawer.vue
@@ -36,7 +36,7 @@
           @click="toggleDrawer"
         >
           <router-link :to="{ name: 'login' }">
-            {{ $t("login.login") }}
+            <i class="button-icon icon-login" /> {{ $t("login.login") }}
           </router-link>
         </li>
         <li
@@ -44,7 +44,7 @@
           @click="toggleDrawer"
         >
           <router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
-            {{ $t("nav.dms") }}
+            <i class="button-icon icon-mail-alt" /> {{ $t("nav.dms") }}
           </router-link>
         </li>
         <li
@@ -52,7 +52,7 @@
           @click="toggleDrawer"
         >
           <router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }">
-            {{ $t("nav.interactions") }}
+            <i class="button-icon icon-bell-alt" /> {{ $t("nav.interactions") }}
           </router-link>
         </li>
       </ul>
@@ -62,7 +62,7 @@
           @click="toggleDrawer"
         >
           <router-link :to="{ name: 'friends' }">
-            {{ $t("nav.timeline") }}
+            <i class="button-icon icon-home-2" /> {{ $t("nav.timeline") }}
           </router-link>
         </li>
         <li
@@ -70,7 +70,7 @@
           @click="toggleDrawer"
         >
           <router-link to="/friend-requests">
-            {{ $t("nav.friend_requests") }}
+            <i class="button-icon icon-user-plus" /> {{ $t("nav.friend_requests") }}
             <span
               v-if="followRequestCount > 0"
               class="badge follow-request-count"
@@ -81,12 +81,12 @@
         </li>
         <li @click="toggleDrawer">
           <router-link to="/main/public">
-            {{ $t("nav.public_tl") }}
+            <i class="button-icon icon-users" /> {{ $t("nav.public_tl") }}
           </router-link>
         </li>
         <li @click="toggleDrawer">
           <router-link to="/main/all">
-            {{ $t("nav.twkn") }}
+            <i class="button-icon icon-globe" /> {{ $t("nav.twkn") }}
           </router-link>
         </li>
         <li
@@ -94,14 +94,14 @@
           @click="toggleDrawer"
         >
           <router-link :to="{ name: 'chat' }">
-            {{ $t("nav.chat") }}
+            <i class="button-icon icon-chat" /> {{ $t("nav.chat") }}
           </router-link>
         </li>
       </ul>
       <ul>
         <li @click="toggleDrawer">
           <router-link :to="{ name: 'search' }">
-            {{ $t("nav.search") }}
+            <i class="button-icon icon-search" /> {{ $t("nav.search") }}
           </router-link>
         </li>
         <li
@@ -109,17 +109,17 @@
           @click="toggleDrawer"
         >
           <router-link :to="{ name: 'who-to-follow' }">
-            {{ $t("nav.who_to_follow") }}
+            <i class="button-icon icon-user-plus" /> {{ $t("nav.who_to_follow") }}
           </router-link>
         </li>
         <li @click="toggleDrawer">
           <router-link :to="{ name: 'settings' }">
-            {{ $t("settings.settings") }}
+            <i class="button-icon icon-cog" /> {{ $t("settings.settings") }}
           </router-link>
         </li>
         <li @click="toggleDrawer">
           <router-link :to="{ name: 'about'}">
-            {{ $t("nav.about") }}
+            <i class="button-icon icon-info-circled" /> {{ $t("nav.about") }}
           </router-link>
         </li>
         <li
@@ -130,7 +130,7 @@
             href="/pleroma/admin/#/login-pleroma"
             target="_blank"
           >
-            {{ $t("nav.administration") }}
+            <i class="button-icon icon-gauge" /> {{ $t("nav.administration") }}
           </a>
         </li>
         <li
@@ -141,7 +141,7 @@
             href="#"
             @click="doLogout"
           >
-            {{ $t("login.logout") }}
+            <i class="button-icon icon-logout" /> {{ $t("login.logout") }}
           </a>
         </li>
       </ul>
diff --git a/static/fontello.json b/static/fontello.json
index c0cf1727..c1ed3393 100755
--- a/static/fontello.json
+++ b/static/fontello.json
@@ -303,6 +303,36 @@
       "css": "gauge",
       "code": 61668,
       "src": "fontawesome"
+    },
+    {
+      "uid": "31972e4e9d080eaa796290349ae6c1fd",
+      "css": "users",
+      "code": 59421,
+      "src": "fontawesome"
+    },
+    {
+      "uid": "e82cedfa1d5f15b00c5a81c9bd731ea2",
+      "css": "info-circled",
+      "code": 59423,
+      "src": "fontawesome"
+    },
+    {
+      "uid": "w3nzesrlbezu6f30q7ytyq919p6gdlb6",
+      "css": "home-2",
+      "code": 59425,
+      "src": "typicons"
+    },
+    {
+      "uid": "dcedf50ab1ede3283d7a6c70e2fe32f3",
+      "css": "chat",
+      "code": 59422,
+      "src": "fontawesome"
+    },
+    {
+      "uid": "3a00327e61b997b58518bd43ed83c3df",
+      "css": "login",
+      "code": 59424,
+      "src": "fontawesome"
     }
   ]
 }
\ No newline at end of file

From a412b53801bb9e9398c4c32aad7c430bf922c723 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Mon, 2 Dec 2019 11:45:55 -0500
Subject: [PATCH 43/62] increase icon width a little bit in the nav panel

---
 src/components/nav_panel/nav_panel.vue     | 4 ++++
 src/components/side_drawer/side_drawer.vue | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue
index d660f189..4b79b500 100644
--- a/src/components/nav_panel/nav_panel.vue
+++ b/src/components/nav_panel/nav_panel.vue
@@ -113,4 +113,8 @@
     }
   }
 }
+
+.nav-panel .button-icon:before {
+  width: 1.1em;
+}
 </style>
diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue
index 1c65c173..31724fa2 100644
--- a/src/components/side_drawer/side_drawer.vue
+++ b/src/components/side_drawer/side_drawer.vue
@@ -215,6 +215,10 @@
   box-shadow: var(--panelShadow);
   background-color: $fallback--bg;
   background-color: var(--bg, $fallback--bg);
+
+  .button-icon:before {
+    width: 1.1em;
+  }
 }
 
 .side-drawer-logo-wrapper {

From 585702b1cedf25547ff5faf0170263088e5484a6 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 12 Dec 2019 18:53:36 +0200
Subject: [PATCH 44/62] fix desktop notifications not working with streaming

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

diff --git a/src/modules/users.js b/src/modules/users.js
index cbec6063..5dc2f36f 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -481,6 +481,8 @@ const users = {
                 store.dispatch('enableMastoSockets').catch((error) => {
                   console.error('Failed initializing MastoAPI Streaming socket', error)
                   startPolling()
+                }).then(() => {
+                  setTimeout(() => store.dispatch('setNotificationsSilence', false), 10000)
                 })
               } else {
                 startPolling()

From addacf36d1ee080158b7acba44b70d31e1edb3da Mon Sep 17 00:00:00 2001
From: Maksim Pechnikov <parallel588@gmail.com>
Date: Thu, 12 Dec 2019 21:19:13 +0300
Subject: [PATCH 45/62] mfa: removed unused code

---
 src/components/login_form/login_form.js | 2 +-
 src/components/mfa_form/totp_form.js    | 1 -
 src/modules/auth_flow.js                | 8 +-------
 3 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/src/components/login_form/login_form.js b/src/components/login_form/login_form.js
index 0b574a04..0d8f1da6 100644
--- a/src/components/login_form/login_form.js
+++ b/src/components/login_form/login_form.js
@@ -58,7 +58,7 @@ const LoginForm = {
         ).then((result) => {
           if (result.error) {
             if (result.error === 'mfa_required') {
-              this.requireMFA({ app: app, settings: result })
+              this.requireMFA({ settings: result })
             } else if (result.identifier === 'password_reset_required') {
               this.$router.push({ name: 'password-reset', params: { passwordResetRequested: true } })
             } else {
diff --git a/src/components/mfa_form/totp_form.js b/src/components/mfa_form/totp_form.js
index 1ec7576b..b774f2d0 100644
--- a/src/components/mfa_form/totp_form.js
+++ b/src/components/mfa_form/totp_form.js
@@ -7,7 +7,6 @@ export default {
   }),
   computed: {
     ...mapGetters({
-      authApp: 'authFlow/app',
       authSettings: 'authFlow/settings'
     }),
     ...mapState({
diff --git a/src/modules/auth_flow.js b/src/modules/auth_flow.js
index d0a90feb..956d40e8 100644
--- a/src/modules/auth_flow.js
+++ b/src/modules/auth_flow.js
@@ -7,7 +7,6 @@ const RECOVERY_STRATEGY = 'recovery'
 
 // initial state
 const state = {
-  app: null,
   settings: {},
   strategy: PASSWORD_STRATEGY,
   initStrategy: PASSWORD_STRATEGY // default strategy from config
@@ -16,14 +15,10 @@ const state = {
 const resetState = (state) => {
   state.strategy = state.initStrategy
   state.settings = {}
-  state.app = null
 }
 
 // getters
 const getters = {
-  app: (state, getters) => {
-    return state.app
-  },
   settings: (state, getters) => {
     return state.settings
   },
@@ -55,9 +50,8 @@ const mutations = {
   requireToken (state) {
     state.strategy = TOKEN_STRATEGY
   },
-  requireMFA (state, { app, settings }) {
+  requireMFA (state, { settings }) {
     state.settings = settings
-    state.app = app
     state.strategy = TOTP_STRATEGY // default strategy of MFA
   },
   requireRecovery (state) {

From 3eeb3dc57296cba13e3760a79b635fba5a332be0 Mon Sep 17 00:00:00 2001
From: Mark Felder <feld@FreeBSD.org>
Date: Thu, 12 Dec 2019 13:37:32 -0600
Subject: [PATCH 46/62] Lint

---
 src/App.vue                           | 2 +-
 src/components/nav_panel/nav_panel.js | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/App.vue b/src/App.vue
index d455e9ed..5f8517d4 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -43,8 +43,8 @@
           <search-bar
             class="nav-icon mobile-hidden"
             @toggled="onSearchBarToggled"
-            @click.stop.native
             v-if="currentUser || !privateMode"
+            @click.stop.native
           />
           <router-link
             class="mobile-hidden"
diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index dbbfb096..f27727fc 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -1,4 +1,3 @@
-import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
 import { mapState } from 'vuex'
 
 const NavPanel = {

From 211d25cd5a4df92f9de249e053e00a7c788aacba Mon Sep 17 00:00:00 2001
From: Mark Felder <feld@FreeBSD.org>
Date: Thu, 12 Dec 2019 13:39:18 -0600
Subject: [PATCH 47/62] More lint

---
 src/components/side_drawer/side_drawer.vue | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue
index 1454e0d8..064472b9 100644
--- a/src/components/side_drawer/side_drawer.vue
+++ b/src/components/side_drawer/side_drawer.vue
@@ -79,12 +79,14 @@
             </span>
           </router-link>
         </li>
-        <li @click="toggleDrawer" v-if="currentUser || !privateMode">
+        <li @click="toggleDrawer"
+          v-if="currentUser || !privateMode">
           <router-link to="/main/public">
             <i class="button-icon icon-users" /> {{ $t("nav.public_tl") }}
           </router-link>
         </li>
-        <li @click="toggleDrawer" v-if="(currentUser || !privateMode) && federating">
+        <li @click="toggleDrawer"
+          v-if="(currentUser || !privateMode) && federating">
           <router-link to="/main/all">
             <i class="button-icon icon-globe" /> {{ $t("nav.twkn") }}
           </router-link>
@@ -99,7 +101,8 @@
         </li>
       </ul>
       <ul>
-        <li @click="toggleDrawer" v-if="currentUser || !privateMode">
+        <li @click="toggleDrawer"
+          v-if="currentUser || !privateMode">
           <router-link :to="{ name: 'search' }">
             <i class="button-icon icon-search" /> {{ $t("nav.search") }}
           </router-link>

From afe5b3a82d5b6e9b02fa6db9354060aa72edb712 Mon Sep 17 00:00:00 2001
From: Mark Felder <feld@FreeBSD.org>
Date: Thu, 12 Dec 2019 13:41:52 -0600
Subject: [PATCH 48/62] More lint

---
 src/components/side_drawer/side_drawer.vue | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue
index 064472b9..bf61d38c 100644
--- a/src/components/side_drawer/side_drawer.vue
+++ b/src/components/side_drawer/side_drawer.vue
@@ -79,14 +79,14 @@
             </span>
           </router-link>
         </li>
-        <li @click="toggleDrawer"
-          v-if="currentUser || !privateMode">
+        <li v-if="currentUser || !privateMode"
+          @click="toggleDrawer">
           <router-link to="/main/public">
             <i class="button-icon icon-users" /> {{ $t("nav.public_tl") }}
           </router-link>
         </li>
-        <li @click="toggleDrawer"
-          v-if="(currentUser || !privateMode) && federating">
+        <li v-if="(currentUser || !privateMode) && federating"
+          @click="toggleDrawer">
           <router-link to="/main/all">
             <i class="button-icon icon-globe" /> {{ $t("nav.twkn") }}
           </router-link>
@@ -101,8 +101,8 @@
         </li>
       </ul>
       <ul>
-        <li @click="toggleDrawer"
-          v-if="currentUser || !privateMode">
+        <li v-if="currentUser || !privateMode"
+          @click="toggleDrawer">
           <router-link :to="{ name: 'search' }">
             <i class="button-icon icon-search" /> {{ $t("nav.search") }}
           </router-link>

From 7ddd5af0812a73d6a898331e38603067e0cd219b Mon Sep 17 00:00:00 2001
From: Mark Felder <feld@FreeBSD.org>
Date: Thu, 12 Dec 2019 13:46:07 -0600
Subject: [PATCH 49/62] Finally trust eslint

---
 src/App.vue                                |  2 +-
 src/components/side_drawer/side_drawer.vue | 18 ++++++++++++------
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/src/App.vue b/src/App.vue
index 5f8517d4..1b1c2648 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -41,9 +41,9 @@
         </div>
         <div class="item right">
           <search-bar
+            v-if="currentUser || !privateMode"
             class="nav-icon mobile-hidden"
             @toggled="onSearchBarToggled"
-            v-if="currentUser || !privateMode"
             @click.stop.native
           />
           <router-link
diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue
index bf61d38c..49c25bba 100644
--- a/src/components/side_drawer/side_drawer.vue
+++ b/src/components/side_drawer/side_drawer.vue
@@ -79,14 +79,18 @@
             </span>
           </router-link>
         </li>
-        <li v-if="currentUser || !privateMode"
-          @click="toggleDrawer">
+        <li
+          v-if="currentUser || !privateMode"
+          @click="toggleDrawer"
+        >
           <router-link to="/main/public">
             <i class="button-icon icon-users" /> {{ $t("nav.public_tl") }}
           </router-link>
         </li>
-        <li v-if="(currentUser || !privateMode) && federating"
-          @click="toggleDrawer">
+        <li
+          v-if="(currentUser || !privateMode) && federating"
+          @click="toggleDrawer"
+        >
           <router-link to="/main/all">
             <i class="button-icon icon-globe" /> {{ $t("nav.twkn") }}
           </router-link>
@@ -101,8 +105,10 @@
         </li>
       </ul>
       <ul>
-        <li v-if="currentUser || !privateMode"
-          @click="toggleDrawer">
+        <li
+          v-if="currentUser || !privateMode"
+          @click="toggleDrawer"
+        >
           <router-link :to="{ name: 'search' }">
             <i class="button-icon icon-search" /> {{ $t("nav.search") }}
           </router-link>

From 2514dc183f604686d1648c0a69f6eba00d943ce7 Mon Sep 17 00:00:00 2001
From: Mark Felder <feld@FreeBSD.org>
Date: Thu, 12 Dec 2019 13:51:50 -0600
Subject: [PATCH 50/62] Logic should be to hide TWKN if not federating OR if
 instance is not public

Private instances should not show any timelines
---
 src/components/nav_panel/nav_panel.vue     | 2 +-
 src/components/side_drawer/side_drawer.vue | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue
index 97c36711..034259d9 100644
--- a/src/components/nav_panel/nav_panel.vue
+++ b/src/components/nav_panel/nav_panel.vue
@@ -33,7 +33,7 @@
             <i class="button-icon icon-users" /> {{ $t("nav.public_tl") }}
           </router-link>
         </li>
-        <li v-if="(currentUser || !privateMode) && federating">
+        <li v-if="federating && !privateMode">
           <router-link :to="{ name: 'public-external-timeline' }">
             <i class="button-icon icon-globe" /> {{ $t("nav.twkn") }}
           </router-link>
diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue
index 49c25bba..3fba9058 100644
--- a/src/components/side_drawer/side_drawer.vue
+++ b/src/components/side_drawer/side_drawer.vue
@@ -88,7 +88,7 @@
           </router-link>
         </li>
         <li
-          v-if="(currentUser || !privateMode) && federating"
+          v-if="federating && !privateMode"
           @click="toggleDrawer"
         >
           <router-link to="/main/all">

From 0743fbb28b94dd4308f8e2ca01d9def91b6ffddf Mon Sep 17 00:00:00 2001
From: Mark Felder <feld@FreeBSD.org>
Date: Thu, 12 Dec 2019 13:56:07 -0600
Subject: [PATCH 51/62] The value we are looking for is
 federationPolicy.enabled, not federationPolicy.federating

Also the || true fallback does not work and always becomes true
---
 src/components/nav_panel/nav_panel.js     | 2 +-
 src/components/side_drawer/side_drawer.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index f27727fc..7da9f8c6 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -11,7 +11,7 @@ const NavPanel = {
     chat: state => state.chat.channel,
     followRequestCount: state => state.api.followRequests.length,
     privateMode: state => state.instance.private,
-    federating: state => state.instance.federationPolicy.federating || true
+    federating: state => state.instance.federationPolicy.enabled
   })
 }
 
diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js
index 22cb1a55..e08f7cbe 100644
--- a/src/components/side_drawer/side_drawer.js
+++ b/src/components/side_drawer/side_drawer.js
@@ -46,7 +46,7 @@ const SideDrawer = {
       return this.$store.state.instance.private
     },
     federating () {
-      return this.$store.state.instance.federationPolicy.federating || true
+      return this.$store.state.instance.federationPolicy.enabled
     }
   },
   methods: {

From 8d14036a23adbd13b098abeeef9622471f4a64d3 Mon Sep 17 00:00:00 2001
From: Mark Felder <feld@FreeBSD.org>
Date: Thu, 12 Dec 2019 15:17:23 -0600
Subject: [PATCH 52/62] Add fallback in case BE does not report federating
 status in nodeinfo

---
 src/components/nav_panel/nav_panel.js     | 2 +-
 src/components/side_drawer/side_drawer.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index 7da9f8c6..515e47e6 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -11,7 +11,7 @@ const NavPanel = {
     chat: state => state.chat.channel,
     followRequestCount: state => state.api.followRequests.length,
     privateMode: state => state.instance.private,
-    federating: state => state.instance.federationPolicy.enabled
+    federating: state => state.instance.federationPolicy.enabled || state.instance.federationPolicy.enabled !== false
   })
 }
 
diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js
index e08f7cbe..670d28b4 100644
--- a/src/components/side_drawer/side_drawer.js
+++ b/src/components/side_drawer/side_drawer.js
@@ -46,7 +46,7 @@ const SideDrawer = {
       return this.$store.state.instance.private
     },
     federating () {
-      return this.$store.state.instance.federationPolicy.enabled
+      return this.$store.state.instance.federationPolicy.enabled || this.$store.state.instance.federationPolicy.enabled !== false
     }
   },
   methods: {

From d899d06973c7c46e77f9e47f480d6967e83b4adf Mon Sep 17 00:00:00 2001
From: Mark Felder <feld@FreeBSD.org>
Date: Thu, 12 Dec 2019 15:29:50 -0600
Subject: [PATCH 53/62] Use a centralized fallback for missing values and use
 instance.federating instead of instance.federation.enabled

---
 src/boot/after_store.js                   | 6 ++++++
 src/components/nav_panel/nav_panel.js     | 2 +-
 src/components/side_drawer/side_drawer.js | 2 +-
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index f169d7ba..228a0497 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -228,6 +228,12 @@ const getNodeInfo = async ({ store }) => {
 
       const federation = metadata.federation
       store.dispatch('setInstanceOption', { name: 'federationPolicy', value: federation })
+      store.dispatch('setInstanceOption', {
+        name: 'federating',
+        value: typeof federation.enabled === 'undefined'
+          ? true
+          : federation.enabled
+      })
 
       const accounts = metadata.staffAccounts
       await resolveStaffAccounts({ store, accounts })
diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index 515e47e6..d9268585 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -11,7 +11,7 @@ const NavPanel = {
     chat: state => state.chat.channel,
     followRequestCount: state => state.api.followRequests.length,
     privateMode: state => state.instance.private,
-    federating: state => state.instance.federationPolicy.enabled || state.instance.federationPolicy.enabled !== false
+    federating: state => state.instance.federating
   })
 }
 
diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js
index 670d28b4..2534eb8f 100644
--- a/src/components/side_drawer/side_drawer.js
+++ b/src/components/side_drawer/side_drawer.js
@@ -46,7 +46,7 @@ const SideDrawer = {
       return this.$store.state.instance.private
     },
     federating () {
-      return this.$store.state.instance.federationPolicy.enabled || this.$store.state.instance.federationPolicy.enabled !== false
+      return this.$store.state.instance.federating
     }
   },
   methods: {

From 1cba6c56f07a0ed3e87ac4b8d3311ecbbbe5b634 Mon Sep 17 00:00:00 2001
From: Hakaba Hitoyo <hakabahitoyo@yahoo.co.jp>
Date: Fri, 13 Dec 2019 17:05:13 +0000
Subject: [PATCH 54/62] i18n/update-ja_easy

---
 src/i18n/ja_easy.json | 43 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/src/i18n/ja_easy.json b/src/i18n/ja_easy.json
index 592a7257..be447f1c 100644
--- a/src/i18n/ja_easy.json
+++ b/src/i18n/ja_easy.json
@@ -1,4 +1,23 @@
 {
+  "about": {
+    "staff": "スタッフ",
+    "federation": "フェデレーション",
+    "mrf_policies": "ゆうこうなMRFポリシー",
+    "mrf_policies_desc": "MRFポリシーは、このインスタンスのフェデレーションのふるまいを、いじります。これらのMRFポリシーがゆうこうになっています:",
+    "mrf_policy_simple": "インスタンスのポリシー",
+    "mrf_policy_simple_accept": "うけいれ",
+    "mrf_policy_simple_accept_desc": "このインスンスは、これらのインスタンスからのメッセージのみをうけいれます:",
+    "mrf_policy_simple_reject": "おことわり",
+    "mrf_policy_simple_reject_desc": "このインスタンスは、これらのインスタンスからのメッセージをうけいれません:",
+    "mrf_policy_simple_quarantine": "けんえき",
+    "mrf_policy_simple_quarantine_desc": "このインスタンスは、これらのインスタンスに、パブリックなとうこうのみを、おくります:",
+    "mrf_policy_simple_ftl_removal": "「つながっているすべてのネットワーク」タイムラインからのぞく",
+    "mrf_policy_simple_ftl_removal_desc": "このインスタンスは、つながっているすべてのネットワーク」タイムラインから、これらのインスタンスを、とりのぞきます:",
+    "mrf_policy_simple_media_removal": "メディアをのぞく",
+    "mrf_policy_simple_media_removal_desc": "このインスタンスは、これらのインスタンスからおくられてきたメディアを、とりのぞきます:",
+    "mrf_policy_simple_media_nsfw": "メディアをすべてセンシティブにする",
+    "mrf_policy_simple_media_nsfw_desc": "このインスタンスは、これらのインスタンスからおくられてきたメディアを、すべて、センシティブにマークします:"
+  },
   "chat": {
     "title": "チャット"
   },
@@ -68,6 +87,7 @@
   },
   "nav": {
     "about": "これはなに?",
+    "administration": "アドミニストレーション",
     "back": "もどる",
     "chat": "ローカルチャット",
     "friend_requests": "フォローリクエスト",
@@ -113,7 +133,9 @@
     "search_emoji": "えもじをさがす",
     "add_emoji": "えもじをうちこむ",
     "custom": "カスタムえもじ",
-    "unicode": "ユニコードえもじ"
+    "unicode": "ユニコードえもじ",
+    "load_all_hint": "はじめの {saneAmount} このえもじだけがロードされています。すべてのえもじをロードすると、パフォーマンスがわるくなるかもしれません。",
+    "load_all": "すべてのえもじをロード ({emojiAmount} こあります)"
   },
   "stickers": {
     "add_sticker": "ステッカーをふやす"
@@ -173,6 +195,11 @@
       "password_confirmation_match": "パスワードがちがいます"
     }
   },
+  "remote_user_resolver": {
+    "remote_user_resolver": "リモートユーザーリゾルバー",
+    "searching_for": "さがしています:",
+    "error": "みつかりませんでした。"
+  },
   "selectable_list": {
     "select_all": "すべてえらぶ"
   },
@@ -220,6 +247,9 @@
     "cGreen": "リピート",
     "cOrange": "おきにいり",
     "cRed": "キャンセル",
+    "change_email": "メールアドレスをかえる",
+    "change_email_error": "メールアドレスをかえようとしましたが、なにかがおかしいです。",
+    "changed_email": "メールアドレスをかえることができました!",
     "change_password": "パスワードをかえる",
     "change_password_error": "パスワードをかえることが、できなかったかもしれません。",
     "changed_password": "パスワードが、かわりました!",
@@ -279,6 +309,7 @@
     "use_contain_fit": "がぞうのサムネイルを、きりぬかない",
     "name": "なまえ",
     "name_bio": "なまえとプロフィール",
+    "new_email": "あたらしいメールアドレス",
     "new_password": "あたらしいパスワード",
     "notification_visibility": "ひょうじするつうち",
     "notification_visibility_follows": "フォロー",
@@ -344,6 +375,8 @@
       "false": "いいえ",
       "true": "はい"
     },
+    "fun": "おたのしみ",
+    "greentext": "ミームやじるし",
     "notifications": "つうち",
     "notification_setting": "つうちをうけとる:",
     "notification_setting_follows": "あなたがフォローしているひとから",
@@ -391,6 +424,7 @@
         "_tab_label": "くわしく",
         "alert": "アラートのバックグラウンド",
         "alert_error": "エラー",
+        "alert_warning": "けいこく",
         "badge": "バッジのバックグラウンド",
         "badge_notification": "つうち",
         "panel_header": "パネルヘッダー",
@@ -542,6 +576,7 @@
     "followers": "フォロワー",
     "following": "フォローしています!",
     "follows_you": "フォローされました!",
+    "hidden": "かくされています",
     "its_you": "これはあなたです!",
     "media": "メディア",
     "mention": "メンション",
@@ -559,6 +594,8 @@
     "unmute": "ミュートをやめる",
     "unmute_progress": "ミュートをとりけしています...",
     "mute_progress": "ミュートしています...",
+    "hide_repeats": "リピートをかくす",
+    "show_repeats": "リピートをみる",
     "admin_menu": {
       "moderation": "モデレーション",
       "grant_admin": "アドミンにする",
@@ -634,6 +671,8 @@
     "return_home": "ホームページにもどる",
     "not_found": "そのメールアドレスまたはユーザーめいを、みつけることができませんでした。",
     "too_many_requests": "パスワードリセットを、ためすことが、おおすぎます。しばらくしてから、ためしてください。",
-    "password_reset_disabled": "このインスタンスでは、パスワードリセットは、できません。インスタンスのアドミニストレーターに、おといあわせください。"
+    "password_reset_disabled": "このインスタンスでは、パスワードリセットは、できません。インスタンスのアドミニストレーターに、おといあわせください。",
+    "password_reset_required": "ログインするには、パスワードをリセットしてください。",
+    "password_reset_required_but_mailer_is_disabled": "あなたはパスワードのリセットがひつようです。しかし、まずいことに、このインスタンスでは、パスワードのリセットができなくなっています。このインスタンスのアドミニストレーターに、おといあわせください。"
   }
 }

From 32d7a49b9d02bfa6c6e997f4d6e923752b062a90 Mon Sep 17 00:00:00 2001
From: Absturztaube <me@absturztaube.ch>
Date: Sun, 15 Dec 2019 17:58:37 +0100
Subject: [PATCH 55/62] use flex for stickers

---
 src/components/sticker_picker/sticker_picker.vue | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/components/sticker_picker/sticker_picker.vue b/src/components/sticker_picker/sticker_picker.vue
index 7d6fdc24..3863908a 100644
--- a/src/components/sticker_picker/sticker_picker.vue
+++ b/src/components/sticker_picker/sticker_picker.vue
@@ -36,16 +36,20 @@
 
 .sticker-picker {
   width: 100%;
-  position: relative;
   .contents {
     min-height: 250px;
     .sticker-picker-content {
+      display: flex;
+      flex-wrap: wrap;
+      padding: 0 4px;
       .sticker {
-        display: inline-block;
-        width: 20%;
-        height: 20%;
+        display: flex;
+        flex: 1 1 auto;
+        margin: 4px;
+        width: 56px;
+        height: 56px;
         img {
-          width: 100%;
+          height: 100%;
           &:hover {
             filter: drop-shadow(0 0 5px var(--link, $fallback--link));
           }

From 506822bed01deb2d2fb98f511902d6801819cbd8 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Mon, 18 Nov 2019 20:29:12 -0500
Subject: [PATCH 56/62] replace setActivationStatus api with new one

---
 .../moderation_tools/moderation_tools.js      |  2 +-
 src/services/api/api.service.js               | 19 +++++++------------
 .../backend_interactor_service.js             |  6 +++---
 3 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/src/components/moderation_tools/moderation_tools.js b/src/components/moderation_tools/moderation_tools.js
index 8aadc8c5..10a20709 100644
--- a/src/components/moderation_tools/moderation_tools.js
+++ b/src/components/moderation_tools/moderation_tools.js
@@ -73,7 +73,7 @@ const ModerationTools = {
     toggleActivationStatus () {
       const store = this.$store
       const status = !!this.user.deactivated
-      store.state.api.backendInteractor.setActivationStatus(this.user, status).then(response => {
+      store.state.api.backendInteractor.toggleActivationStatus(this.user).then(response => {
         if (!response.ok) { return }
         store.commit('updateActivationStatus', { user: this.user, status: status })
       })
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 7eb0547e..dbc8320e 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -12,7 +12,7 @@ const CHANGE_EMAIL_URL = '/api/pleroma/change_email'
 const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
 const TAG_USER_URL = '/api/pleroma/admin/users/tag'
 const PERMISSION_GROUP_URL = (screenName, right) => `/api/pleroma/admin/users/${screenName}/permission_group/${right}`
-const ACTIVATION_STATUS_URL = screenName => `/api/pleroma/admin/users/${screenName}/activation_status`
+const TOGGLE_ACTIVATION_URL = screenName => `/api/pleroma/admin/users/${screenName}/toggle_activation`
 const ADMIN_USERS_URL = '/api/pleroma/admin/users'
 const SUGGESTIONS_URL = '/api/v1/suggestions'
 const NOTIFICATION_SETTINGS_URL = '/api/pleroma/notification_settings'
@@ -450,19 +450,14 @@ const deleteRight = ({ right, credentials, ...user }) => {
   })
 }
 
-const setActivationStatus = ({ status, credentials, ...user }) => {
-  const screenName = user.screen_name
-  const body = {
-    status: status
-  }
-
+// eslint-disable-next-line camelcase
+const toggleActivationStatus = ({ credentials, screen_name }) => {
   const headers = authHeaders(credentials)
   headers['Content-Type'] = 'application/json'
 
-  return fetch(ACTIVATION_STATUS_URL(screenName), {
-    method: 'PUT',
-    headers: headers,
-    body: JSON.stringify(body)
+  return fetch(TOGGLE_ACTIVATION_URL(screen_name), {
+    method: 'PATCH',
+    headers: headers
   })
 }
 
@@ -979,7 +974,7 @@ const apiService = {
   deleteUser,
   addRight,
   deleteRight,
-  setActivationStatus,
+  toggleActivationStatus,
   register,
   getCaptcha,
   updateAvatar,
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index c16bd1f1..e0a15d3b 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -89,8 +89,8 @@ const backendInteractorService = credentials => {
   }
 
   // eslint-disable-next-line camelcase
-  const setActivationStatus = ({ screen_name }, status) => {
-    return apiService.setActivationStatus({ screen_name, status, credentials })
+  const toggleActivationStatus = ({ screen_name }) => {
+    return apiService.toggleActivationStatus({ screen_name, credentials })
   }
 
   // eslint-disable-next-line camelcase
@@ -191,7 +191,7 @@ const backendInteractorService = credentials => {
     addRight,
     deleteRight,
     deleteUser,
-    setActivationStatus,
+    toggleActivationStatus,
     register,
     getCaptcha,
     updateAvatar,

From 45e7f93c49042c365badf0043ebd0480ecbb9c49 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Mon, 18 Nov 2019 20:33:07 -0500
Subject: [PATCH 57/62] refactor toggleActivationStatus

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

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index dbc8320e..b739ec1f 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -452,13 +452,7 @@ const deleteRight = ({ right, credentials, ...user }) => {
 
 // eslint-disable-next-line camelcase
 const toggleActivationStatus = ({ credentials, screen_name }) => {
-  const headers = authHeaders(credentials)
-  headers['Content-Type'] = 'application/json'
-
-  return fetch(TOGGLE_ACTIVATION_URL(screen_name), {
-    method: 'PATCH',
-    headers: headers
-  })
+  return promisedRequest({ url: TOGGLE_ACTIVATION_URL(screen_name), method: 'PATCH', credentials })
 }
 
 const deleteUser = ({ credentials, ...user }) => {

From 36376ce57c93c81317b6a8b0b50699d6b8488f57 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Mon, 18 Nov 2019 20:42:10 -0500
Subject: [PATCH 58/62] use vuex action

---
 src/components/moderation_tools/moderation_tools.js |  7 +------
 src/modules/users.js                                | 10 ++++++++--
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/components/moderation_tools/moderation_tools.js b/src/components/moderation_tools/moderation_tools.js
index 10a20709..02b92fef 100644
--- a/src/components/moderation_tools/moderation_tools.js
+++ b/src/components/moderation_tools/moderation_tools.js
@@ -71,12 +71,7 @@ const ModerationTools = {
       }
     },
     toggleActivationStatus () {
-      const store = this.$store
-      const status = !!this.user.deactivated
-      store.state.api.backendInteractor.toggleActivationStatus(this.user).then(response => {
-        if (!response.ok) { return }
-        store.commit('updateActivationStatus', { user: this.user, status: status })
-      })
+      this.$store.dispatch('toggleActivationStatus', this.user)
     },
     deleteUserDialog (show) {
       this.showDeleteUserDialog = show
diff --git a/src/modules/users.js b/src/modules/users.js
index 14b2d8b5..ec2ef608 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -95,9 +95,9 @@ export const mutations = {
     newRights[right] = value
     set(user, 'rights', newRights)
   },
-  updateActivationStatus (state, { user: { id }, status }) {
+  updateActivationStatus (state, { user: { id }, deactivated }) {
     const user = state.usersObject[id]
-    set(user, 'deactivated', !status)
+    set(user, 'deactivated', deactivated)
   },
   setCurrentUser (state, user) {
     state.lastLoginName = user.screen_name
@@ -331,6 +331,12 @@ const users = {
       return rootState.api.backendInteractor.unsubscribeUser(id)
         .then((relationship) => commit('updateUserRelationship', [relationship]))
     },
+    toggleActivationStatus ({ rootState, commit }, user) {
+      rootState.api.backendInteractor.toggleActivationStatus(user)
+        .then(response => {
+          commit('updateActivationStatus', { user, deactivated: response.deactivated })
+        })
+    },
     registerPushNotifications (store) {
       const token = store.state.currentUser.credentials
       const vapidPublicKey = store.rootState.instance.vapidPublicKey

From 4e4c4af422c400d016e4605f8bcf699f7154a8b4 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 19 Nov 2019 14:41:39 -0500
Subject: [PATCH 59/62] toggle_activation api is also deprecated

---
 src/modules/users.js                          |  7 ++---
 src/services/api/api.service.js               | 31 +++++++++++++++----
 .../backend_interactor_service.js             | 12 +++++--
 3 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/src/modules/users.js b/src/modules/users.js
index ec2ef608..82d3c4e8 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -332,10 +332,9 @@ const users = {
         .then((relationship) => commit('updateUserRelationship', [relationship]))
     },
     toggleActivationStatus ({ rootState, commit }, user) {
-      rootState.api.backendInteractor.toggleActivationStatus(user)
-        .then(response => {
-          commit('updateActivationStatus', { user, deactivated: response.deactivated })
-        })
+      const api = user.deactivated ? rootState.api.backendInteractor.activateUser : rootState.api.backendInteractor.deactivateUser
+      api(user)
+        .then(({ deactivated }) => commit('updateActivationStatus', { user, deactivated }))
     },
     registerPushNotifications (store) {
       const token = store.state.currentUser.credentials
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index b739ec1f..a69fa53c 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1,4 +1,4 @@
-import { each, map, concat, last } from 'lodash'
+import { each, map, concat, last, get } from 'lodash'
 import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
 import 'whatwg-fetch'
 import { RegistrationError, StatusCodeError } from '../errors/errors'
@@ -12,7 +12,8 @@ const CHANGE_EMAIL_URL = '/api/pleroma/change_email'
 const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
 const TAG_USER_URL = '/api/pleroma/admin/users/tag'
 const PERMISSION_GROUP_URL = (screenName, right) => `/api/pleroma/admin/users/${screenName}/permission_group/${right}`
-const TOGGLE_ACTIVATION_URL = screenName => `/api/pleroma/admin/users/${screenName}/toggle_activation`
+const ACTIVATE_USER_URL = '/api/pleroma/admin/users/activate'
+const DEACTIVATE_USER_URL = '/api/pleroma/admin/users/deactivate'
 const ADMIN_USERS_URL = '/api/pleroma/admin/users'
 const SUGGESTIONS_URL = '/api/v1/suggestions'
 const NOTIFICATION_SETTINGS_URL = '/api/pleroma/notification_settings'
@@ -450,9 +451,26 @@ const deleteRight = ({ right, credentials, ...user }) => {
   })
 }
 
-// eslint-disable-next-line camelcase
-const toggleActivationStatus = ({ credentials, screen_name }) => {
-  return promisedRequest({ url: TOGGLE_ACTIVATION_URL(screen_name), method: 'PATCH', credentials })
+const activateUser = ({ credentials, screen_name: nickname }) => {
+  return promisedRequest({
+    url: ACTIVATE_USER_URL,
+    method: 'PATCH',
+    credentials,
+    payload: {
+      nicknames: [nickname]
+    }
+  }).then(response => get(response, 'users.0'))
+}
+
+const deactivateUser = ({ credentials, screen_name: nickname }) => {
+  return promisedRequest({
+    url: DEACTIVATE_USER_URL,
+    method: 'PATCH',
+    credentials,
+    payload: {
+      nicknames: [nickname]
+    }
+  }).then(response => get(response, 'users.0'))
 }
 
 const deleteUser = ({ credentials, ...user }) => {
@@ -968,7 +986,8 @@ const apiService = {
   deleteUser,
   addRight,
   deleteRight,
-  toggleActivationStatus,
+  activateUser,
+  deactivateUser,
   register,
   getCaptcha,
   updateAvatar,
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index e0a15d3b..3d4ec6ac 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -89,8 +89,13 @@ const backendInteractorService = credentials => {
   }
 
   // eslint-disable-next-line camelcase
-  const toggleActivationStatus = ({ screen_name }) => {
-    return apiService.toggleActivationStatus({ screen_name, credentials })
+  const activateUser = ({ screen_name }) => {
+    return apiService.activateUser({ screen_name, credentials })
+  }
+
+  // eslint-disable-next-line camelcase
+  const deactivateUser = ({ screen_name }) => {
+    return apiService.deactivateUser({ screen_name, credentials })
   }
 
   // eslint-disable-next-line camelcase
@@ -191,7 +196,8 @@ const backendInteractorService = credentials => {
     addRight,
     deleteRight,
     deleteUser,
-    toggleActivationStatus,
+    activateUser,
+    deactivateUser,
     register,
     getCaptcha,
     updateAvatar,

From 43197c424366099301e59d3d1c7be58b987cb833 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 26 Dec 2019 14:12:35 +0200
Subject: [PATCH 60/62] Some error handling

---
 src/components/settings/settings.js |  4 ++
 src/modules/api.js                  | 87 ++++++++++++++++-------------
 2 files changed, 51 insertions(+), 40 deletions(-)

diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index 2d7723cc..31a9e9be 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -103,6 +103,10 @@ const settings = {
 
         promise.then(() => {
           this.$store.dispatch('setOption', { name: 'useStreamingApi', value })
+        }).catch((e) => {
+          console.error('Failed starting MastoAPI Streaming socket', e)
+          this.$store.dispatch('disableMastoSockets')
+          this.$store.dispatch('setOption', { name: 'useStreamingApi', value: false })
         })
       }
     }
diff --git a/src/modules/api.js b/src/modules/api.js
index dc91d00e..b6dd7fcf 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -35,60 +35,67 @@ const api = {
     enableMastoSockets (store) {
       const { state, dispatch } = store
       if (state.mastoUserSocket) return
-      dispatch('startMastoUserSocket')
+      return dispatch('startMastoUserSocket')
     },
     disableMastoSockets (store) {
       const { state, dispatch } = store
       if (!state.mastoUserSocket) return
-      dispatch('stopMastoUserSocket')
+      return dispatch('stopMastoUserSocket')
     },
 
     // MastoAPI 'User' sockets
     startMastoUserSocket (store) {
-      const { state, dispatch } = store
-      state.mastoUserSocket = state.backendInteractor.startUserSocket({ store })
-      state.mastoUserSocket.addEventListener(
-        'message',
-        ({ detail: message }) => {
-          if (!message) return // pings
-          if (message.event === 'notification') {
-            dispatch('addNewNotifications', {
-              notifications: [message.notification],
-              older: false
-            })
-          } else if (message.event === 'update') {
-            dispatch('addNewStatuses', {
-              statuses: [message.status],
-              userId: false,
-              showImmediately: false,
-              timeline: 'friends'
-            })
-          }
-        }
-      )
-      state.mastoUserSocket.addEventListener('error', ({ detail: error }) => {
-        console.error('Error in MastoAPI websocket:', error)
-      })
-      state.mastoUserSocket.addEventListener('close', ({ detail: closeEvent }) => {
-        const ignoreCodes = new Set([
-          1000, // Normal (intended) closure
-          1001 // Going away
-        ])
-        const { code } = closeEvent
-        if (ignoreCodes.has(code)) {
-          console.debug(`Not restarting socket becasue of closure code ${code} is in ignore list`)
-        } else {
-          console.warn(`MastoAPI websocket disconnected, restarting. CloseEvent code: ${code}`)
-          dispatch('startFetchingTimeline', { timeline: 'friends' })
-          dispatch('startFetchingNotifications')
-          dispatch('restartMastoUserSocket')
+      return new Promise((resolve, reject) => {
+        try {
+          const { state, dispatch } = store
+          state.mastoUserSocket = state.backendInteractor.startUserSocket({ store })
+          state.mastoUserSocket.addEventListener(
+            'message',
+            ({ detail: message }) => {
+              if (!message) return // pings
+              if (message.event === 'notification') {
+                dispatch('addNewNotifications', {
+                  notifications: [message.notification],
+                  older: false
+                })
+              } else if (message.event === 'update') {
+                dispatch('addNewStatuses', {
+                  statuses: [message.status],
+                  userId: false,
+                  showImmediately: false,
+                  timeline: 'friends'
+                })
+              }
+            }
+          )
+          state.mastoUserSocket.addEventListener('error', ({ detail: error }) => {
+            console.error('Error in MastoAPI websocket:', error)
+          })
+          state.mastoUserSocket.addEventListener('close', ({ detail: closeEvent }) => {
+            const ignoreCodes = new Set([
+              1000, // Normal (intended) closure
+              1001 // Going away
+            ])
+            const { code } = closeEvent
+            if (ignoreCodes.has(code)) {
+              console.debug(`Not restarting socket becasue of closure code ${code} is in ignore list`)
+            } else {
+              console.warn(`MastoAPI websocket disconnected, restarting. CloseEvent code: ${code}`)
+              dispatch('startFetchingTimeline', { timeline: 'friends' })
+              dispatch('startFetchingNotifications')
+              dispatch('restartMastoUserSocket')
+            }
+          })
+          resolve()
+        } catch (e) {
+          reject(e)
         }
       })
     },
     restartMastoUserSocket ({ dispatch }) {
       // This basically starts MastoAPI user socket and stops conventional
       // fetchers when connection reestablished
-      dispatch('startMastoUserSocket').then(() => {
+      return dispatch('startMastoUserSocket').then(() => {
         dispatch('stopFetchingTimeline', { timeline: 'friends' })
         dispatch('stopFetchingNotifications')
       })

From bd07e5de1c03a5619db5af49f14dc20602134881 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 26 Dec 2019 14:35:46 +0200
Subject: [PATCH 61/62] unify showimmideately

---
 src/modules/api.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/modules/api.js b/src/modules/api.js
index b6dd7fcf..9c296275 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -47,7 +47,8 @@ const api = {
     startMastoUserSocket (store) {
       return new Promise((resolve, reject) => {
         try {
-          const { state, dispatch } = store
+          const { state, dispatch, rootState } = store
+          const timelineData = rootState.statuses.timelines.friends
           state.mastoUserSocket = state.backendInteractor.startUserSocket({ store })
           state.mastoUserSocket.addEventListener(
             'message',
@@ -62,7 +63,7 @@ const api = {
                 dispatch('addNewStatuses', {
                   statuses: [message.status],
                   userId: false,
-                  showImmediately: false,
+                  showImmediately: timelineData.visibleStatuses.length === 0,
                   timeline: 'friends'
                 })
               }

From 816c077c4fdd72eb04c5d8fc8bfd567d9a292a3c Mon Sep 17 00:00:00 2001
From: Wyatt Benno <wyattbenno@gmail.com>
Date: Mon, 30 Dec 2019 19:27:44 +0900
Subject: [PATCH 62/62] mfa fix

---
 src/components/user_settings/mfa.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/user_settings/mfa.js b/src/components/user_settings/mfa.js
index 3090138a..abf37062 100644
--- a/src/components/user_settings/mfa.js
+++ b/src/components/user_settings/mfa.js
@@ -139,7 +139,7 @@ const Mfa = {
 
     // fetch settings from server
     async fetchSettings () {
-      let result = await this.backendInteractor.fetchSettingsMFA()
+      let result = await this.backendInteractor.settingsMFA()
       if (result.error) return
       this.settings = result.settings
       this.settings.available = true