Merge branch 'fix/wait-for-request-before-starting-interval' into 'develop'

Fix/wait for request before starting interval - fix #937

Closes #937

See merge request pleroma/pleroma-fe!1222
This commit is contained in:
Shpuld Shpludson 2020-10-01 13:20:14 +00:00
commit 6bd38c7d6f
8 changed files with 49 additions and 16 deletions

View File

@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Polls will be hidden with status content if "Collapse posts with subjects" is enabled and the post is collapsed. - Polls will be hidden with status content if "Collapse posts with subjects" is enabled and the post is collapsed.
### Fixed ### Fixed
- Network fetches don't pile up anymore but wait for previous ones to finish to reduce throttling.
- Autocomplete won't stop at the second @, so it'll still work with "@lain@l" and not start over. - Autocomplete won't stop at the second @, so it'll still work with "@lain@l" and not start over.
- Fixed weird autocomplete behavior when you write ":custom_emoji: ?" - Fixed weird autocomplete behavior when you write ":custom_emoji: ?"

View File

@ -5,6 +5,7 @@ import ChatMessage from '../chat_message/chat_message.vue'
import PostStatusForm from '../post_status_form/post_status_form.vue' import PostStatusForm from '../post_status_form/post_status_form.vue'
import ChatTitle from '../chat_title/chat_title.vue' import ChatTitle from '../chat_title/chat_title.vue'
import chatService from '../../services/chat_service/chat_service.js' import chatService from '../../services/chat_service/chat_service.js'
import { promiseInterval } from '../../services/promise_interval/promise_interval.js'
import { getScrollPosition, getNewTopPosition, isBottomedOut, scrollableContainerHeight } from './chat_layout_utils.js' import { getScrollPosition, getNewTopPosition, isBottomedOut, scrollableContainerHeight } from './chat_layout_utils.js'
const BOTTOMED_OUT_OFFSET = 10 const BOTTOMED_OUT_OFFSET = 10
@ -246,7 +247,7 @@ const Chat = {
const fetchOlderMessages = !!maxId const fetchOlderMessages = !!maxId
const sinceId = fetchLatest && chatMessageService.maxId const sinceId = fetchLatest && chatMessageService.maxId
this.backendInteractor.chatMessages({ id: chatId, maxId, sinceId }) return this.backendInteractor.chatMessages({ id: chatId, maxId, sinceId })
.then((messages) => { .then((messages) => {
// Clear the current chat in case we're recovering from a ws connection loss. // Clear the current chat in case we're recovering from a ws connection loss.
if (isFirstFetch) { if (isFirstFetch) {
@ -287,7 +288,7 @@ const Chat = {
}, },
doStartFetching () { doStartFetching () {
this.$store.dispatch('startFetchingCurrentChat', { this.$store.dispatch('startFetchingCurrentChat', {
fetcher: () => setInterval(() => this.fetchChat({ fetchLatest: true }), 5000) fetcher: () => promiseInterval(() => this.fetchChat({ fetchLatest: true }), 5000)
}) })
this.fetchChat({ isFirstFetch: true }) this.fetchChat({ isFirstFetch: true })
}, },

View File

@ -20,7 +20,7 @@ const api = {
state.fetchers[fetcherName] = fetcher state.fetchers[fetcherName] = fetcher
}, },
removeFetcher (state, { fetcherName, fetcher }) { removeFetcher (state, { fetcherName, fetcher }) {
window.clearInterval(fetcher) state.fetchers[fetcherName].stop()
delete state.fetchers[fetcherName] delete state.fetchers[fetcherName]
}, },
setWsToken (state, token) { setWsToken (state, token) {

View File

@ -3,6 +3,7 @@ import { find, omitBy, orderBy, sumBy } from 'lodash'
import chatService from '../services/chat_service/chat_service.js' import chatService from '../services/chat_service/chat_service.js'
import { parseChat, parseChatMessage } from '../services/entity_normalizer/entity_normalizer.service.js' import { parseChat, parseChatMessage } from '../services/entity_normalizer/entity_normalizer.service.js'
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js' import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
import { promiseInterval } from '../services/promise_interval/promise_interval.js'
const emptyChatList = () => ({ const emptyChatList = () => ({
data: [], data: [],
@ -42,12 +43,10 @@ const chats = {
actions: { actions: {
// Chat list // Chat list
startFetchingChats ({ dispatch, commit }) { startFetchingChats ({ dispatch, commit }) {
const fetcher = () => { const fetcher = () => dispatch('fetchChats', { latest: true })
dispatch('fetchChats', { latest: true })
}
fetcher() fetcher()
commit('setChatListFetcher', { commit('setChatListFetcher', {
fetcher: () => setInterval(() => { fetcher() }, 5000) fetcher: () => promiseInterval(fetcher, 5000)
}) })
}, },
stopFetchingChats ({ commit }) { stopFetchingChats ({ commit }) {
@ -113,14 +112,14 @@ const chats = {
setChatListFetcher (state, { commit, fetcher }) { setChatListFetcher (state, { commit, fetcher }) {
const prevFetcher = state.chatListFetcher const prevFetcher = state.chatListFetcher
if (prevFetcher) { if (prevFetcher) {
clearInterval(prevFetcher) prevFetcher.stop()
} }
state.chatListFetcher = fetcher && fetcher() state.chatListFetcher = fetcher && fetcher()
}, },
setCurrentChatFetcher (state, { fetcher }) { setCurrentChatFetcher (state, { fetcher }) {
const prevFetcher = state.fetcher const prevFetcher = state.fetcher
if (prevFetcher) { if (prevFetcher) {
clearInterval(prevFetcher) prevFetcher.stop()
} }
state.fetcher = fetcher && fetcher() state.fetcher = fetcher && fetcher()
}, },

View File

@ -1,4 +1,5 @@
import apiService from '../api/api.service.js' import apiService from '../api/api.service.js'
import { promiseInterval } from '../promise_interval/promise_interval.js'
const fetchAndUpdate = ({ store, credentials }) => { const fetchAndUpdate = ({ store, credentials }) => {
return apiService.fetchFollowRequests({ credentials }) return apiService.fetchFollowRequests({ credentials })
@ -10,9 +11,9 @@ const fetchAndUpdate = ({ store, credentials }) => {
} }
const startFetching = ({ credentials, store }) => { const startFetching = ({ credentials, store }) => {
fetchAndUpdate({ credentials, store })
const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store }) const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store })
return setInterval(boundFetchAndUpdate, 10000) boundFetchAndUpdate()
return promiseInterval(boundFetchAndUpdate, 10000)
} }
const followRequestFetcher = { const followRequestFetcher = {

View File

@ -1,4 +1,5 @@
import apiService from '../api/api.service.js' import apiService from '../api/api.service.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('setNotificationsError', { value: false })
@ -39,6 +40,7 @@ const fetchAndUpdate = ({ store, credentials, older = false }) => {
args['since'] = Math.max(...readNotifsIds) args['since'] = Math.max(...readNotifsIds)
fetchNotifications({ store, args, older }) fetchNotifications({ store, args, older })
} }
return result return result
} }
} }
@ -53,13 +55,13 @@ const fetchNotifications = ({ store, args, older }) => {
} }
const startFetching = ({ credentials, store }) => { const startFetching = ({ credentials, store }) => {
fetchAndUpdate({ credentials, store })
const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store })
// Initially there's set flag to silence all desktop notifications so // Initially there's set flag to silence all desktop notifications so
// that there won't spam of them when user just opened up the FE we // that there won't spam of them when user just opened up the FE we
// reset that flag after a while to show new notifications once again. // reset that flag after a while to show new notifications once again.
setTimeout(() => store.dispatch('setNotificationsSilence', false), 10000) setTimeout(() => store.dispatch('setNotificationsSilence', false), 10000)
return setInterval(boundFetchAndUpdate, 10000) const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store })
boundFetchAndUpdate()
return promiseInterval(boundFetchAndUpdate, 10000)
} }
const notificationsFetcher = { const notificationsFetcher = {

View File

@ -0,0 +1,27 @@
// promiseInterval - replacement for setInterval for promises, starts counting
// the interval only after a promise is done instead of immediately.
// - promiseCall is a function that returns a promise, it's called the first
// time after the first interval.
// - interval is the interval delay in ms.
export const promiseInterval = (promiseCall, interval) => {
let stopped = false
let timeout = null
const func = () => {
promiseCall().finally(() => {
if (stopped) return
timeout = window.setTimeout(func, interval)
})
}
const stopFetcher = () => {
stopped = true
window.clearTimeout(timeout)
}
timeout = window.setTimeout(func, interval)
return { stop: stopFetcher }
}

View File

@ -1,6 +1,7 @@
import { camelCase } from 'lodash' import { camelCase } from 'lodash'
import apiService from '../api/api.service.js' import apiService from '../api/api.service.js'
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)
@ -71,8 +72,9 @@ const startFetching = ({ timeline = 'friends', credentials, store, userId = fals
const showImmediately = timelineData.visibleStatuses.length === 0 const showImmediately = timelineData.visibleStatuses.length === 0
timelineData.userId = userId timelineData.userId = userId
fetchAndUpdate({ timeline, credentials, store, showImmediately, userId, tag }) fetchAndUpdate({ timeline, credentials, store, showImmediately, userId, tag })
const boundFetchAndUpdate = () => fetchAndUpdate({ timeline, credentials, store, userId, tag }) const boundFetchAndUpdate = () =>
return setInterval(boundFetchAndUpdate, 10000) fetchAndUpdate({ timeline, credentials, store, userId, tag })
return promiseInterval(boundFetchAndUpdate, 10000)
} }
const timelineFetcher = { const timelineFetcher = {
fetchAndUpdate, fetchAndUpdate,