From 49b0f0a04a74039a1b82fbde731828e599123e93 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Sat, 9 Mar 2019 18:33:49 +0200 Subject: Fetching convos via MastoAPI. Had to change conversation component a bit for better support, since MastoAPI doesn't have coversation ids --- src/components/conversation/conversation.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src/components') diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 48b8aaaa..fd4303ca 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -25,7 +25,8 @@ const sortAndFilterConversation = (conversation) => { const conversation = { data () { return { - highlight: null + highlight: null, + relevantIds: [] } }, props: [ @@ -48,9 +49,11 @@ const conversation = { return [] } - const conversationId = this.status.statusnet_conversation_id - const statuses = this.$store.state.statuses.allStatuses - const conversation = filter(statuses, { statusnet_conversation_id: conversationId }) + const statusesObject = this.$store.state.statuses.allStatusesObject + const conversation = this.relevantIds.reduce((acc, id) => { + acc.push(statusesObject[id]) + return acc + }, []) return sortAndFilterConversation(conversation) }, replies () { @@ -83,15 +86,13 @@ const conversation = { methods: { fetchConversation () { if (this.status) { - const conversationId = this.status.statusnet_conversation_id + const conversationId = this.status.id this.$store.state.api.backendInteractor.fetchConversation({id: conversationId}) - .then((statuses) => this.$store.dispatch('addNewStatuses', { statuses })) + .then((statuses) => { + this.$store.dispatch('addNewStatuses', { statuses }) + statuses.forEach(status => this.relevantIds.push(status.id)) + }) .then(() => this.setHighlight(this.statusId)) - } else { - const id = this.$route.params.id - this.$store.state.api.backendInteractor.fetchStatus({id}) - .then((status) => this.$store.dispatch('addNewStatuses', { statuses: [status] })) - .then(() => this.fetchConversation()) } }, getReplies (id) { -- cgit v1.2.3-70-g09d2 From 4f455eefe5af2914d7dece40e027ed35ec8a21b3 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 11 Mar 2019 10:52:28 -0400 Subject: #433: do not remove the reply dialog --- src/components/conversation/conversation.js | 6 +++++- src/components/conversation/conversation.vue | 15 ++++++++++----- src/components/status/status.js | 6 +++--- .../status_or_conversation/status_or_conversation.js | 6 +++++- .../status_or_conversation.vue | 20 ++++++++++++++++++-- 5 files changed, 41 insertions(+), 12 deletions(-) (limited to 'src/components') diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 48b8aaaa..95e484cd 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -30,7 +30,8 @@ const conversation = { }, props: [ 'statusoid', - 'collapsable' + 'collapsable', + 'replying' ], computed: { status () { @@ -102,6 +103,9 @@ const conversation = { }, setHighlight (id) { this.highlight = id + }, + toggleReplying () { + this.$emit('toggleReplying') } } } diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 5528fef6..42d009c9 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -10,14 +10,19 @@
- + class="status-fadein" + />
diff --git a/src/components/status/status.js b/src/components/status/status.js index 9e18fe15..20ca86a6 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -25,11 +25,11 @@ const Status = { 'replies', 'isPreview', 'noHeading', - 'inlineExpanded' + 'inlineExpanded', + 'replying' ], data () { return { - replying: false, expanded: false, unmuted: false, userExpanded: false, @@ -307,7 +307,7 @@ const Status = { } }, toggleReplying () { - this.replying = !this.replying + this.$emit('toggleReplying') }, gotoOriginal (id) { // only handled by conversation, not status_or_conversation diff --git a/src/components/status_or_conversation/status_or_conversation.js b/src/components/status_or_conversation/status_or_conversation.js index 441552ca..749f7665 100644 --- a/src/components/status_or_conversation/status_or_conversation.js +++ b/src/components/status_or_conversation/status_or_conversation.js @@ -5,7 +5,8 @@ const statusOrConversation = { props: ['statusoid'], data () { return { - expanded: false + expanded: false, + replying: false } }, components: { @@ -15,6 +16,9 @@ const statusOrConversation = { methods: { toggleExpanded () { this.expanded = !this.expanded + }, + toggleReplying () { + this.replying = !this.replying } } } diff --git a/src/components/status_or_conversation/status_or_conversation.vue b/src/components/status_or_conversation/status_or_conversation.vue index 9647d5eb..43a60c3a 100644 --- a/src/components/status_or_conversation/status_or_conversation.vue +++ b/src/components/status_or_conversation/status_or_conversation.vue @@ -1,7 +1,23 @@ -- cgit v1.2.3-70-g09d2 From 63d7c7bd80cf8028cdefee99c1cb75614385f96b Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 11 Mar 2019 16:24:37 -0400 Subject: #433: persistency of status form --- src/components/conversation/conversation.js | 36 +++++++++++++++------- src/components/conversation/conversation.vue | 31 ++++++++++++++----- src/components/status/status.js | 7 ++--- .../status_or_conversation.js | 26 ---------------- .../status_or_conversation.vue | 30 ------------------ src/components/timeline/timeline.js | 4 +-- src/components/timeline/timeline.vue | 8 ++++- 7 files changed, 60 insertions(+), 82 deletions(-) delete mode 100644 src/components/status_or_conversation/status_or_conversation.js delete mode 100644 src/components/status_or_conversation/status_or_conversation.vue (limited to 'src/components') diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 95e484cd..4cae0bdb 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -1,4 +1,4 @@ -import { reduce, filter } from 'lodash' +import { reduce, filter, findIndex } from 'lodash' import Status from '../status/status.vue' const sortById = (a, b) => { @@ -25,13 +25,13 @@ const sortAndFilterConversation = (conversation) => { const conversation = { data () { return { - highlight: null + highlight: null, + expanded: false } }, props: [ 'statusoid', - 'collapsable', - 'replying' + 'collapsable' ], computed: { status () { @@ -49,9 +49,18 @@ const conversation = { return [] } + if (!this.expanded) { + return [this.status] + } + const conversationId = this.status.statusnet_conversation_id const statuses = this.$store.state.statuses.allStatuses const conversation = filter(statuses, { statusnet_conversation_id: conversationId }) + + const statusIndex = findIndex(conversation, { id: this.statusId }) + if (statusIndex !== -1) { + conversation[statusIndex] = this.status + } return sortAndFilterConversation(conversation) }, replies () { @@ -75,11 +84,13 @@ const conversation = { components: { Status }, - created () { - this.fetchConversation() - }, watch: { - '$route': 'fetchConversation' + '$route': 'fetchConversation', + expanded (value) { + if (value) { + this.fetchConversation() + } + } }, methods: { fetchConversation () { @@ -99,13 +110,16 @@ const conversation = { return this.replies[id] || [] }, focused (id) { - return id === this.statusId + return this.expanded && id === this.statusId }, setHighlight (id) { this.highlight = id }, - toggleReplying () { - this.$emit('toggleReplying') + getHighlight () { + return this.expanded ? this.highlight : null + }, + toggleExpanded () { + this.expanded = !this.expanded } } } diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 42d009c9..b208d540 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -1,9 +1,9 @@ + + diff --git a/src/components/status/status.js b/src/components/status/status.js index 20ca86a6..8e489704 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -25,11 +25,11 @@ const Status = { 'replies', 'isPreview', 'noHeading', - 'inlineExpanded', - 'replying' + 'inlineExpanded' ], data () { return { + replying: false, expanded: false, unmuted: false, userExpanded: false, @@ -307,10 +307,9 @@ const Status = { } }, toggleReplying () { - this.$emit('toggleReplying') + this.replying = !this.replying }, gotoOriginal (id) { - // only handled by conversation, not status_or_conversation if (this.inConversation) { this.$emit('goto', id) } diff --git a/src/components/status_or_conversation/status_or_conversation.js b/src/components/status_or_conversation/status_or_conversation.js deleted file mode 100644 index 749f7665..00000000 --- a/src/components/status_or_conversation/status_or_conversation.js +++ /dev/null @@ -1,26 +0,0 @@ -import Status from '../status/status.vue' -import Conversation from '../conversation/conversation.vue' - -const statusOrConversation = { - props: ['statusoid'], - data () { - return { - expanded: false, - replying: false - } - }, - components: { - Status, - Conversation - }, - methods: { - toggleExpanded () { - this.expanded = !this.expanded - }, - toggleReplying () { - this.replying = !this.replying - } - } -} - -export default statusOrConversation diff --git a/src/components/status_or_conversation/status_or_conversation.vue b/src/components/status_or_conversation/status_or_conversation.vue deleted file mode 100644 index 43a60c3a..00000000 --- a/src/components/status_or_conversation/status_or_conversation.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - - - diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index c45f8947..1da7d5cc 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -1,6 +1,6 @@ import Status from '../status/status.vue' import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js' -import StatusOrConversation from '../status_or_conversation/status_or_conversation.vue' +import Conversation from '../conversation/conversation.vue' import { throttle } from 'lodash' const Timeline = { @@ -43,7 +43,7 @@ const Timeline = { }, components: { Status, - StatusOrConversation + Conversation }, created () { const store = this.$store diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue index 8f28d65c..e0a34bd1 100644 --- a/src/components/timeline/timeline.vue +++ b/src/components/timeline/timeline.vue @@ -16,7 +16,13 @@
- +
-- cgit v1.2.3-70-g09d2 From 5717d971829c54e4387b05725658e652b69a8b17 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 18 Mar 2019 10:35:13 -0400 Subject: #442 - update placeholder linebreak --- src/components/registration/registration.js | 3 +++ src/components/registration/registration.vue | 2 +- src/i18n/en.json | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/components') diff --git a/src/components/registration/registration.js b/src/components/registration/registration.js index ab6cd64d..8dc00420 100644 --- a/src/components/registration/registration.js +++ b/src/components/registration/registration.js @@ -35,6 +35,9 @@ const registration = { }, computed: { token () { return this.$route.params.token }, + bioPlaceholder () { + return this.$t('registration.bio_placeholder').replace(/\s*\n\s*/g, ' \n') + }, ...mapState({ registrationOpen: (state) => state.instance.registrationOpen, signedIn: (state) => !!state.users.currentUser, diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue index e22b308d..110b27bf 100644 --- a/src/components/registration/registration.vue +++ b/src/components/registration/registration.vue @@ -45,7 +45,7 @@
- +
diff --git a/src/i18n/en.json b/src/i18n/en.json index 0bf8b4e9..e5139a4e 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -97,7 +97,7 @@ "new_captcha": "Click the image to get a new captcha", "username_placeholder": "e.g. lain", "fullname_placeholder": "e.g. Lain Iwakura", - "bio_placeholder": "e.g. \nHi, I'm Lain. \nI’m an anime girl living in suburban Japan. You may know me from the Wired.", + "bio_placeholder": "e.g.\nHi, I'm Lain.\nI’m an anime girl living in suburban Japan. You may know me from the Wired.", "validations": { "username_required": "cannot be left blank", "fullname_required": "cannot be left blank", -- cgit v1.2.3-70-g09d2 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/components/mute_card/mute_card.js | 2 +- src/components/user_card/user_card.js | 20 +++++----- src/components/user_card/user_card.vue | 4 +- src/components/user_settings/user_settings.vue | 6 +++ src/modules/users.js | 32 ++++++++++------ src/services/api/api.service.js | 44 ++++++++++++++++++++-- .../backend_interactor_service.js | 6 ++- src/utils/url.js | 9 +++++ 8 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 src/utils/url.js (limited to 'src/components') diff --git a/src/components/mute_card/mute_card.js b/src/components/mute_card/mute_card.js index 65c9cfb5..5ef17b60 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.muted + return this.user.mastodonMuted } }, components: { diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js index b07da675..61b784fe 100644 --- a/src/components/user_card/user_card.js +++ b/src/components/user_card/user_card.js @@ -121,21 +121,19 @@ export default { }) }, blockUser () { - const store = this.$store - store.state.api.backendInteractor.blockUser(this.user.id) - .then((blockedUser) => { - store.commit('addNewUsers', [blockedUser]) - store.commit('removeStatus', { timeline: 'friends', userId: this.user.id }) - store.commit('removeStatus', { timeline: 'public', userId: this.user.id }) - store.commit('removeStatus', { timeline: 'publicAndExternal', userId: this.user.id }) - }) + this.$store.dispatch('blockUser', this.user.id) }, unblockUser () { - const store = this.$store - store.state.api.backendInteractor.unblockUser(this.user.id) - .then((unblockedUser) => store.commit('addNewUsers', [unblockedUser])) + this.$store.dispatch('unblockUser', this.user.id) + }, + muteUser () { // Mastodon Mute + this.$store.dispatch('muteUser', this.user.id) + }, + unmuteUser () { // Mastodon Unmute + 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) diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index f4114e6e..3259d1c5 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -74,12 +74,12 @@
- - diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index a1123638..c9e68808 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -192,6 +192,12 @@
+ +
+ + + +
diff --git a/src/modules/users.js b/src/modules/users.js index 1fe12fc8..9c89f34a 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -177,9 +177,14 @@ const users = { return blocks }) }, - blockUser (store, id) { - return store.rootState.api.backendInteractor.blockUser(id) - .then((user) => store.commit('addNewUsers', [user])) + blockUser (store, userId) { + return store.rootState.api.backendInteractor.blockUser(userId) + .then((blockedUser) => { + store.commit('addNewUsers', [blockedUser]) + store.commit('removeStatus', { timeline: 'friends', userId }) + store.commit('removeStatus', { timeline: 'public', userId }) + store.commit('removeStatus', { timeline: 'publicAndExternal', userId }) + }) }, unblockUser (store, id) { return store.rootState.api.backendInteractor.unblockUser(id) @@ -188,18 +193,26 @@ const users = { fetchMutes (store) { return store.rootState.api.backendInteractor.fetchMutes() .then((mutedUsers) => { - each(mutedUsers, (user) => { user.muted = true }) + each(mutedUsers, (user) => { user.mastodonMuted = true }) store.commit('addNewUsers', mutedUsers) store.commit('saveMutes', map(mutedUsers, 'id')) }) }, muteUser (store, id) { - return store.state.api.backendInteractor.setUserMute({ id, muted: true }) - .then((user) => store.commit('addNewUsers', [user])) + return store.rootState.api.backendInteractor.muteUser(id) + .then(() => { + const user = store.rootState.users.usersObject[id] + set(user, 'mastodonMuted', true) + store.commit('addNewUsers', [user]) + }) }, unmuteUser (store, id) { - return store.state.api.backendInteractor.setUserMute({ id, muted: false }) - .then((user) => store.commit('addNewUsers', [user])) + return store.rootState.api.backendInteractor.unmuteUser(id) + .then(() => { + const user = store.rootState.users.usersObject[id] + set(user, 'mastodonMuted', false) + store.commit('addNewUsers', [user]) + }) }, addFriends ({ rootState, commit }, fetchBy) { return new Promise((resolve, reject) => { @@ -350,9 +363,6 @@ const users = { // Start getting fresh posts. store.dispatch('startFetching', { timeline: 'friends' }) - // Get user mutes - 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 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, diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js index cbd0b733..674fb4a4 100644 --- a/src/services/backend_interactor_service/backend_interactor_service.js +++ b/src/services/backend_interactor_service/backend_interactor_service.js @@ -67,7 +67,9 @@ const backendInteractorService = (credentials) => { } const fetchMutes = () => apiService.fetchMutes({credentials}) - const fetchBlocks = (params) => apiService.fetchBlocks({credentials, ...params}) + const muteUser = (id) => apiService.muteUser({credentials, id}) + const unmuteUser = (id) => apiService.unmuteUser({credentials, id}) + const fetchBlocks = () => apiService.fetchBlocks({credentials}) const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials}) const fetchOAuthTokens = () => apiService.fetchOAuthTokens({credentials}) const revokeOAuthToken = (id) => apiService.revokeOAuthToken({id, credentials}) @@ -102,6 +104,8 @@ const backendInteractorService = (credentials) => { startFetching, setUserMute, fetchMutes, + muteUser, + unmuteUser, fetchBlocks, fetchOAuthTokens, revokeOAuthToken, diff --git a/src/utils/url.js b/src/utils/url.js new file mode 100644 index 00000000..79ea7394 --- /dev/null +++ b/src/utils/url.js @@ -0,0 +1,9 @@ +// Generate url based on template +// Example: /api/v1/accounts/:id/mute -> /api/v1/accounts/123/mute +export const generateUrl = (template, params = {}) => { + let url = template + Object.entries(params).forEach(([key, value]) => { + url = url.replace(':' + key, value) + }) + return url +} -- cgit v1.2.3-70-g09d2 From a6ce191cbcc34f309e9c4d4e3f7e3c11ed020821 Mon Sep 17 00:00:00 2001 From: taehoon Date: Thu, 28 Feb 2019 22:59:26 -0500 Subject: Update MuteCard ui --- src/components/mute_card/mute_card.vue | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/components') diff --git a/src/components/mute_card/mute_card.vue b/src/components/mute_card/mute_card.vue index e1bfe20b..a4edff03 100644 --- a/src/components/mute_card/mute_card.vue +++ b/src/components/mute_card/mute_card.vue @@ -1,6 +1,6 @@ - \ No newline at end of file + + + -- 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/components') 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 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/components') 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 909c315a44a5c6272f000325e5e9c8b33e75f873 Mon Sep 17 00:00:00 2001 From: taehoon Date: Sun, 17 Mar 2019 23:23:59 -0400 Subject: Get correct mimetype through entity_normalizer --- src/components/post_status_form/post_status_form.js | 2 +- src/services/entity_normalizer/entity_normalizer.service.js | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src/components') diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 142d9d90..1f0df35a 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -292,7 +292,7 @@ const PostStatusForm = { this.submitDisabled = false }, type (fileInfo) { - return fileTypeService.fileType(fileInfo.pleroma.mime_type) + return fileTypeService.fileType(fileInfo.mimetype) }, paste (e) { if (e.clipboardData.files.length > 0) { diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index 57a6adf9..0d653207 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -128,13 +128,12 @@ export const parseUser = (data) => { return output } -const parseAttachment = (data) => { +export const parseAttachment = (data) => { const output = {} const masto = !data.hasOwnProperty('oembed') if (masto) { - // Not exactly same... - output.mimetype = data.type + output.mimetype = data.pleroma.mime_type output.meta = data.meta // not present in BE yet } else { output.mimetype = data.mimetype -- cgit v1.2.3-70-g09d2 From 6a9159b25598d578018643673568bbcd06ea1e12 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 25 Mar 2019 10:50:09 -0400 Subject: #433 - fix broken conversation page --- src/components/conversation-page/conversation-page.vue | 6 +++++- src/components/conversation/conversation.js | 8 ++++++-- src/components/conversation/conversation.vue | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src/components') diff --git a/src/components/conversation-page/conversation-page.vue b/src/components/conversation-page/conversation-page.vue index b03eea28..9e322cf5 100644 --- a/src/components/conversation-page/conversation-page.vue +++ b/src/components/conversation-page/conversation-page.vue @@ -1,5 +1,9 @@ diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 4cae0bdb..5a9568a9 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -31,7 +31,8 @@ const conversation = { }, props: [ 'statusoid', - 'collapsable' + 'collapsable', + 'isPage' ], computed: { status () { @@ -49,7 +50,7 @@ const conversation = { return [] } - if (!this.expanded) { + if (!this.expanded && !this.isPage) { return [this.status] } @@ -79,6 +80,9 @@ const conversation = { i++ return result }, {}) + }, + isExpanded () { + return this.expanded || this.isPage } }, components: { diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index b208d540..3778cc15 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -1,6 +1,6 @@ -- cgit v1.2.3-70-g09d2 From c5ec4829a7a18b20a1525998ba27cc7af5a3da55 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 25 Mar 2019 15:10:45 -0400 Subject: #433 - consider page on focused --- src/components/conversation/conversation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/components') diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index f8887557..94709fd8 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -139,7 +139,7 @@ const conversation = { return this.replies[id] || [] }, focused (id) { - return this.expanded && id === this.statusId + return (this.expanded || this.isPage) && id === this.statusId }, setHighlight (id) { this.highlight = id -- cgit v1.2.3-70-g09d2 From 467647d5d715730a14d41737e4326696ff971cc2 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 25 Mar 2019 16:09:40 -0400 Subject: #433 - fix retweet abnormal behavior --- src/components/conversation/conversation.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src/components') diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 94709fd8..8ad1f44d 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -18,8 +18,13 @@ const sortById = (a, b) => { } } -const sortAndFilterConversation = (conversation) => { - conversation = filter(conversation, (status) => status.type !== 'retweet') +const sortAndFilterConversation = (conversation, statusoid) => { + if (statusoid.type === 'retweet') { + conversation = filter( + conversation, + (status) => (status.type === 'retweet' || status.id !== statusoid.retweeted_status.id) + ) + } return conversation.filter(_ => _).sort(sortById) } @@ -66,7 +71,7 @@ const conversation = { return [] } - if (!this.expanded && !this.isPage) { + if (!this.isExpanded) { return [this.status] } @@ -81,7 +86,7 @@ const conversation = { conversation[statusIndex] = this.status } - return sortAndFilterConversation(conversation) + return sortAndFilterConversation(conversation, this.status) }, replies () { let i = 1 @@ -139,7 +144,7 @@ const conversation = { return this.replies[id] || [] }, focused (id) { - return (this.expanded || this.isPage) && id === this.statusId + return (this.isExpanded) && id === this.status.id }, setHighlight (id) { this.highlight = id @@ -149,6 +154,9 @@ const conversation = { }, toggleExpanded () { this.expanded = !this.expanded + if (!this.expanded) { + this.setHighlight(null) + } } } } -- cgit v1.2.3-70-g09d2 From e23c19468a4436454161fd315c6bfb79aef1b15d Mon Sep 17 00:00:00 2001 From: shpuld Date: Mon, 25 Mar 2019 22:44:58 +0200 Subject: somewhat functioning gesture service --- src/components/side_drawer/side_drawer.js | 21 ++++---- src/services/gesture_service/gesture_service.js | 71 +++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 11 deletions(-) (limited to 'src/components') diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js index ad3738d1..76c64fe0 100644 --- a/src/components/side_drawer/side_drawer.js +++ b/src/components/side_drawer/side_drawer.js @@ -1,17 +1,18 @@ import UserCard from '../user_card/user_card.vue' import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils' - -// TODO: separate touch gesture stuff into their own utils if more components want them -const deltaCoord = (oldCoord, newCoord) => [newCoord[0] - oldCoord[0], newCoord[1] - oldCoord[1]] - -const touchEventCoord = e => ([e.touches[0].screenX, e.touches[0].screenY]) +import GestureService from '../../services/gesture_service/gesture_service' const SideDrawer = { props: [ 'logout' ], data: () => ({ closed: true, - touchCoord: [0, 0] + closeGesture: undefined }), + created () { + const cb = () => this.toggleDrawer() + this.closeGesture = GestureService.swipeGesture(GestureService.DIRECTION_LEFT, cb) + console.log(this.closeGesture) + }, components: { UserCard }, computed: { currentUser () { @@ -46,13 +47,11 @@ const SideDrawer = { this.toggleDrawer() }, touchStart (e) { - this.touchCoord = touchEventCoord(e) + console.log(this) + GestureService.beginSwipe(e, this.closeGesture) }, touchMove (e) { - const delta = deltaCoord(this.touchCoord, touchEventCoord(e)) - if (delta[0] < -30 && Math.abs(delta[1]) < Math.abs(delta[0]) && !this.closed) { - this.toggleDrawer() - } + GestureService.updateSwipe(e, this.closeGesture) } } } diff --git a/src/services/gesture_service/gesture_service.js b/src/services/gesture_service/gesture_service.js index e69de29b..2e39003c 100644 --- a/src/services/gesture_service/gesture_service.js +++ b/src/services/gesture_service/gesture_service.js @@ -0,0 +1,71 @@ + +const DIRECTION_LEFT = [-1, 0] +const DIRECTION_RIGHT = [1, 0] +const DIRECTION_UP = [0, -1] +const DIRECTION_DOWN = [0, 1] + +const deltaCoord = (oldCoord, newCoord) => [newCoord[0] - oldCoord[0], newCoord[1] - oldCoord[1]] + +const touchEventCoord = e => ([e.touches[0].screenX, e.touches[0].screenY]) + +const vectorLength = v => Math.sqrt(v[0] * v[0] + v[1] * v[1]) + +const perpendicular = v => [v[1], v[0]] + +const dotProduct = (v1, v2) => v1[0] * v2[0] + v1[1] * v2[1] + +const vectorFlatten = (v1, v2) => [v1[0] * v2[0], v1[1] * v2[1]] + +// direction: either use the constants above or an arbitrary 2d vector. +// threshold: how many Px to move from touch origin before checking if the +// callback should be called. +// divergentTolerance: a scalr for much of divergent direction we tolerate when +// above threshold. for example, with 1.0 we only call the callback if +// divergent component of delta is < 1.0 * direction component of delta. +const swipeGesture = (direction, onSwipe, threshold = 30, perpendicularTolerance = 1.0) => { + return { + direction, + onSwipe, + threshold, + perpendicularTolerance, + _startPos: [0, 0], + _swiping: false + } +} + +const beginSwipe = (event, gesture) => { + gesture._startPos = touchEventCoord(event) + gesture._swiping = true +} + +const updateSwipe = (event, gesture) => { + if (!gesture._swiping) return + // movement too small + const delta = deltaCoord(gesture._startPos, touchEventCoord(event)) + if (vectorLength(delta) < gesture.threshold) return + // movement is opposite from direction + if (dotProduct(delta, gesture.direction) < 0) return + // movement perpendicular to direction is too much + const towardsDir = vectorFlatten(gesture.direction, delta) + const perpendicularDir = perpendicular(gesture.direction) + const towardsPerpendicular = vectorFlatten(perpendicularDir, delta) + if ( + vectorLength(towardsDir) < + gesture.perpendicularTolerance * vectorLength(towardsPerpendicular) + ) return + + gesture.onSwipe() + gesture._swiping = false +} + +const GestureService = { + DIRECTION_LEFT, + DIRECTION_RIGHT, + DIRECTION_UP, + DIRECTION_DOWN, + swipeGesture, + beginSwipe, + updateSwipe +} + +export default GestureService -- cgit v1.2.3-70-g09d2 From 43e97e590c98d1f1bb500f96d2b604b968fbbbb3 Mon Sep 17 00:00:00 2001 From: dave Date: Wed, 27 Mar 2019 16:00:54 -0400 Subject: #433 - sort conversation for retweets and clean up --- src/components/conversation/conversation.js | 18 +++++------------- src/components/status/status.vue | 4 ++-- 2 files changed, 7 insertions(+), 15 deletions(-) (limited to 'src/components') diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 8ad1f44d..5357b67f 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -3,19 +3,9 @@ import { set } from 'vue' import Status from '../status/status.vue' const sortById = (a, b) => { - const seqA = Number(a.id) - const seqB = Number(b.id) - const isSeqA = !Number.isNaN(seqA) - const isSeqB = !Number.isNaN(seqB) - if (isSeqA && isSeqB) { - return seqA < seqB ? -1 : 1 - } else if (isSeqA && !isSeqB) { - return -1 - } else if (!isSeqA && isSeqB) { - return 1 - } else { - return a.id < b.id ? -1 : 1 - } + const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id + const idB = b.type === 'retweet' ? b.retweeted_status.id : b.id + return idA < idB ? -1 : 1 } const sortAndFilterConversation = (conversation, statusoid) => { @@ -24,6 +14,8 @@ const sortAndFilterConversation = (conversation, statusoid) => { conversation, (status) => (status.type === 'retweet' || status.id !== statusoid.retweeted_status.id) ) + } else { + conversation = filter(conversation, (status) => status.type !== 'retweet') } return conversation.filter(_ => _).sort(sortById) } diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 1f6d0325..da329deb 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -12,7 +12,7 @@