aboutsummaryrefslogtreecommitdiff
path: root/src/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/services')
-rw-r--r--src/services/api/api.service.js63
-rw-r--r--src/services/backend_interactor_service/backend_interactor_service.js25
-rw-r--r--src/services/notifications_fetcher/notifications_fetcher.service.js46
-rw-r--r--src/services/status_poster/status_poster.service.js4
-rw-r--r--src/services/timeline_fetcher/timeline_fetcher.service.js4
-rw-r--r--src/services/user_highlighter/user_highlighter.js48
6 files changed, 181 insertions, 9 deletions
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 0d91851b..87315657 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -8,6 +8,7 @@ const TAG_TIMELINE_URL = '/api/statusnet/tags/timeline'
const FAVORITE_URL = '/api/favorites/create'
const UNFAVORITE_URL = '/api/favorites/destroy'
const RETWEET_URL = '/api/statuses/retweet'
+const UNRETWEET_URL = '/api/statuses/unretweet'
const STATUS_UPDATE_URL = '/api/statuses/update.json'
const STATUS_DELETE_URL = '/api/statuses/destroy'
const STATUS_URL = '/api/statuses/show'
@@ -26,12 +27,17 @@ const BANNER_UPDATE_URL = '/api/account/update_profile_banner.json'
const PROFILE_UPDATE_URL = '/api/account/update_profile.json'
const EXTERNAL_PROFILE_URL = '/api/externalprofile/show.json'
const QVITTER_USER_TIMELINE_URL = '/api/qvitter/statuses/user_timeline.json'
+const QVITTER_USER_NOTIFICATIONS_URL = '/api/qvitter/statuses/notifications.json'
const BLOCKING_URL = '/api/blocks/create.json'
const UNBLOCKING_URL = '/api/blocks/destroy.json'
const USER_URL = '/api/users/show.json'
const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import'
const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account'
const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
+const FOLLOW_REQUESTS_URL = '/api/pleroma/friend_requests'
+const APPROVE_USER_URL = '/api/pleroma/friendships/approve'
+const DENY_USER_URL = '/api/pleroma/friendships/deny'
+const SUGGESTIONS_URL = '/api/v1/suggestions'
import { each, map } from 'lodash'
import 'whatwg-fetch'
@@ -127,11 +133,13 @@ const updateBanner = ({credentials, params}) => {
const updateProfile = ({credentials, params}) => {
let url = PROFILE_UPDATE_URL
+ console.log(params)
+
const form = new FormData()
each(params, (value, key) => {
- if (key === 'description' || /* Always include description, because it might be empty */
- value) {
+ /* Always include description and locked, because it might be empty or false */
+ if (key === 'description' || key === 'locked' || value) {
form.append(key, value)
}
})
@@ -153,6 +161,7 @@ const updateProfile = ({credentials, params}) => {
// bio
// homepage
// location
+// token
const register = (params) => {
const form = new FormData()
@@ -216,6 +225,22 @@ const unblockUser = ({id, credentials}) => {
}).then((data) => data.json())
}
+const approveUser = ({id, credentials}) => {
+ let url = `${APPROVE_USER_URL}?user_id=${id}`
+ return fetch(url, {
+ headers: authHeaders(credentials),
+ method: 'POST'
+ }).then((data) => data.json())
+}
+
+const denyUser = ({id, credentials}) => {
+ let url = `${DENY_USER_URL}?user_id=${id}`
+ return fetch(url, {
+ headers: authHeaders(credentials),
+ method: 'POST'
+ }).then((data) => data.json())
+}
+
const fetchUser = ({id, credentials}) => {
let url = `${USER_URL}?user_id=${id}`
return fetch(url, { headers: authHeaders(credentials) })
@@ -240,6 +265,12 @@ const fetchAllFollowing = ({username, credentials}) => {
.then((data) => data.json())
}
+const fetchFollowRequests = ({credentials}) => {
+ const url = FOLLOW_REQUESTS_URL
+ return fetch(url, { headers: authHeaders(credentials) })
+ .then((data) => data.json())
+}
+
const fetchConversation = ({id, credentials}) => {
let url = `${CONVERSATION_URL}/${id}.json?count=100`
return fetch(url, { headers: authHeaders(credentials) })
@@ -273,8 +304,12 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use
public: PUBLIC_TIMELINE_URL,
friends: FRIENDS_TIMELINE_URL,
mentions: MENTIONS_URL,
+ notifications: QVITTER_USER_NOTIFICATIONS_URL,
'publicAndExternal': PUBLIC_AND_EXTERNAL_TIMELINE_URL,
user: QVITTER_USER_TIMELINE_URL,
+ // separate timeline for own posts, so it won't break due to user timeline bugs
+ // really needed only for broken favorites
+ own: QVITTER_USER_TIMELINE_URL,
tag: TAG_TIMELINE_URL
}
@@ -331,7 +366,14 @@ const retweet = ({ id, credentials }) => {
})
}
-const postStatus = ({credentials, status, spoilerText, visibility, mediaIds, inReplyToStatusId}) => {
+const unretweet = ({ id, credentials }) => {
+ return fetch(`${UNRETWEET_URL}/${id}.json`, {
+ headers: authHeaders(credentials),
+ method: 'POST'
+ })
+}
+
+const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType}) => {
const idsText = mediaIds.join(',')
const form = new FormData()
@@ -339,6 +381,8 @@ const postStatus = ({credentials, status, spoilerText, visibility, mediaIds, inR
form.append('source', 'Pleroma FE')
if (spoilerText) form.append('spoiler_text', spoilerText)
if (visibility) form.append('visibility', visibility)
+ if (sensitive) form.append('sensitive', sensitive)
+ if (contentType) form.append('content_type', contentType)
form.append('media_ids', idsText)
if (inReplyToStatusId) {
form.append('in_reply_to_status_id', inReplyToStatusId)
@@ -413,6 +457,12 @@ const fetchMutes = ({credentials}) => {
}).then((data) => data.json())
}
+const suggestions = ({credentials}) => {
+ return fetch(SUGGESTIONS_URL, {
+ headers: authHeaders(credentials)
+ }).then((data) => data.json())
+}
+
const apiService = {
verifyCredentials,
fetchTimeline,
@@ -428,6 +478,7 @@ const apiService = {
favorite,
unfavorite,
retweet,
+ unretweet,
postStatus,
deleteStatus,
uploadMedia,
@@ -442,7 +493,11 @@ const apiService = {
externalProfile,
followImport,
deleteAccount,
- changePassword
+ changePassword,
+ fetchFollowRequests,
+ approveUser,
+ denyUser,
+ suggestions
}
export default apiService
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 14173558..c84373ac 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -42,15 +42,34 @@ const backendInteractorService = (credentials) => {
return apiService.unblockUser({credentials, id})
}
+ const approveUser = (id) => {
+ return apiService.approveUser({credentials, id})
+ }
+
+ const denyUser = (id) => {
+ return apiService.denyUser({credentials, id})
+ }
+
const startFetching = ({timeline, store, userId = false}) => {
return timelineFetcherService.startFetching({timeline, store, credentials, userId})
}
+ const fetchOldPost = ({store, postId}) => {
+ return timelineFetcherService.fetchAndUpdate({
+ store,
+ credentials,
+ timeline: 'own',
+ older: true,
+ until: postId + 1
+ })
+ }
+
const setUserMute = ({id, muted = true}) => {
return apiService.setUserMute({id, muted, credentials})
}
const fetchMutes = () => apiService.fetchMutes({credentials})
+ const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials})
const register = (params) => apiService.register(params)
const updateAvatar = ({params}) => apiService.updateAvatar({credentials, params})
@@ -77,6 +96,7 @@ const backendInteractorService = (credentials) => {
fetchAllFollowing,
verifyCredentials: apiService.verifyCredentials,
startFetching,
+ fetchOldPost,
setUserMute,
fetchMutes,
register,
@@ -87,7 +107,10 @@ const backendInteractorService = (credentials) => {
externalProfile,
followImport,
deleteAccount,
- changePassword
+ changePassword,
+ fetchFollowRequests,
+ approveUser,
+ denyUser
}
return backendInteractorServiceInstance
diff --git a/src/services/notifications_fetcher/notifications_fetcher.service.js b/src/services/notifications_fetcher/notifications_fetcher.service.js
new file mode 100644
index 00000000..1480cded
--- /dev/null
+++ b/src/services/notifications_fetcher/notifications_fetcher.service.js
@@ -0,0 +1,46 @@
+import apiService from '../api/api.service.js'
+
+const update = ({store, notifications, older}) => {
+ store.dispatch('setNotificationsError', { value: false })
+
+ store.dispatch('addNewNotifications', { notifications, older })
+}
+
+const fetchAndUpdate = ({store, credentials, older = false}) => {
+ const args = { credentials }
+ const rootState = store.rootState || store.state
+ const timelineData = rootState.statuses.notifications
+
+ if (older) {
+ if (timelineData.minId !== Number.POSITIVE_INFINITY) {
+ args['until'] = timelineData.minId
+ }
+ } else {
+ args['since'] = timelineData.maxId
+ }
+
+ args['timeline'] = 'notifications'
+
+ return apiService.fetchTimeline(args)
+ .then((notifications) => {
+ update({store, notifications, older})
+ }, () => store.dispatch('setNotificationsError', { value: true }))
+ .catch(() => store.dispatch('setNotificationsError', { value: true }))
+}
+
+const startFetching = ({credentials, store}) => {
+ fetchAndUpdate({ credentials, store })
+ const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store })
+ // Initially there's set flag to silence all desktop notifications so
+ // that there won't spam of them when user just opened up the FE we
+ // reset that flag after a while to show new notifications once again.
+ setTimeout(() => store.dispatch('setNotificationsSilence', false), 10000)
+ return setInterval(boundFetchAndUpdate, 10000)
+}
+
+const notificationsFetcher = {
+ fetchAndUpdate,
+ startFetching
+}
+
+export default notificationsFetcher
diff --git a/src/services/status_poster/status_poster.service.js b/src/services/status_poster/status_poster.service.js
index 3381e9e2..7f8b0fc0 100644
--- a/src/services/status_poster/status_poster.service.js
+++ b/src/services/status_poster/status_poster.service.js
@@ -1,10 +1,10 @@
import { map } from 'lodash'
import apiService from '../api/api.service.js'
-const postStatus = ({ store, status, spoilerText, visibility, media = [], inReplyToStatusId = undefined }) => {
+const postStatus = ({ store, status, spoilerText, visibility, sensitive, media = [], inReplyToStatusId = undefined, contentType = 'text/plain' }) => {
const mediaIds = map(media, 'id')
- return apiService.postStatus({credentials: store.state.users.currentUser.credentials, status, spoilerText, visibility, mediaIds, inReplyToStatusId})
+ return apiService.postStatus({credentials: store.state.users.currentUser.credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType})
.then((data) => data.json())
.then((data) => {
if (!data.error) {
diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js
index bb5fdc2e..0e3e32d2 100644
--- a/src/services/timeline_fetcher/timeline_fetcher.service.js
+++ b/src/services/timeline_fetcher/timeline_fetcher.service.js
@@ -14,13 +14,13 @@ const update = ({store, statuses, timeline, showImmediately}) => {
})
}
-const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false, showImmediately = false, userId = false, tag = false}) => {
+const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false, showImmediately = false, userId = false, tag = false, until}) => {
const args = { timeline, credentials }
const rootState = store.rootState || store.state
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
if (older) {
- args['until'] = timelineData.minVisibleId
+ args['until'] = until || timelineData.minVisibleId
} else {
args['since'] = timelineData.maxId
}
diff --git a/src/services/user_highlighter/user_highlighter.js b/src/services/user_highlighter/user_highlighter.js
new file mode 100644
index 00000000..ebb25eca
--- /dev/null
+++ b/src/services/user_highlighter/user_highlighter.js
@@ -0,0 +1,48 @@
+import { hex2rgb } from '../color_convert/color_convert.js'
+const highlightStyle = (prefs) => {
+ if (prefs === undefined) return
+ const {color, type} = prefs
+ if (typeof color !== 'string') return
+ const rgb = hex2rgb(color)
+ if (rgb == null) return
+ const solidColor = `rgb(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)})`
+ const tintColor = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .1)`
+ const tintColor2 = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .2)`
+ if (type === 'striped') {
+ return {
+ backgroundImage: [
+ 'repeating-linear-gradient(-45deg,',
+ `${tintColor} ,`,
+ `${tintColor} 20px,`,
+ `${tintColor2} 20px,`,
+ `${tintColor2} 40px`
+ ].join(' '),
+ backgroundPosition: '0 0'
+ }
+ } else if (type === 'solid') {
+ return {
+ backgroundColor: tintColor2
+ }
+ } else if (type === 'side') {
+ return {
+ backgroundImage: [
+ 'linear-gradient(to right,',
+ `${solidColor} ,`,
+ `${solidColor} 2px,`,
+ `transparent 6px`
+ ].join(' '),
+ backgroundPosition: '0 0'
+ }
+ }
+}
+
+const highlightClass = (user) => {
+ return 'USER____' + user.screen_name
+ .replace(/\./g, '_')
+ .replace(/@/g, '_AT_')
+}
+
+export {
+ highlightClass,
+ highlightStyle
+}