diff options
Diffstat (limited to 'src/services')
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 +} |
