mirror of
https://github.com/hanzo-io/team.git
synced 2026-10-30 18:56:23 +00:00
93 lines
3.6 KiB
TypeScript
93 lines
3.6 KiB
TypeScript
import { FrappeError, useFrappeGetCall, SWRConfiguration, useFrappeEventListener } from 'frappe-react-sdk'
|
|
import { createContext, useContext, useEffect, useMemo, useState } from 'react'
|
|
import { KeyedMutator } from 'swr'
|
|
import { useSWRConfig } from 'frappe-react-sdk'
|
|
import { ChannelList } from '@raven/types/common/ChannelListItem'
|
|
|
|
export interface ChannelListContextType extends ChannelList {
|
|
mutate: KeyedMutator<{ message: ChannelList }>,
|
|
error?: FrappeError,
|
|
isLoading: boolean,
|
|
hasData: boolean
|
|
}
|
|
export const ChannelListContext = createContext<ChannelListContextType | null>(null)
|
|
|
|
|
|
/** Use this hook to get the channel list */
|
|
export const useChannelList = (): ChannelListContextType => {
|
|
const context = useContext(ChannelListContext)
|
|
if (!context) {
|
|
throw new Error('useChannelList must be used within a ChannelListProvider')
|
|
}
|
|
return context
|
|
}
|
|
|
|
/**
|
|
* Hook to fetch the channel list - all channels + DM's + other users if any. The channel list is sorted by the last message timestamp.
|
|
* Also listens to the channel_list_updated event to update the channel list
|
|
*
|
|
* This is supposed to be used in the ChannelListContext and only once in the app since it has realtime event listeners
|
|
*/
|
|
export const useChannelListProvider = (swrConfig?: SWRConfiguration): ChannelListContextType => {
|
|
|
|
const { mutate: globalMutate } = useSWRConfig()
|
|
const { data, mutate, ...rest } = useFrappeGetCall<{ message: ChannelList }>("raven.api.raven_channel.get_all_channels", {
|
|
hide_archived: false
|
|
}, `channel_list`, {
|
|
revalidateOnFocus: true,
|
|
...(swrConfig || {})
|
|
})
|
|
|
|
const [newUpdatesAvailable, setNewUpdatesAvailable] = useState(0)
|
|
|
|
useEffect(() => {
|
|
let timeout: NodeJS.Timeout | undefined
|
|
if (newUpdatesAvailable) {
|
|
timeout = setTimeout(() => {
|
|
mutate()
|
|
// Also update the unread channel count
|
|
globalMutate('unread_channel_count')
|
|
setNewUpdatesAvailable(0)
|
|
}, 1000) // 1 second
|
|
}
|
|
return () => clearTimeout(timeout)
|
|
}, [newUpdatesAvailable])
|
|
|
|
/**
|
|
* If a bulk import happens, this gets called multiple times potentially causing the server to go down.
|
|
* Instead, throttle this - wait for all events to subside
|
|
*/
|
|
useFrappeEventListener('channel_list_updated', () => {
|
|
if (!rest.isValidating) {
|
|
setNewUpdatesAvailable((n) => n + 1)
|
|
}
|
|
})
|
|
|
|
const { sortedChannels, sortedDMChannels } = useMemo(() => {
|
|
let sortedChannels = data?.message.channels ?? []
|
|
let sortedDMChannels = data?.message.dm_channels ?? []
|
|
|
|
sortedChannels = sortedChannels.sort((a, b) => {
|
|
const bTimestamp = b.last_message_timestamp ? new Date(b.last_message_timestamp).getTime() : 0
|
|
const aTimestamp = a.last_message_timestamp ? new Date(a.last_message_timestamp).getTime() : 0
|
|
return new Date(bTimestamp).getTime() - new Date(aTimestamp).getTime()
|
|
})
|
|
|
|
sortedDMChannels = sortedDMChannels.sort((a, b) => {
|
|
const bTimestamp = b.last_message_timestamp ? new Date(b.last_message_timestamp).getTime() : 0
|
|
const aTimestamp = a.last_message_timestamp ? new Date(a.last_message_timestamp).getTime() : 0
|
|
return new Date(bTimestamp).getTime() - new Date(aTimestamp).getTime()
|
|
})
|
|
|
|
return { sortedChannels, sortedDMChannels }
|
|
}, [data])
|
|
|
|
return {
|
|
hasData: !!data,
|
|
channels: sortedChannels,
|
|
dm_channels: sortedDMChannels,
|
|
mutate,
|
|
...rest
|
|
}
|
|
|
|
} |