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 }