fix(slides): add more backend code slides

This commit is contained in:
2026-06-19 12:48:28 +03:30
parent 156ecf75d3
commit 9afb8b2de1

View File

@@ -214,27 +214,115 @@
<aside class="notes">This is the main real-time loop: receive text, parse JSON if possible, ignore empty messages, then broadcast.</aside>
</section>
<section class="slide code-slide" data-title="Backend Manager">
<h2>ConnectionManager</h2>
<p class="subtitle">The manager groups sockets by room and removes dead connections.</p>
<section class="slide code-slide" data-title="WebSocket Disconnect Handling">
<h2>Connection Teardown and Presence Update</h2>
<p class="subtitle">Handles user disconnects, cleans up the room, and updates presence for remaining clients.</p>
<div class="code-window">
<div class="code-titlebar"><span></span><span></span><span></span><strong>app/websocket/manager.py</strong></div>
<pre><code><span class="line"><span class="kw">class</span> <span class="fn">ConnectionManager</span>:</span>
<span class="line"> <span class="kw">def</span> <span class="fn">__init__</span>(self):</span>
<span class="line"> self.active_connections = {}</span>
<span class="line"></span>
<span class="line"> <span class="kw">async def</span> <span class="fn">connect</span>(self, websocket, room_id, client_id):</span>
<span class="line"> <span class="kw">await</span> websocket.accept()</span>
<span class="line"> self.active_connections.setdefault(room_id, [])</span>
<span class="line"> self.active_connections[room_id].append(ClientConnection(websocket, client_id))</span>
<span class="line"></span>
<span class="line"> <span class="kw">async def</span> <span class="fn">broadcast_json</span>(self, payload, room_id):</span>
<span class="line"> <span class="kw">for</span> connection <span class="kw">in</span> list(self.active_connections.get(room_id, [])):</span>
<span class="line"> <span class="kw">await</span> connection.websocket.send_json(payload)</span></code></pre>
<div class="code-titlebar">
<span></span><span></span><span></span>
<strong>app/websocket/chat.py</strong>
</div>
<aside class="notes">This slide explains the backend data structure: each room points to a list of active client sockets.</aside>
<pre><code><span class="line"><span class="kw">except</span> WebSocketDisconnect:</span>
<span class="line"> manager.disconnect(websocket, room_id)</span>
<span class="line"> <span class="kw">await</span> manager.broadcast_json(</span>
<span class="line"> event(<span class="str">"system"</span>, room_id, <span class="str">"سیستم"</span>, </span>
<span class="line"> f<span class="str">"{client_id} از اتاق {room_id} خارج شد."</span>),</span>
<span class="line"> room_id,</span>
<span class="line"> )</span>
<span class="line"> <span class="kw">await</span> manager.broadcast_json(</span>
<span class="line"> {</span>
<span class="line"> <span class="str">"type"</span>: <span class="str">"presence"</span>,</span>
<span class="line"> <span class="str">"room_id"</span>: room_id,</span>
<span class="line"> <span class="str">"client_id"</span>: <span class="str">"سیستم"</span>,</span>
<span class="line"> <span class="str">"content"</span>: <span class="str">"presence-updated"</span>,</span>
<span class="line"> <span class="str">"users"</span>: manager.room_users(room_id),</span>
<span class="line"> <span class="str">"timestamp"</span>: now_iso(),</span>
<span class="line"> },</span>
<span class="line"> room_id,</span>
<span class="line"> )</span></code></pre>
</div>
<aside class="notes">
This block handles client disconnection: it removes the websocket from the room,
broadcasts a system message announcing the departure, and then sends an updated
presence payload so all clients can refresh the active user list.
</aside>
</section>
<section class="slide code-slide" data-title="Backend Connection Manager">
<h2>ConnectionManager</h2>
<p class="subtitle">Manages WebSocket connections grouped by room and cleans up disconnected clients.</p>
<div class="code-window">
<div class="code-titlebar">
<span></span><span></span><span></span>
<strong>app/websocket/manager.py</strong>
</div>
<pre><code><span class="line"><span class="kw">class</span> <span class="fn">ConnectionManager</span>:</span>
<span class="line"> <span class="kw">def</span> <span class="fn">__init__</span>(self):</span>
<span class="line"> self.active_connections: dict[str, list[ClientConnection]] = {}</span>
<span class="line"></span>
<span class="line"> <span class="kw">async def</span> <span class="fn">connect</span>(self, websocket: WebSocket, room_id: str, client_id: str):</span>
<span class="line"> <span class="kw">await</span> websocket.accept()</span>
<span class="line"> self.active_connections.setdefault(room_id, [])</span>
<span class="line"> self.active_connections[room_id].append(ClientConnection(websocket=websocket, client_id=client_id))</span>
<span class="line"></span>
<span class="line"> <span class="kw">def</span> <span class="fn">disconnect</span>(self, websocket: WebSocket, room_id: str):</span>
<span class="line"> <span class="kw">if</span> room_id <span class="kw">not</span> <span class="kw">in</span> self.active_connections: <span class="kw">return</span></span>
<span class="line"></span>
<span class="line"> self.active_connections[room_id] = [</span>
<span class="line"> connection</span>
<span class="line"> <span class="kw">for</span> connection <span class="kw">in</span> self.active_connections[room_id] <span class="kw">if</span> connection.websocket <span class="kw">is</span> <span class="kw">not</span> websocket]</span>
<span class="line"></span>
<span class="line"> <span class="kw">if</span> <span class="kw">not</span> self.active_connections[room_id]:</span>
<span class="line"> <span class="kw">del</span> self.active_connections[room_id]</span></code></pre>
</div>
<aside class="notes">
This slide shows how the ConnectionManager tracks active users per room, handles new WebSocket
connections, and removes clients when they disconnect. Empty rooms are automatically cleaned up.
</aside>
</section>
<section class="slide code-slide" data-title="Backend Broadcast Manager">
<h2>Broadcast</h2>
<p class="subtitle">Sends messages to all clients in a room and removes failed WebSocket connections safely.</p>
<div class="code-window">
<div class="code-titlebar">
<span></span><span></span><span></span>
<strong>app/websocket/manager.py</strong>
</div>
<pre><code><span class="line"><span class="kw">class</span> <span class="fn">ConnectionManager</span>:</span>
<span class="line"></span>
<span class="line"> <span class="kw">async def</span> <span class="fn">broadcast_json</span>(self, payload: <span class="kw">dict</span>[str, Any], room_id: str):</span>
<span class="line"> <span class="kw">if</span> room_id <span class="kw">not</span> <span class="kw">in</span> self.active_connections:</span>
<span class="line"> <span class="kw">return</span></span>
<span class="line"></span>
<span class="line"> dead_connections: <span class="kw">list</span>[WebSocket] = []</span>
<span class="line"></span>
<span class="line"> <span class="com"># Iterate over a copy so disconnected clients can be removed safely later.</span></span>
<span class="line"> <span class="kw">for</span> connection <span class="kw">in</span> <span class="kw">list</span>(self.active_connections[room_id]):</span>
<span class="line"> <span class="kw">try</span>:</span>
<span class="line"> <span class="kw">await</span> connection.websocket.send_json(payload)</span>
<span class="line"> <span class="kw">except</span> Exception:</span>
<span class="line"> dead_connections.append(connection.websocket)</span>
<span class="line"></span>
<span class="line"> <span class="kw">for</span> websocket <span class="kw">in</span> dead_connections:</span>
<span class="line"> self.disconnect(websocket, room_id)</span></code></pre>
</div>
<aside class="notes">
This method broadcasts a JSON payload to all clients in a room.
It safely handles broken connections by collecting failed sockets and removing them after iteration,
preventing runtime errors while modifying the connection list.
</aside>
</section>
<section class="slide code-slide" data-title="Frontend State">
<h2>Frontend Codes</h2>
<p class="subtitle">browser state and DOM references.</p>