Skip to content

Commit 6a59d7d

Browse files
docs: add WebDAV & appui module docs, update README & website
1 parent d0363ea commit 6a59d7d

4 files changed

Lines changed: 534 additions & 9 deletions

File tree

README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,22 @@ Plan 模式是纯对话模式,适合复杂需求的前期规划:
225225
| **导入** | 从系统「文件」App 导入任意文件 |
226226
| **排序** | 拖拽手动排序,或按更新时间自动排序 |
227227

228+
#### ☁️ WebDAV 云盘
229+
230+
| 功能 | 描述 |
231+
|------|------|
232+
| **服务器模板** | 坚果云、NextCloud、群晖 NAS 一键配置,支持自定义 WebDAV 服务器 |
233+
| **文件浏览** | 远程目录面包屑导航、骨架屏加载、搜索过滤、排序 |
234+
| **在线编辑** | 远程文本文件直接编辑,ETag 冲突检测,防覆盖 |
235+
| **文件操作** | 上传、下载到工作区、重命名、删除、新建文件夹 |
236+
| **批量操作** | 多选删除、批量下载、批量移动 |
237+
| **收藏夹** | 常用目录快速跳转 |
238+
| **安全** | Keychain 密码存储、自签名证书支持 |
239+
| **坚果云优化** | 内置频率限制保护,指数退避 |
240+
241+
> 从首页「+」新建菜单进入 WebDAV,添加云盘服务器后即可远程管理文件。
242+
> **详细说明:** [WebDAV 功能文档](docs/webdav-module.md)
243+
228244
---
229245

230246
### 📄 多格式支持
@@ -265,6 +281,8 @@ Plan 模式是纯对话模式,适合复杂需求的前期规划:
265281
| **创建 / 删除 / 重命名** | 完整文件操作,含确认对话框 |
266282
| **权限管理** | 查看和修改文件 chmod 权限 |
267283

284+
> **网盘与 WebDAV:** 连接坚果云、NextCloud、群晖等云盘请使用 [WebDAV 功能文档](docs/webdav-module.md)
285+
268286
#### 一键部署
269287

270288
| 功能 | 描述 |
@@ -393,11 +411,24 @@ dialogs.hud_alert("操作完成!")
393411

394412
> **完整 API 文档:** [photos 模块](docs/photos-module.md) · [dialogs 模块](docs/dialogs-module.md) · [clipboard 模块](docs/clipboard-module.md) · [console 模块](docs/console-module.md)
395413
414+
#### 🆕 新增 iOS 原生模块
415+
416+
| 模块 | 功能 | 说明 |
417+
|------|------|------|
418+
| **`location`** | GPS 定位 | 经纬度、海拔、指南针、正向/反向地理编码 |
419+
| **`motion`** | 传感器 | 加速度计、陀螺仪、磁力计、气压计、融合传感器 |
420+
| **`speech`** | 语音合成 | 文字转语音,多语言,语速/音高/音量控制 |
421+
| **`biometric`** | 生物认证 | Face ID / Touch ID 安全认证 |
422+
| **`notification`** | 本地通知 | 定时通知、日历通知、通知管理、角标 |
423+
| **`vision_helper`** | 高级视觉 | 人脸检测、条码/QR 扫描、图像分类、矩形检测 |
424+
425+
> **完整 API 文档:** [新增原生模块文档](docs/new-native-modules.md)
426+
396427
#### 📐 ui 模块 — 原生界面
397428

398429
Pythonista 兼容的 UI 模块,用 Python 创建原生 iOS 界面(View、Button、Label、TextField、ScrollView、TableView、WebView 等),支持 `present()` 全屏/半屏展示、自绘、load_view 等。
399430

400-
> **完整 API 文档:** [ui 模块完整文档](docs/ui-module.md)
431+
> **完整 API 文档:** [ui 模块完整文档](docs/ui-module.md) · [appui 声明式 UI](docs/appui-module.md)
401432
402433
#### 🎮 scene 模块 — 2D 游戏引擎
403434

docs/appui-module.md

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
# appui 模块 — 声明式原生 UI(SwiftUI 风格)
2+
3+
`appui` 是 Python IDE 提供的 **声明式 UI 框架**:用 Python 描述界面结构(栈、列表、表单、导航等),底层由 **SwiftUI** 渲染,适合快速搭建设置页、简单工具界面、原型等场景。
4+
5+
> **与内置帮助一致**:应用内 **设置 → 帮助 → 模块与原生能力指南 → appui — 声明式 UI 框架** 中有与本文同步的速查示例。
6+
7+
---
8+
9+
## `ui` 模块的区别
10+
11+
| 维度 | `ui` 模块 | `appui` 模块 |
12+
|------|-----------|--------------|
13+
| **风格** | Pythonista 兼容的 **UIKit 命令式** API | **声明式** DSL,接近 SwiftUI |
14+
| **典型用法** | `ui.View``present()``load_view`、手势、自定义 `draw` | `appui.VStack``appui.run()`、链式 **修饰符** |
15+
| **状态** | 手动更新控件属性 | `appui.State` **响应式**,改属性可触发界面刷新 |
16+
| **坐标** | 左上角原点,`y` 向下 | 由布局容器与修饰符管理,不写绝对 frame 也能排版 |
17+
| **兼容目标** | 与 Pythonista 脚本、老项目对齐 | 新项目、快速界面、SwiftUI 心智模型 |
18+
19+
两者可同时存在于应用中,按场景选择:**复杂传统 UI / 兼容 Pythonista**`ui`**列表+表单+导航的现代布局** 可优先尝试 `appui`
20+
21+
---
22+
23+
## 快速开始
24+
25+
```python
26+
import appui
27+
28+
state = appui.State(count=0)
29+
30+
def increment():
31+
state.count += 1
32+
33+
def body():
34+
return appui.VStack([
35+
appui.Text(f"计数: {state.count}")
36+
.font("title").bold(),
37+
appui.Button("点击 +1", action=increment)
38+
.button_style("bordered_prominent"),
39+
], spacing=20).padding()
40+
41+
appui.run(body, state=state)
42+
```
43+
44+
---
45+
46+
## 入口与展示
47+
48+
| API | 说明 |
49+
|-----|------|
50+
| `appui.run(body, state=..., presentation=...)` | 运行声明式界面;`body` 为无参函数,返回根视图 |
51+
| `presentation` | `'sheet'` / `'fullscreen'` / `'fullscreen_with_close'` 等,控制模态样式 |
52+
53+
---
54+
55+
## 布局容器
56+
57+
```python
58+
# 垂直 / 水平 / 层叠
59+
appui.VStack(content, alignment, spacing)
60+
appui.HStack(content, alignment, spacing)
61+
appui.ZStack(content, alignment)
62+
63+
# 滚动与网格
64+
appui.ScrollView(content, axes='vertical')
65+
appui.LazyVGrid(columns=[appui.flexible()], content)
66+
67+
# 列表与表单
68+
appui.List(content)
69+
appui.Form([
70+
appui.Section(content, header="标题"),
71+
])
72+
appui.ForEach(data, row_builder, key='id')
73+
```
74+
75+
| 组件 | 用途 |
76+
|------|------|
77+
| `VStack` / `HStack` / `ZStack` | 线性或叠加布局 |
78+
| `ScrollView` | 可滚动内容 |
79+
| `LazyVGrid` + `flexible()` | 自适应列网格 |
80+
| `List` | 列表 |
81+
| `Form` / `Section` | 分组表单 |
82+
| `ForEach` | 由数据驱动多行 |
83+
84+
---
85+
86+
## 导航与标签页
87+
88+
```python
89+
# 导航栈
90+
appui.NavigationStack(
91+
appui.VStack([...])
92+
.navigation_title("首页")
93+
)
94+
appui.NavigationLink("详情", destination=detail())
95+
96+
# 底部标签页
97+
appui.TabView([
98+
appui.Tab(title="首页",
99+
system_image="house.fill",
100+
content=home_view()),
101+
appui.Tab(title="设置",
102+
system_image="gearshape.fill",
103+
content=settings_view()),
104+
])
105+
```
106+
107+
---
108+
109+
## 基础视图与输入控件
110+
111+
**展示**
112+
113+
- `appui.Text(...)`
114+
- `appui.Image(system_name="star.fill")` — SF Symbol
115+
116+
**输入**
117+
118+
```python
119+
appui.TextField("占位符", text=state.name,
120+
on_change=lambda v: setattr(state, 'name', v))
121+
appui.SecureField("密码", text=state.pwd, ...)
122+
appui.TextEditor(text=state.note, on_change=...)
123+
appui.Toggle("开关", is_on=state.on, on_change=...)
124+
appui.Slider(value=state.val, minimum=0, maximum=100)
125+
appui.Picker("选择", selection=state.sel,
126+
options=["A", "B", "C"], on_change=...)
127+
appui.DatePicker("日期", selection=state.date)
128+
```
129+
130+
---
131+
132+
## 修饰符(链式调用)
133+
134+
声明式 API 通过 **返回 self** 的链式方法设置样式与行为:
135+
136+
```python
137+
appui.Text("Hello")
138+
.font("title")
139+
.bold()
140+
.foreground_color("blue")
141+
.padding(16)
142+
.background("gray", corner_radius=12)
143+
.frame(width=200, height=100)
144+
.shadow(radius=4)
145+
.on_tap(action)
146+
.animation("spring")
147+
148+
appui.Image(system_name="star.fill")
149+
.font("system", size=48)
150+
.resizable()
151+
.aspect_ratio(content_mode='fit')
152+
.foreground_color("orange")
153+
```
154+
155+
常见修饰符包括:`font``bold``foreground_color``padding``background``frame``shadow``on_tap``animation` 等(以实际实现为准)。
156+
157+
---
158+
159+
## 状态管理
160+
161+
```python
162+
# 响应式状态 — 属性变化会驱动 UI 更新
163+
state = appui.State(count=0, name='')
164+
state.count += 1
165+
166+
# 不触发刷新的引用容器
167+
ref = appui.Ref(initial=None)
168+
169+
# 计算属性(依赖变化时重算)
170+
@appui.computed(state, depends_on=['count'])
171+
def doubled():
172+
return state.count * 2
173+
174+
# 副作用(依赖变化时执行)
175+
@appui.effect(state, depends_on=['name'])
176+
def on_name_change():
177+
print(f"名字变为: {state.name}")
178+
```
179+
180+
| 类型 | 作用 |
181+
|------|------|
182+
| `State` | 可观察状态,赋值后刷新依赖该状态的视图 |
183+
| `Ref` | 可变引用,适合存放不需要触发整树刷新的对象 |
184+
| `@computed` | 派生数据 |
185+
| `@effect` | 依赖变更时的回调(日志、同步等) |
186+
187+
---
188+
189+
## 手势与弹窗
190+
191+
```python
192+
# 手势
193+
.on_tap(action)
194+
.on_long_press(action, min_duration=0.5)
195+
.on_drag(on_changed=..., on_ended=...)
196+
197+
# 弹窗
198+
.alert("标题", message="内容",
199+
is_presented=state.show_alert,
200+
actions=[appui.Button("确定", action=ok)])
201+
.sheet(is_presented=state.show_sheet,
202+
content=sheet_view())
203+
```
204+
205+
`appui.Button` 既可用在布局中,也可作为 `alert``actions`
206+
207+
---
208+
209+
## 完整示例:计数器 + 多状态
210+
211+
```python
212+
import appui
213+
214+
state = appui.State(count=0, show_alert=False)
215+
216+
def increment():
217+
state.count += 1
218+
219+
def body():
220+
return appui.NavigationStack(
221+
appui.VStack([
222+
appui.Text(f"当前: {state.count}").font("title"),
223+
appui.Button("+1", action=increment),
224+
appui.Button("弹出提示", action=lambda: setattr(state, "show_alert", True)),
225+
], spacing=16)
226+
.padding()
227+
.navigation_title("Demo")
228+
.alert(
229+
"提示",
230+
message="这是一个 alert 示例",
231+
is_presented=state.show_alert,
232+
actions=[appui.Button("好的", action=lambda: setattr(state, "show_alert", False))],
233+
)
234+
)
235+
236+
appui.run(body, state=state, presentation='sheet')
237+
```
238+
239+
---
240+
241+
## 注意事项
242+
243+
1. **线程**:UI 更新应在主线程/框架允许的上下文中进行(与 `ui` 模块相同,避免后台线程直接改 State)。
244+
2. **`scene` 坐标系无关**`appui` 为屏幕 UI;2D 游戏请使用 `scene` 模块。
245+
3. **API 演进**:链式修饰符与控件名可能随版本增加,若 AI 助手或文档滞后,请以 **应用内「模块与原生能力指南」** 为准。
246+
247+
---
248+
249+
## 相关文档
250+
251+
- [ui 模块 — 原生 iOS 界面](ui-module.md)(Pythonista / UIKit)
252+
- [scene 模块 — 2D 游戏引擎](scene-module.md)
253+
- [widget 模块 — 桌面小组件](widget-module.md)

0 commit comments

Comments
 (0)