Skip to content

Commit

Permalink
Merge pull request #904 from The-Commit-Company/avoid-request-waterfalls
Browse files Browse the repository at this point in the history
fix: active users indicator reliability and removed context
  • Loading branch information
nikkothari22 authored May 3, 2024
2 parents ed9addb + 808632a commit b2d6208
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ViewChannelDetailsModalContent } from "../channels/ViewChannelDetailsModal"
import { useContext, useState } from "react"
import { ActiveUsersContext } from "@/utils/users/ActiveUsersProvider"
import { useState } from "react"
import { ChannelListItem } from "@/utils/channel/ChannelListProvider"
import { ChannelMembers } from "@/utils/channel/ChannelMembersProvider"
import { Button, Dialog, Tooltip } from "@radix-ui/themes"
import { UserAvatar } from "@/components/common/UserAvatar"
import { BiSolidUser } from "react-icons/bi"
import { clsx } from "clsx"
import useFetchActiveUsers from "@/hooks/fetchers/useFetchActiveUsers"

interface ViewChannelDetailsButtonProps {
channelData: ChannelListItem,
Expand All @@ -23,7 +23,9 @@ export const ViewChannelDetailsButton = ({ channelData, allowAddMembers, channel
setOpen(false)
}

const activeUsers = useContext(ActiveUsersContext)
const { data } = useFetchActiveUsers()
const activeUsers = data?.message ?? []

const totalMembers = Object.keys(channelMembers).length

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { useNavigate } from 'react-router-dom'
import { UserContext } from '../../../utils/auth/UserProvider'
import { BiSearch, BiX } from 'react-icons/bi'
import { UserListContext } from '@/utils/users/UserListProvider'
import { ActiveUsersContext } from '@/utils/users/ActiveUsersProvider'
import { ModalTypes, useModalManager } from '@/hooks/useModalManager'
import { Flex, IconButton, Box, Text, Link } from '@radix-ui/themes'
import useFetchActiveUsers from '@/hooks/fetchers/useFetchActiveUsers'

interface CommandPaletteProps {
isOpen: boolean,
Expand All @@ -37,7 +37,11 @@ export const CommandPalette = ({ isOpen, onClose }: CommandPaletteProps) => {
const isHome = activePage === ''
const debouncedText = useDebounce(inputValue, 200)
const { currentUser } = useContext(UserContext)
const activeUsers = useContext(ActiveUsersContext)

const { data } = useFetchActiveUsers()

const activeUsers = data?.message ?? []

const { call, reset } = useFrappePostCall<{ message: string }>("raven.api.raven_channel.create_direct_message_channel")
let navigate = useNavigate()

Expand Down
55 changes: 55 additions & 0 deletions raven-app/src/hooks/fetchers/useFetchActiveUsers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { UserContext } from '@/utils/auth/UserProvider'
import { useFrappeEventListener, useFrappeGetCall, useSWRConfig } from 'frappe-react-sdk'
import { useContext } from 'react'
import { useActiveState } from '../useActiveState'

/**
* Hook to fetch active users from the server.
* SWRKey: active_users
*/
const useFetchActiveUsers = () => {
const res = useFrappeGetCall<{ message: string[] }>('raven.api.user_availability.get_active_users',
undefined,
'active_users',
{
dedupingInterval: 1000 * 60 * 5, // 5 minutes - do not refetch if the data is fresh
}
)

return res
}

/**
* Hook to listen to user_active_state_updated event and update the active_users list in realtime
* Also handles the user's active state via visibilty change and idle timer
*/
export const useFetchActiveUsersRealtime = () => {
const { currentUser } = useContext(UserContext)

const { mutate } = useSWRConfig()

useActiveState()

/** Hook to listen to user_active_state */
useFrappeEventListener('raven:user_active_state_updated', (data) => {
if (data.user !== currentUser) {
// If the user is not the current user, update the active_users list
// No need to revalidate the data as the websocket event has emitted the new data for that user
mutate('active_users', (res?: { message: string[] }) => {
if (res) {
if (data.active) {
return { message: [...res.message, data.user] }
} else {
return { message: res.message.filter(user => user !== data.user) }
}
} else {
return undefined
}
}, {
revalidate: false
})
}
})
}

export default useFetchActiveUsers
18 changes: 17 additions & 1 deletion raven-app/src/hooks/useActiveState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,24 @@ export const useActiveState = () => {
useEffect(() => {
// Update user availability when the app is opened
call.get('raven.api.user_availability.refresh_user_active_state', {
deactivate
deactivate: false
})

document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
updateUserActiveState().then(activate)
}
else {
updateUserActiveState(true).then(deactivate)
}
})

return () => {
// Update user availability when the app is closed
call.get('raven.api.user_availability.refresh_user_active_state', {
deactivate: true
})
}
}, [])

return isActive
Expand Down
9 changes: 5 additions & 4 deletions raven-app/src/hooks/useIsUserActive.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { useContext, useMemo } from 'react';
import { ActiveUsersContext } from '../utils/users/ActiveUsersProvider';
import { UserContext } from '@/utils/auth/UserProvider';
import useFetchActiveUsers from './fetchers/useFetchActiveUsers';

export const useIsUserActive = (userID?: string): boolean => {

const { currentUser } = useContext(UserContext)
const activeUsers = useContext(ActiveUsersContext)

const { data } = useFetchActiveUsers()

const isActive = useMemo(() => {
if (userID === currentUser) {
return true
} else if (userID) {
return activeUsers.includes(userID)
return data?.message.includes(userID) ?? false
} else {
return false
}
}, [userID, activeUsers])
}, [userID, data])

return isActive
}
47 changes: 26 additions & 21 deletions raven-app/src/pages/MainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { lazy, Suspense } from 'react'
import { Sidebar } from '../components/layout/Sidebar/Sidebar'
import { ChannelListProvider } from '../utils/channel/ChannelListProvider'
import { UserListProvider } from '@/utils/users/UserListProvider'
import { ActiveUsersProvider } from '@/utils/users/ActiveUsersProvider'
import { hasRavenUserRole } from '@/utils/roles'
import { FullPageLoader } from '@/components/layout/Loaders'
import { MobileAppRedirectBanner } from '@/components/layout/AlertBanner'
import '../components/layout/AlertBanner/styles.css'
import CommandMenu from '@/components/feature/CommandMenu/CommandMenu'
import { useFetchActiveUsersRealtime } from '@/hooks/fetchers/useFetchActiveUsers'

