aboutsummaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/api.js106
-rw-r--r--src/modules/config.js24
-rw-r--r--src/modules/instance.js6
-rw-r--r--src/modules/shout.js (renamed from src/modules/chat.js)6
-rw-r--r--src/modules/statuses.js29
-rw-r--r--src/modules/users.js7
6 files changed, 137 insertions, 41 deletions
diff --git a/src/modules/api.js b/src/modules/api.js
index 08485a30..54f94356 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -3,8 +3,11 @@ import { WSConnectionStatus } from '../services/api/api.service.js'
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
import { Socket } from 'phoenix'
+const retryTimeout = (multiplier) => 1000 * multiplier
+
const api = {
state: {
+ retryMultiplier: 1,
backendInteractor: backendInteractorService(),
fetchers: {},
socket: null,
@@ -34,18 +37,43 @@ const api = {
},
setMastoUserSocketStatus (state, value) {
state.mastoUserSocketStatus = value
+ },
+ incrementRetryMultiplier (state) {
+ state.retryMultiplier = Math.max(++state.retryMultiplier, 3)
+ },
+ resetRetryMultiplier (state) {
+ state.retryMultiplier = 1
}
},
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
+ /**
+ * Global MastoAPI socket control, in future should disable ALL sockets/(re)start relevant sockets
+ *
+ * @param {Boolean} [initial] - whether this enabling happened at boot time or not
+ */
+ enableMastoSockets (store, initial) {
+ const { state, dispatch, commit } = store
+ // Do not initialize unless nonexistent or closed
+ if (
+ state.mastoUserSocket &&
+ ![
+ WebSocket.CLOSED,
+ WebSocket.CLOSING
+ ].includes(state.mastoUserSocket.getState())
+ ) {
+ return
+ }
+ if (initial) {
+ commit('setMastoUserSocketStatus', WSConnectionStatus.STARTING_INITIAL)
+ } else {
+ commit('setMastoUserSocketStatus', WSConnectionStatus.STARTING)
+ }
return dispatch('startMastoUserSocket')
},
disableMastoSockets (store) {
- const { state, dispatch } = store
+ const { state, dispatch, commit } = store
if (!state.mastoUserSocket) return
+ commit('setMastoUserSocketStatus', WSConnectionStatus.DISABLED)
return dispatch('stopMastoUserSocket')
},
@@ -91,11 +119,29 @@ const api = {
}
)
state.mastoUserSocket.addEventListener('open', () => {
+ // Do not show notification when we just opened up the page
+ if (state.mastoUserSocketStatus !== WSConnectionStatus.STARTING_INITIAL) {
+ dispatch('pushGlobalNotice', {
+ level: 'success',
+ messageKey: 'timeline.socket_reconnected',
+ timeout: 5000
+ })
+ }
+ // Stop polling if we were errored or disabled
+ if (new Set([
+ WSConnectionStatus.ERROR,
+ WSConnectionStatus.DISABLED
+ ]).has(state.mastoUserSocketStatus)) {
+ dispatch('stopFetchingTimeline', { timeline: 'friends' })
+ dispatch('stopFetchingNotifications')
+ dispatch('stopFetchingChats')
+ }
+ commit('resetRetryMultiplier')
commit('setMastoUserSocketStatus', WSConnectionStatus.JOINED)
})
state.mastoUserSocket.addEventListener('error', ({ detail: error }) => {
console.error('Error in MastoAPI websocket:', error)
- commit('setMastoUserSocketStatus', WSConnectionStatus.ERROR)
+ // TODO is this needed?
dispatch('clearOpenedChats')
})
state.mastoUserSocket.addEventListener('close', ({ detail: closeEvent }) => {
@@ -106,14 +152,26 @@ const api = {
const { code } = closeEvent
if (ignoreCodes.has(code)) {
console.debug(`Not restarting socket becasue of closure code ${code} is in ignore list`)
+ commit('setMastoUserSocketStatus', WSConnectionStatus.CLOSED)
} else {
console.warn(`MastoAPI websocket disconnected, restarting. CloseEvent code: ${code}`)
- dispatch('startFetchingTimeline', { timeline: 'friends' })
- dispatch('startFetchingNotifications')
- dispatch('startFetchingChats')
- dispatch('restartMastoUserSocket')
+ setTimeout(() => {
+ dispatch('startMastoUserSocket')
+ }, retryTimeout(state.retryMultiplier))
+ commit('incrementRetryMultiplier')
+ if (state.mastoUserSocketStatus !== WSConnectionStatus.ERROR) {
+ dispatch('startFetchingTimeline', { timeline: 'friends' })
+ dispatch('startFetchingNotifications')
+ dispatch('startFetchingChats')
+ dispatch('pushGlobalNotice', {
+ level: 'error',
+ messageKey: 'timeline.socket_broke',
+ messageArgs: [code],
+ timeout: 5000
+ })
+ }
+ commit('setMastoUserSocketStatus', WSConnectionStatus.ERROR)
}
- commit('setMastoUserSocketStatus', WSConnectionStatus.CLOSED)
dispatch('clearOpenedChats')
})
resolve()
@@ -122,15 +180,6 @@ const api = {
}
})
},
- restartMastoUserSocket ({ dispatch }) {
- // This basically starts MastoAPI user socket and stops conventional
- // fetchers when connection reestablished
- return dispatch('startMastoUserSocket').then(() => {
- dispatch('stopFetchingTimeline', { timeline: 'friends' })
- dispatch('stopFetchingNotifications')
- dispatch('stopFetchingChats')
- })
- },
stopMastoUserSocket ({ state, dispatch }) {
dispatch('startFetchingTimeline', { timeline: 'friends' })
dispatch('startFetchingNotifications')
@@ -156,6 +205,13 @@ const api = {
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: timeline, fetcher })
},
+ fetchTimeline (store, timeline, { ...rest }) {
+ store.state.backendInteractor.fetchTimeline({
+ store,
+ timeline,
+ ...rest
+ })
+ },
// Notifications
startFetchingNotifications (store) {
@@ -168,6 +224,12 @@ const api = {
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: 'notifications', fetcher })
},
+ fetchNotifications (store, { ...rest }) {
+ store.state.backendInteractor.fetchNotifications({
+ store,
+ ...rest
+ })
+ },
// Follow requests
startFetchingFollowRequests (store) {
@@ -193,12 +255,12 @@ const api = {
initializeSocket ({ dispatch, commit, state, rootState }) {
// Set up websocket connection
const token = state.wsToken
- if (rootState.instance.chatAvailable && typeof token !== 'undefined' && state.socket === null) {
+ if (rootState.instance.shoutAvailable && typeof token !== 'undefined' && state.socket === null) {
const socket = new Socket('/socket', { params: { token } })
socket.connect()
commit('setSocket', socket)
- dispatch('initializeChat', socket)
+ dispatch('initializeShout', socket)
}
},
disconnectFromSocket ({ commit, state }) {
diff --git a/src/modules/config.js b/src/modules/config.js
index f992519e..33e2cb50 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -21,6 +21,7 @@ export const defaultState = {
customThemeSource: undefined,
hideISP: false,
hideInstanceWallpaper: false,
+ hideShoutbox: false,
// bad name: actually hides posts of muted USERS
hideMutedPosts: undefined, // instance default
collapseMessageWithSubject: undefined, // instance default
@@ -44,7 +45,7 @@ export const defaultState = {
likes: true,
repeats: true,
moves: true,
- emojiReactions: false,
+ emojiReactions: true,
followRequest: true,
chatMention: true
},
@@ -54,6 +55,7 @@ export const defaultState = {
interfaceLanguage: browserLocale,
hideScopeNotice: false,
useStreamingApi: false,
+ sidebarRight: undefined, // instance default
scopeCopy: undefined, // instance default
subjectLineBehavior: undefined, // instance default
alwaysShowSubjectInput: undefined, // instance default
@@ -67,7 +69,8 @@ export const defaultState = {
greentext: undefined, // instance default
hidePostStats: undefined, // instance default
hideUserStats: undefined, // instance default
- virtualScrolling: undefined // instance default
+ virtualScrolling: undefined, // instance default
+ sensitiveByDefault: undefined // instance default
}
// caching the instance default properties
@@ -91,7 +94,8 @@ const config = {
const { defaultConfig } = rootGetters
return {
...defaultConfig,
- ...state
+ // Do not override with undefined
+ ...Object.fromEntries(Object.entries(state).filter(([k, v]) => v !== undefined))
}
}
},
@@ -109,6 +113,20 @@ const config = {
}
},
actions: {
+ loadSettings ({ dispatch }, data) {
+ const knownKeys = new Set(Object.keys(defaultState))
+ const presentKeys = new Set(Object.keys(data))
+ const intersection = new Set()
+ for (let elem of presentKeys) {
+ if (knownKeys.has(elem)) {
+ intersection.add(elem)
+ }
+ }
+
+ intersection.forEach(
+ name => dispatch('setOption', { name, value: data[name] })
+ )
+ },
setHighlight ({ commit, dispatch }, { user, color, type }) {
commit('setHighlight', { user, color, type })
},
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 411b1caa..539b9c66 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -19,7 +19,6 @@ const defaultState = {
defaultBanner: '/images/banner.png',
background: '/static/aurora_borealis.jpg',
collapseMessageWithSubject: false,
- disableChat: false,
greentext: false,
hideFilteredStatuses: false,
hideMutedPosts: false,
@@ -43,6 +42,7 @@ const defaultState = {
subjectLineBehavior: 'email',
theme: 'pleroma-dark',
virtualScrolling: true,
+ sensitiveByDefault: false,
// Nasty stuff
customEmoji: [],
@@ -56,7 +56,7 @@ const defaultState = {
knownDomains: [],
// Feature-set, apparently, not everything here is reported...
- chatAvailable: false,
+ shoutAvailable: false,
pleromaChatMessagesAvailable: false,
gopherAvailable: false,
mediaProxyAvailable: false,
@@ -106,7 +106,7 @@ const instance = {
case 'name':
dispatch('setPageTitle')
break
- case 'chatAvailable':
+ case 'shoutAvailable':
if (value) {
dispatch('initializeSocket')
}
diff --git a/src/modules/chat.js b/src/modules/shout.js
index c798549d..507a4d83 100644
--- a/src/modules/chat.js
+++ b/src/modules/shout.js
@@ -1,4 +1,4 @@
-const chat = {
+const shout = {
state: {
messages: [],
channel: { state: '' }
@@ -16,7 +16,7 @@ const chat = {
}
},
actions: {
- initializeChat (store, socket) {
+ initializeShout (store, socket) {
const channel = socket.channel('chat:public')
channel.on('new_msg', (msg) => {
store.commit('addMessage', msg)
@@ -30,4 +30,4 @@ const chat = {
}
}
-export default chat
+export default shout
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 33c68c57..ac5d25c4 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -13,7 +13,11 @@ import {
omitBy
} from 'lodash'
import { set } from 'vue'
-import { isStatusNotification, maybeShowNotification } from '../services/notification_utils/notification_utils.js'
+import {
+ isStatusNotification,
+ isValidNotification,
+ maybeShowNotification
+} from '../services/notification_utils/notification_utils.js'
import apiService from '../services/api/api.service.js'
const emptyTl = (userId = 0) => ({
@@ -310,8 +314,24 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
}
}
+const updateNotificationsMinMaxId = (state, notification) => {
+ state.notifications.maxId = notification.id > state.notifications.maxId
+ ? notification.id
+ : state.notifications.maxId
+ state.notifications.minId = notification.id < state.notifications.minId
+ ? notification.id
+ : state.notifications.minId
+}
+
const addNewNotifications = (state, { dispatch, notifications, older, visibleNotificationTypes, rootGetters, newNotificationSideEffects }) => {
each(notifications, (notification) => {
+ // If invalid notification, update ids but don't add it to store
+ if (!isValidNotification(notification)) {
+ console.error('Invalid notification:', notification)
+ updateNotificationsMinMaxId(state, notification)
+ return
+ }
+
if (isStatusNotification(notification.type)) {
notification.action = addStatusToGlobalStorage(state, notification.action).item
notification.status = notification.status && addStatusToGlobalStorage(state, notification.status).item
@@ -323,12 +343,7 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot
// Only add a new notification if we don't have one for the same action
if (!state.notifications.idStore.hasOwnProperty(notification.id)) {
- state.notifications.maxId = notification.id > state.notifications.maxId
- ? notification.id
- : state.notifications.maxId
- state.notifications.minId = notification.id < state.notifications.minId
- ? notification.id
- : state.notifications.minId
+ updateNotificationsMinMaxId(state, notification)
state.notifications.data.push(notification)
state.notifications.idStore[notification.id] = notification
diff --git a/src/modules/users.js b/src/modules/users.js
index 655db4c7..2b416f94 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -531,7 +531,7 @@ const users = {
if (user.token) {
store.dispatch('setWsToken', user.token)
- // Initialize the chat socket.
+ // Initialize the shout socket.
store.dispatch('initializeSocket')
}
@@ -547,9 +547,10 @@ const users = {
}
if (store.getters.mergedConfig.useStreamingApi) {
- store.dispatch('enableMastoSockets').catch((error) => {
+ store.dispatch('fetchTimeline', 'friends', { since: null })
+ store.dispatch('fetchNotifications', { since: null })
+ store.dispatch('enableMastoSockets', true).catch((error) => {
console.error('Failed initializing MastoAPI Streaming socket', error)
- startPolling()
}).then(() => {
store.dispatch('fetchChats', { latest: true })
setTimeout(() => store.dispatch('setNotificationsSilence', false), 10000)