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 @@
+
+
+ {{ $t('settings.useStreamingApi') }}
+
+
+ {{ $t('settings.useStreamingApiWarning') }}
+
+
+
{{ $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
}