Skip to content

Commit ced799a

Browse files
committed
Update
1 parent 6937051 commit ced799a

1 file changed

Lines changed: 329 additions & 0 deletions

File tree

website/huong-dan-depend.md

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
# Hướng dẫn sử dụng thuộc tính `depend-*` trong KR Script
2+
3+
Tài liệu này giải thích chi tiết cách dùng từng thuộc tính `depend-*` để điều khiển ẩn/hiện param theo giá trị của (các) param khác, dựa theo logic hiện có trong `ActionParamsLayoutRender.kt` + `PageConfigReader.kt`.
4+
5+
## Cơ chế chung
6+
7+
Mỗi `<param>` có thể khai báo phụ thuộc vào 1 hoặc nhiều `<param>` khác (gọi là **param cha**). Khi giá trị param cha thay đổi, hàm `evaluateDependencies()` chạy lại, tính `shouldShow` cho từng param (có tính cả cascade — xem mục 10) rồi set `View.VISIBLE` / `View.GONE`.
8+
9+
---
10+
11+
## 1. `depend-on` (hoặc `depend`)
12+
13+
**Mục đích:** khai báo (các) param cha mà param này phụ thuộc vào. Nhiều param cha nối bằng `|`.
14+
15+
```xml
16+
<param name="mode" type="select" title="Chế độ" option-sh="echo -e 'basic\nadvanced'" />
17+
18+
<param name="advanced_opt" type="input" title="Tùy chọn nâng cao"
19+
depend-on="mode" depend-value="advanced" />
20+
```
21+
`advanced_opt` chỉ hiện khi `mode = advanced`.
22+
23+
Nhiều cha:
24+
```xml
25+
depend-on="mode|target_fs"
26+
```
27+
→ phụ thuộc đồng thời `mode``target_fs` (cách kết hợp do `depend-logic` quyết định).
28+
29+
---
30+
31+
## 2. `depend-value`
32+
33+
**Mục đích:** giá trị cần khớp ở param cha tương ứng. Vị trí trong `depend-value` khớp theo đúng thứ tự khai báo ở `depend-on` (cách nhau bởi `|`). Trong mỗi vị trí, nhiều giá trị chấp nhận (OR) cách nhau bởi dấu phẩy.
34+
35+
```xml
36+
depend-on="mode|target_fs"
37+
depend-value="advanced|EXT4,F2FS"
38+
```
39+
→ điều kiện 1: `mode` khớp khi = `advanced`.
40+
→ điều kiện 2: `target_fs` khớp khi = `EXT4` **hoặc** `F2FS`.
41+
42+
Giá trị so khớp không chỉ khớp `value` thực tế mà còn khớp `title` hiển thị, hoặc phần trong ngoặc `()` của title (ví dụ option có title `"A (so)"` thì `depend-value="A"` hoặc `depend-value="so"` hoặc `depend-value="(so)"` đều khớp được).
43+
44+
---
45+
46+
## 3. `depend-mode`
47+
48+
**Mục đích:** quy định khi khớp `depend-value` thì **hiện** hay **ẩn**. Mặc định `"show"`. Có thể khai riêng cho từng param cha, nối bằng `|`.
49+
50+
```xml
51+
depend-on="mode"
52+
depend-value="basic"
53+
depend-mode="hide"
54+
```
55+
→ Khi `mode = basic` thì **ẩn** param này (ngược lại với mặc định).
56+
57+
Nhiều cha, mode khác nhau:
58+
```xml
59+
depend-on="mode|target_fs"
60+
depend-value="basic|EROFS"
61+
depend-mode="hide|show"
62+
```
63+
→ cha 1 (`mode=basic`) → ẩn khi khớp. Cha 2 (`target_fs=EROFS`) → hiện khi khớp.
64+
65+
---
66+
67+
## 4. `depend-logic`
68+
69+
**Mục đích:** cách kết hợp nhiều điều kiện khi có ≥2 param cha. Có 5 chế độ.
70+
71+
### `and` (mặc định)
72+
Tất cả điều kiện phải cùng "muốn hiện" (`wantShow`) thì mới hiện.
73+
```xml
74+
<param name="wifi" type="switch" title="WiFi" />
75+
<param name="battery_saver" type="switch" title="Tiết kiệm pin" />
76+
77+
<param name="wifi_boost" type="switch" title="Tăng tốc WiFi"
78+
depend-on="wifi|battery_saver"
79+
depend-value="1|0"
80+
depend-mode="show|show"
81+
depend-logic="and" />
82+
```
83+
→ Chỉ hiện khi WiFi bật **** tiết kiệm pin tắt.
84+
85+
### `priority` (hoặc `or`) — ưu tiên trái → phải
86+
Xét từng điều kiện theo thứ tự khai báo; điều kiện nào **khớp trước** quyết định luôn kết quả (không xét tiếp).
87+
```xml
88+
<param name="target_fs" type="select" title="Định dạng" option-sh="..." />
89+
<param name="images" type="select" title="Loại ảnh" option-sh="..." />
90+
91+
<param name="erofs_notice" type="input" title="Cảnh báo EROFS"
92+
depend-on="target_fs|images"
93+
depend-value="EXT4,F2FS|(erofs)"
94+
depend-mode="hide|show"
95+
depend-logic="priority" />
96+
```
97+
→ Nếu `target_fs = EXT4/F2FS`**ẩn ngay** (không xét `images` nữa).
98+
→ Nếu `target_fs` không khớp → xét tiếp `images`; nếu `images = (erofs)`**hiện**.
99+
→ Nếu không điều kiện nào khớp → dùng `depend-default`.
100+
101+
### `priority-rtl` (hoặc `or-rtl`)
102+
Giống `priority` nhưng xét từ phải sang trái (điều kiện cuối cùng trong `depend-on` được xét trước).
103+
```xml
104+
depend-on="a|b|c"
105+
depend-value="1|2|3"
106+
depend-logic="priority-rtl"
107+
```
108+
→ Xét `c` trước, rồi `b`, rồi `a`.
109+
110+
### `xor`
111+
Chỉ hiện khi **đúng một** điều kiện khớp (không hơn, không kém).
112+
```xml
113+
<param name="use_manual" type="switch" title="Nhập tay" />
114+
<param name="use_auto" type="switch" title="Tự động" />
115+
116+
<param name="conflict_warning" type="input" title="⚠ Xung đột cấu hình"
117+
depend-on="use_manual|use_auto"
118+
depend-value="1|1"
119+
depend-logic="xor" />
120+
```
121+
→ Nếu **cả hai** hoặc **không cái nào** bật → không hiện cảnh báo. Chỉ hiện khi đúng 1 trong 2 bật.
122+
123+
### `nand`
124+
Phủ định của `and` — hiện khi **không phải tất cả** điều kiện đều thỏa (ít nhất 1 cái không thỏa thì hiện).
125+
```xml
126+
depend-on="a|b"
127+
depend-value="1|1"
128+
depend-logic="nand"
129+
```
130+
→ Hiện trừ khi cả `a=1``b=1` cùng lúc.
131+
132+
---
133+
134+
## 5. `depend-default`
135+
136+
**Mục đích:** kết quả khi **không có điều kiện nào khớp** (chỉ có ý nghĩa rõ với `priority`/`priority-rtl`, hoặc khi param cha không tìm thấy). Giá trị: `"show"` (mặc định) hoặc `"hide"`.
137+
138+
```xml
139+
<param name="advanced_toggle" type="input" title="Tuỳ chọn hiếm gặp"
140+
depend-on="mode"
141+
depend-value="expert"
142+
depend-logic="priority"
143+
depend-default="hide" />
144+
```
145+
→ Chỉ hiện khi `mode = expert`; mọi trường hợp khác (kể cả không xác định được `mode`) → **ẩn** thay vì mặc định hiện như trước.
146+
147+
---
148+
149+
## 6. `depend-initial` (hoặc `depend-initial-state`)
150+
151+
**Mục đích:** trạng thái ẩn/hiện **ngay lúc mở dialog**, trước khi kịp đánh giá điều kiện thật (tránh nhấp nháy khi load). Giá trị: `"auto"` (mặc định — dựa theo `depend-default`), `"show"`, `"hide"`.
152+
153+
```xml
154+
<param name="big_form" type="input" title="Form phức tạp"
155+
depend-on="enable_big_form"
156+
depend-value="1"
157+
depend-initial="hide" />
158+
```
159+
→ Ngay khi dialog vừa mở, `big_form` bị ẩn tức thì (không đợi 1 nhịp `evaluateDependencies()` chạy xong mới ẩn), tránh hiện rồi biến mất gây giật màn hình.
160+
161+
---
162+
163+
## 7. `depend-negate`
164+
165+
**Mục đích:** đảo ngược toàn bộ kết quả cuối cùng của khối điều kiện (áp dụng sau khi đã tính `and`/`nand`/`xor`). Giá trị: `"true"`/`"1"`/`"negate"`.
166+
167+
```xml
168+
<param name="admin_mode" type="switch" title="Admin" />
169+
170+
<param name="user_only_hint" type="input" title="Chỉ dành cho người dùng thường"
171+
depend-on="admin_mode"
172+
depend-value="1"
173+
depend-negate="true" />
174+
```
175+
→ Bình thường `depend-value="1"` nghĩa là hiện khi `admin_mode=1`. Có `depend-negate="true"` → đảo lại: hiện khi `admin_mode != 1`.
176+
177+
Kết hợp với `xor` để bắt "cả 2 cùng bật":
178+
```xml
179+
depend-on="use_manual|use_auto"
180+
depend-value="1|1"
181+
depend-logic="xor"
182+
depend-negate="true"
183+
```
184+
`xor` gốc chỉ đúng khi *đúng một* cái bật → `negate` đảo lại → hiện khi **cả hai cùng bật hoặc cùng tắt** (loại trừ trường hợp chỉ 1 cái bật).
185+
186+
---
187+
188+
## 8. `depend-threshold`
189+
190+
**Mục đích:** chỉ áp dụng cho `depend-logic="and"` (mặc định) — quy định **% tối thiểu** số điều kiện cần thỏa thay vì bắt buộc 100%. Giá trị: số nguyên 0–100 (mặc định `-1` = 100%).
191+
192+
```xml
193+
<param name="cond_a" type="switch" title="Điều kiện A" />
194+
<param name="cond_b" type="switch" title="Điều kiện B" />
195+
<param name="cond_c" type="switch" title="Điều kiện C" />
196+
197+
<param name="need_2_of_3" type="input" title="Cần ít nhất 2/3 điều kiện"
198+
depend-on="cond_a|cond_b|cond_c"
199+
depend-value="1|1|1"
200+
depend-threshold="67" />
201+
```
202+
→ 3 điều kiện, ngưỡng 67% ≈ tối thiểu 2/3 → chỉ cần 2 trong 3 công tắc bật là hiện, không cần cả 3.
203+
204+
---
205+
206+
## 9. `depend-include-hidden`
207+
208+
**Mục đích:** khi param bị **ẩn**, mặc định nó vẫn được đưa vào kết quả `readParamsValue()` nếu có giá trị (không bắt buộc `required`). Thuộc tính này hiện chỉ ảnh hưởng tới việc bỏ qua kiểm tra `required` khi ẩn — không phải "loại bỏ khỏi params". Giá trị: `"true"`/`"1"`.
209+
210+
```xml
211+
<param name="hidden_debug_flag" type="input" title="Debug flag" value="0"
212+
depend-on="dev_mode"
213+
depend-value="1"
214+
depend-include-hidden="true" />
215+
```
216+
→ Dùng khi bạn muốn 1 giá trị mặc định (`value="0"`) vẫn được gửi lên script kể cả khi param đang ẩn (ví dụ 1 cờ ẩn luôn đi kèm mọi lần chạy, người dùng chỉ chỉnh nó khi bật `dev_mode`).
217+
218+
> ⚠️ Nếu muốn **loại hẳn giá trị của param ẩn khỏi kết quả**, cần sửa thêm đoạn `readParamsValue()` (chưa áp dụng trong bản hiện tại).
219+
220+
---
221+
222+
## 10. `depend-cascade` — cha ẩn thì con ẩn theo *(mới)*
223+
224+
**Mặc định: BẬT SẴN (`true`)** — không cần khai báo gì cũng đã có hiệu lực.
225+
226+
**Mục đích:** nếu **bất kỳ param cha nào** trong `depend-on` đang **bị ẩn** (do chính `depend-on` của nó, hoặc do một chuỗi phụ thuộc nhiều cấp phía trên), param con này **tự động ẩn theo luôn**, bất kể giá trị hiện tại của cha có khớp `depend-value` hay không.
227+
228+
Việc tính toán chạy qua **nhiều lượt (fixed-point)** cho tới khi trạng thái ổn định, nên hoạt động đúng dù param cha được khai báo **trước hay sau** param con trong file XML, và lan truyền đúng qua **chuỗi nhiều cấp** (con của con của con...).
229+
230+
### Ví dụ: chuỗi phụ thuộc 3 cấp
231+
232+
```xml
233+
<param name="mode" type="select" title="Chế độ"
234+
option-sh="echo -e 'basic\nadvanced'" />
235+
236+
<!-- Cấp 2: chỉ hiện khi mode = advanced -->
237+
<param name="target_fs" type="select" title="Định dạng đích"
238+
option-sh="echo -e 'EXT4\nF2FS\nEROFS'"
239+
depend-on="mode" depend-value="advanced" />
240+
241+
<!-- Cấp 3: phụ thuộc vào target_fs (là param cấp 2, có thể đang ẩn) -->
242+
<param name="erofs_readonly_hint" type="input" title="⚠ EROFS chỉ đọc"
243+
depend-on="target_fs" depend-value="EROFS" />
244+
```
245+
246+
- Khi `mode = basic``target_fs` bị ẩn (không khớp `advanced`).
247+
-`depend-cascade` mặc định bật, `erofs_readonly_hint` **cũng tự ẩn theo `target_fs`**, dù giá trị đang lưu trong `target_fs` (widget đã bị ẩn, người dùng không sửa được nữa) tình cờ vẫn là `EROFS` từ trước đó. Nếu không có cascade, `erofs_readonly_hint` sẽ hiện ra một cách vô lý dù `target_fs` (cha trực tiếp của nó) đang không hiển thị trên màn hình.
248+
- Chỉ khi `mode = advanced` (→ `target_fs` hiện) **** người dùng chọn `target_fs = EROFS`, thì `erofs_readonly_hint` mới thực sự hiện.
249+
250+
### Tắt cascade cho 1 param cụ thể
251+
252+
Trường hợp hiếm gặp — bạn muốn param con vẫn tự đánh giá theo **giá trị** của cha ngay cả khi hàng chứa cha đang ẩn khỏi màn hình:
253+
254+
```xml
255+
<param name="always_evaluate" type="input" title="Luôn tự xét theo giá trị cha"
256+
depend-on="target_fs" depend-value="EROFS"
257+
depend-cascade="false" />
258+
```
259+
`always_evaluate` sẽ hiện khi `target_fs` **có giá trị** `EROFS`, kể cả khi bản thân dòng `target_fs` đang bị ẩn khỏi giao diện.
260+
261+
---
262+
263+
## 11. `depend-onchange` (hoặc `depend-on-change`, `depend-callback`) — đã thực thi *(mới)*
264+
265+
**Mục đích:** chạy 1 đoạn shell script mỗi khi trạng thái ẩn/hiện của param này **thực sự đổi** (từ hiện → ẩn hoặc ẩn → hiện). Script chạy trên **luồng nền riêng** (không chạy trên UI thread, tránh treo giao diện khi lệnh root mất thời gian).
266+
267+
Script nhận được 2 biến môi trường:
268+
269+
| Biến | Ý nghĩa |
270+
|---|---|
271+
| `$PARAM_NAME` | Tên param vừa đổi trạng thái |
272+
| `$PARAM_VISIBLE` | `1` nếu param vừa chuyển sang **hiện**, `0` nếu vừa chuyển sang **ẩn** |
273+
274+
### Ví dụ 1: ghi log mỗi khi 1 param đổi trạng thái
275+
276+
```xml
277+
<param name="mode" type="select" title="Chế độ"
278+
option-sh="echo -e 'basic\nadvanced'" />
279+
280+
<param name="advanced_opt" type="input" title="Tùy chọn nâng cao"
281+
depend-on="mode" depend-value="advanced"
282+
depend-onchange="log -t krscript &quot;advanced_opt doi trang thai: visible=$PARAM_VISIBLE&quot;" />
283+
```
284+
→ Mỗi lần `advanced_opt` chuyển ẩn ↔ hiện (do người dùng đổi `mode`), dòng log được ghi ra logcat.
285+
286+
### Ví dụ 2: tự dọn dẹp giá trị khi param bị ẩn đi
287+
288+
```xml
289+
<param name="temp_folder" type="folder" title="Thư mục tạm" value=""
290+
depend-on="use_temp_folder" depend-value="1"
291+
depend-onchange="if [ &quot;$PARAM_VISIBLE&quot; = &quot;0&quot; ]; then rm -rf /sdcard/krscript_temp; fi" />
292+
```
293+
→ Khi `temp_folder` bị ẩn đi (người dùng tắt `use_temp_folder`), script tự xoá thư mục tạm tương ứng — hữu ích để dọn rác khi 1 tính năng bị tắt.
294+
295+
### Ví dụ 3: kết hợp `depend-cascade` + `depend-onchange`
296+
297+
```xml
298+
<param name="root_access" type="switch" title="Quyền Root" />
299+
300+
<param name="deep_clean" type="switch" title="Dọn dẹp sâu"
301+
depend-on="root_access" depend-value="1" />
302+
303+
<param name="deep_clean_confirm" type="input" title="Xác nhận dọn dẹp sâu"
304+
depend-on="deep_clean" depend-value="1"
305+
depend-onchange="log -t krscript &quot;deep_clean_confirm: $PARAM_VISIBLE&quot;" />
306+
```
307+
→ Nếu `root_access` tắt → `deep_clean` tự ẩn (điều kiện `depend-value` không khớp) → nhờ `depend-cascade`, `deep_clean_confirm` **cũng ẩn theo `deep_clean`**`deep_clean` từng có giá trị `1` trước đó → `depend-onchange` của `deep_clean_confirm` được gọi đúng 1 lần với `PARAM_VISIBLE=0`.
308+
309+
> ⚠️ **Lưu ý:** callback chạy bằng quyền root qua `ScriptEnvironmen.executeResultRoot`, hiện **chưa được truyền** `PAGE_CONFIG_DIR` / `PAGE_WORK_DIR` (biến môi trường chỉ có khi chạy trong ngữ cảnh của 1 trang cấu hình cụ thể). Nếu cần các biến này trong script `depend-onchange`, cần bổ sung thêm việc truyền `NodeInfoBase` vào `ActionParamsLayoutRender`.
310+
>
311+
> Callback **không** gọi khi dialog vừa mở (chỉ gọi khi có thay đổi thật so với lần đánh giá trước).
312+
313+
---
314+
315+
## Bảng tóm tắt nhanh
316+
317+
| Thuộc tính | Áp dụng cho | Giá trị | Mặc định |
318+
|---|---|---|---|
319+
| `depend-on` / `depend` | tên param cha | text, `\|` cách nhau ||
320+
| `depend-value` | điều kiện khớp | text, `,` OR trong 1 vị trí, `\|` cách vị trí ||
321+
| `depend-mode` | show/hide khi khớp | `show`/`hide`, có thể riêng từng cha | `show` |
322+
| `depend-logic` | cách kết hợp nhiều cha | `and`, `priority`/`or`, `priority-rtl`/`or-rtl`, `xor`, `nand` | `and` |
323+
| `depend-default` | kết quả khi không match | `show`/`hide` | `show` |
324+
| `depend-initial` / `depend-initial-state` | trạng thái lúc mở dialog | `auto`/`show`/`hide` | `auto` |
325+
| `depend-negate` | đảo kết quả cuối | `true`/`1`/`negate` | `false` |
326+
| `depend-threshold` | % điều kiện cần thỏa (chỉ `and`) | 0–100 | -1 (=100%) |
327+
| `depend-include-hidden` | có bỏ qua required khi ẩn | `true`/`1` | `false` |
328+
| `depend-cascade` | cha ẩn thì con ẩn theo | `true`/`false` | `true` |
329+
| `depend-onchange` / `depend-on-change` / `depend-callback` | script chạy khi đổi trạng thái | text (shell script), có `$PARAM_NAME`/`$PARAM_VISIBLE` ||

0 commit comments

Comments
 (0)