diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 9ea8c2a7..1c457099 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -3,6 +3,7 @@ import UserCard from '../user_card/user_card.vue' import FollowCard from '../follow_card/follow_card.vue' import Timeline from '../timeline/timeline.vue' import Conversation from '../conversation/conversation.vue' +import Checkbox from 'src/components/checkbox/checkbox.vue' import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx' import RichContent from 'src/components/rich_content/rich_content.jsx' import List from '../list/list.vue' @@ -55,7 +56,12 @@ const UserProfile = { followsTab: 'users', footerRef: null, note: null, - noteLoading: false + noteLoading: false, + showPinned: true, + filterParams: { + showReplies: false, + showRepeats: true, + } } }, created () { @@ -70,10 +76,22 @@ const UserProfile = { }, computed: { timeline () { - return this.$store.state.statuses.timelines.user + const { user, pinned } = this.$store.state.statuses.timelines + if (!this.showPinned) { + return user + } + return { + ...user, + statuses: [...pinned.statuses, ...user.statuses], + visibleStatuses: [...pinned.visibleStatuses, ...user.visibleStatuses], + statusesObject: { + ...pinned.statusesObject, + ...user.statusesObject, + } + } }, - replies () { - return this.$store.state.statuses.timelines.replies + hasPinned () { + return !!(this.user.pinnedStatusIds || []).length }, favorites () { return this.$store.state.statuses.timelines.favorites @@ -118,16 +136,27 @@ const UserProfile = { if (this.isUs) timelineTabMap['favorites'] = 'favorites' const timeline = timelineTabMap[nextTab] + const fetchArgs = { timeline: timeline, userId: this.userId } + if (timeline === 'user') { + const params = [] + if (!this.filterParams.showReplies) { + params.push(['exclude_replies', 1]) + } + if (!this.filterParams.showRepeats) { + params.push(['exclude_reblogs', 1]) + } + fetchArgs.params = params + } if (timeline) { this.stopFetching() - this.$store.dispatch('startFetchingTimeline', { timeline: timeline, userId: this.userId }) + this.$store.dispatch('startFetchingTimeline', fetchArgs) } }, load (userNameOrId) { const loadById = (userId) => { this.userId = userId - const timelines = ['user', 'favorites', 'replies', 'media'] + const timelines = ['pinned', 'user', 'favorites', 'media'] timelines.forEach((timeline) => { this.$store.commit('clearTimeline', { timeline: timeline }) }) @@ -165,7 +194,6 @@ const UserProfile = { }, stopFetching () { this.$store.dispatch('stopFetchingTimeline', 'user') - this.$store.dispatch('stopFetchingTimeline', 'replies') this.$store.dispatch('stopFetchingTimeline', 'favorites') this.$store.dispatch('stopFetchingTimeline', 'media') }, @@ -198,6 +226,15 @@ const UserProfile = { }, 1500) }, watch: { + filterParams: { + handler () { + // Clear the user timeline if previously fetched posts may not be relevant anymore + this.$store.dispatch('stopFetchingTimeline', 'user') + this.$store.commit('clearTimeline', { timeline: 'user', excludeUserId: true }) + this.onRouteChange(null, this.tab) + }, + deep: true + }, '$route.params.id': function (newVal) { if (isUserPage(this.$route) && newVal) { this.switchUser(newVal) @@ -215,16 +252,17 @@ const UserProfile = { } }, components: { + Checkbox, + Conversation, + FollowCard, FollowedTagCard, - UserCard, - Timeline, + FollowedTagList, FollowerList, FriendList, - FollowCard, - TabSwitcher, - Conversation, RichContent, - FollowedTagList + TabSwitcher, + Timeline, + UserCard } } diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index 5465778a..c6779112 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -75,31 +75,26 @@ :render-only-focused="true" :on-switch="onTabSwitch" > - - +
+
+ {{ $t('user_card.with_replies') }} + {{ $t('user_card.with_repeats') }} + {{ $t('user_card.with_pinned') }} +
+ +
({ bookmarks: emptyTl(), list: emptyTl(), bubble: emptyTl(), - replies: emptyTl() + pinned: emptyTl(), } }) @@ -184,7 +184,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us // This makes sure that user timeline won't get data meant for other // user. I.e. opening different user profiles makes request which could // return data late after user already viewing different user profile - if ((timeline === 'user' || timeline === 'media' || timeline === 'replies') && timelineObject.userId !== userId) { + if ((timeline === 'user' || timeline === 'media') && timelineObject.userId !== userId) { return } @@ -641,7 +641,7 @@ const statuses = { }, fetchPinnedStatuses ({ rootState, dispatch }, userId) { rootState.api.backendInteractor.fetchPinnedStatuses({ id: userId }) - .then(statuses => dispatch('addNewStatuses', { statuses, timeline: 'user', userId, showImmediately: true, noIdUpdate: true })) + .then(statuses => dispatch('addNewStatuses', { statuses, timeline: 'pinned', userId, showImmediately: true, noIdUpdate: true })) }, pinStatus ({ rootState, dispatch }, statusId) { return rootState.api.backendInteractor.pinOwnStatus({ id: statusId }) diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 947e9da9..5387f209 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -695,7 +695,8 @@ const fetchTimeline = ({ listId = false, tag = false, withMuted = false, - replyVisibility = 'all' + replyVisibility = 'all', + params = [] }) => { const timelineUrls = { public: MASTODON_PUBLIC_TIMELINE, @@ -713,11 +714,10 @@ const fetchTimeline = ({ bookmarks: MASTODON_BOOKMARK_TIMELINE_URL } const isNotifications = timeline === 'notifications' - const params = [] let url = timelineUrls[timeline] - if (timeline === 'user' || timeline === 'media' || timeline === 'replies') { + if (timeline === 'user' || timeline === 'media') { url = url(userId) } @@ -749,9 +749,6 @@ const fetchTimeline = ({ if (replyVisibility !== 'all') { params.push(['reply_visibility', replyVisibility]) } - if (timeline === 'user') { - params.push(['exclude_replies', 1]) - } params.push(['limit', 20]) diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js index 58515387..113a3ed5 100644 --- a/src/services/backend_interactor_service/backend_interactor_service.js +++ b/src/services/backend_interactor_service/backend_interactor_service.js @@ -7,8 +7,8 @@ import configFetcher from '../config_fetcher/config_fetcher.service.js' import reportsFetcher from '../reports_fetcher/reports_fetcher.service.js' const backendInteractorService = credentials => ({ - startFetchingTimeline ({ timeline, store, userId = false, listId = false, tag }) { - return timelineFetcher.startFetching({ timeline, store, credentials, userId, listId, tag }) + startFetchingTimeline ({ timeline, store, userId = false, listId = false, tag, params }) { + return timelineFetcher.startFetching({ timeline, store, credentials, userId, listId, tag, params }) }, fetchTimeline (args) { diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js index c833ef32..3b751255 100644 --- a/src/services/timeline_fetcher/timeline_fetcher.service.js +++ b/src/services/timeline_fetcher/timeline_fetcher.service.js @@ -26,9 +26,10 @@ const fetchAndUpdate = ({ listId = false, tag = false, until, - since + since, + params }) => { - const args = { timeline, credentials } + const args = { timeline, credentials, params } const rootState = store.rootState || store.state const { getters } = store const timelineData = rootState.statuses.timelines[camelCase(timeline)] @@ -78,13 +79,13 @@ const fetchAndUpdate = ({ }) } -const startFetching = ({ timeline = 'friends', credentials, store, userId = false, listId = false, tag = false }) => { +const startFetching = ({ timeline = 'friends', credentials, store, userId = false, listId = false, tag = false, params }) => { const rootState = store.rootState || store.state const timelineData = rootState.statuses.timelines[camelCase(timeline)] const showImmediately = timelineData.visibleStatuses.length === 0 timelineData.userId = userId timelineData.listId = listId - fetchAndUpdate({ timeline, credentials, store, showImmediately, userId, listId, tag }) + fetchAndUpdate({ timeline, credentials, store, showImmediately, userId, listId, tag, params }) const boundFetchAndUpdate = () => fetchAndUpdate({ timeline, credentials, store, userId, listId, tag }) return promiseInterval(boundFetchAndUpdate, 20000)