aboutsummaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/announcements.js135
-rw-r--r--src/modules/api.js2
-rw-r--r--src/modules/config.js4
-rw-r--r--src/modules/instance.js14
-rw-r--r--src/modules/serverSideStorage.js15
-rw-r--r--src/modules/statuses.js4
-rw-r--r--src/modules/users.js10
7 files changed, 175 insertions, 9 deletions
diff --git a/src/modules/announcements.js b/src/modules/announcements.js
new file mode 100644
index 00000000..e4d2d2b0
--- /dev/null
+++ b/src/modules/announcements.js
@@ -0,0 +1,135 @@
+const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5
+
+export const defaultState = {
+ announcements: [],
+ supportsAnnouncements: true,
+ fetchAnnouncementsTimer: undefined
+}
+
+export const mutations = {
+ setAnnouncements (state, announcements) {
+ state.announcements = announcements
+ },
+ setAnnouncementRead (state, { id, read }) {
+ const index = state.announcements.findIndex(a => a.id === id)
+
+ if (index < 0) {
+ return
+ }
+
+ state.announcements[index].read = read
+ },
+ setFetchAnnouncementsTimer (state, timer) {
+ state.fetchAnnouncementsTimer = timer
+ },
+ setSupportsAnnouncements (state, supportsAnnouncements) {
+ state.supportsAnnouncements = supportsAnnouncements
+ }
+}
+
+export const getters = {
+ unreadAnnouncementCount (state, _getters, rootState) {
+ if (!rootState.users.currentUser) {
+ return 0
+ }
+
+ const unread = state.announcements.filter(announcement => !(announcement.inactive || announcement.read))
+ return unread.length
+ }
+}
+
+const announcements = {
+ state: defaultState,
+ mutations,
+ getters,
+ actions: {
+ fetchAnnouncements (store) {
+ if (!store.state.supportsAnnouncements) {
+ return Promise.resolve()
+ }
+
+ const currentUser = store.rootState.users.currentUser
+ const isAdmin = currentUser && currentUser.role === 'admin'
+
+ const getAnnouncements = async () => {
+ if (!isAdmin) {
+ return store.rootState.api.backendInteractor.fetchAnnouncements()
+ }
+
+ const all = await store.rootState.api.backendInteractor.adminFetchAnnouncements()
+ const visible = await store.rootState.api.backendInteractor.fetchAnnouncements()
+ const visibleObject = visible.reduce((a, c) => {
+ a[c.id] = c
+ return a
+ }, {})
+ const getWithinVisible = announcement => visibleObject[announcement.id]
+
+ all.forEach(announcement => {
+ const visibleAnnouncement = getWithinVisible(announcement)
+ if (!visibleAnnouncement) {
+ announcement.inactive = true
+ } else {
+ announcement.read = visibleAnnouncement.read
+ }
+ })
+
+ return all
+ }
+
+ return getAnnouncements()
+ .then(announcements => {
+ store.commit('setAnnouncements', announcements)
+ })
+ .catch(error => {
+ // If and only if backend does not support announcements, it would return 404.
+ // In this case, silently ignores it.
+ if (error && error.statusCode === 404) {
+ store.commit('setSupportsAnnouncements', false)
+ } else {
+ throw error
+ }
+ })
+ },
+ markAnnouncementAsRead (store, id) {
+ return store.rootState.api.backendInteractor.dismissAnnouncement({ id })
+ .then(() => {
+ store.commit('setAnnouncementRead', { id, read: true })
+ })
+ },
+ startFetchingAnnouncements (store) {
+ if (store.state.fetchAnnouncementsTimer) {
+ return
+ }
+
+ const interval = setInterval(() => store.dispatch('fetchAnnouncements'), FETCH_ANNOUNCEMENT_INTERVAL_MS)
+ store.commit('setFetchAnnouncementsTimer', interval)
+
+ return store.dispatch('fetchAnnouncements')
+ },
+ stopFetchingAnnouncements (store) {
+ const interval = store.state.fetchAnnouncementsTimer
+ store.commit('setFetchAnnouncementsTimer', undefined)
+ clearInterval(interval)
+ },
+ postAnnouncement (store, { content, startsAt, endsAt, allDay }) {
+ return store.rootState.api.backendInteractor.postAnnouncement({ content, startsAt, endsAt, allDay })
+ .then(() => {
+ return store.dispatch('fetchAnnouncements')
+ })
+ },
+ editAnnouncement (store, { id, content, startsAt, endsAt, allDay }) {
+ return store.rootState.api.backendInteractor.editAnnouncement({ id, content, startsAt, endsAt, allDay })
+ .then(() => {
+ return store.dispatch('fetchAnnouncements')
+ })
+ },
+ deleteAnnouncement (store, id) {
+ return store.rootState.api.backendInteractor.deleteAnnouncement({ id })
+ .then(() => {
+ return store.dispatch('fetchAnnouncements')
+ })
+ }
+ }
+}
+
+export default announcements
diff --git a/src/modules/api.js b/src/modules/api.js
index 0acc03f1..fee584e8 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -216,7 +216,7 @@ const api = {
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: timeline, fetcher })
},
- fetchTimeline (store, timeline, { ...rest }) {
+ fetchTimeline (store, { timeline, ...rest }) {
store.state.backendInteractor.fetchTimeline({
store,
timeline,
diff --git a/src/modules/config.js b/src/modules/config.js
index c966602e..3cd6888f 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -83,8 +83,8 @@ export const defaultState = {
useContainFit: true,
disableStickyHeaders: false,
showScrollbars: false,
- userPopoverAvatarAction: 'close',
- userPopoverOverlay: true,
+ userPopoverAvatarAction: 'open',
+ userPopoverOverlay: false,
sidebarColumnWidth: '25rem',
contentColumnWidth: '45rem',
notifsColumnWidth: '25rem',
diff --git a/src/modules/instance.js b/src/modules/instance.js
index b1bc9779..3b15e62e 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -36,6 +36,8 @@ const REGIONAL_INDICATORS = (() => {
return res
})()
+const REMOTE_INTERACTION_URL = '/main/ostatus'
+
const defaultState = {
// Stuff from apiConfig
name: 'Pleroma FE',
@@ -214,6 +216,18 @@ const instance = {
},
instanceDomain (state) {
return new URL(state.server).hostname
+ },
+ remoteInteractionLink (state) {
+ const server = state.server.endsWith('/') ? state.server.slice(0, -1) : state.server
+ const link = server + REMOTE_INTERACTION_URL
+
+ return ({ statusId, nickname }) => {
+ if (statusId) {
+ return `${link}?status_id=${statusId}`
+ } else {
+ return `${link}?nickname=${nickname}`
+ }
+ }
}
},
actions: {
diff --git a/src/modules/serverSideStorage.js b/src/modules/serverSideStorage.js
index 56164be7..c933ce8d 100644
--- a/src/modules/serverSideStorage.js
+++ b/src/modules/serverSideStorage.js
@@ -1,5 +1,5 @@
import { toRaw } from 'vue'
-import { isEqual, cloneDeep, set, get, clamp, flatten, groupBy, findLastIndex, takeRight } from 'lodash'
+import { isEqual, cloneDeep, set, get, clamp, flatten, groupBy, findLastIndex, takeRight, uniqWith } from 'lodash'
import { CURRENT_UPDATE_COUNTER } from 'src/components/update_notification/update_notification.js'
export const VERSION = 1
@@ -149,12 +149,21 @@ const _mergeJournal = (...journals) => {
if (path.startsWith('collections')) {
const lastRemoveIndex = findLastIndex(journal, ({ operation }) => operation === 'removeFromCollection')
// everything before last remove is unimportant
+ let remainder
if (lastRemoveIndex > 0) {
- return journal.slice(lastRemoveIndex)
+ remainder = journal.slice(lastRemoveIndex)
} else {
// everything else doesn't need trimming
- return journal
+ remainder = journal
}
+ return uniqWith(remainder, (a, b) => {
+ if (a.path !== b.path) { return false }
+ if (a.operation !== b.operation) { return false }
+ if (a.operation === 'addToCollection') {
+ return a.args[0] === b.args[0]
+ }
+ return false
+ })
} else if (path.startsWith('simple')) {
// Only the last record is important
return takeRight(journal)
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 803d7019..5a5c7b1b 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -761,8 +761,8 @@ const statuses = {
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 })
+ search (store, { q, resolve, limit, offset, following, type }) {
+ return store.rootState.api.backendInteractor.search2({ q, resolve, limit, offset, following, type })
.then((data) => {
store.commit('addNewUsers', data.accounts)
store.commit('addNewStatuses', { statuses: data.statuses })
diff --git a/src/modules/users.js b/src/modules/users.js
index eef87c2c..053e44b6 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -56,6 +56,11 @@ const removeUserFromFollowers = (store, id) => {
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
}
+const editUserNote = (store, { id, comment }) => {
+ return store.rootState.api.backendInteractor.editUserNote({ id, comment })
+ .then((relationship) => store.commit('updateUserRelationship', [relationship]))
+}
+
const muteUser = (store, id) => {
const predictedRelationship = store.state.relationships[id] || { id }
predictedRelationship.muting = true
@@ -335,6 +340,9 @@ const users = {
unblockUsers (store, ids = []) {
return Promise.all(ids.map(id => unblockUser(store, id)))
},
+ editUserNote (store, args) {
+ return editUserNote(store, args)
+ },
fetchMutes (store) {
return store.rootState.api.backendInteractor.fetchMutes()
.then((mutes) => {
@@ -588,7 +596,7 @@ const users = {
}
if (store.getters.mergedConfig.useStreamingApi) {
- store.dispatch('fetchTimeline', 'friends', { since: null })
+ store.dispatch('fetchTimeline', { timeline: 'friends', since: null })
store.dispatch('fetchNotifications', { since: null })
store.dispatch('enableMastoSockets', true).catch((error) => {
console.error('Failed initializing MastoAPI Streaming socket', error)