mirror of
https://github.com/ericasch6/scrum-poker-internal.git
synced 2026-10-13 18:32:09 +00:00
95 lines
2.2 KiB
TypeScript
95 lines
2.2 KiB
TypeScript
import { router } from '@inertiajs/vue3';
|
|
import { onScopeDispose, watch } from 'vue';
|
|
|
|
import { getEcho } from '@/lib/echo';
|
|
import type { RoomStateChangedPayload } from '@/types/room';
|
|
|
|
const ROOM_EVENT = '.room.state.changed';
|
|
|
|
export function useRoomRealtime(
|
|
roomId: () => string,
|
|
stateVersion: () => number,
|
|
): void {
|
|
let reloadInProgress = false;
|
|
let pendingVersion = 0;
|
|
let disposed = false;
|
|
|
|
function reloadRoom(): void {
|
|
if (reloadInProgress || disposed) {
|
|
return;
|
|
}
|
|
|
|
reloadInProgress = true;
|
|
|
|
router.reload({
|
|
only: ['room', 'currentPlayer'],
|
|
onFinish: () => {
|
|
reloadInProgress = false;
|
|
|
|
if (disposed) {
|
|
return;
|
|
}
|
|
|
|
if (pendingVersion > stateVersion()) {
|
|
reloadRoom();
|
|
|
|
return;
|
|
}
|
|
|
|
pendingVersion = stateVersion();
|
|
},
|
|
});
|
|
}
|
|
|
|
function handleRoomChange(payload: RoomStateChangedPayload): void {
|
|
if (
|
|
typeof payload.version !== 'number' ||
|
|
payload.version <= Math.max(stateVersion(), pendingVersion)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
pendingVersion = payload.version;
|
|
|
|
if (payload.change === 'room_deleted') {
|
|
router.visit('/', { replace: true });
|
|
|
|
return;
|
|
}
|
|
|
|
reloadRoom();
|
|
}
|
|
|
|
const stopWatchingRoom = watch(
|
|
roomId,
|
|
(nextRoomId, _previousRoomId, onCleanup) => {
|
|
const echo = getEcho();
|
|
const channelName = `rooms.${nextRoomId}`;
|
|
|
|
pendingVersion = stateVersion();
|
|
echo.channel(channelName).listen(ROOM_EVENT, handleRoomChange);
|
|
|
|
onCleanup(() => {
|
|
echo.leaveChannel(channelName);
|
|
});
|
|
},
|
|
{ immediate: true },
|
|
);
|
|
|
|
const stopWatchingVersion = watch(
|
|
stateVersion,
|
|
(version) => {
|
|
if (!reloadInProgress) {
|
|
pendingVersion = Math.max(pendingVersion, version);
|
|
}
|
|
},
|
|
{ flush: 'sync' },
|
|
);
|
|
|
|
onScopeDispose(() => {
|
|
disposed = true;
|
|
stopWatchingRoom();
|
|
stopWatchingVersion();
|
|
});
|
|
}
|