Marco310 commited on
Commit
c98862f
·
1 Parent(s): aba9311

Feat: Add Home Button

Browse files
Files changed (4) hide show
  1. app.py +38 -13
  2. ui/components/header.py +23 -16
  3. ui/renderers.py +9 -4
  4. ui/theme.py +52 -1
app.py CHANGED
@@ -22,7 +22,7 @@ from ui.renderers import (
22
  from core.visualizers import create_animated_map
23
 
24
  # ===== UI Components =====
25
- from ui.components.header import create_header, create_top_controls
26
  from ui.components.input_form import create_input_form, toggle_location_inputs
27
  from ui.components.confirmation import create_confirmation_area
28
  from ui.components.results import create_team_area, create_result_area, create_tabs
@@ -204,8 +204,9 @@ class LifeFlowAI:
204
  def build_interface(self):
205
  with gr.Blocks(title=APP_TITLE) as demo:
206
  gr.HTML(get_enhanced_css())
207
- create_header()
208
- theme_btn, settings_btn, doc_btn = create_top_controls()
 
209
 
210
  # State
211
  session_state = gr.State(value=UserSession().to_dict())
@@ -244,6 +245,27 @@ class LifeFlowAI:
244
  doc_modal, close_doc_btn = create_doc_modal()
245
 
246
  # ===== Event Binding =====
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
 
248
  auto_location.change(fn=toggle_location_inputs, inputs=[auto_location], outputs=[location_inputs])
249
 
@@ -268,17 +290,20 @@ class LifeFlowAI:
268
  outputs=[chat_history_output, task_list_display, session_state]
269
  ).then(fn=lambda: "", outputs=[chat_input])
270
 
271
- # Exit
 
 
 
 
 
 
 
 
 
 
272
  exit_btn_inline.click(
273
- fn=lambda: (
274
- gr.update(visible=True), gr.update(visible=False),
275
- gr.update(visible=False), gr.update(visible=False),
276
- gr.update(visible=False), gr.update(visible=False),
277
- gr.update(visible=False), "",
278
- create_agent_stream_output(),
279
- "Ready...",
280
- UserSession().to_dict()
281
- ),
282
  outputs=[
283
  input_area, task_confirm_area, chat_input_area, result_area,
284
  team_area, report_tab, map_tab, user_input,
 
22
  from core.visualizers import create_animated_map
23
 
24
  # ===== UI Components =====
25
+ from ui.components.header import create_header
26
  from ui.components.input_form import create_input_form, toggle_location_inputs
27
  from ui.components.confirmation import create_confirmation_area
28
  from ui.components.results import create_team_area, create_result_area, create_tabs
 
204
  def build_interface(self):
205
  with gr.Blocks(title=APP_TITLE) as demo:
206
  gr.HTML(get_enhanced_css())
207
+ #create_header()
208
+ #theme_btn, settings_btn, doc_btn = create_top_controls()
209
+ home_btn, theme_btn, settings_btn, doc_btn = create_header()
210
 
211
  # State
212
  session_state = gr.State(value=UserSession().to_dict())
 
245
  doc_modal, close_doc_btn = create_doc_modal()
246
 
247
  # ===== Event Binding =====
248
+ def reset_app(old_session_data):
249
+ # 1. 讀取舊 Session
250
+ old_session = UserSession.from_dict(old_session_data)
251
+
252
+ # 2. 創建新 Session (數據歸零)
253
+ new_session = UserSession()
254
+
255
+ # 3. 🔥 關鍵:繼承舊的設定 (API Keys, Model)
256
+ new_session.custom_settings = old_session.custom_settings
257
+
258
+ # 4. 回傳重置後的 UI 狀態
259
+ return (
260
+ gr.update(visible=True), gr.update(visible=False), # Input Show, Confirm Hide
261
+ gr.update(visible=False), gr.update(visible=False), # Chat Hide, Result Hide
262
+ gr.update(visible=False), gr.update(visible=False), # Team Hide, Report Hide
263
+ gr.update(visible=False), "", # Map Hide, Textbox Clear
264
+ create_agent_stream_output(),
265
+ "Ready...",
266
+ new_session.to_dict() # Reset Session but keep keys
267
+ )
268
+
269
 
270
  auto_location.change(fn=toggle_location_inputs, inputs=[auto_location], outputs=[location_inputs])
271
 
 
290
  outputs=[chat_history_output, task_list_display, session_state]
291
  ).then(fn=lambda: "", outputs=[chat_input])
292
 
293
+ home_btn.click(
294
+ fn=reset_app,
295
+ inputs=[session_state],
296
+ outputs=[
297
+ input_area, task_confirm_area, chat_input_area, result_area,
298
+ team_area, report_tab, map_tab, user_input,
299
+ agent_stream_output, status_bar, session_state
300
+ ]
301
+ )
302
+
303
+ # 綁定原有的 Exit 按鈕 (加入 inputs)
304
  exit_btn_inline.click(
305
+ fn=reset_app,
306
+ inputs=[session_state],
 
 
 
 
 
 
 
307
  outputs=[
308
  input_area, task_confirm_area, chat_input_area, result_area,
309
  team_area, report_tab, map_tab, user_input,
ui/components/header.py CHANGED
@@ -1,23 +1,30 @@
1
-
2
  """
3
- LifeFlow AI - Header Component (Clean Style)
4
  """
5
  import gradio as gr
6
 
7
  def create_header():
8
- return gr.HTML("""
9
- <div class="app-header">
10
- <h1>✨ LifeFlow AI</h1>
11
- <p>Your Intelligent Daily Trip Planning Assistant</p>
12
- </div>
13
- """)
 
 
 
 
 
 
 
14
 
15
- def create_top_controls():
16
- with gr.Group(elem_id="top-controls"):
17
- # 按鈕本身樣式由 CSS 控制,這裡保持結構簡單
18
- with gr.Row():
19
- theme_btn = gr.Button("🌓", size="sm", min_width=40)
20
- settings_btn = gr.Button("⚙️", size="sm", min_width=40)
21
- doc_btn = gr.Button("📖", size="sm", min_width=40)
 
22
 
23
- return theme_btn, settings_btn, doc_btn
 
 
1
  """
2
+ LifeFlow AI - Header Component (Layout Improved)
3
  """
4
  import gradio as gr
5
 
6
  def create_header():
7
+ """
8
+ 創建整合式 Header:左側標題,右側控制區
9
+ 回傳按鈕物件供 app.py 綁定事件
10
+ """
11
+ with gr.Row(elem_classes="header-row", elem_id="header-container"):
12
+ # 左側:標題區
13
+ with gr.Column(scale=6, min_width=200):
14
+ gr.HTML("""
15
+ <div class="app-header-left">
16
+ <h1 style="margin: 0; font-size: 1.8rem;">✨ LifeFlow AI</h1>
17
+ <p style="margin: 0; color: #64748b; font-size: 0.9rem;">Intelligent Trip Planner</p>
18
+ </div>
19
+ """)
20
 
21
+ # 右側:功能按鈕區 (包含 Home 鍵)
22
+ with gr.Column(scale=2, min_width=200):
23
+ with gr.Row(elem_classes="header-controls"):
24
+ # 移除 tooltip 參數,保留其他設定
25
+ home_btn = gr.Button("🏠", size="sm", min_width=40, elem_classes="icon-btn")
26
+ theme_btn = gr.Button("🌓", size="sm", min_width=40, elem_classes="icon-btn")
27
+ settings_btn = gr.Button("⚙️", size="sm", min_width=40, elem_classes="icon-btn")
28
+ doc_btn = gr.Button("📖", size="sm", min_width=40, elem_classes="icon-btn")
29
 
30
+ return home_btn, theme_btn, settings_btn, doc_btn
ui/renderers.py CHANGED
@@ -13,22 +13,27 @@ def create_agent_stream_output() -> str:
13
  </div>
14
  """
15
 
 
16
  def create_agent_card_enhanced(agent_key: str, status: str = "idle", message: str = "") -> str:
17
  agent = AGENTS_INFO.get(agent_key, {})
18
  color = agent.get("color", "#6366f1")
19
 
20
  status_color = "#94a3b8" # gray
21
- if status == "working": status_color = "#f59e0b" # orange
22
- if status == "complete": status_color = "#10b981" # green
23
 
24
- active_class = "active" if status == "working" else ""
 
 
 
 
25
 
 
26
  return f"""
27
  <div class="agent-card-mini {active_class}" style="border-top: 3px solid {color}">
28
  <div class="agent-avatar-mini">{agent.get("avatar", "🤖")}</div>
29
  <div class="agent-name-mini">{agent.get("name", "Agent")}</div>
30
  <span class="agent-status-dot" style="background-color: {status_color}"></span>
31
- <div style="font-size: 10px; color: #64748b; margin-top: 4px;">{status}</div>
32
  </div>
33
  """
34
 
 
13
  </div>
14
  """
15
 
16
+
17
  def create_agent_card_enhanced(agent_key: str, status: str = "idle", message: str = "") -> str:
18
  agent = AGENTS_INFO.get(agent_key, {})
19
  color = agent.get("color", "#6366f1")
20
 
21
  status_color = "#94a3b8" # gray
22
+ active_class = ""
 
23
 
24
+ if status == "working":
25
+ status_color = "#f59e0b" # orange
26
+ active_class = "working" # 🔥 這裡對應 CSS 的動畫 class
27
+ elif status == "complete":
28
+ status_color = "#10b981" # green
29
 
30
+ # 確保 active_class 被加入 div class 列表
31
  return f"""
32
  <div class="agent-card-mini {active_class}" style="border-top: 3px solid {color}">
33
  <div class="agent-avatar-mini">{agent.get("avatar", "🤖")}</div>
34
  <div class="agent-name-mini">{agent.get("name", "Agent")}</div>
35
  <span class="agent-status-dot" style="background-color: {status_color}"></span>
36
+ <div style="font-size: 10px; color: #64748b; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;">{message}</div>
37
  </div>
38
  """
39
 
ui/theme.py CHANGED
@@ -25,7 +25,7 @@ def get_enhanced_css() -> str:
25
  font-family: var(--font-main) !important;
26
  background: #f8fafc !important;
27
  }
28
-
29
  /* ============= 毛玻璃卡片風格 ============= */
30
  .glass-card {
31
  background: var(--glass-bg);
@@ -56,6 +56,57 @@ def get_enhanced_css() -> str:
56
  color: #64748b;
57
  font-weight: 400;
58
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  /* ============= 按鈕優化 ============= */
61
  button.primary {
 
25
  font-family: var(--font-main) !important;
26
  background: #f8fafc !important;
27
  }
28
+
29
  /* ============= 毛玻璃卡片風格 ============= */
30
  .glass-card {
31
  background: var(--glass-bg);
 
56
  color: #64748b;
57
  font-weight: 400;
58
  }
59
+
60
+ /* ============= Header 優化 (Flex Layout) ============= */
61
+ .header-row {
62
+ align-items: center !important;
63
+ margin-bottom: 20px !important;
64
+ padding: 10px 20px !important;
65
+ background: rgba(255, 255, 255, 0.5);
66
+ backdrop-filter: blur(10px);
67
+ border-radius: 16px;
68
+ border: 1px solid rgba(255, 255, 255, 0.5);
69
+ }
70
+ .app-header-left h1 {
71
+ background: linear-gradient(to right, #6366f1, #ec4899);
72
+ -webkit-background-clip: text;
73
+ -webkit-text-fill-color: transparent;
74
+ }
75
+
76
+ /* 按鈕微調 */
77
+ .icon-btn {
78
+ background: transparent !important;
79
+ border: 1px solid #e2e8f0 !important;
80
+ box-shadow: none !important;
81
+ }
82
+ .icon-btn:hover {
83
+ background: #f1f5f9 !important;
84
+ border-color: #cbd5e1 !important;
85
+ }
86
+
87
+ /* ============= Agent 呼吸動畫 (關鍵修改) ============= */
88
+ @keyframes breathing-glow {
89
+ 0% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.4); border-color: #6366f1; }
90
+ 70% { box-shadow: 0 0 0 6px rgba(99, 102, 241, 0); border-color: #818cf8; }
91
+ 100% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0); border-color: #6366f1; }
92
+ }
93
+
94
+ .agent-card-mini.working {
95
+ animation: breathing-glow 2s infinite;
96
+ background: linear-gradient(to bottom right, #fff, #eff6ff);
97
+ transform: scale(1.05); /* 稍微放大 */
98
+ z-index: 10;
99
+ }
100
+
101
+ /* ============= AI Conversation 優化 ============= */
102
+ .reasoning-timeline {
103
+ max-height: 400px;
104
+ overflow-y: auto;
105
+ padding-right: 10px;
106
+ /* 讓最新的訊息看起來像是在終端機中彈出 */
107
+ display: flex;
108
+ flex-direction: column-reverse;
109
+ }
110
 
111
  /* ============= 按鈕優化 ============= */
112
  button.primary {