diff options
Diffstat (limited to 'src/modules')
| -rw-r--r-- | src/modules/chat.js | 10 | ||||
| -rw-r--r-- | src/modules/config.js | 1 | ||||
| -rw-r--r-- | src/modules/instance.js | 8 | ||||
| -rw-r--r-- | src/modules/statuses.js | 83 | ||||
| -rw-r--r-- | src/modules/users.js | 117 |
5 files changed, 152 insertions, 67 deletions
diff --git a/src/modules/chat.js b/src/modules/chat.js index 383ac75c..2804e577 100644 --- a/src/modules/chat.js +++ b/src/modules/chat.js @@ -1,12 +1,16 @@ const chat = { state: { messages: [], - channel: {state: ''} + channel: {state: ''}, + socket: null }, 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) @@ -16,8 +20,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) }) diff --git a/src/modules/config.js b/src/modules/config.js index 6d8aad35..1666a2c5 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -5,6 +5,7 @@ const browserLocale = (window.navigator.language || 'en').split('-')[0] const defaultState = { colors: {}, + hideMutedPosts: undefined, // instance default collapseMessageWithSubject: undefined, // instance default hideAttachments: false, hideAttachmentsInConv: false, diff --git a/src/modules/instance.js b/src/modules/instance.js index 7b67890f..3a559ba0 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -17,6 +17,7 @@ const defaultState = { showInstanceSpecificPanel: false, formattingOptionsEnabled: false, alwaysShowSubjectInput: true, + hideMutedPosts: false, collapseMessageWithSubject: false, hidePostStats: false, hideUserStats: false, @@ -37,6 +38,7 @@ const defaultState = { emoji: [], customEmoji: [], restrictedNicknames: [], + postFormats: [], // Feature-set, apparently, not everything here is reported... mediaProxyAvailable: false, @@ -47,7 +49,11 @@ const defaultState = { // Html stuff instanceSpecificPanelContent: '', - tos: '' + tos: '', + + // Version Information + backendVersion: '', + frontendVersion: '' } const instance = { diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 826b544c..742eecba 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -1,4 +1,5 @@ -import { remove, slice, each, find, maxBy, minBy, merge, last, isArray } from 'lodash' +import { remove, slice, each, find, maxBy, minBy, merge, first, last, isArray, omitBy } from 'lodash' +import { set } from 'vue' import apiService from '../services/api/api.service.js' // import parse from '../services/status_parser/status_parser.js' @@ -10,6 +11,7 @@ const emptyTl = (userId = 0) => ({ visibleStatusesObject: {}, newStatusCount: 0, maxId: 0, + minId: 0, minVisibleId: 0, loading: false, followers: [], @@ -18,7 +20,7 @@ const emptyTl = (userId = 0) => ({ flushMarker: 0 }) -export const defaultState = { +export const defaultState = () => ({ allStatuses: [], allStatusesObject: {}, maxId: 0, @@ -29,7 +31,8 @@ export const defaultState = { data: [], idStore: {}, loading: false, - error: false + error: false, + fetcherId: null }, favorites: new Set(), error: false, @@ -44,7 +47,7 @@ export const defaultState = { tag: emptyTl(), dms: emptyTl() } -} +}) export const prepareStatus = (status) => { // Set deleted flag @@ -70,7 +73,9 @@ const mergeOrAdd = (arr, obj, item) => { if (oldItem) { // We already have this, so only merge the new info. - merge(oldItem, item) + // We ignore null values to avoid overwriting existing properties with missing data + // we also skip 'user' because that is handled by users module + merge(oldItem, omitBy(item, (v, k) => v === null || k === 'user')) // Reactivity fix. oldItem.attachments.splice(oldItem.attachments.length) return {item: oldItem, new: false} @@ -78,7 +83,7 @@ const mergeOrAdd = (arr, obj, item) => { // This is a new item, prepare it prepareStatus(item) arr.push(item) - obj[item.id] = item + set(obj, item.id, item) return {item, new: true} } } @@ -117,11 +122,16 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us const timelineObject = state.timelines[timeline] const maxNew = statuses.length > 0 ? maxBy(statuses, 'id').id : 0 - const older = timeline && maxNew < timelineObject.maxId + const minNew = statuses.length > 0 ? minBy(statuses, 'id').id : 0 + const newer = timeline && maxNew > timelineObject.maxId && statuses.length > 0 + const older = timeline && (minNew < timelineObject.minId || timelineObject.minId === 0) && statuses.length > 0 - if (timeline && !noIdUpdate && statuses.length > 0 && !older) { + if (!noIdUpdate && newer) { timelineObject.maxId = maxNew } + if (!noIdUpdate && older) { + timelineObject.minId = minNew + } // This makes sure that user timeline won't get data meant for other // user. I.e. opening different user profiles makes request which could @@ -255,12 +265,9 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us processor(status) }) - // Keep the visible statuses sorted + // Keep the visible statuses sorted if (timeline) { sortTimeline(timelineObject) - if ((older || timelineObject.minVisibleId <= 0) && statuses.length > 0) { - timelineObject.minVisibleId = minBy(statuses, 'id').id - } } } @@ -309,18 +316,39 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot }) } +const removeStatus = (state, { timeline, userId }) => { + const timelineObject = state.timelines[timeline] + if (userId) { + remove(timelineObject.statuses, { user: { id: userId } }) + remove(timelineObject.visibleStatuses, { user: { id: userId } }) + timelineObject.minVisibleId = timelineObject.visibleStatuses.length > 0 ? last(timelineObject.visibleStatuses).id : 0 + timelineObject.maxId = timelineObject.statuses.length > 0 ? first(timelineObject.statuses).id : 0 + } +} + export const mutations = { addNewStatuses, addNewNotifications, + removeStatus, showNewStatuses (state, { timeline }) { const oldTimeline = (state.timelines[timeline]) oldTimeline.newStatusCount = 0 oldTimeline.visibleStatuses = slice(oldTimeline.statuses, 0, 50) oldTimeline.minVisibleId = last(oldTimeline.visibleStatuses).id + oldTimeline.minId = oldTimeline.minVisibleId oldTimeline.visibleStatusesObject = {} each(oldTimeline.visibleStatuses, (status) => { oldTimeline.visibleStatusesObject[status.id] = status }) }, + setNotificationFetcher (state, { fetcherId }) { + state.notifications.fetcherId = fetcherId + }, + resetStatuses (state) { + const emptyState = defaultState() + Object.entries(emptyState).forEach(([key, value]) => { + state[key] = value + }) + }, clearTimeline (state, { timeline }) { state.timelines[timeline] = emptyTl(state.timelines[timeline].userId) }, @@ -335,6 +363,15 @@ export const mutations = { }, setRetweeted (state, { status, value }) { const newStatus = state.allStatusesObject[status.id] + + if (newStatus.repeated !== value) { + if (value) { + newStatus.repeat_num++ + } else { + newStatus.repeat_num-- + } + } + newStatus.repeated = value }, setDeleted (state, { status }) { @@ -371,7 +408,7 @@ export const mutations = { } const statuses = { - state: defaultState, + state: defaultState(), actions: { addNewStatuses ({ rootState, commit }, { statuses, showImmediately = false, timeline = false, noIdUpdate = false, userId }) { commit('addNewStatuses', { statuses, showImmediately, timeline, noIdUpdate, user: rootState.users.currentUser, userId }) @@ -391,6 +428,12 @@ const statuses = { setNotificationsSilence ({ rootState, commit }, { value }) { commit('setNotificationsSilence', { value }) }, + stopFetchingNotifications ({ rootState, commit }) { + if (rootState.statuses.notifications.fetcherId) { + window.clearInterval(rootState.statuses.notifications.fetcherId) + } + commit('setNotificationFetcher', { fetcherId: null }) + }, deleteStatus ({ rootState, commit }, status) { commit('setDeleted', { status }) apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials }) @@ -399,13 +442,6 @@ const statuses = { // Optimistic favoriting... commit('setFavorited', { status, value: true }) apiService.favorite({ id: status.id, credentials: rootState.users.currentUser.credentials }) - .then(response => { - if (response.ok) { - return response.json() - } else { - return {} - } - }) .then(status => { commit('setFavoritedConfirm', { status }) }) @@ -414,13 +450,6 @@ const statuses = { // Optimistic favoriting... commit('setFavorited', { status, value: false }) apiService.unfavorite({ id: status.id, credentials: rootState.users.currentUser.credentials }) - .then(response => { - if (response.ok) { - return response.json() - } else { - return {} - } - }) .then(status => { commit('setFavoritedConfirm', { status }) }) diff --git a/src/modules/users.js b/src/modules/users.js index 093af497..1a507d31 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -1,5 +1,5 @@ import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js' -import { compact, map, each, merge, find } from 'lodash' +import { compact, map, each, merge, find, last } from 'lodash' import { set } from 'vue' import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js' import oauthApi from '../services/new_api/oauth' @@ -16,9 +16,9 @@ export const mergeOrAdd = (arr, obj, item) => { } else { // This is a new item, prepare it arr.push(item) - obj[item.id] = item + set(obj, item.id, item) if (item.screen_name && !item.screen_name.includes('@')) { - obj[item.screen_name] = item + set(obj, item.screen_name.toLowerCase(), item) } return { item, new: true } } @@ -52,23 +52,23 @@ export const mutations = { state.loggingIn = false }, // TODO Clean after ourselves? - addFriends (state, { id, friends, page }) { + addFriends (state, { id, friends }) { const user = state.usersObject[id] each(friends, friend => { if (!find(user.friends, { id: friend.id })) { user.friends.push(friend) } }) - user.friendsPage = page + 1 + user.lastFriendId = last(friends).id }, - addFollowers (state, { id, followers, page }) { + addFollowers (state, { id, followers }) { const user = state.usersObject[id] each(followers, follower => { if (!find(user.followers, { id: follower.id })) { user.followers.push(follower) } }) - user.followersPage = page + 1 + user.lastFollowerId = last(followers).id }, // Because frontend doesn't have a reason to keep these stuff in memory // outside of viewing someones user profile. @@ -78,7 +78,7 @@ export const mutations = { return } user.friends = [] - user.friendsPage = 0 + user.lastFriendId = null }, clearFollowers (state, userId) { const user = state.usersObject[userId] @@ -86,15 +86,36 @@ export const mutations = { return } user.followers = [] - user.followersPage = 0 + user.lastFollowerId = null }, addNewUsers (state, users) { each(users, (user) => mergeOrAdd(state.users, state.usersObject, user)) }, - saveBlocks (state, blockIds) { + updateUserRelationship (state, relationships) { + relationships.forEach((relationship) => { + const user = state.usersObject[relationship.id] + if (user) { + user.follows_you = relationship.followed_by + user.following = relationship.following + user.muted = relationship.muting + user.statusnet_blocking = relationship.blocking + } + }) + }, + updateBlocks (state, blockedUsers) { + // Reset statusnet_blocking of all fetched users + each(state.users, (user) => { user.statusnet_blocking = false }) + each(blockedUsers, (user) => mergeOrAdd(state.users, state.usersObject, user)) + }, + saveBlockIds (state, blockIds) { state.currentUser.blockIds = blockIds }, - saveMutes (state, muteIds) { + updateMutes (state, mutedUsers) { + // Reset muted of all fetched users + each(state.users, (user) => { user.muted = false }) + each(mutedUsers, (user) => mergeOrAdd(state.users, state.usersObject, user)) + }, + saveMuteIds (state, muteIds) { state.currentUser.muteIds = muteIds }, setUserForStatus (state, status) { @@ -122,12 +143,14 @@ export const mutations = { } export const getters = { - userById: state => id => - state.users.find(user => user.id === id), - userByName: state => name => - state.users.find(user => user.screen_name && - (user.screen_name.toLowerCase() === name.toLowerCase()) - ) + findUser: state => query => { + const result = state.usersObject[query] + // In case it's a screen_name, we can try searching case-insensitive + if (!result && typeof query === 'string') { + return state.usersObject[query.toLowerCase()] + } + return result + } } export const defaultState = { @@ -147,47 +170,59 @@ const users = { actions: { fetchUser (store, id) { return store.rootState.api.backendInteractor.fetchUser({ id }) - .then((user) => store.commit('addNewUsers', [user])) + .then((user) => { + store.commit('addNewUsers', [user]) + return user + }) + }, + fetchUserRelationship (store, id) { + return store.rootState.api.backendInteractor.fetchUserRelationship({ id }) + .then((relationships) => store.commit('updateUserRelationship', relationships)) }, fetchBlocks (store) { return store.rootState.api.backendInteractor.fetchBlocks() .then((blocks) => { - store.commit('saveBlocks', map(blocks, 'id')) - store.commit('addNewUsers', blocks) + store.commit('saveBlockIds', map(blocks, 'id')) + store.commit('updateBlocks', blocks) return blocks }) }, - blockUser (store, id) { - return store.rootState.api.backendInteractor.blockUser(id) - .then((user) => store.commit('addNewUsers', [user])) + blockUser (store, userId) { + return store.rootState.api.backendInteractor.blockUser(userId) + .then((relationship) => { + store.commit('updateUserRelationship', [relationship]) + store.commit('removeStatus', { timeline: 'friends', userId }) + store.commit('removeStatus', { timeline: 'public', userId }) + store.commit('removeStatus', { timeline: 'publicAndExternal', userId }) + }) }, unblockUser (store, id) { return store.rootState.api.backendInteractor.unblockUser(id) - .then((user) => store.commit('addNewUsers', [user])) + .then((relationship) => store.commit('updateUserRelationship', [relationship])) }, fetchMutes (store) { return store.rootState.api.backendInteractor.fetchMutes() - .then((mutedUsers) => { - each(mutedUsers, (user) => { user.muted = true }) - store.commit('addNewUsers', mutedUsers) - store.commit('saveMutes', map(mutedUsers, 'id')) + .then((mutes) => { + store.commit('updateMutes', mutes) + store.commit('saveMuteIds', map(mutes, 'id')) + return mutes }) }, muteUser (store, id) { - return store.state.api.backendInteractor.setUserMute({ id, muted: true }) - .then((user) => store.commit('addNewUsers', [user])) + return store.rootState.api.backendInteractor.muteUser(id) + .then((relationship) => store.commit('updateUserRelationship', [relationship])) }, unmuteUser (store, id) { - return store.state.api.backendInteractor.setUserMute({ id, muted: false }) - .then((user) => store.commit('addNewUsers', [user])) + return store.rootState.api.backendInteractor.unmuteUser(id) + .then((relationship) => store.commit('updateUserRelationship', [relationship])) }, addFriends ({ rootState, commit }, fetchBy) { return new Promise((resolve, reject) => { const user = rootState.users.usersObject[fetchBy] - const page = user.friendsPage || 1 - rootState.api.backendInteractor.fetchFriends({ id: user.id, page }) + const maxId = user.lastFriendId + rootState.api.backendInteractor.fetchFriends({ id: user.id, maxId }) .then((friends) => { - commit('addFriends', { id: user.id, friends, page }) + commit('addFriends', { id: user.id, friends }) resolve(friends) }).catch(() => { reject() @@ -196,10 +231,10 @@ const users = { }, addFollowers ({ rootState, commit }, fetchBy) { const user = rootState.users.usersObject[fetchBy] - const page = user.followersPage || 1 - return rootState.api.backendInteractor.fetchFollowers({ id: user.id, page }) + const maxId = user.lastFollowerId + return rootState.api.backendInteractor.fetchFollowers({ id: user.id, maxId }) .then((followers) => { - commit('addFollowers', { id: user.id, followers, page }) + commit('addFollowers', { id: user.id, followers }) return followers }) }, @@ -292,9 +327,12 @@ const users = { logout (store) { store.commit('clearCurrentUser') + store.dispatch('disconnectFromChat') store.commit('setToken', false) store.dispatch('stopFetching', 'friends') store.commit('setBackendInteractor', backendInteractorService()) + store.dispatch('stopFetchingNotifications') + store.commit('resetStatuses') }, loginUser (store, accessToken) { return new Promise((resolve, reject) => { @@ -319,6 +357,9 @@ const users = { if (user.token) { store.dispatch('setWsToken', user.token) + + // Initialize the chat socket. + store.dispatch('initializeSocket') } // Start getting fresh posts. |
