import gradio as gr def create_input_form(agent_stream_html): """創建優化後的輸入表單 - 放棄 gr.Examples,改用純按鈕""" with gr.Group(elem_classes="glass-card") as input_area: gr.Markdown("### 📝 What's your plan today?") # 1. 主要輸入區 user_input = gr.Textbox( label="Describe your tasks", placeholder="e.g., I need to visit the dentist at 10am...", lines=3, elem_id="main-input" ) # 2. 位置設定 (保持不變) with gr.Accordion("📍 Location Settings", open=True): auto_location = gr.Checkbox(label="Auto-detect my location", value=False) with gr.Group(visible=True) as location_inputs: with gr.Row(): lat_input = gr.Number(label="Latitude", value=25.033, precision=6, scale=1) lon_input = gr.Number(label="Longitude", value=121.565, precision=6, scale=1) # 3. 快速範例 (⭐⭐ 重製版:使用 Button 取代 Examples ⭐⭐) gr.Markdown("##### ⚡ Quick Start Examples") # 定義範例文字 ex_text_1 = "Errands run: Post office, bank, and supermarket. Start at tomorrow 10 AM, finish by 1 PM." ex_text_2 = """ I need to run some errands tomorrow morning starting at 9:30 AM. 1. Go to a Bank. 2. Drop off a package at the Post Office. 3. Buy groceries. I need to be back home by 1:00 PM for a meeting. """ ex_text_3 = """ I am arriving at Cordoba Train Station next Sunday at 11:00 AM. 1. I want to visit the magnificent 'Mezquita-Catedral'. 2. Walk across the 'Roman Bridge' for photos. 3. Find a place to eat the famous 'Salmorejo' for lunch. I need to be back at the station to catch my return train by 4:30 PM. """ with gr.Column(elem_classes="example-container"): btn_ex1 = gr.Button(ex_text_1, size="sm", variant="secondary", elem_classes="example-btn") btn_ex2 = gr.Button(ex_text_2[:100]+'...' if len(ex_text_2)>100 else ex_text_2, size="sm", variant="secondary", elem_classes="example-btn") btn_ex3 = gr.Button(ex_text_3[:100]+'...' if len(ex_text_3)>100 else ex_text_3, size="sm", variant="secondary", elem_classes="example-btn") # 4. 主按鈕 analyze_btn = gr.Button("🚀 Analyze & Plan Trip", variant="primary", size="lg") # 5. Agent 狀態區 gr.Markdown("---") gr.Markdown("### 🤖 Agent Status") agent_stream_output = gr.HTML( value=agent_stream_html, elem_classes="agent-stream-box-step1", visible=True ) geo_js = """ (is_auto, curr_lat, curr_lon) => { if (!is_auto) { // 如果是「取消勾選」,保持原值不變 return [curr_lat, curr_lon]; } // 如果是「勾選」,開始定位 return new Promise((resolve) => { if (!navigator.geolocation) { alert("Geolocation is not supported by your browser."); resolve([curr_lat, curr_lon]); // 失敗回傳原值 return; } // 顯示讀取中的狀態 (可選) // document.body.style.cursor = 'wait'; navigator.geolocation.getCurrentPosition( (position) => { // document.body.style.cursor = 'default'; // 成功!回傳經緯度 resolve([position.coords.latitude, position.coords.longitude]); }, (error) => { // document.body.style.cursor = 'default'; let msg = "Unknown error"; switch(error.code) { case 1: msg = "Permission denied. Please allow location access."; break; case 2: msg = "Position unavailable."; break; case 3: msg = "Timeout."; break; } alert("📍 Location Error: " + msg); resolve([curr_lat, curr_lon]); // 失敗回傳原值 }, { enableHighAccuracy: true, timeout: 8000 } ); }); } """ # 綁定事件 1: 控制輸入框顯示/隱藏 (Python 邏輯) auto_location.change( fn=lambda x: gr.update(visible=not x), inputs=[auto_location], outputs=[location_inputs] ) # 綁定事件 2: 執行 JS 定位 (JS 邏輯) # 注意 inputs 包含了 lat/lon,這樣 JS 才能在失敗/取消時把原值傳回來 auto_location.change( fn=None, inputs=[auto_location, lat_input, lon_input], outputs=[lat_input, lon_input], js=geo_js ) # ⭐⭐ 綁定點擊事件 ⭐⭐ # 點擊按鈕 -> 把按鈕文字填入 user_input btn_ex1.click(lambda: ex_text_1, outputs=user_input) btn_ex2.click(lambda: ex_text_2, outputs=user_input) btn_ex3.click(lambda: ex_text_3, outputs=user_input) return (input_area, agent_stream_output, user_input, auto_location, location_inputs, lat_input, lon_input, analyze_btn) def toggle_location_inputs(auto_loc): return gr.update(visible=not auto_loc)