fix: avoid rapid polling while fetching teams in selector (#5485)
This commit is contained in:
parent
53e8b28459
commit
aa1583763a
7 changed files with 55 additions and 24 deletions
|
|
@ -203,7 +203,7 @@
|
||||||
class="!focus-visible:text-blue-600 !hover:text-blue-600 h-8 rounded border border-blue-600/25 bg-blue-500/10 pr-8 !text-blue-500 hover:border-blue-600/20 hover:bg-blue-600/20 focus-visible:border-blue-600/20 focus-visible:bg-blue-600/20"
|
class="!focus-visible:text-blue-600 !hover:text-blue-600 h-8 rounded border border-blue-600/25 bg-blue-500/10 pr-8 !text-blue-500 hover:border-blue-600/20 hover:bg-blue-600/20 focus-visible:border-blue-600/20 focus-visible:bg-blue-600/20"
|
||||||
/>
|
/>
|
||||||
</HoppSmartSelectWrapper>
|
</HoppSmartSelectWrapper>
|
||||||
<template #content="{ hide }">
|
<template #content="{ hide, state }">
|
||||||
<div
|
<div
|
||||||
ref="accountActions"
|
ref="accountActions"
|
||||||
class="flex flex-col focus:outline-none"
|
class="flex flex-col focus:outline-none"
|
||||||
|
|
@ -211,7 +211,7 @@
|
||||||
@keyup.escape="hide()"
|
@keyup.escape="hide()"
|
||||||
@click="hide()"
|
@click="hide()"
|
||||||
>
|
>
|
||||||
<WorkspaceSelector />
|
<WorkspaceSelector :state="state" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</tippy>
|
</tippy>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="rootEl">
|
<div class="flex flex-col">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<HoppSmartItem
|
<HoppSmartItem
|
||||||
|
|
@ -81,6 +81,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watch } from "vue"
|
import { computed, ref, watch } from "vue"
|
||||||
import { useReadonlyStream } from "~/composables/stream"
|
import { useReadonlyStream } from "~/composables/stream"
|
||||||
|
|
@ -96,11 +97,16 @@ import { useLocalState } from "~/newstore/localstate"
|
||||||
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
||||||
import { WorkspaceService } from "~/services/workspace.service"
|
import { WorkspaceService } from "~/services/workspace.service"
|
||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
import { useElementVisibility, useIntervalFn } from "@vueuse/core"
|
import { useIntervalFn, watchDebounced } from "@vueuse/core"
|
||||||
|
import { TippyState } from "~/modules/tippy"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const colorMode = useColorMode()
|
const colorMode = useColorMode()
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
state: TippyState | null
|
||||||
|
}>()
|
||||||
|
|
||||||
const showModalAdd = ref(false)
|
const showModalAdd = ref(false)
|
||||||
|
|
||||||
const currentUser = useReadonlyStream(
|
const currentUser = useReadonlyStream(
|
||||||
|
|
@ -116,27 +122,35 @@ const teamListAdapterError = useReadonlyStream(teamListadapter.error$, null)
|
||||||
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
||||||
const teamListFetched = ref(false)
|
const teamListFetched = ref(false)
|
||||||
|
|
||||||
const rootEl = ref<HTMLElement>()
|
const {
|
||||||
const elVisible = useElementVisibility(rootEl)
|
pause: pauseListPoll,
|
||||||
|
resume: resumeListPoll,
|
||||||
const { pause: pauseListPoll, resume: resumeListPoll } = useIntervalFn(() => {
|
isActive: isListPolling,
|
||||||
if (teamListadapter.isInitialized) {
|
} = useIntervalFn(
|
||||||
teamListadapter.fetchList()
|
|
||||||
}
|
|
||||||
}, 10000)
|
|
||||||
|
|
||||||
watch(
|
|
||||||
elVisible,
|
|
||||||
() => {
|
() => {
|
||||||
if (elVisible.value) {
|
if (teamListadapter.isInitialized) {
|
||||||
teamListadapter.fetchList()
|
teamListadapter.fetchList()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
10000,
|
||||||
|
{ immediate: false }
|
||||||
|
)
|
||||||
|
|
||||||
resumeListPoll()
|
// A debounced watcher to avoid rapid polling when component is mounted.
|
||||||
|
// only poll when the component is visible and pause when not visible.
|
||||||
|
watchDebounced(
|
||||||
|
() => props.state?.isVisible,
|
||||||
|
(isVisible) => {
|
||||||
|
if (isVisible) {
|
||||||
|
if (!isListPolling.value) {
|
||||||
|
teamListadapter.fetchList()
|
||||||
|
resumeListPoll()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pauseListPoll()
|
pauseListPoll()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ debounce: 200 }
|
||||||
)
|
)
|
||||||
|
|
||||||
watch(myTeams, (teams) => {
|
watch(myTeams, (teams) => {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import {
|
||||||
getDefaultRESTRequest,
|
getDefaultRESTRequest,
|
||||||
translateToNewRESTCollection,
|
translateToNewRESTCollection,
|
||||||
HoppGQLRequest,
|
HoppGQLRequest,
|
||||||
translateToNewGQLCollection
|
translateToNewGQLCollection,
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,14 @@ import "tippy.js/animations/scale-subtle.css"
|
||||||
import "tippy.js/dist/border.css"
|
import "tippy.js/dist/border.css"
|
||||||
import "tippy.js/dist/svg-arrow.css"
|
import "tippy.js/dist/svg-arrow.css"
|
||||||
|
|
||||||
|
export type TippyState = {
|
||||||
|
isEnabled: boolean
|
||||||
|
isVisible: boolean
|
||||||
|
isDestroyed: boolean
|
||||||
|
isMounted: boolean
|
||||||
|
isShown: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export default <HoppModule>{
|
export default <HoppModule>{
|
||||||
onVueAppInit(app) {
|
onVueAppInit(app) {
|
||||||
app.use(VueTippy)
|
app.use(VueTippy)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
HoppRESTHeaders,
|
HoppRESTHeaders,
|
||||||
HoppRESTRequest,
|
HoppRESTRequest,
|
||||||
makeCollection,
|
makeCollection,
|
||||||
GQLHeader
|
GQLHeader,
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import { cloneDeep } from "lodash-es"
|
import { cloneDeep } from "lodash-es"
|
||||||
import { pluck } from "rxjs/operators"
|
import { pluck } from "rxjs/operators"
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { Service } from "dioc"
|
import { Service } from "dioc"
|
||||||
import { markRaw } from "vue"
|
import { markRaw } from "vue"
|
||||||
import {
|
import {
|
||||||
body,
|
body,
|
||||||
relayRequestToNativeAdapter,
|
relayRequestToNativeAdapter,
|
||||||
RelayRequest,
|
RelayRequest,
|
||||||
RelayResponse,
|
RelayResponse,
|
||||||
RelayCapabilities
|
RelayCapabilities,
|
||||||
} from "@hoppscotch/kernel"
|
} from "@hoppscotch/kernel"
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import { pipe } from "fp-ts/function"
|
import { pipe } from "fp-ts/function"
|
||||||
|
|
|
||||||
|
|
@ -1059,6 +1059,15 @@ export class TeamCollectionsService extends Service<void> {
|
||||||
collections.forEach((coll) => this.entityIDs.add(`collection-${coll.id}`))
|
collections.forEach((coll) => this.entityIDs.add(`collection-${coll.id}`))
|
||||||
requests.forEach((req) => this.entityIDs.add(`request-${req.id}`))
|
requests.forEach((req) => this.entityIDs.add(`request-${req.id}`))
|
||||||
|
|
||||||
|
this.collections.value = [...tree]
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error expanding collection ${collectionID}:`, error)
|
||||||
|
|
||||||
|
// Set empty arrays instead of leaving as null to prevent future expansion attempts
|
||||||
|
// This prevents the infinite loop by ensuring the collection is marked as expanded
|
||||||
|
collection.children = []
|
||||||
|
collection.requests = []
|
||||||
|
|
||||||
this.collections.value = [...tree]
|
this.collections.value = [...tree]
|
||||||
} finally {
|
} finally {
|
||||||
this.loadingCollections.value = this.loadingCollections.value.filter(
|
this.loadingCollections.value = this.loadingCollections.value.filter(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue