mirror of
https://github.com/langgenius/dify.git
synced 2026-08-01 01:49:30 +08:00
126 lines
4.0 KiB
TypeScript
126 lines
4.0 KiB
TypeScript
import { useSuspenseQuery } from '@tanstack/react-query'
|
|
import dayjs from 'dayjs'
|
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
import { NUM_INFINITE } from '@/app/components/billing/config'
|
|
import { Plan } from '@/app/components/billing/type'
|
|
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
|
import { isServer } from '@/utils/client'
|
|
|
|
type TriggerEventsLimitModalContent = {
|
|
usage: number
|
|
total: number
|
|
resetInDays?: number
|
|
}
|
|
|
|
type TriggerEventsLimitModalState = TriggerEventsLimitModalContent & {
|
|
storageKey: string
|
|
persistDismiss: boolean
|
|
}
|
|
|
|
type TriggerPlanInfo = {
|
|
type: Plan
|
|
usage: { triggerEvents: number }
|
|
total: { triggerEvents: number }
|
|
reset: { triggerEvents?: number | null }
|
|
}
|
|
|
|
type UseTriggerEventsLimitModalOptions = {
|
|
plan: TriggerPlanInfo
|
|
isFetchedPlan: boolean
|
|
currentWorkspaceId?: string
|
|
}
|
|
|
|
type UseTriggerEventsLimitModalResult = {
|
|
triggerEventsLimitModal: TriggerEventsLimitModalContent | null
|
|
dismissTriggerEventsLimitModal: () => void
|
|
}
|
|
|
|
const TRIGGER_EVENTS_LOCALSTORAGE_PREFIX = 'trigger-events-limit-dismissed'
|
|
|
|
export const useTriggerEventsLimitModal = ({
|
|
plan,
|
|
isFetchedPlan,
|
|
currentWorkspaceId,
|
|
}: UseTriggerEventsLimitModalOptions): UseTriggerEventsLimitModalResult => {
|
|
const { data: deploymentEdition } = useSuspenseQuery({
|
|
...systemFeaturesQueryOptions(),
|
|
select: ({ deployment_edition }) => deployment_edition,
|
|
})
|
|
const [triggerEventsLimitModal, setTriggerEventsLimitModal] =
|
|
useState<TriggerEventsLimitModalState | null>(null)
|
|
const dismissedTriggerEventsLimitStorageKeysRef = useRef<Record<string, boolean>>({})
|
|
|
|
useEffect(() => {
|
|
if (deploymentEdition !== 'CLOUD') return
|
|
if (isServer) return
|
|
if (!currentWorkspaceId) return
|
|
if (!isFetchedPlan) {
|
|
setTriggerEventsLimitModal(null)
|
|
return
|
|
}
|
|
|
|
const { type, usage, total, reset } = plan
|
|
const isUnlimited = total.triggerEvents === NUM_INFINITE
|
|
const reachedLimit = total.triggerEvents > 0 && usage.triggerEvents >= total.triggerEvents
|
|
|
|
if (type === Plan.team || isUnlimited || !reachedLimit) {
|
|
if (triggerEventsLimitModal) setTriggerEventsLimitModal(null)
|
|
return
|
|
}
|
|
|
|
const triggerResetInDays =
|
|
type === Plan.professional && total.triggerEvents !== NUM_INFINITE
|
|
? (reset.triggerEvents ?? undefined)
|
|
: undefined
|
|
const cycleTag = (() => {
|
|
if (typeof reset.triggerEvents === 'number')
|
|
return dayjs().startOf('day').add(reset.triggerEvents, 'day').format('YYYY-MM-DD')
|
|
if (type === Plan.sandbox) return dayjs().endOf('month').format('YYYY-MM-DD')
|
|
return 'none'
|
|
})()
|
|
const storageKey = `${TRIGGER_EVENTS_LOCALSTORAGE_PREFIX}-${currentWorkspaceId}-${type}-${total.triggerEvents}-${cycleTag}`
|
|
if (dismissedTriggerEventsLimitStorageKeysRef.current[storageKey]) return
|
|
|
|
let persistDismiss = true
|
|
let hasDismissed = false
|
|
try {
|
|
if (localStorage.getItem(storageKey) === '1') hasDismissed = true
|
|
} catch {
|
|
persistDismiss = false
|
|
}
|
|
if (hasDismissed) return
|
|
|
|
if (triggerEventsLimitModal?.storageKey === storageKey) return
|
|
|
|
setTriggerEventsLimitModal({
|
|
usage: usage.triggerEvents,
|
|
total: total.triggerEvents,
|
|
resetInDays: triggerResetInDays,
|
|
storageKey,
|
|
persistDismiss,
|
|
})
|
|
}, [plan, isFetchedPlan, triggerEventsLimitModal, currentWorkspaceId, deploymentEdition])
|
|
|
|
const dismissTriggerEventsLimitModal = useCallback(() => {
|
|
if (!triggerEventsLimitModal) return
|
|
|
|
const { storageKey, persistDismiss } = triggerEventsLimitModal
|
|
if (persistDismiss) {
|
|
try {
|
|
localStorage.setItem(storageKey, '1')
|
|
setTriggerEventsLimitModal(null)
|
|
return
|
|
} catch {
|
|
// ignore error and fall back to in-memory guard
|
|
}
|
|
}
|
|
dismissedTriggerEventsLimitStorageKeysRef.current[storageKey] = true
|
|
setTriggerEventsLimitModal(null)
|
|
}, [triggerEventsLimitModal])
|
|
|
|
return {
|
|
triggerEventsLimitModal,
|
|
dismissTriggerEventsLimitModal,
|
|
}
|
|
}
|