Skip to content

Commit 1adfb24

Browse files
committed
Add utility to swap emojis for text when running ros2 node from terminal
PyQT does not support using emojis when running from terminal. To support emojis we must build a full app
1 parent 88d3b19 commit 1adfb24

File tree

1 file changed

+139
-0
lines changed
  • coffee_ws/src/coffee_voice_agent_ui/coffee_voice_agent_ui

1 file changed

+139
-0
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Emoji Utilities - Platform-specific emoji handling
4+
5+
Provides cross-platform emoji support with automatic fallbacks for macOS
6+
to prevent Qt rendering crashes in external terminal contexts.
7+
"""
8+
9+
import sys
10+
11+
12+
class EmojiManager:
13+
"""Centralized emoji management with platform-specific fallbacks"""
14+
15+
def __init__(self):
16+
self.is_macos = sys.platform == "darwin"
17+
18+
# Emoji mappings: (ubuntu_emoji, macos_fallback)
19+
self.emoji_map = {
20+
# Main UI section emojis
21+
'agent_status': ('🤖', '[AI]'),
22+
'admin_override': ('⚙️', '[ADMIN]'),
23+
'analytics': ('📊', '[DATA]'),
24+
'conversation': ('💬', '[CHAT]'),
25+
'emotion_center': ('🎭', '[EMO]'),
26+
'tool_activity': ('🔧', '[TOOL]'),
27+
'virtual_requests': ('☕', '[REQ]'),
28+
29+
# Status indicators
30+
'connected': ('✅', '[✓]'),
31+
'disconnected': ('❌', '[X]'),
32+
'online': ('✅', '[ON]'),
33+
'offline': ('❌', '[OFF]'),
34+
35+
# Activity/Action emojis
36+
'session_performance': ('📈', '[PERF]'),
37+
'popular_interactions': ('🎯', '[POP]'),
38+
'emotion_trends': ('🎭', '[TREND]'),
39+
'system_metrics': ('⚙️', '[SYS]'),
40+
'active_tools': ('⚡', '[ACTIVE]'),
41+
'total_today': ('📈', '[TOTAL]'),
42+
'recent_activity': ('📋', '[RECENT]'),
43+
'usage_statistics': ('📊', '[STATS]'),
44+
'conversation_time': ('⏰', '[TIME]'),
45+
'user_timeout': ('⏱️', '[TIMEOUT]'),
46+
'lock_scroll': ('🔒', '[LOCK]'),
47+
'auto_scroll': ('📜', '[SCROLL]'),
48+
'clear': ('🗑️', '[CLEAR]'),
49+
'vip_status': ('📊', '[VIP]'),
50+
'vip_history': ('📋', '[HIST]'),
51+
'test_request': ('☕', '[TEST]'),
52+
53+
# User/Agent/Tool indicators
54+
'user': ('👤', '[USER]'),
55+
'agent': ('🤖', '[AI]'),
56+
'tool': ('🔧', '[TOOL]'),
57+
58+
# Emotion emojis (extensive mapping for EmotionDisplayWidget)
59+
'friendly': ('😊', 'friendly'),
60+
'excited': ('🤩', 'excited!'),
61+
'curious': ('🤔', 'curious?'),
62+
'sleepy': ('😴', 'sleepy'),
63+
'waiting': ('😌', 'waiting'),
64+
'excuse': ('😅', 'excuse me'),
65+
'helpful': ('🤝', 'helpful'),
66+
'empathetic': ('🥺', 'caring'),
67+
'confused': ('😕', 'confused'),
68+
'proud': ('😊', 'proud'),
69+
'playful': ('😄', 'playful'),
70+
'focused': ('🧐', 'focused'),
71+
'surprised': ('😮', 'surprised!'),
72+
'enthusiastic': ('🎉', 'enthusiastic!'),
73+
'warm': ('🤗', 'warm'),
74+
'professional': ('👔', 'professional'),
75+
'cheerful': ('😁', 'cheerful'),
76+
}
77+
78+
def get(self, key, default=''):
79+
"""Get emoji for the given key, with platform-specific fallback"""
80+
if key not in self.emoji_map:
81+
return default
82+
83+
emoji, fallback = self.emoji_map[key]
84+
return fallback if self.is_macos else emoji
85+
86+
def format_title(self, emoji_key, title):
87+
"""Format a title with appropriate emoji/fallback"""
88+
emoji = self.get(emoji_key)
89+
if emoji:
90+
return f"{emoji} {title}"
91+
return title
92+
93+
def format_status(self, emoji_key, status_text):
94+
"""Format a status message with appropriate emoji/fallback"""
95+
emoji = self.get(emoji_key)
96+
if emoji:
97+
return f"{emoji} {status_text}"
98+
return status_text
99+
100+
def get_connection_status(self, connected):
101+
"""Get connection status with appropriate emoji/fallback"""
102+
if connected:
103+
return self.format_status('connected', 'Connected')
104+
else:
105+
return self.format_status('disconnected', 'Disconnected')
106+
107+
def debug_info(self):
108+
"""Get debug information about emoji handling"""
109+
return {
110+
'platform': sys.platform,
111+
'is_macos': self.is_macos,
112+
'emoji_mode': 'fallback' if self.is_macos else 'emoji',
113+
'total_mappings': len(self.emoji_map)
114+
}
115+
116+
117+
# Global emoji manager instance
118+
emoji_manager = EmojiManager()
119+
120+
121+
# Convenience functions for easy access
122+
def get_emoji(key, default=''):
123+
"""Get platform-appropriate emoji or fallback"""
124+
return emoji_manager.get(key, default)
125+
126+
127+
def format_title(emoji_key, title):
128+
"""Format title with platform-appropriate emoji"""
129+
return emoji_manager.format_title(emoji_key, title)
130+
131+
132+
def format_status(emoji_key, status_text):
133+
"""Format status with platform-appropriate emoji"""
134+
return emoji_manager.format_status(emoji_key, status_text)
135+
136+
137+
def get_connection_status(connected):
138+
"""Get formatted connection status"""
139+
return emoji_manager.get_connection_status(connected)

0 commit comments

Comments
 (0)