Merge branch 'fix/timeline-error-handling-fixes' into 'develop'
Various timeline fixes See merge request pleroma/pleroma-fe!1283
This commit is contained in:
commit
d770bab1b0
|
@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed the occasional bug where screen would scroll 1px when typing into a reply form
|
- Fixed the occasional bug where screen would scroll 1px when typing into a reply form
|
||||||
|
- Fixed timeline errors locking timelines
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Errors when fetching are now shown with popup errors instead of "Error fetching updates" in panel headers
|
||||||
- Fixed custom emoji not working in profile field names
|
- Fixed custom emoji not working in profile field names
|
||||||
- Fixed pinned statuses not appearing in user profiles
|
- Fixed pinned statuses not appearing in user profiles
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,6 @@
|
||||||
class="badge badge-notification unseen-count"
|
class="badge badge-notification unseen-count"
|
||||||
>{{ unseenCount }}</span>
|
>{{ unseenCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
v-if="error"
|
|
||||||
class="loadmore-error alert error"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('timeline.error_fetching') }}
|
|
||||||
</div>
|
|
||||||
<button
|
<button
|
||||||
v-if="unseenCount"
|
v-if="unseenCount"
|
||||||
class="read-button"
|
class="read-button"
|
||||||
|
|
|
@ -50,17 +50,10 @@ const Timeline = {
|
||||||
TimelineMenu
|
TimelineMenu
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
timelineError () {
|
|
||||||
return this.$store.state.statuses.error
|
|
||||||
},
|
|
||||||
errorData () {
|
|
||||||
return this.$store.state.statuses.errorData
|
|
||||||
},
|
|
||||||
newStatusCount () {
|
newStatusCount () {
|
||||||
return this.timeline.newStatusCount
|
return this.timeline.newStatusCount
|
||||||
},
|
},
|
||||||
showLoadButton () {
|
showLoadButton () {
|
||||||
if (this.timelineError || this.errorData) return false
|
|
||||||
return this.timeline.newStatusCount > 0 || this.timeline.flushMarker !== 0
|
return this.timeline.newStatusCount > 0 || this.timeline.flushMarker !== 0
|
||||||
},
|
},
|
||||||
loadButtonString () {
|
loadButtonString () {
|
||||||
|
@ -171,11 +164,12 @@ const Timeline = {
|
||||||
userId: this.userId,
|
userId: this.userId,
|
||||||
tag: this.tag
|
tag: this.tag
|
||||||
}).then(({ statuses }) => {
|
}).then(({ statuses }) => {
|
||||||
store.commit('setLoading', { timeline: this.timelineName, value: false })
|
|
||||||
if (statuses && statuses.length === 0) {
|
if (statuses && statuses.length === 0) {
|
||||||
this.bottomedOut = true
|
this.bottomedOut = true
|
||||||
}
|
}
|
||||||
})
|
}).finally(() =>
|
||||||
|
store.commit('setLoading', { timeline: this.timelineName, value: false })
|
||||||
|
)
|
||||||
}, 1000, this),
|
}, 1000, this),
|
||||||
determineVisibleStatuses () {
|
determineVisibleStatuses () {
|
||||||
if (!this.$refs.timeline) return
|
if (!this.$refs.timeline) return
|
||||||
|
|
|
@ -2,22 +2,8 @@
|
||||||
<div :class="[classes.root, 'Timeline']">
|
<div :class="[classes.root, 'Timeline']">
|
||||||
<div :class="classes.header">
|
<div :class="classes.header">
|
||||||
<TimelineMenu v-if="!embedded" />
|
<TimelineMenu v-if="!embedded" />
|
||||||
<div
|
|
||||||
v-if="timelineError"
|
|
||||||
class="loadmore-error alert error"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('timeline.error_fetching') }}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else-if="errorData"
|
|
||||||
class="loadmore-error alert error"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ errorData.statusText }}
|
|
||||||
</div>
|
|
||||||
<button
|
<button
|
||||||
v-else-if="showLoadButton"
|
v-if="showLoadButton"
|
||||||
class="loadmore-button"
|
class="loadmore-button"
|
||||||
@click.prevent="showNewStatuses"
|
@click.prevent="showNewStatuses"
|
||||||
>
|
>
|
||||||
|
@ -76,18 +62,12 @@
|
||||||
{{ $t('timeline.no_more_statuses') }}
|
{{ $t('timeline.no_more_statuses') }}
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
v-else-if="!timeline.loading && !errorData"
|
v-else-if="!timeline.loading"
|
||||||
href="#"
|
href="#"
|
||||||
@click.prevent="fetchOlderStatuses()"
|
@click.prevent="fetchOlderStatuses()"
|
||||||
>
|
>
|
||||||
<div class="new-status-notification text-center panel-footer">{{ $t('timeline.load_older') }}</div>
|
<div class="new-status-notification text-center panel-footer">{{ $t('timeline.load_older') }}</div>
|
||||||
</a>
|
</a>
|
||||||
<a
|
|
||||||
v-else-if="errorData"
|
|
||||||
href="#"
|
|
||||||
>
|
|
||||||
<div class="new-status-notification text-center panel-footer">{{ errorData.error }}</div>
|
|
||||||
</a>
|
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="new-status-notification text-center panel-footer"
|
class="new-status-notification text-center panel-footer"
|
||||||
|
|
|
@ -19,7 +19,7 @@ library.add(
|
||||||
faChevronDown
|
faChevronDown
|
||||||
)
|
)
|
||||||
|
|
||||||
// Route -> i18n key mapping, exported andnot in the computed
|
// Route -> i18n key mapping, exported and not in the computed
|
||||||
// because nav panel benefits from the same information.
|
// because nav panel benefits from the same information.
|
||||||
export const timelineNames = () => {
|
export const timelineNames = () => {
|
||||||
return {
|
return {
|
||||||
|
@ -27,8 +27,7 @@ export const timelineNames = () => {
|
||||||
'bookmarks': 'nav.bookmarks',
|
'bookmarks': 'nav.bookmarks',
|
||||||
'dms': 'nav.dms',
|
'dms': 'nav.dms',
|
||||||
'public-timeline': 'nav.public_tl',
|
'public-timeline': 'nav.public_tl',
|
||||||
'public-external-timeline': 'nav.twkn',
|
'public-external-timeline': 'nav.twkn'
|
||||||
'tag-timeline': 'tag'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,7 @@
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"broken_favorite": "Unknown status, searching for it…",
|
"broken_favorite": "Unknown status, searching for it…",
|
||||||
|
"error": "Error fetching notifications: {0}",
|
||||||
"favorited_you": "favorited your status",
|
"favorited_you": "favorited your status",
|
||||||
"followed_you": "followed you",
|
"followed_you": "followed you",
|
||||||
"follow_request": "wants to follow you",
|
"follow_request": "wants to follow you",
|
||||||
|
@ -634,7 +635,7 @@
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"collapse": "Collapse",
|
"collapse": "Collapse",
|
||||||
"conversation": "Conversation",
|
"conversation": "Conversation",
|
||||||
"error_fetching": "Error fetching updates",
|
"error": "Error fetching timeline: {0}",
|
||||||
"load_older": "Load older statuses",
|
"load_older": "Load older statuses",
|
||||||
"no_retweet_hint": "Post is marked as followers-only or direct and cannot be repeated",
|
"no_retweet_hint": "Post is marked as followers-only or direct and cannot be repeated",
|
||||||
"repeated": "repeated",
|
"repeated": "repeated",
|
||||||
|
|
|
@ -39,8 +39,7 @@ const emptyNotifications = () => ({
|
||||||
minId: Number.POSITIVE_INFINITY,
|
minId: Number.POSITIVE_INFINITY,
|
||||||
data: [],
|
data: [],
|
||||||
idStore: {},
|
idStore: {},
|
||||||
loading: false,
|
loading: false
|
||||||
error: false
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const defaultState = () => ({
|
export const defaultState = () => ({
|
||||||
|
@ -50,8 +49,6 @@ export const defaultState = () => ({
|
||||||
maxId: 0,
|
maxId: 0,
|
||||||
notifications: emptyNotifications(),
|
notifications: emptyNotifications(),
|
||||||
favorites: new Set(),
|
favorites: new Set(),
|
||||||
error: false,
|
|
||||||
errorData: null,
|
|
||||||
timelines: {
|
timelines: {
|
||||||
mentions: emptyTl(),
|
mentions: emptyTl(),
|
||||||
public: emptyTl(),
|
public: emptyTl(),
|
||||||
|
@ -462,18 +459,9 @@ export const mutations = {
|
||||||
const newStatus = state.allStatusesObject[id]
|
const newStatus = state.allStatusesObject[id]
|
||||||
newStatus.nsfw = nsfw
|
newStatus.nsfw = nsfw
|
||||||
},
|
},
|
||||||
setError (state, { value }) {
|
|
||||||
state.error = value
|
|
||||||
},
|
|
||||||
setErrorData (state, { value }) {
|
|
||||||
state.errorData = value
|
|
||||||
},
|
|
||||||
setNotificationsLoading (state, { value }) {
|
setNotificationsLoading (state, { value }) {
|
||||||
state.notifications.loading = value
|
state.notifications.loading = value
|
||||||
},
|
},
|
||||||
setNotificationsError (state, { value }) {
|
|
||||||
state.notifications.error = value
|
|
||||||
},
|
|
||||||
setNotificationsSilence (state, { value }) {
|
setNotificationsSilence (state, { value }) {
|
||||||
state.notifications.desktopNotificationSilence = value
|
state.notifications.desktopNotificationSilence = value
|
||||||
},
|
},
|
||||||
|
@ -588,18 +576,9 @@ const statuses = {
|
||||||
}
|
}
|
||||||
commit('addNewNotifications', { dispatch, notifications, older, rootGetters, newNotificationSideEffects })
|
commit('addNewNotifications', { dispatch, notifications, older, rootGetters, newNotificationSideEffects })
|
||||||
},
|
},
|
||||||
setError ({ rootState, commit }, { value }) {
|
|
||||||
commit('setError', { value })
|
|
||||||
},
|
|
||||||
setErrorData ({ rootState, commit }, { value }) {
|
|
||||||
commit('setErrorData', { value })
|
|
||||||
},
|
|
||||||
setNotificationsLoading ({ rootState, commit }, { value }) {
|
setNotificationsLoading ({ rootState, commit }, { value }) {
|
||||||
commit('setNotificationsLoading', { value })
|
commit('setNotificationsLoading', { value })
|
||||||
},
|
},
|
||||||
setNotificationsError ({ rootState, commit }, { value }) {
|
|
||||||
commit('setNotificationsError', { value })
|
|
||||||
},
|
|
||||||
setNotificationsSilence ({ rootState, commit }, { value }) {
|
setNotificationsSilence ({ rootState, commit }, { value }) {
|
||||||
commit('setNotificationsSilence', { value })
|
commit('setNotificationsSilence', { value })
|
||||||
},
|
},
|
||||||
|
|
|
@ -560,7 +560,7 @@ const fetchTimeline = ({
|
||||||
})
|
})
|
||||||
.then((data) => data.json())
|
.then((data) => data.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data.error) {
|
if (!data.errors) {
|
||||||
return { data: data.map(isNotifications ? parseNotification : parseStatus), pagination }
|
return { data: data.map(isNotifications ? parseNotification : parseStatus), pagination }
|
||||||
} else {
|
} else {
|
||||||
data.status = status
|
data.status = status
|
||||||
|
|
|
@ -2,7 +2,6 @@ import apiService from '../api/api.service.js'
|
||||||
import { promiseInterval } from '../promise_interval/promise_interval.js'
|
import { promiseInterval } from '../promise_interval/promise_interval.js'
|
||||||
|
|
||||||
const update = ({ store, notifications, older }) => {
|
const update = ({ store, notifications, older }) => {
|
||||||
store.dispatch('setNotificationsError', { value: false })
|
|
||||||
store.dispatch('addNewNotifications', { notifications, older })
|
store.dispatch('addNewNotifications', { notifications, older })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +46,22 @@ const fetchAndUpdate = ({ store, credentials, older = false }) => {
|
||||||
|
|
||||||
const fetchNotifications = ({ store, args, older }) => {
|
const fetchNotifications = ({ store, args, older }) => {
|
||||||
return apiService.fetchTimeline(args)
|
return apiService.fetchTimeline(args)
|
||||||
.then(({ data: notifications }) => {
|
.then((response) => {
|
||||||
|
if (response.errors) {
|
||||||
|
throw new Error(`${response.status} ${response.statusText}`)
|
||||||
|
}
|
||||||
|
const notifications = response.data
|
||||||
update({ store, notifications, older })
|
update({ store, notifications, older })
|
||||||
return notifications
|
return notifications
|
||||||
}, () => store.dispatch('setNotificationsError', { value: true }))
|
})
|
||||||
.catch(() => store.dispatch('setNotificationsError', { value: true }))
|
.catch((error) => {
|
||||||
|
store.dispatch('pushGlobalNotice', {
|
||||||
|
level: 'error',
|
||||||
|
messageKey: 'notifications.error',
|
||||||
|
messageArgs: [error.message],
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const startFetching = ({ credentials, store }) => {
|
const startFetching = ({ credentials, store }) => {
|
||||||
|
|
|
@ -6,9 +6,6 @@ import { promiseInterval } from '../promise_interval/promise_interval.js'
|
||||||
const update = ({ store, statuses, timeline, showImmediately, userId, pagination }) => {
|
const update = ({ store, statuses, timeline, showImmediately, userId, pagination }) => {
|
||||||
const ccTimeline = camelCase(timeline)
|
const ccTimeline = camelCase(timeline)
|
||||||
|
|
||||||
store.dispatch('setError', { value: false })
|
|
||||||
store.dispatch('setErrorData', { value: null })
|
|
||||||
|
|
||||||
store.dispatch('addNewStatuses', {
|
store.dispatch('addNewStatuses', {
|
||||||
timeline: ccTimeline,
|
timeline: ccTimeline,
|
||||||
userId,
|
userId,
|
||||||
|
@ -52,9 +49,8 @@ const fetchAndUpdate = ({
|
||||||
|
|
||||||
return apiService.fetchTimeline(args)
|
return apiService.fetchTimeline(args)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.error) {
|
if (response.errors) {
|
||||||
store.dispatch('setErrorData', { value: response })
|
throw new Error(`${response.status} ${response.statusText}`)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: statuses, pagination } = response
|
const { data: statuses, pagination } = response
|
||||||
|
@ -63,7 +59,15 @@ const fetchAndUpdate = ({
|
||||||
}
|
}
|
||||||
update({ store, statuses, timeline, showImmediately, userId, pagination })
|
update({ store, statuses, timeline, showImmediately, userId, pagination })
|
||||||
return { statuses, pagination }
|
return { statuses, pagination }
|
||||||
}, () => store.dispatch('setError', { value: true }))
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
store.dispatch('pushGlobalNotice', {
|
||||||
|
level: 'error',
|
||||||
|
messageKey: 'timeline.error',
|
||||||
|
messageArgs: [error.message],
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const startFetching = ({ timeline = 'friends', credentials, store, userId = false, tag = false }) => {
|
const startFetching = ({ timeline = 'friends', credentials, store, userId = false, tag = false }) => {
|
||||||
|
|
|
@ -8,8 +8,7 @@ const localVue = createLocalVue()
|
||||||
localVue.use(Vuex)
|
localVue.use(Vuex)
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
clearTimeline: () => {},
|
clearTimeline: () => {}
|
||||||
setError: () => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
|
Loading…
Reference in New Issue