## CHANGES

- Fixed unread indicator to show on active tabs immediately 🔴
- Removed debug logging from theme synchronization code 🧹
- Cleaned up broadcast service console.log statements everywhere 🗑️
- Updated test to verify unread dots on active tabs 
- Simplified theme change broadcasting logic for web clients 🎨
- Removed verbose WebSocket session output logging noise 🔇
- Streamlined broadcast methods by removing debug counters 📊
- Enhanced unread indicator behavior for better user feedback 👁️
- Optimized persistence handler theme broadcast conditions 
- Improved code readability by removing sync debug traces 📖
This commit is contained in:
Pedram Amini
2025-12-16 18:03:25 -06:00
parent 098453e621
commit 6402f50bfa
4 changed files with 18 additions and 49 deletions

View File

@@ -412,7 +412,7 @@ describe('TabBar', () => {
expect(unreadDot).toHaveStyle({ backgroundColor: mockTheme.colors.accent });
});
it('does not show unread indicator for active tab', () => {
it('shows unread indicator for active tab (when manually marked)', () => {
const tabs = [createTab({ id: 'tab-1', name: 'Tab 1', hasUnread: true })];
const { container } = render(
@@ -426,7 +426,11 @@ describe('TabBar', () => {
/>
);
expect(container.querySelector('[title="New messages"]')).not.toBeInTheDocument();
// Unread indicator should show immediately even on active tab
// This allows users to mark a tab as unread and see the indicator right away
const unreadDot = container.querySelector('[title="New messages"]');
expect(unreadDot).toBeInTheDocument();
expect(unreadDot).toHaveStyle({ backgroundColor: mockTheme.colors.accent });
});
it('does not show unread indicator for busy tab', () => {

View File

@@ -81,18 +81,11 @@ export function registerPersistenceHandlers(deps: PersistenceHandlerDependencies
const webServer = getWebServer();
// Broadcast theme changes to connected web clients
if (key === 'activeThemeId') {
const clientCount = webServer?.getWebClientCount() ?? 0;
console.log(`[SYNC-DEBUG] Theme change: webServer=${!!webServer}, clientCount=${clientCount}, themeId=${value}`);
if (webServer && clientCount > 0) {
const theme = getThemeById(value);
console.log(`[SYNC-DEBUG] Theme resolved: ${theme ? theme.name : 'null'}`);
if (theme) {
webServer.broadcastThemeChange(theme);
logger.info(`Broadcasted theme change to web clients: ${value}`, 'WebServer');
}
} else {
console.log(`[SYNC-DEBUG] Theme change NOT broadcast: no webServer or no clients`);
if (key === 'activeThemeId' && webServer && webServer.getWebClientCount() > 0) {
const theme = getThemeById(value);
if (theme) {
webServer.broadcastThemeChange(theme);
logger.info(`Broadcasted theme change to web clients: ${value}`, 'WebServer');
}
}

View File

@@ -128,24 +128,14 @@ export class BroadcastService {
* Broadcast a message to all connected web clients
*/
broadcastToAll(message: object): void {
if (!this.getWebClients) {
console.log(`[SYNC-DEBUG] broadcastToAll: getWebClients callback not set!`);
return;
}
const clients = this.getWebClients();
const msgType = (message as Record<string, unknown>).type || 'unknown';
console.log(`[SYNC-DEBUG] broadcastToAll: type=${msgType}, clients=${clients.size}`);
if (!this.getWebClients) return;
const data = JSON.stringify(message);
let sentCount = 0;
for (const client of clients.values()) {
for (const client of this.getWebClients().values()) {
if (client.socket.readyState === WebSocket.OPEN) {
client.socket.send(data);
sentCount++;
}
}
console.log(`[SYNC-DEBUG] broadcastToAll: sent to ${sentCount}/${clients.size} clients`);
}
/**
@@ -154,30 +144,13 @@ export class BroadcastService {
broadcastToSession(sessionId: string, message: object): void {
if (!this.getWebClients) return;
const clients = this.getWebClients();
const data = JSON.stringify(message);
let sentCount = 0;
const msgType = (message as Record<string, unknown>).type || 'unknown';
for (const client of clients.values()) {
const isOpen = client.socket.readyState === WebSocket.OPEN;
const matchesSession = client.subscribedSessionId === sessionId || !client.subscribedSessionId;
const shouldSend = isOpen && matchesSession;
if (msgType === 'session_output') {
console.log(`[WebBroadcast] Client ${client.id}: isOpen=${isOpen}, subscribedTo=${client.subscribedSessionId || 'none'}, matchesSession=${matchesSession}, shouldSend=${shouldSend}`);
}
if (shouldSend) {
for (const client of this.getWebClients().values()) {
if (client.socket.readyState === WebSocket.OPEN &&
(client.subscribedSessionId === sessionId || !client.subscribedSessionId)) {
client.socket.send(data);
sentCount++;
}
}
// Log summary for session_output
if (msgType === 'session_output') {
console.log(`[WebBroadcast] Sent session_output to ${sentCount}/${clients.size} clients for session ${sessionId}`);
}
}
/**
@@ -269,7 +242,6 @@ export class BroadcastService {
* Called when the user changes the theme in the desktop app
*/
broadcastThemeChange(theme: Theme): void {
console.log(`[SYNC-DEBUG] BroadcastService.broadcastThemeChange called: ${theme.name}`);
this.broadcastToAll({
type: 'theme',
theme,

View File

@@ -226,8 +226,8 @@ function Tab({
/>
)}
{/* Unread indicator - solid dot for tabs with unread messages (only when not active and not busy) */}
{!isActive && tab.state !== 'busy' && tab.hasUnread && (
{/* Unread indicator - solid dot for tabs with unread messages (not shown when busy) */}
{tab.state !== 'busy' && tab.hasUnread && (
<div
className="w-2 h-2 rounded-full shrink-0"
style={{ backgroundColor: theme.colors.accent }}