const AddRavenUsersPage = lazy(() => import('@/pages/AddRavenUsersPage'))

Expand All @@ -19,26 +19,7 @@ export const MainPage = () => {

if (isRavenUser) {
return (
<UserListProvider>
<ChannelListProvider>
<ActiveUsersProvider>
<div className='web-app'>
<Flex>
<Box className={`w-64 bg-gray-2 border-r-gray-3 border-r dark:bg-gray-1`} left="0" top='0' position="fixed">
<Sidebar />
</Box>
<Box className='ml-[var(--sidebar-width)] w-[calc(100vw-var(--sidebar-width))] dark:bg-gray-2'>
<Outlet />
</Box>
</Flex>
</div>
<div className='mobile-app-message'>
<MobileAppRedirectBanner />
</div>
<CommandMenu />
</ActiveUsersProvider>
</ChannelListProvider>
</UserListProvider>
<MainPageContent />
)
} else {
// If the user does not have the Raven User role, then show an error message if the user cannot add more people.
Expand All @@ -48,4 +29,28 @@ export const MainPage = () => {
</Suspense>
}

}

const MainPageContent = () => {

useFetchActiveUsersRealtime()

return <UserListProvider>
<ChannelListProvider>
<div className='web-app'>
<Flex>
<Box className={`w-64 bg-gray-2 border-r-gray-3 border-r dark:bg-gray-1`} left="0" top='0' position="fixed">
<Sidebar />
</Box>
<Box className='ml-[var(--sidebar-width)] w-[calc(100vw-var(--sidebar-width))] dark:bg-gray-2'>
<Outlet />
</Box>
</Flex>
</div>
<div className='mobile-app-message'>
<MobileAppRedirectBanner />
</div>
<CommandMenu />
</ChannelListProvider>
</UserListProvider>
}
5 changes: 1 addition & 4 deletions raven-app/src/utils/channel/ChannelRedirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Outlet, useLocation, useNavigate } from 'react-router-dom'
import { hasRavenUserRole } from '../roles'
import { FullPageLoader } from '@/components/layout/Loaders'
import AddRavenUsersPage from '@/pages/AddRavenUsersPage'
import { ActiveUsersProvider } from '../users/ActiveUsersProvider'
import { UserListProvider } from '../users/UserListProvider'
import { ChannelListProvider } from './ChannelListProvider'

Expand All @@ -30,9 +29,7 @@ export const ChannelRedirect = () => {
return (
<UserListProvider>
<ChannelListProvider>
<ActiveUsersProvider>
<Outlet />
</ActiveUsersProvider>
<Outlet />
</ChannelListProvider>
</UserListProvider>
)
Expand Down
17 changes: 0 additions & 17 deletions raven-app/src/utils/users/ActiveUsersProvider.tsx

This file was deleted.

0 comments on commit b2d6208

Please sign in to comment.