@@ -10,6 +10,8 @@ import { useAuth } from "@/lib/auth.svelte";
1010import { getWebSocket } from "@/lib/websocket" ;
1111import type { WsEvent } from "@/lib/websocket/types" ;
1212
13+ type WsHandler = ( event : WsEvent ) => void ;
14+
1315/**
1416 * Controller for managing message list state and operations.
1517 * Handles fetching messages, managing UI state for dropdowns/palettes,
@@ -48,6 +50,10 @@ export class MessageListController {
4850 pinMessage : ReturnType < typeof useMutation < { messageId : string } , Message > > ;
4951 unpinMessage : ReturnType < typeof useMutation < { messageId : string } , Message > > ;
5052
53+ // WebSocket cleanup
54+ private wsHandlers : { type : string ; handler : WsHandler } [ ] = [ ] ;
55+ private ws : ReturnType < typeof getWebSocket > | null = null ;
56+
5157 constructor ( props : ( ) => { organizationId : string ; channelId : string } ) {
5258 const api = getApiClient ( ) ;
5359 this . organizationId = props ( ) . organizationId ;
@@ -114,11 +120,11 @@ export class MessageListController {
114120
115121 // WebSocket integration
116122 try {
117- const ws = getWebSocket ( ) ;
118- ws . subscribe ( this . channelId ) ;
123+ this . ws = getWebSocket ( ) ;
124+ this . ws . subscribe ( this . channelId ) ;
119125
120126 // Handle new messages
121- ws . on ( "message:created" , ( event : WsEvent ) => {
127+ const handleCreated : WsHandler = ( event ) => {
122128 if (
123129 event . type === "message:created" &&
124130 event . channelId === this . channelId
@@ -128,10 +134,10 @@ export class MessageListController {
128134 this . messagesData = [ ...this . messagesData , newMessage ] ;
129135 }
130136 }
131- } ) ;
137+ } ;
132138
133139 // Handle message updates
134- ws . on ( "message:updated" , ( event : WsEvent ) => {
140+ const handleUpdated : WsHandler = ( event ) => {
135141 if (
136142 event . type === "message:updated" &&
137143 event . channelId === this . channelId
@@ -141,10 +147,10 @@ export class MessageListController {
141147 m . id === updated . id ? updated : m ,
142148 ) ;
143149 }
144- } ) ;
150+ } ;
145151
146152 // Handle message deletions
147- ws . on ( "message:deleted" , ( event : WsEvent ) => {
153+ const handleDeleted : WsHandler = ( event ) => {
148154 if (
149155 event . type === "message:deleted" &&
150156 event . channelId === this . channelId
@@ -153,7 +159,17 @@ export class MessageListController {
153159 ( m ) => m . id !== event . messageId ,
154160 ) ;
155161 }
156- } ) ;
162+ } ;
163+
164+ this . ws . on ( "message:created" , handleCreated ) ;
165+ this . ws . on ( "message:updated" , handleUpdated ) ;
166+ this . ws . on ( "message:deleted" , handleDeleted ) ;
167+
168+ this . wsHandlers = [
169+ { type : "message:created" , handler : handleCreated } ,
170+ { type : "message:updated" , handler : handleUpdated } ,
171+ { type : "message:deleted" , handler : handleDeleted } ,
172+ ] ;
157173 } catch ( error ) {
158174 console . warn ( "WebSocket not initialized:" , error ) ;
159175 }
@@ -242,4 +258,16 @@ export class MessageListController {
242258 await this . messages . refetch ( ) ;
243259 this . visibleDropdown = null ;
244260 }
261+
262+ /**
263+ * Cleanup WebSocket subscriptions. Call this when the component unmounts.
264+ */
265+ destroy ( ) {
266+ if ( this . ws ) {
267+ for ( const { type, handler } of this . wsHandlers ) {
268+ this . ws . off ( type , handler ) ;
269+ }
270+ this . ws . unsubscribe ( this . channelId ) ;
271+ }
272+ }
245273}
0 commit comments