termux_gui/components/
web_view.rs

1//! WebView component - 网页视图组件
2//!
3//! WebView 用于在应用中显示网页内容,支持加载URL、运行JavaScript等功能。
4
5use serde_json::json;
6use crate::activity::Activity;
7use crate::view::View;
8use crate::error::Result;
9
10/// WebView 组件,用于显示网页内容
11pub struct WebView {
12    view: View,
13    aid: i64,
14}
15
16impl WebView {
17    /// 创建一个新的 WebView
18    ///
19    /// # 参数
20    /// - `activity`: Activity 引用
21    /// - `parent`: 可选的父视图ID
22    ///
23    /// # 示例
24    /// ```no_run
25    /// let webview = WebView::new(&mut activity, Some(layout_id))?;
26    /// ```
27    pub fn new(activity: &mut Activity, parent: Option<i64>) -> Result<Self> {
28        eprintln!("[DEBUG] WebView::new() - creating WebView...");
29        
30        let mut params = json!({
31            "aid": activity.id()
32        });
33        
34        if let Some(parent_id) = parent {
35            params["parent"] = json!(parent_id);
36        }
37        
38        eprintln!("[DEBUG] WebView::new() - sending createWebView...");
39        let response = activity.send_read(&json!({
40            "method": "createWebView",
41            "params": params
42        }))?;
43        
44        eprintln!("[DEBUG] WebView::new() - got response: {:?}", response);
45        
46        let id = response
47            .as_i64()
48            .ok_or_else(|| crate::error::GuiError::InvalidResponse("Invalid id".to_string()))?;
49        
50        Ok(WebView {
51            view: View::new(id),
52            aid: activity.id(),
53        })
54    }
55    
56    /// 获取视图ID
57    pub fn id(&self) -> i64 {
58        self.view.id()
59    }
60    
61    /// 获取视图引用
62    pub fn view(&self) -> &View {
63        &self.view
64    }
65    
66    /// 加载URI/URL
67    ///
68    /// # 参数
69    /// - `activity`: Activity 引用
70    /// - `uri`: 要加载的URL,例如 "https://www.google.com"
71    ///
72    /// # 示例
73    /// ```no_run
74    /// webview.load_uri(&mut activity, "https://www.google.com")?;
75    /// ```
76    pub fn load_uri(&self, activity: &mut Activity, uri: &str) -> Result<()> {
77        activity.send(&json!({
78            "method": "loadURI",
79            "params": {
80                "aid": self.aid,
81                "id": self.view.id(),
82                "uri": uri
83            }
84        }))?;
85        Ok(())
86    }
87    
88    /// 设置HTML内容
89    ///
90    /// # 参数
91    /// - `activity`: Activity 引用
92    /// - `data`: HTML文档内容
93    ///
94    /// # 示例
95    /// ```no_run
96    /// webview.set_data(&mut activity, "<html><body><h1>Hello</h1></body></html>")?;
97    /// ```
98    pub fn set_data(&self, activity: &mut Activity, data: &str) -> Result<()> {
99        activity.send(&json!({
100            "method": "setData",
101            "params": {
102                "aid": self.aid,
103                "id": self.view.id(),
104                "doc": data
105            }
106        }))?;
107        Ok(())
108    }
109    
110    /// 允许JavaScript执行
111    ///
112    /// 如果请求允许JavaScript,会弹出用户确认对话框,用户可以拒绝。
113    /// 此方法会阻塞直到用户响应。
114    ///
115    /// # 参数
116    /// - `activity`: Activity 引用
117    /// - `allow`: 是否允许JavaScript
118    ///
119    /// # 返回
120    /// 返回调用后JavaScript是否启用
121    pub fn allow_javascript(&self, activity: &mut Activity, allow: bool) -> Result<bool> {
122        let response = activity.send_read(&json!({
123            "method": "allowJavascript",
124            "params": {
125                "aid": self.aid,
126                "id": self.view.id(),
127                "allow": allow
128            }
129        }))?;
130        
131        Ok(response.as_bool().unwrap_or(false))
132    }
133    
134    /// 允许从 content:// URI 加载内容
135    ///
136    /// # 参数
137    /// - `activity`: Activity 引用
138    /// - `allow`: 是否允许
139    pub fn allow_content_uri(&self, activity: &mut Activity, allow: bool) -> Result<()> {
140        activity.send(&json!({
141            "method": "allowContentURI",
142            "params": {
143                "aid": self.aid,
144                "id": self.view.id(),
145                "allow": allow
146            }
147        }))?;
148        Ok(())
149    }
150    
151    /// 允许导航到不同站点
152    ///
153    /// # 参数
154    /// - `activity`: Activity 引用
155    /// - `allow`: 是否允许用户和JavaScript导航到不同站点
156    pub fn allow_navigation(&self, activity: &mut Activity, allow: bool) -> Result<()> {
157        activity.send(&json!({
158            "method": "allowNavigation",
159            "params": {
160                "aid": self.aid,
161                "id": self.view.id(),
162                "allow": allow
163            }
164        }))?;
165        Ok(())
166    }
167    
168    /// 在WebView中执行JavaScript代码
169    ///
170    /// 需要先通过 allow_javascript() 启用JavaScript。
171    ///
172    /// # 参数
173    /// - `activity`: Activity 引用
174    /// - `code`: 要执行的JavaScript代码
175    ///
176    /// # 示例
177    /// ```no_run
178    /// webview.evaluate_js(&mut activity, "alert('Hello from JavaScript!');")?;
179    /// ```
180    pub fn evaluate_js(&self, activity: &mut Activity, code: &str) -> Result<()> {
181        activity.send(&json!({
182            "method": "evaluateJS",
183            "params": {
184                "aid": self.aid,
185                "id": self.view.id(),
186                "code": code
187            }
188        }))?;
189        Ok(())
190    }
191    
192    /// 后退到历史记录的上一页
193    pub fn go_back(&self, activity: &mut Activity) -> Result<()> {
194        activity.send(&json!({
195            "method": "goBack",
196            "params": {
197                "aid": self.aid,
198                "id": self.view.id()
199            }
200        }))?;
201        Ok(())
202    }
203    
204    /// 前进到历史记录的下一页
205    pub fn go_forward(&self, activity: &mut Activity) -> Result<()> {
206        activity.send(&json!({
207            "method": "goForward",
208            "params": {
209                "aid": self.aid,
210                "id": self.view.id()
211            }
212        }))?;
213        Ok(())
214    }
215}