From 897131572f62c36277e06e464f328f37cf6acad2 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 14 Nov 2019 00:47:20 +0200
Subject: Made it optional

---
 src/components/settings/settings.vue | 11 +++++++++++
 1 file changed, 11 insertions(+)

(limited to 'src/components/settings/settings.vue')

diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index a83489d2..c4021137 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -270,6 +270,17 @@
                 </li>
               </ul>
             </div>
+
+            <div class="setting-item">
+              <h2>{{ $t('settings.fun') }}</h2>
+              <ul class="setting-list">
+                <li>
+                  <Checkbox v-model="greentext">
+                    {{ $t('settings.greentext') }} {{ $t('settings.instance_default', { value: greentextLocalizedValue }) }}
+                  </Checkbox>
+                </li>
+              </ul>
+            </div>
           </div>
 
           <div :label="$t('settings.theme')">
-- 
cgit v1.2.3-70-g09d2


From 6af870cd9069a8fc45b7684d264656dad0cf4a70 Mon Sep 17 00:00:00 2001
From: kPherox <admin@mail.kr-kp.com>
Date: Wed, 11 Dec 2019 00:00:10 +0900
Subject: Add view for moves notifications

---
 src/components/notification/notification.vue          | 14 +++++++++++++-
 src/components/notifications/notifications.scss       |  7 ++++++-
 src/components/settings/settings.vue                  |  5 +++++
 src/i18n/en.json                                      |  1 +
 src/modules/config.js                                 |  3 ++-
 src/modules/statuses.js                               |  3 ++-
 src/services/notification_utils/notification_utils.js |  3 ++-
 src/services/push/push.js                             |  3 ++-
 static/fontello.json                                  |  6 ++++++
 9 files changed, 39 insertions(+), 6 deletions(-)

(limited to 'src/components/settings/settings.vue')

diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index 1f192c77..cf4d8072 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -74,9 +74,13 @@
               <i class="fa icon-user-plus lit" />
               <small>{{ $t('notifications.followed_you') }}</small>
             </span>
+            <span v-if="notification.type === 'move'">
+              <i class="fa icon-arrow-curved lit" />
+              <small>{{ $t('notifications.moved_to') }}</small>
+            </span>
           </div>
           <div
-            v-if="notification.type === 'follow'"
+            v-if="notification.type === 'follow' || notification.type === 'move'"
             class="timeago"
           >
             <span class="faint">
@@ -115,6 +119,14 @@
             @{{ notification.from_profile.screen_name }}
           </router-link>
         </div>
+        <div
+          v-else-if="notification.type === 'move'"
+          class="move-text"
+        >
+          <router-link :to="userProfileLink">
+            @{{ notification.target.screen_name }}
+          </router-link>
+        </div>
         <template v-else>
           <status
             class="faint"
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index 71876b14..148ac7f2 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -76,7 +76,7 @@
     }
   }
 
-  .follow-text {
+  .follow-text, .move-text {
     padding: 0.5em 0;
   }
 
@@ -151,6 +151,11 @@
       color: var(--cOrange, $fallback--cOrange);
     }
 
+    .icon-arrow-curved.lit {
+      color: $fallback--cBlue;
+      color: var(--cBlue, $fallback--cBlue);
+    }
+
     .status-content {
       margin: 0;
       max-height: 300px;
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index c4021137..31329e82 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -314,6 +314,11 @@
                       {{ $t('settings.notification_visibility_mentions') }}
                     </Checkbox>
                   </li>
+                  <li>
+                    <Checkbox v-model="notificationVisibility.moves">
+                      {{ $t('settings.notification_visibility_moves') }}
+                    </Checkbox>
+                  </li>
                 </ul>
               </div>
               <div>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index f46d5b3d..dcd2f3d7 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -312,6 +312,7 @@
     "notification_visibility_likes": "Likes",
     "notification_visibility_mentions": "Mentions",
     "notification_visibility_repeats": "Repeats",
+    "notification_visibility_moves": "Moves",
     "no_rich_text_description": "Strip rich text formatting from all posts",
     "no_blocks": "No blocks",
     "no_mutes": "No mutes",
diff --git a/src/modules/config.js b/src/modules/config.js
index 329b4091..cc47c848 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -28,7 +28,8 @@ export const defaultState = {
     follows: true,
     mentions: true,
     likes: true,
-    repeats: true
+    repeats: true,
+    moves: true
   },
   webPushNotifications: false,
   muteWords: [],
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 3cf74a43..420b3183 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -66,7 +66,8 @@ const visibleNotificationTypes = (rootState) => {
     rootState.config.notificationVisibility.likes && 'like',
     rootState.config.notificationVisibility.mentions && 'mention',
     rootState.config.notificationVisibility.repeats && 'repeat',
-    rootState.config.notificationVisibility.follows && 'follow'
+    rootState.config.notificationVisibility.follows && 'follow',
+    rootState.config.notificationVisibility.moves && 'move'
   ].filter(_ => _)
 }
 
diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js
index 7021adbd..b08514da 100644
--- a/src/services/notification_utils/notification_utils.js
+++ b/src/services/notification_utils/notification_utils.js
@@ -6,7 +6,8 @@ export const visibleTypes = store => ([
   store.state.config.notificationVisibility.likes && 'like',
   store.state.config.notificationVisibility.mentions && 'mention',
   store.state.config.notificationVisibility.repeats && 'repeat',
-  store.state.config.notificationVisibility.follows && 'follow'
+  store.state.config.notificationVisibility.follows && 'follow',
+  store.state.config.notificationVisibility.moves && 'move'
 ].filter(_ => _))
 
 const sortById = (a, b) => {
diff --git a/src/services/push/push.js b/src/services/push/push.js
index 1b189a29..5836fc26 100644
--- a/src/services/push/push.js
+++ b/src/services/push/push.js
@@ -65,7 +65,8 @@ function sendSubscriptionToBackEnd (subscription, token, notificationVisibility)
           follow: notificationVisibility.follows,
           favourite: notificationVisibility.likes,
           mention: notificationVisibility.mentions,
-          reblog: notificationVisibility.repeats
+          reblog: notificationVisibility.repeats,
+          move: notificationVisibility.moves
         }
       }
     })
diff --git a/static/fontello.json b/static/fontello.json
index c0cf1727..642381a1 100755
--- a/static/fontello.json
+++ b/static/fontello.json
@@ -303,6 +303,12 @@
       "css": "gauge",
       "code": 61668,
       "src": "fontawesome"
+    },
+    {
+      "uid": "f3ebd6751c15a280af5cc5f4a764187d",
+      "css": "arrow-curved",
+      "code": 59421,
+      "src": "iconic"
     }
   ]
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


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: 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(-)

(limited to 'src/components/settings/settings.vue')

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
 }
 
-- 
cgit v1.2.3-70-g09d2

