aboutsummaryrefslogtreecommitdiff
path: root/src/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/services')
-rw-r--r--src/services/api/api.service.js45
-rw-r--r--src/services/backend_interactor_service/backend_interactor_service.js10
-rw-r--r--src/services/component_utils/component_utils.js10
-rw-r--r--src/services/entity_normalizer/entity_normalizer.service.js3
-rw-r--r--src/services/errors/errors.js14
-rw-r--r--src/services/follow_request_fetcher/follow_request_fetcher.service.js21
-rw-r--r--src/services/notifications_fetcher/notifications_fetcher.service.js12
-rw-r--r--src/services/timeline_fetcher/timeline_fetcher.service.js2
8 files changed, 111 insertions, 6 deletions
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 92daa04e..2de87026 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -18,6 +18,7 @@ const MENTIONS_URL = '/api/statuses/mentions.json'
const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json'
const FOLLOWERS_URL = '/api/statuses/followers.json'
const FRIENDS_URL = '/api/statuses/friends.json'
+const BLOCKS_URL = '/api/statuses/blocks.json'
const FOLLOWING_URL = '/api/friendships/create.json'
const UNFOLLOWING_URL = '/api/friendships/destroy.json'
const QVITTER_USER_PREF_URL = '/api/qvitter/set_profile_pref.json'
@@ -46,6 +47,7 @@ const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
import { each, map } from 'lodash'
import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
import 'whatwg-fetch'
+import { StatusCodeError } from '../errors/errors'
const oldfetch = window.fetch
@@ -243,7 +245,15 @@ const denyUser = ({id, credentials}) => {
const fetchUser = ({id, credentials}) => {
let url = `${USER_URL}?user_id=${id}`
return fetch(url, { headers: authHeaders(credentials) })
- .then((data) => data.json())
+ .then((response) => {
+ return new Promise((resolve, reject) => response.json()
+ .then((json) => {
+ if (!response.ok) {
+ return reject(new StatusCodeError(response.status, json, { url }, response))
+ }
+ return resolve(json)
+ }))
+ })
.then((data) => parseUser(data))
}
@@ -258,7 +268,7 @@ const fetchFriends = ({id, page, credentials}) => {
}
const exportFriends = ({id, credentials}) => {
- let url = `${FRIENDS_URL}?user_id=${id}&export=true`
+ let url = `${FRIENDS_URL}?user_id=${id}&all=true`
return fetch(url, { headers: authHeaders(credentials) })
.then((data) => data.json())
.then((data) => data.map(parseUser))
@@ -519,6 +529,34 @@ const fetchMutes = ({credentials}) => {
}).then((data) => data.json())
}
+const fetchBlocks = ({page, credentials}) => {
+ return fetch(BLOCKS_URL, {
+ headers: authHeaders(credentials)
+ }).then((data) => {
+ if (data.ok) {
+ return data.json()
+ }
+ throw new Error('Error fetching blocks', data)
+ })
+}
+
+const fetchOAuthTokens = ({credentials}) => {
+ const url = '/api/oauth_tokens.json'
+
+ return fetch(url, {
+ headers: authHeaders(credentials)
+ }).then((data) => data.json())
+}
+
+const revokeOAuthToken = ({id, credentials}) => {
+ const url = `/api/oauth_tokens/${id}`
+
+ return fetch(url, {
+ headers: authHeaders(credentials),
+ method: 'DELETE'
+ })
+}
+
const suggestions = ({credentials}) => {
return fetch(SUGGESTIONS_URL, {
headers: authHeaders(credentials)
@@ -560,6 +598,9 @@ const apiService = {
fetchAllFollowing,
setUserMute,
fetchMutes,
+ fetchBlocks,
+ fetchOAuthTokens,
+ revokeOAuthToken,
register,
getCaptcha,
updateAvatar,
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 80c5cc5e..7e972d7b 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -54,8 +54,8 @@ const backendInteractorService = (credentials) => {
return apiService.denyUser({credentials, id})
}
- const startFetching = ({timeline, store, userId = false}) => {
- return timelineFetcherService.startFetching({timeline, store, credentials, userId})
+ const startFetching = ({timeline, store, userId = false, tag}) => {
+ return timelineFetcherService.startFetching({timeline, store, credentials, userId, tag})
}
const setUserMute = ({id, muted = true}) => {
@@ -63,7 +63,10 @@ const backendInteractorService = (credentials) => {
}
const fetchMutes = () => apiService.fetchMutes({credentials})
+ const fetchBlocks = (params) => apiService.fetchBlocks({credentials, ...params})
const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials})
+ const fetchOAuthTokens = () => apiService.fetchOAuthTokens({credentials})
+ const revokeOAuthToken = (id) => apiService.revokeOAuthToken({id, credentials})
const getCaptcha = () => apiService.getCaptcha()
const register = (params) => apiService.register(params)
@@ -94,6 +97,9 @@ const backendInteractorService = (credentials) => {
startFetching,
setUserMute,
fetchMutes,
+ fetchBlocks,
+ fetchOAuthTokens,
+ revokeOAuthToken,
register,
getCaptcha,
updateAvatar,
diff --git a/src/services/component_utils/component_utils.js b/src/services/component_utils/component_utils.js
new file mode 100644
index 00000000..77ea14a1
--- /dev/null
+++ b/src/services/component_utils/component_utils.js
@@ -0,0 +1,10 @@
+import isFunction from 'lodash/isFunction'
+
+const getComponentOptions = (Component) => (isFunction(Component)) ? Component.options : Component
+
+const getComponentProps = (Component) => getComponentOptions(Component).props
+
+export {
+ getComponentOptions,
+ getComponentProps
+}
diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js
index 828c48f9..d20ce77f 100644
--- a/src/services/entity_normalizer/entity_normalizer.service.js
+++ b/src/services/entity_normalizer/entity_normalizer.service.js
@@ -117,6 +117,9 @@ export const parseUser = (data) => {
output.statuses_count = data.statuses_count
output.friends = []
output.followers = []
+ if (data.pleroma) {
+ output.follow_request_count = data.pleroma.follow_request_count
+ }
return output
}
diff --git a/src/services/errors/errors.js b/src/services/errors/errors.js
new file mode 100644
index 00000000..548f3c68
--- /dev/null
+++ b/src/services/errors/errors.js
@@ -0,0 +1,14 @@
+export function StatusCodeError (statusCode, body, options, response) {
+ this.name = 'StatusCodeError'
+ this.statusCode = statusCode
+ this.message = statusCode + ' - ' + (JSON && JSON.stringify ? JSON.stringify(body) : body)
+ this.error = body // legacy attribute
+ this.options = options
+ this.response = response
+
+ if (Error.captureStackTrace) { // required for non-V8 environments
+ Error.captureStackTrace(this)
+ }
+}
+StatusCodeError.prototype = Object.create(Error.prototype)
+StatusCodeError.prototype.constructor = StatusCodeError
diff --git a/src/services/follow_request_fetcher/follow_request_fetcher.service.js b/src/services/follow_request_fetcher/follow_request_fetcher.service.js
new file mode 100644
index 00000000..125ff3e1
--- /dev/null
+++ b/src/services/follow_request_fetcher/follow_request_fetcher.service.js
@@ -0,0 +1,21 @@
+import apiService from '../api/api.service.js'
+
+const fetchAndUpdate = ({ store, credentials }) => {
+ return apiService.fetchFollowRequests({ credentials })
+ .then((requests) => {
+ store.commit('setFollowRequests', requests)
+ }, () => {})
+ .catch(() => {})
+}
+
+const startFetching = ({credentials, store}) => {
+ fetchAndUpdate({ credentials, store })
+ const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store })
+ return setInterval(boundFetchAndUpdate, 10000)
+}
+
+const followRequestFetcher = {
+ startFetching
+}
+
+export default followRequestFetcher
diff --git a/src/services/notifications_fetcher/notifications_fetcher.service.js b/src/services/notifications_fetcher/notifications_fetcher.service.js
index b69ec643..3ecdae6a 100644
--- a/src/services/notifications_fetcher/notifications_fetcher.service.js
+++ b/src/services/notifications_fetcher/notifications_fetcher.service.js
@@ -16,7 +16,17 @@ const fetchAndUpdate = ({store, credentials, older = false}) => {
args['until'] = timelineData.minId
}
} else {
- args['since'] = timelineData.maxId
+ // load unread notifications repeadedly to provide consistency between browser tabs
+ const notifications = timelineData.data
+ const unread = notifications.filter(n => !n.seen).map(n => n.id)
+ if (!unread.length) {
+ args['since'] = timelineData.maxId
+ } else {
+ args['since'] = Math.min(...unread) - 1
+ if (timelineData.maxId !== Math.max(...unread)) {
+ args['until'] = Math.max(...unread, args['since'] + 20)
+ }
+ }
}
args['timeline'] = 'notifications'
diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js
index 64f8f468..6f99616f 100644
--- a/src/services/timeline_fetcher/timeline_fetcher.service.js
+++ b/src/services/timeline_fetcher/timeline_fetcher.service.js
@@ -21,7 +21,7 @@ const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
if (older) {
- args['until'] = until || timelineData.minVisibleId
+ args['until'] = until || timelineData.minId
} else {
args['since'] = timelineData.maxId
}