mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-06 17:07:46 +00:00
🐛(frontend) fix concurrent PATCH races on room settings
Rapid toggles could persist a stale configuration: each PATCH replaces the full room config, and every call site built it from a render-time snapshot. A toggle issued before the previous one resolved therefore overwrote the newer value with an older one. Handle the cache centrally in usePatchRoom so the next toggle always reads an up-to-date configuration.
This commit is contained in:
committed by
aleb_the_flash
parent
c23f449520
commit
22a1713c60
@@ -50,6 +50,7 @@ and this project adheres to
|
||||
- 💄(frontend) show pointer cursor on interactive switches
|
||||
- 🐛(frontend) fix icon centering in the Switch primitive
|
||||
- 🐛(frontend) keep Unicode initials intact in avatar
|
||||
- 🐛(frontend) prevent concurrent settings updates from overwriting each other
|
||||
|
||||
## [1.24.0] - 2026-07-21
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import { type ApiRoom } from './ApiRoom'
|
||||
import { fetchApi } from '@/api/fetchApi'
|
||||
import { useMutation, type UseMutationOptions } from '@tanstack/react-query'
|
||||
import type { ApiError } from '@/api/ApiError'
|
||||
import { queryClient } from '@/api/queryClient'
|
||||
import { keys } from '@/api/queryKeys'
|
||||
|
||||
export type PatchRoomParams = {
|
||||
roomId: string
|
||||
@@ -15,11 +17,25 @@ export const patchRoom = ({ roomId, room }: PatchRoomParams) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const patchRoomMutationKey = ['patchRoom']
|
||||
|
||||
export function usePatchRoom(
|
||||
options?: UseMutationOptions<ApiRoom, ApiError, PatchRoomParams>
|
||||
) {
|
||||
return useMutation<ApiRoom, ApiError, PatchRoomParams>({
|
||||
mutationKey: patchRoomMutationKey,
|
||||
mutationFn: patchRoom,
|
||||
onSuccess: options?.onSuccess,
|
||||
onMutate: async ({ roomId, room: partialRoom }) => {
|
||||
await queryClient.cancelQueries({ queryKey: [keys.room, roomId] })
|
||||
queryClient.setQueryData<ApiRoom>([keys.room, roomId], (previous) =>
|
||||
previous ? { ...previous, ...partialRoom } : previous
|
||||
)
|
||||
},
|
||||
onSettled: (_data, _error, { roomId }) => {
|
||||
if (queryClient.isMutating({ mutationKey: patchRoomMutationKey }) === 1) {
|
||||
queryClient.invalidateQueries({ queryKey: [keys.room, roomId] })
|
||||
}
|
||||
},
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useTranslation } from 'react-i18next'
|
||||
import { usePatchRoom } from '@/features/rooms/api/patchRoom'
|
||||
import { fetchRoom } from '@/features/rooms/api/fetchRoom'
|
||||
import { ApiAccessLevel } from '@/features/rooms/api/ApiRoom'
|
||||
import { queryClient } from '@/api/queryClient'
|
||||
import { keys } from '@/api/queryKeys'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useParams } from 'wouter'
|
||||
@@ -206,11 +205,7 @@ export const Admin = () => {
|
||||
patchRoom({
|
||||
roomId,
|
||||
room: { access_level: value as ApiAccessLevel },
|
||||
})
|
||||
.then((room) => {
|
||||
queryClient.setQueryData([keys.room, roomId], room)
|
||||
})
|
||||
.catch((e) => console.error(e))
|
||||
}).catch((e) => console.error(e))
|
||||
}
|
||||
items={[
|
||||
{
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { usePatchRoom } from '@/features/rooms/api/patchRoom'
|
||||
import { useRoomData } from '@/features/rooms/livekit/hooks/useRoomData'
|
||||
import { useCallback } from 'react'
|
||||
import { queryClient } from '@/api/queryClient'
|
||||
import { keys } from '@/api/queryKeys'
|
||||
|
||||
export const usePermissionsManager = () => {
|
||||
const { mutateAsync: patchRoom } = usePatchRoom()
|
||||
@@ -23,13 +21,11 @@ export const usePermissionsManager = () => {
|
||||
everyone_can_mute: enabled,
|
||||
}
|
||||
|
||||
const room = await patchRoom({
|
||||
await patchRoom({
|
||||
roomId,
|
||||
room: { configuration: newConfiguration },
|
||||
})
|
||||
|
||||
queryClient.setQueryData([keys.room, roomId], room)
|
||||
|
||||
return { configuration: newConfiguration }
|
||||
} catch (error) {
|
||||
console.error('Failed to update muting permission:', error)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { RoomEvent, Track } from 'livekit-client'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { queryClient } from '@/api/queryClient'
|
||||
import { keys } from '@/api/queryKeys'
|
||||
import { useConfig } from '@/api/useConfig'
|
||||
import { usePatchRoom } from '@/features/rooms/api/patchRoom'
|
||||
import { useRemoteParticipants } from '@livekit/components-react'
|
||||
@@ -79,13 +77,11 @@ export const usePublishSourcesManager = () => {
|
||||
can_publish_sources: newSources,
|
||||
}
|
||||
|
||||
const room = await patchRoom({
|
||||
await patchRoom({
|
||||
roomId,
|
||||
room: { configuration: newConfiguration },
|
||||
})
|
||||
|
||||
queryClient.setQueryData([keys.room, roomId], room)
|
||||
|
||||
await updateParticipantsPermissions(
|
||||
unprivilegedRemoteParticipants,
|
||||
newSources
|
||||
|
||||
@@ -7,7 +7,6 @@ import { css } from '@/styled-system/css'
|
||||
import { Button, Field, H, Text } from '@/primitives'
|
||||
import { Spinner } from '@/primitives/Spinner'
|
||||
import { keys } from '@/api/queryKeys'
|
||||
import { queryClient } from '@/api/queryClient'
|
||||
import { useConfig } from '@/api/useConfig'
|
||||
import { useUser } from '@/features/auth/api/useUser'
|
||||
import { authUrl } from '@/features/auth/utils/authUrl'
|
||||
@@ -109,11 +108,7 @@ const SettingsPopup = () => {
|
||||
patchRoom({
|
||||
roomId: roomSlug,
|
||||
room: { configuration: newConfiguration },
|
||||
})
|
||||
.then((updatedRoom) => {
|
||||
queryClient.setQueryData([keys.room, roomSlug], updatedRoom)
|
||||
})
|
||||
.catch((e) => console.error(e))
|
||||
}).catch((e) => console.error(e))
|
||||
}
|
||||
|
||||
const updateSource = (sources: Source[], enabled: boolean) => {
|
||||
@@ -334,11 +329,7 @@ const SettingsPopup = () => {
|
||||
patchRoom({
|
||||
roomId: roomSlug,
|
||||
room: { access_level: value as ApiAccessLevel },
|
||||
})
|
||||
.then((updatedRoom) => {
|
||||
queryClient.setQueryData([keys.room, roomSlug], updatedRoom)
|
||||
})
|
||||
.catch((e) => console.error(e))
|
||||
}).catch((e) => console.error(e))
|
||||
}
|
||||
items={[
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user