File size: 5,106 Bytes
4abc17c
 
a3b49e8
4abc17c
a3b49e8
aba9311
 
 
 
6b71d3d
4abc17c
aba9311
a3b49e8
aba9311
 
4abc17c
 
a3b49e8
 
 
6b71d3d
 
 
 
 
a3b49e8
 
 
 
 
 
aba9311
a3b49e8
 
 
 
4abc17c
a3b49e8
aba9311
4abc17c
a3b49e8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4abc17c
 
 
a3b49e8
3b3daa9
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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 = "Plan a trip to visit Taipei 101, then have lunch at Din Tai Fung."
        ex_text_2 = "Errands run: Post office, bank, and supermarket. Start at 10 AM, finish by 1 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, 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)

    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)