Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 23 additions & 16 deletions deep-sea-stories/packages/backend/src/controllers/peers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { RoomId } from '@fishjam-cloud/js-server-sdk';
import {
RoomNotFoundException,
type RoomId,
} from '@fishjam-cloud/js-server-sdk';
import { TRPCError } from '@trpc/server';
import { GameRoomFullError } from '../domain/errors.js';
import { GameRoom } from '../game/room.js';
Expand All @@ -9,30 +12,34 @@ import { publicProcedure } from '../trpc.js';
export const createPeer = publicProcedure
.input(createPeerInputSchema)
.mutation(async ({ ctx, input }) => {
const room = await ctx.fishjam.getRoom(input.roomId as RoomId);
if (!room) {
throw new Error(`Room with id ${input.roomId} does not exist`);
}
try {
const room = await ctx.fishjam.getRoom(input.roomId as RoomId);

let gameRoom = roomService.getGameRoom(room.id);
if (!gameRoom) {
gameRoom = new GameRoom(ctx.fishjam, ctx.notifierService, room.id);
roomService.setGameRoom(room.id, gameRoom);
}
let gameRoom = roomService.getGameRoom(room.id);
if (!gameRoom) {
gameRoom = new GameRoom(ctx.fishjam, ctx.notifierService, room.id);
roomService.setGameRoom(room.id, gameRoom);
}

try {
const { peer, peerToken } = await gameRoom.addPlayer(input.name);
return {
peer,
token: peerToken,
};
} catch (error) {
if (error instanceof GameRoomFullError) {
} catch (e) {
if (e instanceof RoomNotFoundException) {
console.warn(`Room ${input.roomId} not found`);
throw new TRPCError({
code: 'NOT_FOUND',
message: `Room does not exist`,
});
}
if (e instanceof GameRoomFullError) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: error.message,
code: 'CONFLICT',
message: e.message,
});
}
throw error;
throw e;
}
});
32 changes: 16 additions & 16 deletions deep-sea-stories/packages/backend/src/game/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,28 +200,28 @@ export class GameRoom {
this.gameTimeoutId = null;
}

if (this.gameSession) {
await this.gameSession.stopGame(wait);
try {
try {
if (this.gameSession) {
await this.gameSession.stopGame(wait);
await this.fishjamClient.deletePeer(
this.roomId,
this.gameSession.agentId,
);
this.gameSession = null;
} catch (e) {
if (!(e instanceof PeerNotFoundException)) throw e;
}
} catch (e) {
if (!(e instanceof PeerNotFoundException)) throw e;
} finally {
this.gameSession = null;
this.story = undefined;

this.notifierService.emitNotification(this.roomId, {
type: 'gameEnded' as const,
timestamp: Date.now(),
});

this.gameStarted = false;
console.log(`Stopped game for room ${this.roomId}`);
}

this.story = undefined;

this.notifierService.emitNotification(this.roomId, {
type: 'gameEnded' as const,
timestamp: Date.now(),
});

this.gameStarted = false;
console.log(`Stopped game for room ${this.roomId}`);
}

private async createFishjamAgent() {
Expand Down
11 changes: 6 additions & 5 deletions deep-sea-stories/packages/web/src/components/AgentModeToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { EarOff, Headphones } from 'lucide-react';
import { Check, CircleX, EarOff, Headphones } from 'lucide-react';
import { type FC, useEffect, useState } from 'react';
import { toast } from 'sonner';
import { useTRPCClient } from '@/contexts/trpc';
import { useAgentEvents } from '@/hooks/useAgentEvents';
import { Button } from './ui/button';
import { toast } from './ui/sonner';

type AgentModeToggleProps = {
roomId: string;
Expand Down Expand Up @@ -40,10 +40,11 @@ const AgentModeToggle: FC<AgentModeToggleProps> = ({ roomId }) => {
muted: !isAiMuted,
});

toast.success(!isAiMuted ? 'Agent deafened' : 'Agent listening');
toast(!isAiMuted ? 'Agent deafened' : 'Agent listening', Check);
} catch (error) {
console.error('Failed to toggle AI mode:', error);
toast.error('Failed to toggle mode');
console.error(error);
const verb = isAiMuted ? 'undeafen' : 'deafen';
toast(`Failed to ${verb} agent`, CircleX);
} finally {
setIsMutating(false);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { StoryData } from '@deep-sea-stories/common';
import { Check } from 'lucide-react';
import { Check, X } from 'lucide-react';
import type { FC } from 'react';
import { useEffect, useState } from 'react';
import { useTRPCClient } from '@/contexts/trpc';
Expand Down Expand Up @@ -38,7 +38,7 @@ const StorySelectionPanel: FC<StorySelectionPanelProps> = ({
setStories(fetchedStories);
} catch (error) {
console.error('Failed to fetch stories:', error);
toast('Failed to load stories', Check);
toast('Failed to load stories', X);
} finally {
setIsLoadingStories(false);
}
Expand All @@ -63,7 +63,7 @@ const StorySelectionPanel: FC<StorySelectionPanelProps> = ({
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Failed to select story';
toast(`Error: ${errorMessage}`, Check);
toast(errorMessage, X);
} finally {
setIsStarting(false);
}
Expand Down
2 changes: 1 addition & 1 deletion deep-sea-stories/packages/web/src/components/ui/sonner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const Toaster = ({ ...props }: ToasterProps) => {
toastOptions={{
classNames: {
toast:
'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg',
'group toast group-[.toaster]:text-foreground group-[.toaster]:border-border w-full items-center justify-center flex group-[.toaster]:shadow-lg',
description: 'group-[.toast]:text-muted-foreground',
actionButton:
'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground',
Expand Down
5 changes: 4 additions & 1 deletion deep-sea-stories/packages/web/src/views/HomeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Footer from '@/components/Footer';
import TitleBar from '@/components/TitleBar';
import { Button } from '@/components/ui/button';
import { useTRPCClient } from '@/contexts/trpc';
import { toast } from '@/components/ui/sonner';
import { CircleX } from 'lucide-react';

export default function HomeView() {
const navigate = useNavigate();
Expand All @@ -16,7 +18,8 @@ export default function HomeView() {
const room = await trpcClient.createRoom.mutate();
navigate(`/${room.id}`);
} catch (error) {
console.error('Failed to create room:', error);
toast('Failed to create room', CircleX);
console.error(error);
} finally {
setIsLoading(false);
}
Expand Down
15 changes: 9 additions & 6 deletions deep-sea-stories/packages/web/src/views/JoinView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
useInitializeDevices,
useMicrophone,
} from '@fishjam-cloud/react-client';
import { Camera, Mic, User } from 'lucide-react';
import { Camera, CircleX, Mic, User } from 'lucide-react';
import type { FC } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { DeviceSelect } from '@/components/DeviceSelect';
Expand Down Expand Up @@ -66,13 +66,16 @@ const JoinView: FC<JoinViewProps> = ({ roomId }) => {
peerMetadata: { name },
});
} catch (error) {
if (
error instanceof TRPCClientError &&
error.data?.code === 'BAD_REQUEST'
) {
if (!(error instanceof TRPCClientError)) {
console.error(error);
return;
}

if (error.data?.code === 'BAD_REQUEST') {
toast(error.message, User);
} else {
toast(error.message, CircleX);
}
console.error(error);
}
}, [trpcClient, roomId, joinRoom, name]);

Expand Down