aboutsummaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/api.js21
-rw-r--r--src/modules/auth_flow.js90
-rw-r--r--src/modules/chat.js12
-rw-r--r--src/modules/config.js36
-rw-r--r--src/modules/errors.js1
-rw-r--r--src/modules/instance.js27
-rw-r--r--src/modules/oauth.js45
-rw-r--r--src/modules/oauth_tokens.js4
-rw-r--r--src/modules/polls.js70
-rw-r--r--src/modules/postStatus.js25
-rw-r--r--src/modules/statuses.js86
-rw-r--r--src/modules/users.js135
12 files changed, 440 insertions, 112 deletions
diff --git a/src/modules/api.js b/src/modules/api.js
index 7ed3edac..eb6a7980 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -6,7 +6,6 @@ const api = {
backendInteractor: backendInteractorService(),
fetchers: {},
socket: null,
- chatDisabled: false,
followRequests: []
},
mutations: {
@@ -25,9 +24,6 @@ const api = {
setSocket (state, socket) {
state.socket = socket
},
- setChatDisabled (state, value) {
- state.chatDisabled = value
- },
setFollowRequests (state, value) {
state.followRequests = value
}
@@ -55,17 +51,20 @@ const api = {
setWsToken (store, token) {
store.commit('setWsToken', token)
},
- initializeSocket (store) {
+ initializeSocket ({ dispatch, commit, state, rootState }) {
// Set up websocket connection
- if (!store.state.chatDisabled) {
- const token = store.state.wsToken
- const socket = new Socket('/socket', {params: {token}})
+ const token = state.wsToken
+ if (rootState.instance.chatAvailable && typeof token !== 'undefined' && state.socket === null) {
+ const socket = new Socket('/socket', { params: { token } })
socket.connect()
- store.dispatch('initializeChat', socket)
+
+ commit('setSocket', socket)
+ dispatch('initializeChat', socket)
}
},
- disableChat (store) {
- store.commit('setChatDisabled', true)
+ disconnectFromSocket ({ commit, state }) {
+ state.socket && state.socket.disconnect()
+ commit('setSocket', null)
},
removeFollowRequest (store, request) {
let requests = store.state.followRequests.filter((it) => it !== request)
diff --git a/src/modules/auth_flow.js b/src/modules/auth_flow.js
new file mode 100644
index 00000000..d0a90feb
--- /dev/null
+++ b/src/modules/auth_flow.js
@@ -0,0 +1,90 @@
+const PASSWORD_STRATEGY = 'password'
+const TOKEN_STRATEGY = 'token'
+
+// MFA strategies
+const TOTP_STRATEGY = 'totp'
+const RECOVERY_STRATEGY = 'recovery'
+
+// initial state
+const state = {
+ app: null,
+ settings: {},
+ strategy: PASSWORD_STRATEGY,
+ initStrategy: PASSWORD_STRATEGY // default strategy from config
+}
+
+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
+ },
+ requiredPassword: (state, getters, rootState) => {
+ return state.strategy === PASSWORD_STRATEGY
+ },
+ requiredToken: (state, getters, rootState) => {
+ return state.strategy === TOKEN_STRATEGY
+ },
+ requiredTOTP: (state, getters, rootState) => {
+ return state.strategy === TOTP_STRATEGY
+ },
+ requiredRecovery: (state, getters, rootState) => {
+ return state.strategy === RECOVERY_STRATEGY
+ }
+}
+
+// mutations
+const mutations = {
+ setInitialStrategy (state, strategy) {
+ if (strategy) {
+ state.initStrategy = strategy
+ state.strategy = strategy
+ }
+ },
+ requirePassword (state) {
+ state.strategy = PASSWORD_STRATEGY
+ },
+ requireToken (state) {
+ state.strategy = TOKEN_STRATEGY
+ },
+ requireMFA (state, { app, settings }) {
+ state.settings = settings
+ state.app = app
+ state.strategy = TOTP_STRATEGY // default strategy of MFA
+ },
+ requireRecovery (state) {
+ state.strategy = RECOVERY_STRATEGY
+ },
+ requireTOTP (state) {
+ state.strategy = TOTP_STRATEGY
+ },
+ abortMFA (state) {
+ resetState(state)
+ }
+}
+
+// actions
+const actions = {
+ // eslint-disable-next-line camelcase
+ async login ({ state, dispatch, commit }, { access_token }) {
+ commit('setToken', access_token, { root: true })
+ await dispatch('loginUser', access_token, { root: true })
+ resetState(state)
+ }
+}
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ mutations,
+ actions
+}
diff --git a/src/modules/chat.js b/src/modules/chat.js
index 2804e577..c798549d 100644
--- a/src/modules/chat.js
+++ b/src/modules/chat.js
@@ -1,16 +1,12 @@
const chat = {
state: {
messages: [],
- channel: {state: ''},
- socket: null
+ channel: { state: '' }
},
mutations: {
setChannel (state, channel) {
state.channel = channel
},
- setSocket (state, socket) {
- state.socket = socket
- },
addMessage (state, message) {
state.messages.push(message)
state.messages = state.messages.slice(-19, 20)
@@ -20,16 +16,12 @@ const chat = {
}
},
actions: {
- disconnectFromChat (store) {
- store.state.socket.disconnect()
- },
initializeChat (store, socket) {
const channel = socket.channel('chat:public')
- store.commit('setSocket', socket)
channel.on('new_msg', (msg) => {
store.commit('addMessage', msg)
})
- channel.on('messages', ({messages}) => {
+ channel.on('messages', ({ messages }) => {
store.commit('setMessages', messages)
})
channel.join()
diff --git a/src/modules/config.js b/src/modules/config.js
index a8da525a..78314118 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -3,10 +3,12 @@ import { setPreset, applyTheme } from '../services/style_setter/style_setter.js'
const browserLocale = (window.navigator.language || 'en').split('-')[0]
-const defaultState = {
+export const defaultState = {
colors: {},
+ // bad name: actually hides posts of muted USERS
hideMutedPosts: undefined, // instance default
collapseMessageWithSubject: undefined, // instance default
+ padEmoji: true,
hideAttachments: false,
hideAttachmentsInConv: false,
maxThumbnails: 16,
@@ -36,11 +38,37 @@ const defaultState = {
subjectLineBehavior: undefined, // instance default
alwaysShowSubjectInput: undefined, // instance default
postContentType: undefined, // instance default
- minimalScopesMode: undefined // instance default
+ minimalScopesMode: undefined, // instance default
+ // This hides statuses filtered via a word filter
+ hideFilteredStatuses: undefined, // instance default
+ playVideosInModal: false,
+ useOneClickNsfw: false,
+ useContainFit: false,
+ hidePostStats: undefined, // instance default
+ hideUserStats: undefined // instance default
}
+// caching the instance default properties
+export const instanceDefaultProperties = Object.entries(defaultState)
+ .filter(([key, value]) => value === undefined)
+ .map(([key, value]) => key)
+
const config = {
state: defaultState,
+ getters: {
+ mergedConfig (state, getters, rootState, rootGetters) {
+ const { instance } = rootState
+ return {
+ ...state,
+ ...instanceDefaultProperties
+ .map(key => [key, state[key] === undefined
+ ? instance[key]
+ : state[key]
+ ])
+ .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {})
+ }
+ }
+ },
mutations: {
setOption (state, { name, value }) {
set(state, name, value)
@@ -56,10 +84,10 @@ const config = {
},
actions: {
setHighlight ({ commit, dispatch }, { user, color, type }) {
- commit('setHighlight', {user, color, type})
+ commit('setHighlight', { user, color, type })
},
setOption ({ commit, dispatch }, { name, value }) {
- commit('setOption', {name, value})
+ commit('setOption', { name, value })
switch (name) {
case 'theme':
setPreset(value, commit)
diff --git a/src/modules/errors.js b/src/modules/errors.js
index c809e1b5..ca89dc0f 100644
--- a/src/modules/errors.js
+++ b/src/modules/errors.js
@@ -9,4 +9,3 @@ export function humanizeErrors (errors) {
return [...errs, message]
}, [])
}
-
diff --git a/src/modules/instance.js b/src/modules/instance.js
index d4185f6a..0c1235ca 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -1,5 +1,6 @@
import { set } from 'vue'
import { setPreset } from '../services/style_setter/style_setter.js'
+import { instanceDefaultProperties } from './config.js'
const defaultState = {
// Stuff from static/config.json and apiConfig
@@ -16,7 +17,6 @@ const defaultState = {
redirectRootNoLogin: '/main/all',
redirectRootLogin: '/main/friends',
showInstanceSpecificPanel: false,
- formattingOptionsEnabled: false,
alwaysShowSubjectInput: true,
hideMutedPosts: false,
collapseMessageWithSubject: false,
@@ -27,7 +27,6 @@ const defaultState = {
scopeCopy: true,
subjectLineBehavior: 'email',
postContentType: 'text/plain',
- loginMethod: 'password',
nsfwCensorImage: undefined,
vapidPublicKey: undefined,
noAttachmentLinks: false,
@@ -54,7 +53,15 @@ const defaultState = {
// Version Information
backendVersion: '',
- frontendVersion: ''
+ frontendVersion: '',
+
+ pollsAvailable: false,
+ pollLimits: {
+ max_options: 4,
+ max_option_chars: 255,
+ min_expiration: 60,
+ max_expiration: 60 * 60 * 24
+ }
}
const instance = {
@@ -66,13 +73,25 @@ const instance = {
}
}
},
+ getters: {
+ instanceDefaultConfig (state) {
+ return instanceDefaultProperties
+ .map(key => [key, state[key]])
+ .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {})
+ }
+ },
actions: {
setInstanceOption ({ commit, dispatch }, { name, value }) {
- commit('setInstanceOption', {name, value})
+ commit('setInstanceOption', { name, value })
switch (name) {
case 'name':
dispatch('setPageTitle')
break
+ case 'chatAvailable':
+ if (value) {
+ dispatch('initializeSocket')
+ }
+ break
}
},
setTheme ({ commit }, themeName) {
diff --git a/src/modules/oauth.js b/src/modules/oauth.js
index 144ff830..a2a83450 100644
--- a/src/modules/oauth.js
+++ b/src/modules/oauth.js
@@ -1,16 +1,47 @@
+import { delete as del } from 'vue'
+
const oauth = {
state: {
- client_id: false,
- client_secret: false,
- token: false
+ clientId: false,
+ clientSecret: false,
+ /* App token is authentication for app without any user, used mostly for
+ * MastoAPI's registration of new users, stored so that we can fall back to
+ * it on logout
+ */
+ appToken: false,
+ /* User token is authentication for app with user, this is for every calls
+ * that need authorized user to be successful (i.e. posting, liking etc)
+ */
+ userToken: false
},
mutations: {
- setClientData (state, data) {
- state.client_id = data.client_id
- state.client_secret = data.client_secret
+ setClientData (state, { clientId, clientSecret }) {
+ state.clientId = clientId
+ state.clientSecret = clientSecret
+ },
+ setAppToken (state, token) {
+ state.appToken = token
},
setToken (state, token) {
- state.token = token
+ state.userToken = token
+ },
+ clearToken (state) {
+ state.userToken = false
+ // state.token is userToken with older name, coming from persistent state
+ // let's clear it as well, since it is being used as a fallback of state.userToken
+ del(state, 'token')
+ }
+ },
+ getters: {
+ getToken: state => () => {
+ // state.token is userToken with older name, coming from persistent state
+ // added here for smoother transition, otherwise user will be logged out
+ return state.userToken || state.token || state.appToken
+ },
+ getUserToken: state => () => {
+ // state.token is userToken with older name, coming from persistent state
+ // added here for smoother transition, otherwise user will be logged out
+ return state.userToken || state.token
}
}
}
diff --git a/src/modules/oauth_tokens.js b/src/modules/oauth_tokens.js
index 00ac1431..0159a3f1 100644
--- a/src/modules/oauth_tokens.js
+++ b/src/modules/oauth_tokens.js
@@ -3,12 +3,12 @@ const oauthTokens = {
tokens: []
},
actions: {
- fetchTokens ({rootState, commit}) {
+ fetchTokens ({ rootState, commit }) {
rootState.api.backendInteractor.fetchOAuthTokens().then((tokens) => {
commit('swapTokens', tokens)
})
},
- revokeToken ({rootState, commit, state}, id) {
+ revokeToken ({ rootState, commit, state }, id) {
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
new file mode 100644
index 00000000..e6158b63
--- /dev/null
+++ b/src/modules/polls.js
@@ -0,0 +1,70 @@
+import { merge } from 'lodash'
+import { set } from 'vue'
+
+const polls = {
+ state: {
+ // Contains key = id, value = number of trackers for this poll
+ trackedPolls: {},
+ pollsObject: {}
+ },
+ mutations: {
+ mergeOrAddPoll (state, poll) {
+ const existingPoll = state.pollsObject[poll.id]
+ // Make expired-state change trigger re-renders properly
+ poll.expired = Date.now() > Date.parse(poll.expires_at)
+ if (existingPoll) {
+ set(state.pollsObject, poll.id, merge(existingPoll, poll))
+ } else {
+ set(state.pollsObject, poll.id, poll)
+ }
+ },
+ trackPoll (state, pollId) {
+ const currentValue = state.trackedPolls[pollId]
+ if (currentValue) {
+ set(state.trackedPolls, pollId, currentValue + 1)
+ } else {
+ set(state.trackedPolls, pollId, 1)
+ }
+ },
+ untrackPoll (state, pollId) {
+ const currentValue = state.trackedPolls[pollId]
+ if (currentValue) {
+ set(state.trackedPolls, pollId, currentValue - 1)
+ } else {
+ set(state.trackedPolls, pollId, 0)
+ }
+ }
+ },
+ actions: {
+ mergeOrAddPoll ({ commit }, poll) {
+ commit('mergeOrAddPoll', poll)
+ },
+ updateTrackedPoll ({ rootState, dispatch, commit }, pollId) {
+ rootState.api.backendInteractor.fetchPoll(pollId).then(poll => {
+ setTimeout(() => {
+ if (rootState.polls.trackedPolls[pollId]) {
+ dispatch('updateTrackedPoll', pollId)
+ }
+ }, 30 * 1000)
+ commit('mergeOrAddPoll', poll)
+ })
+ },
+ trackPoll ({ rootState, commit, dispatch }, pollId) {
+ if (!rootState.polls.trackedPolls[pollId]) {
+ setTimeout(() => dispatch('updateTrackedPoll', pollId), 30 * 1000)
+ }
+ commit('trackPoll', pollId)
+ },
+ untrackPoll ({ commit }, pollId) {
+ commit('untrackPoll', pollId)
+ },
+ votePoll ({ rootState, commit }, { id, pollId, choices }) {
+ return rootState.api.backendInteractor.vote(pollId, choices).then(poll => {
+ commit('mergeOrAddPoll', poll)
+ return poll
+ })
+ }
+ }
+}
+
+export default polls
diff --git a/src/modules/postStatus.js b/src/modules/postStatus.js
new file mode 100644
index 00000000..638c1fb2
--- /dev/null
+++ b/src/modules/postStatus.js
@@ -0,0 +1,25 @@
+const postStatus = {
+ state: {
+ params: null,
+ modalActivated: false
+ },
+ mutations: {
+ openPostStatusModal (state, params) {
+ state.params = params
+ state.modalActivated = true
+ },
+ closePostStatusModal (state) {
+ state.modalActivated = false
+ }
+ },
+ actions: {
+ openPostStatusModal ({ commit }, params) {
+ commit('openPostStatusModal', params)
+ },
+ closePostStatusModal ({ commit }) {
+ commit('closePostStatusModal')
+ }
+ }
+}
+
+export default postStatus
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index e6ee5447..f11ffdcd 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -80,13 +80,13 @@ const mergeOrAdd = (arr, obj, item) => {
merge(oldItem, omitBy(item, (v, k) => v === null || k === 'user'))
// Reactivity fix.
oldItem.attachments.splice(oldItem.attachments.length)
- return {item: oldItem, new: false}
+ return { item: oldItem, new: false }
} else {
// This is a new item, prepare it
prepareStatus(item)
arr.push(item)
set(obj, item.id, item)
- return {item, new: true}
+ return { item, new: true }
}
}
@@ -137,7 +137,7 @@ const removeStatusFromGlobalStorage = (state, status) => {
// TODO: Need to remove from allStatusesObject?
// Remove possible notification
- remove(state.notifications.data, ({action: {id}}) => id === status.id)
+ remove(state.notifications.data, ({ action: { id } }) => id === status.id)
// Remove from conversation
const conversationId = status.statusnet_conversation_id
@@ -146,7 +146,8 @@ const removeStatusFromGlobalStorage = (state, status) => {
}
}
-const addNewStatuses = (state, { statuses, showImmediately = false, timeline, user = {}, noIdUpdate = false, userId }) => {
+const addNewStatuses = (state, { statuses, showImmediately = false, timeline, user = {},
+ noIdUpdate = false, userId }) => {
// Sanity check
if (!isArray(statuses)) {
return false
@@ -269,7 +270,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
},
'deletion': (deletion) => {
const uri = deletion.uri
- const status = find(allStatuses, {uri})
+ const status = find(allStatuses, { uri })
if (!status) {
return
}
@@ -394,8 +395,9 @@ export const mutations = {
state[key] = value
})
},
- clearTimeline (state, { timeline }) {
- state.timelines[timeline] = emptyTl(state.timelines[timeline].userId)
+ clearTimeline (state, { timeline, excludeUserId = false }) {
+ const userId = excludeUserId ? state.timelines[timeline].userId : undefined
+ state.timelines[timeline] = emptyTl(userId)
},
clearNotifications (state) {
state.notifications = emptyNotifications()
@@ -424,9 +426,13 @@ export const mutations = {
newStatus.favoritedBy.push(user)
}
},
- setPinned (state, status) {
+ setMutedStatus (state, status) {
const newStatus = state.allStatusesObject[status.id]
- newStatus.pinned = status.pinned
+ newStatus.thread_muted = status.thread_muted
+
+ if (newStatus.thread_muted !== undefined) {
+ state.conversationsObject[newStatus.statusnet_conversation_id].forEach(status => { status.thread_muted = newStatus.thread_muted })
+ }
},
setRetweeted (state, { status, value }) {
const newStatus = state.allStatusesObject[status.id]
@@ -490,10 +496,23 @@ export const mutations = {
queueFlush (state, { timeline, id }) {
state.timelines[timeline].flushMarker = id
},
- addFavsAndRepeats (state, { id, favoritedByUsers, rebloggedByUsers }) {
+ addRepeats (state, { id, rebloggedByUsers, currentUser }) {
const newStatus = state.allStatusesObject[id]
- newStatus.favoritedBy = favoritedByUsers.filter(_ => _)
newStatus.rebloggedBy = rebloggedByUsers.filter(_ => _)
+ // repeats stats can be incorrect based on polling condition, let's update them using the most recent data
+ newStatus.repeat_num = newStatus.rebloggedBy.length
+ newStatus.repeated = !!newStatus.rebloggedBy.find(({ id }) => currentUser.id === id)
+ },
+ addFavs (state, { id, favoritedByUsers, currentUser }) {
+ const newStatus = state.allStatusesObject[id]
+ newStatus.favoritedBy = favoritedByUsers.filter(_ => _)
+ // favorites stats can be incorrect based on polling condition, let's update them using the most recent data
+ newStatus.fave_num = newStatus.favoritedBy.length
+ newStatus.favorited = !!newStatus.favoritedBy.find(({ id }) => currentUser.id === id)
+ },
+ updateStatusWithPoll (state, { id, poll }) {
+ const status = state.allStatusesObject[id]
+ status.poll = poll
}
}
@@ -518,6 +537,10 @@ const statuses = {
setNotificationsSilence ({ rootState, commit }, { value }) {
commit('setNotificationsSilence', { value })
},
+ fetchStatus ({ rootState, dispatch }, id) {
+ rootState.api.backendInteractor.fetchStatus({ id })
+ .then((status) => dispatch('addNewStatuses', { statuses: [status] }))
+ },
deleteStatus ({ rootState, commit }, status) {
commit('setDeleted', { status })
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })
@@ -539,15 +562,23 @@ const statuses = {
},
fetchPinnedStatuses ({ rootState, dispatch }, userId) {
rootState.api.backendInteractor.fetchPinnedStatuses(userId)
- .then(statuses => dispatch('addNewStatuses', { statuses, timeline: 'user', userId, showImmediately: true }))
+ .then(statuses => dispatch('addNewStatuses', { statuses, timeline: 'user', userId, showImmediately: true, noIdUpdate: true }))
},
- pinStatus ({ rootState, commit }, statusId) {
+ pinStatus ({ rootState, dispatch }, statusId) {
return rootState.api.backendInteractor.pinOwnStatus(statusId)
- .then((status) => commit('setPinned', status))
+ .then((status) => dispatch('addNewStatuses', { statuses: [status] }))
},
- unpinStatus ({ rootState, commit }, statusId) {
+ unpinStatus ({ rootState, dispatch }, statusId) {
rootState.api.backendInteractor.unpinOwnStatus(statusId)
- .then((status) => commit('setPinned', status))
+ .then((status) => dispatch('addNewStatuses', { statuses: [status] }))
+ },
+ muteConversation ({ rootState, commit }, statusId) {
+ return rootState.api.backendInteractor.muteConversation(statusId)
+ .then((status) => commit('setMutedStatus', status))
+ },
+ unmuteConversation ({ rootState, commit }, statusId) {
+ return rootState.api.backendInteractor.unmuteConversation(statusId)
+ .then((status) => commit('setMutedStatus', status))
},
retweet ({ rootState, commit }, status) {
// Optimistic retweeting...
@@ -575,9 +606,26 @@ const statuses = {
Promise.all([
rootState.api.backendInteractor.fetchFavoritedByUsers(id),
rootState.api.backendInteractor.fetchRebloggedByUsers(id)
- ]).then(([favoritedByUsers, rebloggedByUsers]) =>
- commit('addFavsAndRepeats', { id, favoritedByUsers, rebloggedByUsers })
- )
+ ]).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)
+ .then(favoritedByUsers => commit('addFavs', { id, favoritedByUsers, currentUser: rootState.users.currentUser }))
+ },
+ fetchRepeats ({ rootState, commit }, id) {
+ rootState.api.backendInteractor.fetchRebloggedByUsers(id)
+ .then(rebloggedByUsers => commit('addRepeats', { id, rebloggedByUsers, currentUser: rootState.users.currentUser }))
+ },
+ search (store, { q, resolve, limit, offset, following }) {
+ return store.rootState.api.backendInteractor.search2({ q, resolve, limit, offset, following })
+ .then((data) => {
+ store.commit('addNewUsers', data.accounts)
+ store.commit('addNewStatuses', { statuses: data.statuses })
+ return data
+ })
}
},
mutations
diff --git a/src/modules/users.js b/src/modules/users.js
index e72a657c..6d259dc2 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -1,10 +1,8 @@
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
-import userSearchApi from '../services/new_api/user_search.js'
+import oauthApi from '../services/new_api/oauth.js'
import { compact, map, each, merge, last, concat, uniq } from 'lodash'
import { set } from 'vue'
import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js'
-import oauthApi from '../services/new_api/oauth'
-import { humanizeErrors } from './errors'
// TODO: Unify with mergeOrAdd in statuses.js
export const mergeOrAdd = (arr, obj, item) => {
@@ -62,6 +60,18 @@ const unmuteUser = (store, id) => {
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
}
+const hideReblogs = (store, userId) => {
+ return store.rootState.api.backendInteractor.followUser({ id: userId, reblogs: false })
+ .then((relationship) => {
+ store.commit('updateUserRelationship', [relationship])
+ })
+}
+
+const showReblogs = (store, userId) => {
+ return store.rootState.api.backendInteractor.followUser({ id: userId, reblogs: true })
+ .then((relationship) => store.commit('updateUserRelationship', [relationship]))
+}
+
export const mutations = {
setMuted (state, { user: { id }, muted }) {
const user = state.usersObject[id]
@@ -136,6 +146,8 @@ export const mutations = {
user.following = relationship.following
user.muted = relationship.muting
user.statusnet_blocking = relationship.blocking
+ user.subscribed = relationship.subscribing
+ user.showing_reblogs = relationship.showing_reblogs
}
})
},
@@ -165,13 +177,13 @@ export const mutations = {
state.currentUser.muteIds.push(muteId)
}
},
- setPinned (state, status) {
+ setPinnedToUser (state, status) {
const user = state.usersObject[status.user.id]
- const index = user.pinnedStatuseIds.indexOf(status.id)
+ const index = user.pinnedStatusIds.indexOf(status.id)
if (status.pinned && index === -1) {
- user.pinnedStatuseIds.push(status.id)
+ user.pinnedStatusIds.push(status.id)
} else if (!status.pinned && index !== -1) {
- user.pinnedStatuseIds.splice(index, 1)
+ user.pinnedStatusIds.splice(index, 1)
}
},
setUserForStatus (state, status) {
@@ -273,6 +285,12 @@ const users = {
unmuteUser (store, id) {
return unmuteUser(store, id)
},
+ hideReblogs (store, id) {
+ return hideReblogs(store, id)
+ },
+ showReblogs (store, id) {
+ return showReblogs(store, id)
+ },
muteUsers (store, ids = []) {
return Promise.all(ids.map(id => muteUser(store, id)))
},
@@ -305,6 +323,14 @@ const users = {
clearFollowers ({ commit }, userId) {
commit('clearFollowers', userId)
},
+ subscribeUser ({ rootState, commit }, id) {
+ return rootState.api.backendInteractor.subscribeUser(id)
+ .then((relationship) => commit('updateUserRelationship', [relationship]))
+ },
+ unsubscribeUser ({ rootState, commit }, id) {
+ return rootState.api.backendInteractor.unsubscribeUser(id)
+ .then((relationship) => commit('updateUserRelationship', [relationship]))
+ },
registerPushNotifications (store) {
const token = store.state.currentUser.credentials
const vapidPublicKey = store.rootState.instance.vapidPublicKey
@@ -331,13 +357,13 @@ const users = {
// Reconnect users to statuses
store.commit('setUserForStatus', status)
// Set pinned statuses to user
- store.commit('setPinned', status)
+ store.commit('setPinnedToUser', status)
})
each(compact(map(statuses, 'retweeted_status')), (status) => {
// Reconnect users to retweets
store.commit('setUserForStatus', status)
// Set pinned retweets to user
- store.commit('setPinned', status)
+ store.commit('setPinnedToUser', status)
})
},
addNewNotifications (store, { notifications }) {
@@ -347,8 +373,8 @@ const users = {
const notificationsObject = store.rootState.statuses.notifications.idStore
const relevantNotifications = Object.entries(notificationsObject)
- .filter(([k, val]) => notificationIds.includes(k))
- .map(([k, val]) => val)
+ .filter(([k, val]) => notificationIds.includes(k))
+ .map(([k, val]) => val)
// Reconnect users to notifications
each(relevantNotifications, (notification) => {
@@ -356,8 +382,7 @@ const users = {
})
},
searchUsers (store, query) {
- // TODO: Move userSearch api into api.service
- return userSearchApi.search({query, store: { state: store.rootState }})
+ return store.rootState.api.backendInteractor.searchUsers(query)
.then((users) => {
store.commit('addNewUsers', users)
return users
@@ -368,48 +393,50 @@ const users = {
let rootState = store.rootState
- let response = await rootState.api.backendInteractor.register(userInfo)
- if (response.ok) {
- const data = {
- oauth: rootState.oauth,
- instance: rootState.instance.server
- }
- let app = await oauthApi.getOrCreateApp(data)
- let result = await oauthApi.getTokenWithCredentials({
- app,
- instance: data.instance,
- username: userInfo.username,
- password: userInfo.password
- })
+ try {
+ let data = await rootState.api.backendInteractor.register(userInfo)
store.commit('signUpSuccess')
- store.commit('setToken', result.access_token)
- store.dispatch('loginUser', result.access_token)
- } else {
- const data = await response.json()
- let errors = JSON.parse(data.error)
- // replace ap_id with username
- if (errors.ap_id) {
- errors.username = errors.ap_id
- delete errors.ap_id
- }
- errors = humanizeErrors(errors)
+ store.commit('setToken', data.access_token)
+ store.dispatch('loginUser', data.access_token)
+ } catch (e) {
+ let errors = e.message
store.commit('signUpFailure', errors)
- throw Error(errors)
+ throw e
}
},
async getCaptcha (store) {
- return await store.rootState.api.backendInteractor.getCaptcha()
+ return store.rootState.api.backendInteractor.getCaptcha()
},
logout (store) {
- store.commit('clearCurrentUser')
- store.dispatch('disconnectFromChat')
- store.commit('setToken', false)
- store.dispatch('stopFetching', 'friends')
- store.commit('setBackendInteractor', backendInteractorService())
- store.dispatch('stopFetching', 'notifications')
- store.commit('clearNotifications')
- store.commit('resetStatuses')
+ const { oauth, instance } = store.rootState
+
+ const data = {
+ ...oauth,
+ commit: store.commit,
+ instance: instance.server
+ }
+
+ return oauthApi.getOrCreateApp(data)
+ .then((app) => {
+ const params = {
+ app,
+ instance: data.instance,
+ token: oauth.userToken
+ }
+
+ return oauthApi.revokeToken(params)
+ })
+ .then(() => {
+ store.commit('clearCurrentUser')
+ store.dispatch('disconnectFromSocket')
+ store.commit('clearToken')
+ store.dispatch('stopFetching', 'friends')
+ store.commit('setBackendInteractor', backendInteractorService(store.getters.getToken()))
+ store.dispatch('stopFetching', 'notifications')
+ store.commit('clearNotifications')
+ store.commit('resetStatuses')
+ })
},
loginUser (store, accessToken) {
return new Promise((resolve, reject) => {
@@ -456,19 +483,19 @@ const users = {
// Authentication failed
commit('endLogin')
if (response.status === 401) {
- reject('Wrong username or password')
+ reject(new Error('Wrong username or password'))
} else {
- reject('An error occurred, please try again')
+ reject(new Error('An error occurred, please try again'))
}
}
commit('endLogin')
resolve()
})
- .catch((error) => {
- console.log(error)
- commit('endLogin')
- reject('Failed to connect to server, try again')
- })
+ .catch((error) => {
+ console.log(error)
+ commit('endLogin')
+ reject(new Error('Failed to connect to server, try again'))
+ })
})
}
}