From 3255950b0e9a16f2a477d606b91d90bed8a6cef7 Mon Sep 17 00:00:00 2001
From: taehoon
Date: Sun, 24 Feb 2019 03:02:04 -0500
Subject: Add mute/unmute featrue and mutes management tab
---
src/services/api/api.service.js | 44 +++++++++++++++++++++++++++++++++++++----
1 file changed, 40 insertions(+), 4 deletions(-)
(limited to 'src/services/api/api.service.js')
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 176f1c18..92abf94b 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1,3 +1,5 @@
+import { generateUrl } from '../../utils/url'
+
/* eslint-env browser */
const LOGIN_URL = '/api/account/verify_credentials.json'
const FRIENDS_TIMELINE_URL = '/api/statuses/friends_timeline.json'
@@ -19,6 +21,9 @@ 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 MUTES_URL = '/api/v1/mutes.json'
+const MUTING_URL = '/api/v1/accounts/:id/mute'
+const UNMUTING_URL = '/api/v1/accounts/:id/unmute'
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'
@@ -538,14 +543,43 @@ const changePassword = ({credentials, password, newPassword, newPasswordConfirma
}
const fetchMutes = ({credentials}) => {
- const url = '/api/qvitter/mutes.json'
+ return fetch(MUTES_URL, {
+ headers: authHeaders(credentials)
+ }).then((data) => {
+ if (data.ok) {
+ return data.json()
+ }
+ throw new Error('Error fetching mutes', data)
+ })
+}
+const muteUser = ({id, credentials}) => {
+ const url = generateUrl(MUTING_URL, { id })
return fetch(url, {
- headers: authHeaders(credentials)
- }).then((data) => data.json())
+ headers: authHeaders(credentials),
+ method: 'POST'
+ }).then((data) => {
+ if (data.ok) {
+ return data.json()
+ }
+ throw new Error('Error muting', data)
+ })
+}
+
+const unmuteUser = ({id, credentials}) => {
+ const url = generateUrl(UNMUTING_URL, { id })
+ return fetch(url, {
+ headers: authHeaders(credentials),
+ method: 'POST'
+ }).then((data) => {
+ if (data.ok) {
+ return data.json()
+ }
+ throw new Error('Error unmuting', data)
+ })
}
-const fetchBlocks = ({page, credentials}) => {
+const fetchBlocks = ({credentials}) => {
return fetch(BLOCKS_URL, {
headers: authHeaders(credentials)
}).then((data) => {
@@ -620,6 +654,8 @@ const apiService = {
fetchAllFollowing,
setUserMute,
fetchMutes,
+ muteUser,
+ unmuteUser,
fetchBlocks,
fetchOAuthTokens,
revokeOAuthToken,
--
cgit v1.2.3-70-g09d2
From 302310a653083bc82226cf0743d52fc02c277a8a Mon Sep 17 00:00:00 2001
From: taehoon
Date: Fri, 1 Mar 2019 11:37:34 -0500
Subject: Remove old muting logic
---
src/components/mute_card/mute_card.js | 2 +-
src/components/user_card/user_card.js | 10 ++--------
src/modules/users.js | 12 +++++++++---
src/services/api/api.service.js | 18 ------------------
.../backend_interactor_service.js | 5 -----
5 files changed, 12 insertions(+), 35 deletions(-)
(limited to 'src/services/api/api.service.js')
diff --git a/src/components/mute_card/mute_card.js b/src/components/mute_card/mute_card.js
index 5ef17b60..65c9cfb5 100644
--- a/src/components/mute_card/mute_card.js
+++ b/src/components/mute_card/mute_card.js
@@ -12,7 +12,7 @@ const MuteCard = {
return this.$store.getters.findUser(this.userId)
},
muted () {
- return this.user.mastodonMuted
+ return this.user.muted
}
},
components: {
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index 61b784fe..197c61d5 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -126,18 +126,12 @@ export default {
unblockUser () {
this.$store.dispatch('unblockUser', this.user.id)
},
- muteUser () { // Mastodon Mute
+ muteUser () {
this.$store.dispatch('muteUser', this.user.id)
},
- unmuteUser () { // Mastodon Unmute
+ unmuteUser () {
this.$store.dispatch('unmuteUser', this.user.id)
},
- toggleMute () {
- // TODO: Pleroma mute/unmute, Need to migrate to the Mastodon API
- const store = this.$store
- store.commit('setMuted', {user: this.user, muted: !this.user.muted})
- store.state.api.backendInteractor.setUserMute(this.user)
- },
setProfileView (v) {
if (this.switcher) {
const store = this.$store
diff --git a/src/modules/users.js b/src/modules/users.js
index af40be3d..5e53aafb 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -110,11 +110,11 @@ export const mutations = {
},
muteUser (state, id) {
const user = state.usersObject[id]
- set(user, 'mastodonMuted', true)
+ set(user, 'muted', true)
},
unmuteUser (state, id) {
const user = state.usersObject[id]
- set(user, 'mastodonMuted', false)
+ set(user, 'muted', false)
},
setUserForStatus (state, status) {
status.user = state.usersObject[status.user.id]
@@ -206,9 +206,10 @@ const users = {
return Promise.all(promises)
})
.then((mutedUsers) => {
- each(mutedUsers, (user) => { user.mastodonMuted = true })
+ each(mutedUsers, (user) => { user.muted = true })
store.commit('addNewUsers', mutedUsers)
store.commit('saveMutes', map(mutedUsers, 'id'))
+ // TODO: Unset muted property of the rest users
})
},
muteUser (store, id) {
@@ -368,6 +369,11 @@ const users = {
// Start getting fresh posts.
store.dispatch('startFetching', { timeline: 'friends' })
+ // Fetch mutes
+ // TODO: We should not show timeline until fetchMutes is resolved
+ // However, we can get rid of this logic totally if we can know user muted state from user object
+ store.dispatch('fetchMutes')
+
// Fetch our friends
store.rootState.api.backendInteractor.fetchFriends({ id: user.id })
.then((friends) => commit('addNewUsers', friends))
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 92abf94b..7da2758a 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -26,7 +26,6 @@ const MUTING_URL = '/api/v1/accounts/:id/mute'
const UNMUTING_URL = '/api/v1/accounts/:id/unmute'
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'
const REGISTRATION_URL = '/api/account/register.json'
const AVATAR_UPDATE_URL = '/api/qvitter/update_avatar.json'
const BG_UPDATE_URL = '/api/qvitter/update_background_image.json'
@@ -343,22 +342,6 @@ const fetchStatus = ({id, credentials}) => {
.then((data) => parseStatus(data))
}
-const setUserMute = ({id, credentials, muted = true}) => {
- const form = new FormData()
-
- const muteInteger = muted ? 1 : 0
-
- form.append('namespace', 'qvitter')
- form.append('data', muteInteger)
- form.append('topic', `mute:${id}`)
-
- return fetch(QVITTER_USER_PREF_URL, {
- method: 'POST',
- headers: authHeaders(credentials),
- body: form
- })
-}
-
const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false}) => {
const timelineUrls = {
public: PUBLIC_TIMELINE_URL,
@@ -652,7 +635,6 @@ const apiService = {
deleteStatus,
uploadMedia,
fetchAllFollowing,
- setUserMute,
fetchMutes,
muteUser,
unmuteUser,
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 674fb4a4..0f0bcddc 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -62,10 +62,6 @@ const backendInteractorService = (credentials) => {
return timelineFetcherService.startFetching({timeline, store, credentials, userId, tag})
}
- const setUserMute = ({id, muted = true}) => {
- return apiService.setUserMute({id, muted, credentials})
- }
-
const fetchMutes = () => apiService.fetchMutes({credentials})
const muteUser = (id) => apiService.muteUser({credentials, id})
const unmuteUser = (id) => apiService.unmuteUser({credentials, id})
@@ -102,7 +98,6 @@ const backendInteractorService = (credentials) => {
fetchAllFollowing,
verifyCredentials: apiService.verifyCredentials,
startFetching,
- setUserMute,
fetchMutes,
muteUser,
unmuteUser,
--
cgit v1.2.3-70-g09d2
From d65422a6a59e0126201f71d0ca42343c075da54e Mon Sep 17 00:00:00 2001
From: taehoon
Date: Fri, 1 Mar 2019 22:47:07 -0500
Subject: Improve fetch error handling using a util
---
src/services/api/api.service.js | 54 ++++++++++++++---------------------------
1 file changed, 18 insertions(+), 36 deletions(-)
(limited to 'src/services/api/api.service.js')
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 7da2758a..b7fcf510 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -64,6 +64,19 @@ let fetch = (url, options) => {
return oldfetch(fullUrl, options)
}
+const promisedRequest = (url, options) => {
+ return fetch(url, options)
+ .then((response) => {
+ return new Promise((resolve, reject) => response.json()
+ .then((json) => {
+ if (!response.ok) {
+ return reject(new StatusCodeError(response.status, json, { url, options }, response))
+ }
+ return resolve(json)
+ }))
+ })
+}
+
// Params
// cropH
// cropW
@@ -249,16 +262,7 @@ const denyUser = ({id, credentials}) => {
const fetchUser = ({id, credentials}) => {
let url = `${MASTODON_USER_URL}/${id}`
- return fetch(url, { headers: authHeaders(credentials) })
- .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)
- }))
- })
+ return promisedRequest(url, { headers: authHeaders(credentials) })
.then((data) => parseUser(data))
}
@@ -526,50 +530,28 @@ const changePassword = ({credentials, password, newPassword, newPasswordConfirma
}
const fetchMutes = ({credentials}) => {
- return fetch(MUTES_URL, {
- headers: authHeaders(credentials)
- }).then((data) => {
- if (data.ok) {
- return data.json()
- }
- throw new Error('Error fetching mutes', data)
- })
+ return promisedRequest(MUTES_URL, { headers: authHeaders(credentials) })
}
const muteUser = ({id, credentials}) => {
const url = generateUrl(MUTING_URL, { id })
- return fetch(url, {
+ return promisedRequest(url, {
headers: authHeaders(credentials),
method: 'POST'
- }).then((data) => {
- if (data.ok) {
- return data.json()
- }
- throw new Error('Error muting', data)
})
}
const unmuteUser = ({id, credentials}) => {
const url = generateUrl(UNMUTING_URL, { id })
- return fetch(url, {
+ return promisedRequest(url, {
headers: authHeaders(credentials),
method: 'POST'
- }).then((data) => {
- if (data.ok) {
- return data.json()
- }
- throw new Error('Error unmuting', data)
})
}
const fetchBlocks = ({credentials}) => {
- return fetch(BLOCKS_URL, {
+ return promisedRequest(BLOCKS_URL, {
headers: authHeaders(credentials)
- }).then((data) => {
- if (data.ok) {
- return data.json()
- }
- throw new Error('Error fetching blocks', data)
})
}
--
cgit v1.2.3-70-g09d2
From 333afd213892087f5047fabdc2cc21b70ddcf76d Mon Sep 17 00:00:00 2001
From: taehoon
Date: Fri, 1 Mar 2019 22:50:06 -0500
Subject: Minor code refactoring
---
src/services/api/api.service.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
(limited to 'src/services/api/api.service.js')
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index b7fcf510..14bc919f 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1,5 +1,3 @@
-import { generateUrl } from '../../utils/url'
-
/* eslint-env browser */
const LOGIN_URL = '/api/account/verify_credentials.json'
const FRIENDS_TIMELINE_URL = '/api/statuses/friends_timeline.json'
@@ -53,6 +51,7 @@ import { each, map } from 'lodash'
import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
import 'whatwg-fetch'
import { StatusCodeError } from '../errors/errors'
+import { generateUrl } from '../../utils/url'
const oldfetch = window.fetch
--
cgit v1.2.3-70-g09d2
From 9857002bf5dc902302644e981712b611124a5845 Mon Sep 17 00:00:00 2001
From: taehoon
Date: Sat, 2 Mar 2019 08:07:14 -0500
Subject: Add hideMutedPosts setting and wire up to post-returning endpoints
---
src/boot/after_store.js | 1 +
src/components/settings/settings.js | 8 ++++++++
src/components/settings/settings.vue | 4 ++++
src/i18n/en.json | 1 +
src/modules/config.js | 1 +
src/modules/instance.js | 1 +
src/services/api/api.service.js | 3 ++-
src/services/timeline_fetcher/timeline_fetcher.service.js | 4 ++++
8 files changed, 22 insertions(+), 1 deletion(-)
(limited to 'src/services/api/api.service.js')
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index a5f8c978..f5e84cbc 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -97,6 +97,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
copyInstanceOption('showInstanceSpecificPanel')
copyInstanceOption('scopeOptionsEnabled')
copyInstanceOption('formattingOptionsEnabled')
+ copyInstanceOption('hideMutedPosts')
copyInstanceOption('collapseMessageWithSubject')
copyInstanceOption('loginMethod')
copyInstanceOption('scopeCopy')
diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index b77c5197..1d5f75ed 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -47,6 +47,11 @@ const settings = {
pauseOnUnfocusedLocal: user.pauseOnUnfocused,
hoverPreviewLocal: user.hoverPreview,
+ hideMutedPostsLocal: typeof user.hideMutedPosts === 'undefined'
+ ? instance.hideMutedPosts
+ : user.hideMutedPosts,
+ hideMutedPostsDefault: this.$t('settings.values.' + instance.hideMutedPosts),
+
collapseMessageWithSubjectLocal: typeof user.collapseMessageWithSubject === 'undefined'
? instance.collapseMessageWithSubject
: user.collapseMessageWithSubject,
@@ -177,6 +182,9 @@ const settings = {
value = filter(value.split('\n'), (word) => trim(word).length > 0)
this.$store.dispatch('setOption', { name: 'muteWords', value })
},
+ hideMutedPostsLocal (value) {
+ this.$store.dispatch('setOption', { name: 'hideMutedPosts', value })
+ },
collapseMessageWithSubjectLocal (value) {
this.$store.dispatch('setOption', { name: 'collapseMessageWithSubject', value })
},
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 17f1f1a1..33dad549 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -36,6 +36,10 @@
{{$t('nav.timeline')}}
+ -
+
+
+
-
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 8586f993..a15cecaf 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -9,10 +9,8 @@ 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'
-const MEDIA_UPLOAD_URL = '/api/statusnet/media/upload'
const CONVERSATION_URL = '/api/statusnet/conversation'
const MENTIONS_URL = '/api/statuses/mentions.json'
const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json'
@@ -46,6 +44,8 @@ const MASTODON_BLOCK_USER_URL = id => `/api/v1/accounts/${id}/block`
const MASTODON_UNBLOCK_USER_URL = id => `/api/v1/accounts/${id}/unblock`
const MASTODON_MUTE_USER_URL = id => `/api/v1/accounts/${id}/mute`
const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute`
+const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
+const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
import { each, map } from 'lodash'
import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
@@ -439,23 +439,25 @@ const unretweet = ({ id, credentials }) => {
})
}
-const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType, noAttachmentLinks}) => {
- const idsText = mediaIds.join(',')
+const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType}) => {
const form = new FormData()
form.append('status', status)
form.append('source', 'Pleroma FE')
- if (noAttachmentLinks) form.append('no_attachment_links', noAttachmentLinks)
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 (mediaIds) {
+ mediaIds.forEach(val => {
+ form.append('media_ids[]', val)
+ })
+ }
if (inReplyToStatusId) {
- form.append('in_reply_to_status_id', inReplyToStatusId)
+ form.append('in_reply_to_id', inReplyToStatusId)
}
- return fetch(STATUS_UPDATE_URL, {
+ return fetch(MASTODON_POST_STATUS_URL, {
body: form,
method: 'POST',
headers: authHeaders(credentials)
@@ -480,13 +482,12 @@ const deleteStatus = ({ id, credentials }) => {
}
const uploadMedia = ({formData, credentials}) => {
- return fetch(MEDIA_UPLOAD_URL, {
+ return fetch(MASTODON_MEDIA_UPLOAD_URL, {
body: formData,
method: 'POST',
headers: authHeaders(credentials)
})
- .then((response) => response.text())
- .then((text) => (new DOMParser()).parseFromString(text, 'application/xml'))
+ .then((response) => response.json())
}
const followImport = ({params, credentials}) => {
diff --git a/src/services/status_poster/status_poster.service.js b/src/services/status_poster/status_poster.service.js
index f1932bb6..e70b0f26 100644
--- a/src/services/status_poster/status_poster.service.js
+++ b/src/services/status_poster/status_poster.service.js
@@ -4,7 +4,7 @@ import apiService from '../api/api.service.js'
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, sensitive, mediaIds, inReplyToStatusId, contentType, noAttachmentLinks: store.state.instance.noAttachmentLinks})
+ return apiService.postStatus({credentials: store.state.users.currentUser.credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType})
.then((data) => {
if (!data.error) {
store.dispatch('addNewStatuses', {
@@ -26,25 +26,7 @@ const postStatus = ({ store, status, spoilerText, visibility, sensitive, media =
const uploadMedia = ({ store, formData }) => {
const credentials = store.state.users.currentUser.credentials
- return apiService.uploadMedia({ credentials, formData }).then((xml) => {
- // Firefox and Chrome treat method differently...
- let link = xml.getElementsByTagName('link')
-
- if (link.length === 0) {
- link = xml.getElementsByTagName('atom:link')
- }
-
- link = link[0]
-
- const mediaData = {
- id: xml.getElementsByTagName('media_id')[0].textContent,
- url: xml.getElementsByTagName('media_url')[0].textContent,
- image: link.getAttribute('href'),
- mimetype: link.getAttribute('type')
- }
-
- return mediaData
- })
+ return apiService.uploadMedia({ credentials, formData })
}
const statusPosterService = {
--
cgit v1.2.3-70-g09d2
From 966add1b2996b87019051d8c924edb4af0bafb80 Mon Sep 17 00:00:00 2001
From: taehoon
Date: Sun, 17 Mar 2019 23:22:54 -0400
Subject: Set default parameter
---
src/services/api/api.service.js | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
(limited to 'src/services/api/api.service.js')
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index a15cecaf..079462f7 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -48,7 +48,7 @@ const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
import { each, map } from 'lodash'
-import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
+import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
import 'whatwg-fetch'
import { StatusCodeError } from '../errors/errors'
@@ -439,7 +439,7 @@ const unretweet = ({ id, credentials }) => {
})
}
-const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType}) => {
+const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds = [], inReplyToStatusId, contentType}) => {
const form = new FormData()
form.append('status', status)
@@ -448,11 +448,9 @@ const postStatus = ({credentials, status, spoilerText, visibility, sensitive, me
if (visibility) form.append('visibility', visibility)
if (sensitive) form.append('sensitive', sensitive)
if (contentType) form.append('content_type', contentType)
- if (mediaIds) {
- mediaIds.forEach(val => {
- form.append('media_ids[]', val)
- })
- }
+ mediaIds.forEach(val => {
+ form.append('media_ids[]', val)
+ })
if (inReplyToStatusId) {
form.append('in_reply_to_id', inReplyToStatusId)
}
@@ -487,7 +485,8 @@ const uploadMedia = ({formData, credentials}) => {
method: 'POST',
headers: authHeaders(credentials)
})
- .then((response) => response.json())
+ .then((data) => data.json())
+ .then((data) => parseAttachment(data))
}
const followImport = ({params, credentials}) => {
--
cgit v1.2.3-70-g09d2