Add active WebSocket client tracking and display
Track and display the number of active WebSocket connections viewing the aircraft tracker. Features: Backend: - Add getActiveClientCount() method for thread-safe client counting - Include active_clients count in all statistics responses - Integrate with existing stats API endpoints Frontend: - Display "X viewer(s)" in header stats with proper plural/singular grammar - Add "Active Viewers" card to Statistics view - Real-time updates as clients connect/disconnect - Fallback to 1 when stats not yet available This adds a social element showing "Now being watched by X users" style information prominently in the interface. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
802e964cc0
commit
6414ea72f1
3 changed files with 34 additions and 4 deletions
|
|
@ -257,7 +257,7 @@ func (s *Server) isAircraftUseful(aircraft *merger.AircraftState) bool {
|
|||
// - 503 Service Unavailable when the service is degraded (no active sources)
|
||||
func (s *Server) handleHealthCheck(w http.ResponseWriter, r *http.Request) {
|
||||
sources := s.merger.GetSources()
|
||||
stats := s.merger.GetStatistics()
|
||||
stats := s.addServerStats(s.merger.GetStatistics())
|
||||
aircraft := s.merger.GetAircraft()
|
||||
|
||||
// Check if we have any active sources
|
||||
|
|
@ -393,7 +393,7 @@ func (s *Server) handleGetSources(w http.ResponseWriter, r *http.Request) {
|
|||
//
|
||||
// The exact statistics depend on the merger implementation.
|
||||
func (s *Server) handleGetStats(w http.ResponseWriter, r *http.Request) {
|
||||
stats := s.merger.GetStatistics()
|
||||
stats := s.addServerStats(s.merger.GetStatistics())
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(stats)
|
||||
|
|
@ -576,10 +576,23 @@ func (s *Server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
|||
// ICAO addresses are converted to hex strings for consistent JSON representation.
|
||||
// This initial data allows the client to immediately display current aircraft
|
||||
// without waiting for the next periodic update.
|
||||
// getActiveClientCount returns the number of currently connected WebSocket clients.
|
||||
func (s *Server) getActiveClientCount() int {
|
||||
s.wsClientsMu.RLock()
|
||||
defer s.wsClientsMu.RUnlock()
|
||||
return len(s.wsClients)
|
||||
}
|
||||
|
||||
// addServerStats adds server-specific statistics to the merger stats.
|
||||
func (s *Server) addServerStats(stats map[string]interface{}) map[string]interface{} {
|
||||
stats["active_clients"] = s.getActiveClientCount()
|
||||
return stats
|
||||
}
|
||||
|
||||
func (s *Server) sendInitialData(conn *websocket.Conn) {
|
||||
aircraft := s.merger.GetAircraft()
|
||||
sources := s.merger.GetSources()
|
||||
stats := s.merger.GetStatistics()
|
||||
stats := s.addServerStats(s.merger.GetStatistics())
|
||||
|
||||
// Convert ICAO keys to hex strings and filter useful aircraft
|
||||
aircraftMap := make(map[string]*merger.AircraftState)
|
||||
|
|
@ -671,7 +684,7 @@ func (s *Server) periodicUpdateRoutine() {
|
|||
func (s *Server) broadcastUpdate() {
|
||||
aircraft := s.merger.GetAircraft()
|
||||
sources := s.merger.GetSources()
|
||||
stats := s.merger.GetStatistics()
|
||||
stats := s.addServerStats(s.merger.GetStatistics())
|
||||
|
||||
// Convert ICAO keys to hex strings and filter useful aircraft
|
||||
aircraftMap := make(map[string]*merger.AircraftState)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue