Merge branch '564' into 'develop'
Restore scroll position for user profile when navigate back and forward Closes #636 and #564 See merge request pleroma/pleroma-fe!914
This commit is contained in:
commit
e5fe4f420c
7 changed files with 89 additions and 74 deletions
|
@ -13,8 +13,8 @@ const Interactions = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onModeSwitch (index, dataset) {
|
onModeSwitch (key) {
|
||||||
this.filterMode = tabModeDict[dataset.filter]
|
this.filterMode = tabModeDict[key]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -10,18 +10,15 @@
|
||||||
:on-switch="onModeSwitch"
|
:on-switch="onModeSwitch"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
data-tab-dummy
|
key="mentions"
|
||||||
data-filter="mentions"
|
|
||||||
:label="$t('nav.mentions')"
|
:label="$t('nav.mentions')"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
data-tab-dummy
|
key="likes+repeats"
|
||||||
data-filter="likes+repeats"
|
|
||||||
:label="$t('interactions.favs_repeats')"
|
:label="$t('interactions.favs_repeats')"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
data-tab-dummy
|
key="follows"
|
||||||
data-filter="follows"
|
|
||||||
:label="$t('interactions.follows')"
|
:label="$t('interactions.follows')"
|
||||||
/>
|
/>
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
|
|
|
@ -75,8 +75,8 @@ const Search = {
|
||||||
const length = this[tabName].length
|
const length = this[tabName].length
|
||||||
return length === 0 ? '' : ` (${length})`
|
return length === 0 ? '' : ` (${length})`
|
||||||
},
|
},
|
||||||
onResultTabSwitch (_index, dataset) {
|
onResultTabSwitch (key) {
|
||||||
this.currenResultTab = dataset.filter
|
this.currenResultTab = key
|
||||||
},
|
},
|
||||||
getActiveTab () {
|
getActiveTab () {
|
||||||
if (this.visibleStatuses.length > 0) {
|
if (this.visibleStatuses.length > 0) {
|
||||||
|
|
|
@ -31,21 +31,18 @@
|
||||||
<tab-switcher
|
<tab-switcher
|
||||||
ref="tabSwitcher"
|
ref="tabSwitcher"
|
||||||
:on-switch="onResultTabSwitch"
|
:on-switch="onResultTabSwitch"
|
||||||
:custom-active="currenResultTab"
|
:active-tab="currenResultTab"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
data-tab-dummy
|
key="statuses"
|
||||||
data-filter="statuses"
|
|
||||||
:label="$t('user_card.statuses') + resultCount('visibleStatuses')"
|
:label="$t('user_card.statuses') + resultCount('visibleStatuses')"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
data-tab-dummy
|
key="people"
|
||||||
data-filter="people"
|
|
||||||
:label="$t('search.people') + resultCount('users')"
|
:label="$t('search.people') + resultCount('users')"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
data-tab-dummy
|
key="hashtags"
|
||||||
data-filter="hashtags"
|
|
||||||
:label="$t('search.hashtags') + resultCount('hashtags')"
|
:label="$t('search.hashtags') + resultCount('hashtags')"
|
||||||
/>
|
/>
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
|
|
|
@ -4,12 +4,22 @@ import './tab_switcher.scss'
|
||||||
|
|
||||||
export default Vue.component('tab-switcher', {
|
export default Vue.component('tab-switcher', {
|
||||||
name: 'TabSwitcher',
|
name: 'TabSwitcher',
|
||||||
props: ['renderOnlyFocused', 'onSwitch', 'customActive'],
|
props: ['renderOnlyFocused', 'onSwitch', 'activeTab'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
active: this.$slots.default.findIndex(_ => _.tag)
|
active: this.$slots.default.findIndex(_ => _.tag)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
activeIndex () {
|
||||||
|
// In case of controlled component
|
||||||
|
if (this.activeTab) {
|
||||||
|
return this.$slots.default.findIndex(slot => this.activeTab === slot.key)
|
||||||
|
} else {
|
||||||
|
return this.active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
beforeUpdate () {
|
beforeUpdate () {
|
||||||
const currentSlot = this.$slots.default[this.active]
|
const currentSlot = this.$slots.default[this.active]
|
||||||
if (!currentSlot.tag) {
|
if (!currentSlot.tag) {
|
||||||
|
@ -17,21 +27,13 @@ export default Vue.component('tab-switcher', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
activateTab (index, dataset) {
|
activateTab (index) {
|
||||||
return () => {
|
return () => {
|
||||||
if (typeof this.onSwitch === 'function') {
|
if (typeof this.onSwitch === 'function') {
|
||||||
this.onSwitch.call(null, index, this.$slots.default[index].elm.dataset)
|
this.onSwitch.call(null, this.$slots.default[index].key)
|
||||||
}
|
}
|
||||||
this.active = index
|
this.active = index
|
||||||
}
|
}
|
||||||
},
|
|
||||||
isActiveTab (index) {
|
|
||||||
const customActiveIndex = this.$slots.default.findIndex(slot => {
|
|
||||||
const dataFilter = slot.data && slot.data.attrs && slot.data.attrs['data-filter']
|
|
||||||
return this.customActive && this.customActive === dataFilter
|
|
||||||
})
|
|
||||||
|
|
||||||
return customActiveIndex > -1 ? customActiveIndex === index : index === this.active
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render (h) {
|
render (h) {
|
||||||
|
@ -41,13 +43,13 @@ export default Vue.component('tab-switcher', {
|
||||||
const classesTab = ['tab']
|
const classesTab = ['tab']
|
||||||
const classesWrapper = ['tab-wrapper']
|
const classesWrapper = ['tab-wrapper']
|
||||||
|
|
||||||
if (this.isActiveTab(index)) {
|
if (this.activeIndex === index) {
|
||||||
classesTab.push('active')
|
classesTab.push('active')
|
||||||
classesWrapper.push('active')
|
classesWrapper.push('active')
|
||||||
}
|
}
|
||||||
if (slot.data.attrs.image) {
|
if (slot.data.attrs.image) {
|
||||||
return (
|
return (
|
||||||
<div class={ classesWrapper.join(' ')}>
|
<div class={classesWrapper.join(' ')}>
|
||||||
<button
|
<button
|
||||||
disabled={slot.data.attrs.disabled}
|
disabled={slot.data.attrs.disabled}
|
||||||
onClick={this.activateTab(index)}
|
onClick={this.activateTab(index)}
|
||||||
|
@ -59,7 +61,7 @@ export default Vue.component('tab-switcher', {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div class={ classesWrapper.join(' ')}>
|
<div class={classesWrapper.join(' ')}>
|
||||||
<button
|
<button
|
||||||
disabled={slot.data.attrs.disabled}
|
disabled={slot.data.attrs.disabled}
|
||||||
onClick={this.activateTab(index)}
|
onClick={this.activateTab(index)}
|
||||||
|
@ -71,7 +73,7 @@ export default Vue.component('tab-switcher', {
|
||||||
|
|
||||||
const contents = this.$slots.default.map((slot, index) => {
|
const contents = this.$slots.default.map((slot, index) => {
|
||||||
if (!slot.tag) return
|
if (!slot.tag) return
|
||||||
const active = index === this.active
|
const active = this.activeIndex === index
|
||||||
if (this.renderOnlyFocused) {
|
if (this.renderOnlyFocused) {
|
||||||
return active
|
return active
|
||||||
? <div class="active">{slot}</div>
|
? <div class="active">{slot}</div>
|
||||||
|
|
|
@ -22,21 +22,23 @@ const FriendList = withLoadMore({
|
||||||
additionalPropNames: ['userId']
|
additionalPropNames: ['userId']
|
||||||
})(List)
|
})(List)
|
||||||
|
|
||||||
|
const defaultTabKey = 'statuses'
|
||||||
|
|
||||||
const UserProfile = {
|
const UserProfile = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
error: false,
|
error: false,
|
||||||
userId: null
|
userId: null,
|
||||||
|
tab: defaultTabKey
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
// Make sure that timelines used in this page are empty
|
|
||||||
this.cleanUp()
|
|
||||||
const routeParams = this.$route.params
|
const routeParams = this.$route.params
|
||||||
this.load(routeParams.name || routeParams.id)
|
this.load(routeParams.name || routeParams.id)
|
||||||
|
this.tab = get(this.$route, 'query.tab', defaultTabKey)
|
||||||
},
|
},
|
||||||
destroyed () {
|
destroyed () {
|
||||||
this.cleanUp()
|
this.stopFetching()
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
timeline () {
|
timeline () {
|
||||||
|
@ -67,17 +69,36 @@ const UserProfile = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
load (userNameOrId) {
|
load (userNameOrId) {
|
||||||
|
const startFetchingTimeline = (timeline, userId) => {
|
||||||
|
// Clear timeline only if load another user's profile
|
||||||
|
if (userId !== this.$store.state.statuses.timelines[timeline].userId) {
|
||||||
|
this.$store.commit('clearTimeline', { timeline })
|
||||||
|
}
|
||||||
|
this.$store.dispatch('startFetchingTimeline', { timeline, userId })
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadById = (userId) => {
|
||||||
|
this.userId = userId
|
||||||
|
startFetchingTimeline('user', userId)
|
||||||
|
startFetchingTimeline('media', userId)
|
||||||
|
if (this.isUs) {
|
||||||
|
startFetchingTimeline('favorites', userId)
|
||||||
|
}
|
||||||
|
// Fetch all pinned statuses immediately
|
||||||
|
this.$store.dispatch('fetchPinnedStatuses', userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset view
|
||||||
|
this.userId = null
|
||||||
|
this.error = false
|
||||||
|
|
||||||
// Check if user data is already loaded in store
|
// Check if user data is already loaded in store
|
||||||
const user = this.$store.getters.findUser(userNameOrId)
|
const user = this.$store.getters.findUser(userNameOrId)
|
||||||
if (user) {
|
if (user) {
|
||||||
this.userId = user.id
|
loadById(user.id)
|
||||||
this.fetchTimelines()
|
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('fetchUser', userNameOrId)
|
this.$store.dispatch('fetchUser', userNameOrId)
|
||||||
.then(({ id }) => {
|
.then(({ id }) => loadById(id))
|
||||||
this.userId = id
|
|
||||||
this.fetchTimelines()
|
|
||||||
})
|
|
||||||
.catch((reason) => {
|
.catch((reason) => {
|
||||||
const errorMessage = get(reason, 'error.error')
|
const errorMessage = get(reason, 'error.error')
|
||||||
if (errorMessage === 'No user with such user_id') { // Known error
|
if (errorMessage === 'No user with such user_id') { // Known error
|
||||||
|
@ -90,40 +111,33 @@ const UserProfile = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchTimelines () {
|
stopFetching () {
|
||||||
const userId = this.userId
|
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'user', userId })
|
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'media', userId })
|
|
||||||
if (this.isUs) {
|
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'favorites', userId })
|
|
||||||
}
|
|
||||||
// Fetch all pinned statuses immediately
|
|
||||||
this.$store.dispatch('fetchPinnedStatuses', userId)
|
|
||||||
},
|
|
||||||
cleanUp () {
|
|
||||||
this.$store.dispatch('stopFetching', 'user')
|
this.$store.dispatch('stopFetching', 'user')
|
||||||
this.$store.dispatch('stopFetching', 'favorites')
|
this.$store.dispatch('stopFetching', 'favorites')
|
||||||
this.$store.dispatch('stopFetching', 'media')
|
this.$store.dispatch('stopFetching', 'media')
|
||||||
this.$store.commit('clearTimeline', { timeline: 'user' })
|
},
|
||||||
this.$store.commit('clearTimeline', { timeline: 'favorites' })
|
switchUser (userNameOrId) {
|
||||||
this.$store.commit('clearTimeline', { timeline: 'media' })
|
this.stopFetching()
|
||||||
|
this.load(userNameOrId)
|
||||||
|
},
|
||||||
|
onTabSwitch (tab) {
|
||||||
|
this.tab = tab
|
||||||
|
this.$router.replace({ query: { tab } })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route.params.id': function (newVal) {
|
'$route.params.id': function (newVal) {
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
this.cleanUp()
|
this.switchUser(newVal)
|
||||||
this.load(newVal)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'$route.params.name': function (newVal) {
|
'$route.params.name': function (newVal) {
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
this.cleanUp()
|
this.switchUser(newVal)
|
||||||
this.load(newVal)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
$route () {
|
'$route.query': function (newVal) {
|
||||||
this.$refs.tabSwitcher.activateTab(0)()
|
this.tab = newVal.tab || defaultTabKey
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -12,22 +12,24 @@
|
||||||
rounded="top"
|
rounded="top"
|
||||||
/>
|
/>
|
||||||
<tab-switcher
|
<tab-switcher
|
||||||
ref="tabSwitcher"
|
:active-tab="tab"
|
||||||
:render-only-focused="true"
|
:render-only-focused="true"
|
||||||
|
:on-switch="onTabSwitch"
|
||||||
>
|
>
|
||||||
<div :label="$t('user_card.statuses')">
|
<Timeline
|
||||||
<Timeline
|
key="statuses"
|
||||||
:count="user.statuses_count"
|
:label="$t('user_card.statuses')"
|
||||||
:embedded="true"
|
:count="user.statuses_count"
|
||||||
:title="$t('user_profile.timeline_title')"
|
:embedded="true"
|
||||||
:timeline="timeline"
|
:title="$t('user_profile.timeline_title')"
|
||||||
timeline-name="user"
|
:timeline="timeline"
|
||||||
:user-id="userId"
|
timeline-name="user"
|
||||||
:pinned-status-ids="user.pinnedStatusIds"
|
:user-id="userId"
|
||||||
/>
|
:pinned-status-ids="user.pinnedStatusIds"
|
||||||
</div>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="followsTabVisible"
|
v-if="followsTabVisible"
|
||||||
|
key="followees"
|
||||||
:label="$t('user_card.followees')"
|
:label="$t('user_card.followees')"
|
||||||
:disabled="!user.friends_count"
|
:disabled="!user.friends_count"
|
||||||
>
|
>
|
||||||
|
@ -42,6 +44,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="followersTabVisible"
|
v-if="followersTabVisible"
|
||||||
|
key="followers"
|
||||||
:label="$t('user_card.followers')"
|
:label="$t('user_card.followers')"
|
||||||
:disabled="!user.followers_count"
|
:disabled="!user.followers_count"
|
||||||
>
|
>
|
||||||
|
@ -58,6 +61,7 @@
|
||||||
</FollowerList>
|
</FollowerList>
|
||||||
</div>
|
</div>
|
||||||
<Timeline
|
<Timeline
|
||||||
|
key="media"
|
||||||
:label="$t('user_card.media')"
|
:label="$t('user_card.media')"
|
||||||
:disabled="!media.visibleStatuses.length"
|
:disabled="!media.visibleStatuses.length"
|
||||||
:embedded="true"
|
:embedded="true"
|
||||||
|
@ -68,6 +72,7 @@
|
||||||
/>
|
/>
|
||||||
<Timeline
|
<Timeline
|
||||||
v-if="isUs"
|
v-if="isUs"
|
||||||
|
key="favorites"
|
||||||
:label="$t('user_card.favorites')"
|
:label="$t('user_card.favorites')"
|
||||||
:disabled="!favorites.visibleStatuses.length"
|
:disabled="!favorites.visibleStatuses.length"
|
||||||
:embedded="true"
|
:embedded="true"
|
||||||
|
|
Loading…
Reference in a new issue