opencode-skills-collection 4.0.69 → 4.0.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +39 -1
- package/bundled-skills/api-integration-architect/SKILL.md +241 -0
- package/bundled-skills/apify-generate-output-schema/SKILL.md +438 -0
- package/bundled-skills/apify-integration-development/SKILL.md +168 -0
- package/bundled-skills/apify-integration-development/references/ai-framework-package.md +158 -0
- package/bundled-skills/apify-integration-development/references/ai-harness-plugin.md +192 -0
- package/bundled-skills/apify-integration-development/references/sdk-integration.md +236 -0
- package/bundled-skills/apify-integration-development/references/workflow-automation.md +163 -0
- package/bundled-skills/architecture-review/README.md +42 -0
- package/bundled-skills/architecture-review/SKILL.md +77 -0
- package/bundled-skills/architecture-review/examples.md +11 -0
- package/bundled-skills/architecture-review/reference/best-practices.md +7 -0
- package/bundled-skills/architecture-review/reference/capabilities.md +20 -0
- package/bundled-skills/architecture-review/reference/fallbacks.md +11 -0
- package/bundled-skills/architecture-review/reference/graph.md +15 -0
- package/bundled-skills/architecture-review/reference/mcp.md +14 -0
- package/bundled-skills/architecture-review/reference/workflow.md +15 -0
- package/bundled-skills/architecture-review/templates/architecture-review.md +21 -0
- package/bundled-skills/code-review-sensei/SKILL.md +177 -0
- package/bundled-skills/codebase-onboarding/README.md +42 -0
- package/bundled-skills/codebase-onboarding/SKILL.md +77 -0
- package/bundled-skills/codebase-onboarding/examples.md +11 -0
- package/bundled-skills/codebase-onboarding/reference/best-practices.md +7 -0
- package/bundled-skills/codebase-onboarding/reference/capabilities.md +20 -0
- package/bundled-skills/codebase-onboarding/reference/fallbacks.md +11 -0
- package/bundled-skills/codebase-onboarding/reference/graph.md +15 -0
- package/bundled-skills/codebase-onboarding/reference/mcp.md +14 -0
- package/bundled-skills/codebase-onboarding/reference/workflow.md +15 -0
- package/bundled-skills/codebase-onboarding/templates/repository-onboarding.md +21 -0
- package/bundled-skills/connection-auth-rules/SKILL.md +199 -0
- package/bundled-skills/connection-auth-rules/fetch_schema.py +320 -0
- package/bundled-skills/dependency-analysis/README.md +42 -0
- package/bundled-skills/dependency-analysis/SKILL.md +76 -0
- package/bundled-skills/dependency-analysis/examples.md +11 -0
- package/bundled-skills/dependency-analysis/reference/best-practices.md +7 -0
- package/bundled-skills/dependency-analysis/reference/capabilities.md +20 -0
- package/bundled-skills/dependency-analysis/reference/fallbacks.md +11 -0
- package/bundled-skills/dependency-analysis/reference/graph.md +15 -0
- package/bundled-skills/dependency-analysis/reference/mcp.md +14 -0
- package/bundled-skills/dependency-analysis/reference/workflow.md +15 -0
- package/bundled-skills/dependency-analysis/templates/dependency-review.md +21 -0
- package/bundled-skills/devops-pipeline-builder/SKILL.md +200 -0
- package/bundled-skills/eas-app-stores/SKILL.md +197 -0
- package/bundled-skills/eas-app-stores/agents/openai.yaml +4 -0
- package/bundled-skills/eas-app-stores/references/app-store-metadata.md +497 -0
- package/bundled-skills/eas-app-stores/references/ios-app-store.md +376 -0
- package/bundled-skills/eas-app-stores/references/native-ios.md +167 -0
- package/bundled-skills/eas-app-stores/references/play-store.md +244 -0
- package/bundled-skills/eas-app-stores/references/testflight.md +62 -0
- package/bundled-skills/eas-app-stores/references/workflows.md +120 -0
- package/bundled-skills/eas-hosting/SKILL.md +448 -0
- package/bundled-skills/eas-hosting/agents/openai.yaml +4 -0
- package/bundled-skills/eas-observe/SKILL.md +75 -0
- package/bundled-skills/eas-observe/agents/openai.yaml +4 -0
- package/bundled-skills/eas-observe/references/metrics.md +98 -0
- package/bundled-skills/eas-observe/references/queries.md +403 -0
- package/bundled-skills/eas-observe/references/setup.md +476 -0
- package/bundled-skills/eas-observe/references/third-party.md +136 -0
- package/bundled-skills/eas-simulator/SKILL.md +251 -0
- package/bundled-skills/eas-simulator/agents/openai.yaml +4 -0
- package/bundled-skills/eas-simulator/references/controllers.md +135 -0
- package/bundled-skills/eas-simulator/references/run-your-app.md +240 -0
- package/bundled-skills/eas-simulator/references/troubleshooting.md +47 -0
- package/bundled-skills/eas-workflows/SKILL.md +119 -0
- package/bundled-skills/eas-workflows/agents/openai.yaml +4 -0
- package/bundled-skills/eas-workflows/scripts/fetch.js +109 -0
- package/bundled-skills/expo-animation/LICENSE +21 -0
- package/bundled-skills/expo-animation/RECIPES.md +385 -0
- package/bundled-skills/expo-animation/SKILL.md +295 -0
- package/bundled-skills/expo-animation/agents/openai.yaml +4 -0
- package/bundled-skills/fact-check-x-unified/SKILL.md +178 -0
- package/bundled-skills/fact-check-x-unified/agents/openai.yaml +4 -0
- package/bundled-skills/fact-check-x-unified/references/acceptance-criteria.md +44 -0
- package/bundled-skills/fact-check-x-unified/references/contracts.md +39 -0
- package/bundled-skills/fact-check-x-unified/scripts/common.py +31 -0
- package/bundled-skills/fact-check-x-unified/scripts/fact_check_x.py +1832 -0
- package/bundled-skills/fact-check-x-unified/scripts/trusted_search_config.py +324 -0
- package/bundled-skills/fact-check-x-unified/tests/anchor_downgrade_test.py +90 -0
- package/bundled-skills/fact-check-x-unified/tests/multi_platform_test.py +369 -0
- package/bundled-skills/fact-check-x-unified/tests/smoke_test.py +740 -0
- package/bundled-skills/fact-check-x-unified/tests/stage_checkpoint_test.py +103 -0
- package/bundled-skills/fact-check-x-unified/tests/trusted_search_config_test.py +156 -0
- package/bundled-skills/gpt-taste/SKILL.md +8 -1
- package/bundled-skills/hf-cli/SKILL.md +263 -0
- package/bundled-skills/huggingface-community-evals/SKILL.md +228 -0
- package/bundled-skills/huggingface-community-evals/examples/.env.example +3 -0
- package/bundled-skills/huggingface-community-evals/examples/USAGE_EXAMPLES.md +101 -0
- package/bundled-skills/huggingface-community-evals/scripts/inspect_eval_uv.py +104 -0
- package/bundled-skills/huggingface-community-evals/scripts/inspect_vllm_uv.py +306 -0
- package/bundled-skills/huggingface-community-evals/scripts/lighteval_vllm_uv.py +297 -0
- package/bundled-skills/huggingface-datasets/SKILL.md +130 -0
- package/bundled-skills/jev-social/SKILL.md +182 -0
- package/bundled-skills/longbridge-derivatives/SKILL.md +117 -0
- package/bundled-skills/longbridge-derivatives/references/option.md +36 -0
- package/bundled-skills/longbridge-derivatives/references/options-advanced.md +101 -0
- package/bundled-skills/longbridge-derivatives/references/options-pnl.md +74 -0
- package/bundled-skills/longbridge-derivatives/references/options-strategy.md +82 -0
- package/bundled-skills/longbridge-derivatives/references/options-volatility.md +70 -0
- package/bundled-skills/longbridge-derivatives/references/warrant.md +12 -0
- package/bundled-skills/longbridge-quant/SKILL.md +151 -0
- package/bundled-skills/longbridge-quant/references/correlation.md +51 -0
- package/bundled-skills/longbridge-quant/references/execution-model.md +68 -0
- package/bundled-skills/longbridge-quant/references/factor-research.md +95 -0
- package/bundled-skills/longbridge-quant/references/factor-screen.md +101 -0
- package/bundled-skills/longbridge-quant/references/hedging.md +136 -0
- package/bundled-skills/longbridge-quant/references/ml-strategy.md +77 -0
- package/bundled-skills/longbridge-quant/references/multifactor.md +68 -0
- package/bundled-skills/longbridge-quant/references/pairs-trading.md +61 -0
- package/bundled-skills/longbridge-quant/references/quant-cli.md +133 -0
- package/bundled-skills/longbridge-quant/references/quant-stats.md +150 -0
- package/bundled-skills/longbridge-quant/references/seasonality.md +50 -0
- package/bundled-skills/longbridge-quant/references/strategy-optimizer.md +68 -0
- package/bundled-skills/longbridge-quant/references/volatility-strategy.md +52 -0
- package/bundled-skills/longbridge-research/SKILL.md +187 -0
- package/bundled-skills/longbridge-research/references/company-profile.md +96 -0
- package/bundled-skills/longbridge-research/references/company-tearsheet.md +82 -0
- package/bundled-skills/longbridge-research/references/competitive-analysis.md +81 -0
- package/bundled-skills/longbridge-research/references/consensus.md +92 -0
- package/bundled-skills/longbridge-research/references/coverage-initiation.md +76 -0
- package/bundled-skills/longbridge-research/references/defi-yield.md +60 -0
- package/bundled-skills/longbridge-research/references/finance-calendar.md +165 -0
- package/bundled-skills/longbridge-research/references/financial-planning.md +77 -0
- package/bundled-skills/longbridge-research/references/forecast-eps.md +39 -0
- package/bundled-skills/longbridge-research/references/fund-holder.md +44 -0
- package/bundled-skills/longbridge-research/references/hkipo-analysis.md +101 -0
- package/bundled-skills/longbridge-research/references/industry-peers.md +46 -0
- package/bundled-skills/longbridge-research/references/industry-rank.md +62 -0
- package/bundled-skills/longbridge-research/references/insider-trades.md +48 -0
- package/bundled-skills/longbridge-research/references/institution-rating.md +62 -0
- package/bundled-skills/longbridge-research/references/investment-ideas.md +69 -0
- package/bundled-skills/longbridge-research/references/investment-proposal.md +95 -0
- package/bundled-skills/longbridge-research/references/investors.md +87 -0
- package/bundled-skills/longbridge-research/references/onchain.md +70 -0
- package/bundled-skills/longbridge-research/references/post-investment.md +76 -0
- package/bundled-skills/longbridge-research/references/shareholder.md +72 -0
- package/bundled-skills/longbridge-research/references/short-positions.md +50 -0
- package/bundled-skills/longbridge-research/references/short-trades.md +50 -0
- package/bundled-skills/longbridge-research/references/stock-research.md +61 -0
- package/bundled-skills/longbridge-research/references/thesis-tracker.md +64 -0
- package/bundled-skills/makepad-2-0-animation/SKILL.md +318 -0
- package/bundled-skills/makepad-2-0-animation/references/animator-reference.md +433 -0
- package/bundled-skills/makepad-2-0-dsl/SKILL.md +492 -0
- package/bundled-skills/makepad-2-0-dsl/references/dsl-syntax-reference.md +511 -0
- package/bundled-skills/makepad-2-0-dsl/references/extended-guide.md +56 -0
- package/bundled-skills/makepad-2-0-dsl/references/property-system.md +757 -0
- package/bundled-skills/makepad-2-0-events/SKILL.md +497 -0
- package/bundled-skills/makepad-2-0-events/references/event-patterns.md +802 -0
- package/bundled-skills/makepad-2-0-events/references/extended-guide.md +590 -0
- package/bundled-skills/makepad-2-0-layout/SKILL.md +499 -0
- package/bundled-skills/makepad-2-0-layout/references/extended-guide.md +243 -0
- package/bundled-skills/makepad-2-0-layout/references/layout-patterns.md +881 -0
- package/bundled-skills/makepad-2-0-widgets/SKILL.md +261 -0
- package/bundled-skills/makepad-2-0-widgets/references/widget-advanced.md +648 -0
- package/bundled-skills/makepad-2-0-widgets/references/widget-catalog.md +547 -0
- package/bundled-skills/meeting-distiller-pro/SKILL.md +120 -0
- package/bundled-skills/monte-carlo-analyze-root-cause/SKILL.md +12 -1
- package/bundled-skills/monte-carlo-asset-health/SKILL.md +12 -1
- package/bundled-skills/monte-carlo-context-detection/SKILL.md +170 -0
- package/bundled-skills/monte-carlo-context-detection/references/signal-definitions.md +46 -0
- package/bundled-skills/remotion-captions/SKILL.md +57 -0
- package/bundled-skills/remotion-captions/agents/openai.yaml +7 -0
- package/bundled-skills/remotion-captions/assets/remotion-icon.svg +4 -0
- package/bundled-skills/remotion-captions/display-captions.md +190 -0
- package/bundled-skills/remotion-captions/import-srt-captions.md +73 -0
- package/bundled-skills/remotion-captions/transcribe-captions.md +70 -0
- package/bundled-skills/remotion-create/SKILL.md +106 -0
- package/bundled-skills/remotion-create/agents/openai.yaml +7 -0
- package/bundled-skills/remotion-create/assets/remotion-icon.svg +4 -0
- package/bundled-skills/remotion-create/tailwind.md +11 -0
- package/bundled-skills/remotion-create/video-layout.md +9 -0
- package/bundled-skills/remotion-docs/SKILL.md +67 -0
- package/bundled-skills/remotion-docs/agents/openai.yaml +7 -0
- package/bundled-skills/remotion-docs/assets/remotion-icon.svg +4 -0
- package/bundled-skills/remotion-interactivity/SKILL.md +270 -0
- package/bundled-skills/remotion-interactivity/agents/openai.yaml +7 -0
- package/bundled-skills/remotion-interactivity/assets/remotion-icon.svg +4 -0
- package/bundled-skills/remotion-render/SKILL.md +48 -0
- package/bundled-skills/remotion-render/agents/openai.yaml +7 -0
- package/bundled-skills/remotion-render/assets/remotion-icon.svg +4 -0
- package/bundled-skills/remotion-render/transparent-videos.md +106 -0
- package/bundled-skills/saas-pricing-strategist/SKILL.md +169 -0
- package/bundled-skills/score-eval/SKILL.md +35 -0
- package/bundled-skills/writing-guidelines/SKILL.md +60 -0
- package/package.json +1 -1
- package/skills_index.json +980 -3
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
Use dot notation to access nested widgets:
|
|
2
|
+
|
|
3
|
+
```rust
|
|
4
|
+
self.ui.label(cx, ids!(container.inner.child_label))
|
|
5
|
+
self.ui.button(cx, ids!(toolbar.save_button))
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
### Generic widget access
|
|
9
|
+
|
|
10
|
+
```rust
|
|
11
|
+
self.ui.widget(cx, ids!(my_widget)) // -> WidgetRef (untyped)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Common widget setter methods (called from Rust)
|
|
15
|
+
|
|
16
|
+
```rust
|
|
17
|
+
// Label
|
|
18
|
+
self.ui.label(cx, ids!(my_label)).set_text(cx, "Hello");
|
|
19
|
+
|
|
20
|
+
// TextInput
|
|
21
|
+
self.ui.text_input(cx, ids!(my_input)).set_text(cx, "default value");
|
|
22
|
+
|
|
23
|
+
// CheckBox
|
|
24
|
+
if let Some(mut inner) = self.ui.check_box(cx, ids!(my_check)).borrow_mut() {
|
|
25
|
+
inner.set_active(cx, true);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// DropDown
|
|
29
|
+
self.ui.drop_down(cx, ids!(my_dd)).set_selected_item(cx, 2);
|
|
30
|
+
self.ui.drop_down(cx, ids!(my_dd)).set_labels(cx, vec!["A".into(), "B".into()]);
|
|
31
|
+
|
|
32
|
+
// Slider
|
|
33
|
+
self.ui.slider(cx, ids!(my_slider)).set_value(cx, 0.5);
|
|
34
|
+
|
|
35
|
+
// Redraw any widget
|
|
36
|
+
self.ui.widget(cx, ids!(my_widget)).redraw(cx);
|
|
37
|
+
|
|
38
|
+
// Visibility
|
|
39
|
+
self.ui.button(cx, ids!(my_button)).set_visible(cx, false);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 7. Widget Methods from Splash
|
|
45
|
+
|
|
46
|
+
Inside `script_mod!` Splash code, access widgets through the `ui` prefix:
|
|
47
|
+
|
|
48
|
+
```splash
|
|
49
|
+
// Trigger a re-render of a view's on_render handler
|
|
50
|
+
ui.main_view.render()
|
|
51
|
+
|
|
52
|
+
// Get text from a TextInput
|
|
53
|
+
let text = ui.todo_input.text()
|
|
54
|
+
|
|
55
|
+
// Set text on a TextInput
|
|
56
|
+
ui.todo_input.set_text("")
|
|
57
|
+
|
|
58
|
+
// Trigger a click on another widget
|
|
59
|
+
ui.add_button.on_click()
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 8. Hit Events (Low-Level)
|
|
65
|
+
|
|
66
|
+
For custom widgets that need raw input handling, the `Hit` enum provides low-level
|
|
67
|
+
events. Access them through `event.hits(cx, area)` in a widget's `handle_event`.
|
|
68
|
+
|
|
69
|
+
```rust
|
|
70
|
+
pub enum Hit {
|
|
71
|
+
// Keyboard focus
|
|
72
|
+
KeyFocus(KeyFocusEvent),
|
|
73
|
+
KeyFocusLost(KeyFocusEvent),
|
|
74
|
+
|
|
75
|
+
// Keyboard input
|
|
76
|
+
KeyDown(KeyEvent),
|
|
77
|
+
KeyUp(KeyEvent),
|
|
78
|
+
|
|
79
|
+
// Text input
|
|
80
|
+
TextInput(TextInputEvent),
|
|
81
|
+
TextRangeReplace(TextRangeReplaceEvent),
|
|
82
|
+
TextCopy(TextClipboardEvent),
|
|
83
|
+
TextCut(TextClipboardEvent),
|
|
84
|
+
ImeAction(ImeActionEvent),
|
|
85
|
+
|
|
86
|
+
// Pointer/finger events
|
|
87
|
+
FingerDown(FingerDownEvent),
|
|
88
|
+
FingerMove(FingerMoveEvent),
|
|
89
|
+
FingerUp(FingerUpEvent),
|
|
90
|
+
FingerScroll(FingerScrollEvent),
|
|
91
|
+
FingerLongPress(FingerLongPressEvent),
|
|
92
|
+
|
|
93
|
+
// Hover events
|
|
94
|
+
FingerHoverIn(FingerHoverEvent),
|
|
95
|
+
FingerHoverOver(FingerHoverEvent),
|
|
96
|
+
FingerHoverOut(FingerHoverEvent),
|
|
97
|
+
|
|
98
|
+
// Triggers
|
|
99
|
+
Trigger(TriggerHitEvent),
|
|
100
|
+
|
|
101
|
+
Nothing,
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Usage in custom widgets
|
|
106
|
+
|
|
107
|
+
```rust
|
|
108
|
+
impl Widget for MyCustomWidget {
|
|
109
|
+
fn handle_event(&mut self, cx: &mut Cx, event: &Event, _scope: &mut Scope) {
|
|
110
|
+
match event.hits(cx, self.draw_bg.area()) {
|
|
111
|
+
Hit::FingerDown(fd) => {
|
|
112
|
+
cx.set_key_focus(self.draw_bg.area());
|
|
113
|
+
// fd.abs -- absolute position
|
|
114
|
+
// fd.rel -- relative position within widget
|
|
115
|
+
// fd.modifiers -- KeyModifiers
|
|
116
|
+
}
|
|
117
|
+
Hit::FingerUp(fu) => {
|
|
118
|
+
if fu.is_over {
|
|
119
|
+
// Finger was released inside the widget = click
|
|
120
|
+
let uid = self.widget_uid();
|
|
121
|
+
cx.widget_action(uid, MyWidgetAction::Clicked);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
Hit::FingerMove(fm) => {
|
|
125
|
+
// fm.abs, fm.rel -- current position
|
|
126
|
+
}
|
|
127
|
+
Hit::FingerHoverIn(_) => {
|
|
128
|
+
self.animator_play(cx, ids!(hover.on));
|
|
129
|
+
}
|
|
130
|
+
Hit::FingerHoverOut(_) => {
|
|
131
|
+
self.animator_play(cx, ids!(hover.off));
|
|
132
|
+
}
|
|
133
|
+
Hit::KeyDown(ke) => {
|
|
134
|
+
match ke.key_code {
|
|
135
|
+
KeyCode::ReturnKey => { /* handle enter */ }
|
|
136
|
+
KeyCode::Escape => { /* handle escape */ }
|
|
137
|
+
_ => {}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
_ => {}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 9. Timer Events
|
|
149
|
+
|
|
150
|
+
Timers are created via `Cx` methods and received in `handle_timer`.
|
|
151
|
+
|
|
152
|
+
### Creating timers
|
|
153
|
+
|
|
154
|
+
```rust
|
|
155
|
+
// One-shot timer (fires once after delay in seconds)
|
|
156
|
+
let timer: Timer = cx.start_timeout(2.0); // 2 seconds
|
|
157
|
+
|
|
158
|
+
// Repeating timer (fires every interval seconds)
|
|
159
|
+
let timer: Timer = cx.start_interval(0.5); // every 500ms
|
|
160
|
+
|
|
161
|
+
// Stop a timer
|
|
162
|
+
cx.stop_timer(timer);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Handling timer events
|
|
166
|
+
|
|
167
|
+
```rust
|
|
168
|
+
#[derive(Script, ScriptHook)]
|
|
169
|
+
pub struct App {
|
|
170
|
+
#[live]
|
|
171
|
+
ui: WidgetRef,
|
|
172
|
+
#[rust]
|
|
173
|
+
poll_timer: Timer,
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
impl MatchEvent for App {
|
|
177
|
+
fn handle_startup(&mut self, cx: &mut Cx) {
|
|
178
|
+
self.poll_timer = cx.start_interval(30.0);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
fn handle_timer(&mut self, cx: &mut Cx, event: &TimerEvent) {
|
|
182
|
+
if self.poll_timer.is_timer(event).is_some() {
|
|
183
|
+
self.do_periodic_work(cx);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 10. HTTP / Network Events
|
|
192
|
+
|
|
193
|
+
### Making HTTP requests from Rust
|
|
194
|
+
|
|
195
|
+
```rust
|
|
196
|
+
let request_id = live_id!(my_request);
|
|
197
|
+
let mut req = HttpRequest::new(url, HttpMethod::Get);
|
|
198
|
+
req.set_header("Content-Type", "application/json");
|
|
199
|
+
req.set_body(body_bytes);
|
|
200
|
+
cx.http_request(request_id, req);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Handling HTTP responses
|
|
204
|
+
|
|
205
|
+
```rust
|
|
206
|
+
impl MatchEvent for App {
|
|
207
|
+
fn handle_http_response(&mut self, cx: &mut Cx, request_id: LiveId, response: &HttpResponse) {
|
|
208
|
+
if request_id == live_id!(my_request) {
|
|
209
|
+
let body = &response.body;
|
|
210
|
+
// Process response...
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
fn handle_http_request_error(&mut self, cx: &mut Cx, request_id: LiveId, err: &HttpError) {
|
|
215
|
+
if request_id == live_id!(my_request) {
|
|
216
|
+
log!("Request failed: {}", err.message);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
fn handle_http_progress(&mut self, cx: &mut Cx, request_id: LiveId, progress: &HttpProgress) {
|
|
221
|
+
if request_id == live_id!(my_request) {
|
|
222
|
+
let pct = progress.loaded as f64 / progress.total as f64;
|
|
223
|
+
// Update progress UI...
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// For streaming responses
|
|
228
|
+
fn handle_http_stream(&mut self, cx: &mut Cx, request_id: LiveId, data: &HttpResponse) {
|
|
229
|
+
// Receive incremental chunks
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
fn handle_http_stream_complete(&mut self, cx: &mut Cx, request_id: LiveId, data: &HttpResponse) {
|
|
233
|
+
// Stream finished
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Making HTTP requests from Splash
|
|
239
|
+
|
|
240
|
+
```splash
|
|
241
|
+
let req = net.HttpRequest{
|
|
242
|
+
url: "https://api.example.com/data"
|
|
243
|
+
method: net.HttpMethod.GET
|
|
244
|
+
headers: {"Content-Type": "application/json"}
|
|
245
|
+
}
|
|
246
|
+
net.http_request(req) do net.HttpEvents{
|
|
247
|
+
on_response: |res| {
|
|
248
|
+
// handle response
|
|
249
|
+
let data = res.body.to_string().parse_json()
|
|
250
|
+
}
|
|
251
|
+
on_error: |e| {
|
|
252
|
+
// handle error
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Streaming HTTP request
|
|
257
|
+
let req = net.HttpRequest{
|
|
258
|
+
url: "https://api.openai.com/v1/chat/completions"
|
|
259
|
+
method: net.HttpMethod.POST
|
|
260
|
+
headers: {"Content-Type": "application/json"}
|
|
261
|
+
is_streaming: true
|
|
262
|
+
body: {model: "gpt-4" messages: [{role: "user" content: "Hello"}]}
|
|
263
|
+
}
|
|
264
|
+
net.http_request(req) do net.HttpEvents{
|
|
265
|
+
on_stream: fn(res){
|
|
266
|
+
// Process each streaming chunk
|
|
267
|
+
let chunk = res.body.to_string()
|
|
268
|
+
}
|
|
269
|
+
on_complete: fn(res){
|
|
270
|
+
// Stream finished
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## 11. Event Flow Diagram
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
User Input (click/key/mouse)
|
|
281
|
+
|
|
|
282
|
+
v
|
|
283
|
+
Platform Event Loop (Cx)
|
|
284
|
+
|
|
|
285
|
+
v
|
|
286
|
+
AppMain::handle_event(&mut self, cx, event)
|
|
287
|
+
|
|
|
288
|
+
+--> self.match_event(cx, event)
|
|
289
|
+
| |
|
|
290
|
+
| +--> MatchEvent::handle_startup / handle_shutdown / ...
|
|
291
|
+
| +--> MatchEvent::handle_actions(cx, actions)
|
|
292
|
+
| | |
|
|
293
|
+
| | +--> self.ui.button(cx, ids!(name)).clicked(actions)
|
|
294
|
+
| | +--> script_eval!(cx, { ... })
|
|
295
|
+
| | |
|
|
296
|
+
| | v
|
|
297
|
+
| | ScriptVm::eval -> updates Splash state
|
|
298
|
+
| | |
|
|
299
|
+
| | +--> ui.view.render() -> schedules re-draw
|
|
300
|
+
| |
|
|
301
|
+
| +--> MatchEvent::handle_timer(cx, event)
|
|
302
|
+
| +--> MatchEvent::handle_http_response(cx, id, response)
|
|
303
|
+
| +--> MatchEvent::handle_key_down(cx, event)
|
|
304
|
+
|
|
|
305
|
+
+--> self.ui.handle_event(cx, event, scope)
|
|
306
|
+
|
|
|
307
|
+
+--> Widget tree event propagation
|
|
308
|
+
+--> Hit detection (FingerDown/Up/Move)
|
|
309
|
+
+--> Splash on_click / on_return handlers execute
|
|
310
|
+
+--> on_render handlers execute during draw
|
|
311
|
+
+--> Widget actions emitted -> feed back into Actions
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## 12. Complete Patterns
|
|
317
|
+
|
|
318
|
+
### Pattern 1: Counter (button click -> state update -> re-render)
|
|
319
|
+
|
|
320
|
+
```rust
|
|
321
|
+
use makepad_widgets::*;
|
|
322
|
+
|
|
323
|
+
app_main!(App);
|
|
324
|
+
|
|
325
|
+
script_mod! {
|
|
326
|
+
use mod.prelude.widgets.*
|
|
327
|
+
let state = {
|
|
328
|
+
counter: 0
|
|
329
|
+
}
|
|
330
|
+
mod.state = state
|
|
331
|
+
startup() do #(App::script_component(vm)){
|
|
332
|
+
ui: Root{
|
|
333
|
+
on_startup: ||{
|
|
334
|
+
ui.main_view.render()
|
|
335
|
+
}
|
|
336
|
+
main_window := Window{
|
|
337
|
+
window.inner_size: vec2(420, 220)
|
|
338
|
+
body +: {
|
|
339
|
+
main_view := View{
|
|
340
|
+
width: Fill
|
|
341
|
+
height: Fill
|
|
342
|
+
flow: Down
|
|
343
|
+
spacing: 12
|
|
344
|
+
align: Center
|
|
345
|
+
on_render: ||{
|
|
346
|
+
counter_label := Label{
|
|
347
|
+
text: "Count: " + state.counter
|
|
348
|
+
draw_text.text_style.font_size: 24
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
increment_button := Button{
|
|
353
|
+
text: "Increment"
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
impl App {
|
|
362
|
+
fn run(vm: &mut ScriptVm) -> Self {
|
|
363
|
+
crate::makepad_widgets::script_mod(vm);
|
|
364
|
+
App::from_script_mod(vm, self::script_mod)
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
#[derive(Script, ScriptHook)]
|
|
369
|
+
pub struct App {
|
|
370
|
+
#[live]
|
|
371
|
+
ui: WidgetRef,
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
impl MatchEvent for App {
|
|
375
|
+
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
|
|
376
|
+
if self.ui.button(cx, ids!(increment_button)).clicked(actions) {
|
|
377
|
+
script_eval!(cx, {
|
|
378
|
+
mod.state.counter += 1
|
|
379
|
+
ui.main_view.render()
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
impl AppMain for App {
|
|
386
|
+
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
|
387
|
+
self.match_event(cx, event);
|
|
388
|
+
self.ui.handle_event(cx, event, &mut Scope::empty());
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Pattern 2: Form (text input -> validation -> submission)
|
|
394
|
+
|
|
395
|
+
```splash
|
|
396
|
+
// Inside script_mod!
|
|
397
|
+
|
|
398
|
+
fn submit_form(){
|
|
399
|
+
let name = ui.name_input.text()
|
|
400
|
+
let email = ui.email_input.text()
|
|
401
|
+
if name == "" {
|
|
402
|
+
ui.error_label.set_text("Name is required")
|
|
403
|
+
} else if email == "" {
|
|
404
|
+
ui.error_label.set_text("Email is required")
|
|
405
|
+
} else {
|
|
406
|
+
// Process form...
|
|
407
|
+
ui.error_label.set_text("")
|
|
408
|
+
ui.name_input.set_text("")
|
|
409
|
+
ui.email_input.set_text("")
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// In the UI tree:
|
|
414
|
+
name_input := TextInput{
|
|
415
|
+
empty_text: "Your name"
|
|
416
|
+
}
|
|
417
|
+
email_input := TextInput{
|
|
418
|
+
empty_text: "your@email.com"
|
|
419
|
+
on_return: || submit_form()
|
|
420
|
+
}
|
|
421
|
+
submit_button := Button{
|
|
422
|
+
text: "Submit"
|
|
423
|
+
on_click: || submit_form()
|
|
424
|
+
}
|
|
425
|
+
error_label := Label{
|
|
426
|
+
text: ""
|
|
427
|
+
draw_text.color: #f00
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Pattern 3: List with per-item events
|
|
432
|
+
|
|
433
|
+
```splash
|
|
434
|
+
let items = []
|
|
435
|
+
items.push({name: "Item A", selected: false})
|
|
436
|
+
items.push({name: "Item B", selected: false})
|
|
437
|
+
|
|
438
|
+
fn toggle_item(index, checked){
|
|
439
|
+
items[index].selected = checked
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
fn delete_item(index){
|
|
443
|
+
items.remove(index)
|
|
444
|
+
ui.item_list.render()
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// In UI:
|
|
448
|
+
item_list := ScrollYView{
|
|
449
|
+
width: Fill height: Fill
|
|
450
|
+
new_batch: true
|
|
451
|
+
on_render: ||{
|
|
452
|
+
for i, item in items {
|
|
453
|
+
RoundedView{
|
|
454
|
+
width: Fill height: Fit
|
|
455
|
+
flow: Right
|
|
456
|
+
check := CheckBox{
|
|
457
|
+
active: item.selected
|
|
458
|
+
on_click: |checked| toggle_item(i, checked)
|
|
459
|
+
}
|
|
460
|
+
Label{text: item.name}
|
|
461
|
+
Button{
|
|
462
|
+
text: "Delete"
|
|
463
|
+
on_click: || delete_item(i)
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### Pattern 4: Cross-layer communication (Splash state + Rust logic)
|
|
472
|
+
|
|
473
|
+
```rust
|
|
474
|
+
// Rust side: handle complex logic, then update Splash state
|
|
475
|
+
impl MatchEvent for App {
|
|
476
|
+
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
|
|
477
|
+
if self.ui.button(cx, ids!(fetch_button)).clicked(actions) {
|
|
478
|
+
// Rust handles the HTTP request
|
|
479
|
+
let request_id = live_id!(fetch_data);
|
|
480
|
+
let req = HttpRequest::new("https://api.example.com/data", HttpMethod::Get);
|
|
481
|
+
cx.http_request(request_id, req);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
fn handle_http_response(&mut self, cx: &mut Cx, request_id: LiveId, response: &HttpResponse) {
|
|
486
|
+
if request_id == live_id!(fetch_data) {
|
|
487
|
+
let data = String::from_utf8_lossy(&response.body).to_string();
|
|
488
|
+
// Bridge back to Splash to update UI
|
|
489
|
+
script_eval!(cx, {
|
|
490
|
+
mod.state.data = #(data)
|
|
491
|
+
mod.state.loading = false
|
|
492
|
+
ui.results_view.render()
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## Source Files Reference
|
|
502
|
+
|
|
503
|
+
| File | Purpose |
|
|
504
|
+
|------|---------|
|
|
505
|
+
| `draw/src/match_event.rs` | `MatchEvent` trait definition |
|
|
506
|
+
| `widgets/src/widget_match_event.rs` | `WidgetMatchEvent` trait (for custom widgets) |
|
|
507
|
+
| `platform/src/event/event.rs` | `Event` enum, `Hit` enum, `Timer` |
|
|
508
|
+
| `platform/src/event/finger.rs` | Finger/pointer event types |
|
|
509
|
+
| `platform/script/src/lib.rs` | `script_eval!` macro definition |
|
|
510
|
+
| `platform/script/derive/src/lib.rs` | `script_apply_eval!` proc macro |
|
|
511
|
+
| `widgets/src/button.rs` | Button action API |
|
|
512
|
+
| `widgets/src/text_input.rs` | TextInput action API |
|
|
513
|
+
| `widgets/src/check_box.rs` | CheckBox action API |
|
|
514
|
+
| `widgets/src/drop_down.rs` | DropDown action API |
|
|
515
|
+
| `widgets/src/slider.rs` | Slider action API |
|
|
516
|
+
| `widgets/src/radio_button.rs` | RadioButton action API |
|
|
517
|
+
| `examples/counter/src/app.rs` | Counter example (minimal) |
|
|
518
|
+
| `examples/todo/src/app.rs` | Todo example (comprehensive) |
|
|
519
|
+
| `examples/git/src/app.rs` | Git example (HTTP, timers) |
|
|
520
|
+
| `examples/camera/src/` | Camera example (media events) |
|
|
521
|
+
| `examples/text_selection/src/` | Text selection example |
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
## 13. New Events (March 2026)
|
|
526
|
+
|
|
527
|
+
### Selection & Clipboard Events
|
|
528
|
+
|
|
529
|
+
New `Hit` variants for text selection and clipboard operations:
|
|
530
|
+
|
|
531
|
+
```rust
|
|
532
|
+
Hit::TextCopy(TextClipboardEvent) // User copied text (Ctrl+C or native toolbar)
|
|
533
|
+
Hit::TextCut(TextClipboardEvent) // User cut text (Ctrl+X or native toolbar)
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**Mobile Selection Handles:** Native selection handles on iOS/Android emit:
|
|
537
|
+
```rust
|
|
538
|
+
Event::SelectionHandleDrag // User dragging a selection handle
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
Long-press on text selects a word and shows the native clipboard toolbar. TextFlow widget integrates clipboard actions automatically.
|
|
542
|
+
|
|
543
|
+
### Popup Window Events
|
|
544
|
+
|
|
545
|
+
For popup windows (context menus, dropdowns):
|
|
546
|
+
```rust
|
|
547
|
+
Event::WindowClosed // Popup window was closed
|
|
548
|
+
Event::PopupDismissed // Popup was dismissed by compositor (Wayland) or click-outside
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
`WindowClosed` is always emitted before `PopupDismissed`. Apps must handle `PopupDismissed` for explicit-close semantics.
|
|
552
|
+
|
|
553
|
+
### IME Events
|
|
554
|
+
|
|
555
|
+
IME (Input Method Editor) support for CJK text input:
|
|
556
|
+
```rust
|
|
557
|
+
Hit::ImeAction(ImeActionEvent) // IME composition committed/cancelled
|
|
558
|
+
Hit::TextRangeReplace(TextRangeReplaceEvent) // IME text replacement
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**Linux X11 IME:** Full IME support added for X11. IME popup window positioning fixed to avoid appearing without TextInput focus.
|
|
562
|
+
|
|
563
|
+
### Video & Media Events
|
|
564
|
+
|
|
565
|
+
```rust
|
|
566
|
+
// In MatchEvent trait:
|
|
567
|
+
fn handle_video_inputs(&mut self, _cx: &mut Cx, _e: &VideoInputsEvent) {}
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
Video input device enumeration events from the media plugin system. Camera and video playback events route through the media plugin architecture.
|
|
571
|
+
|
|
572
|
+
### Primary Selection (Linux)
|
|
573
|
+
|
|
574
|
+
Linux primary selection (middle-click paste):
|
|
575
|
+
- **Wayland:** `zwp_primary_selection_device_manager_v1` protocol
|
|
576
|
+
- **X11:** PRIMARY atom handling
|
|
577
|
+
- Integrated with TextInput and TextFlow widgets automatically
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
## Examples
|
|
581
|
+
|
|
582
|
+
```text
|
|
583
|
+
User: Apply this skill to my current task.
|
|
584
|
+
Assistant: Follow the workflow in this skill, cite limitations, and ask before risky steps.
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
## Limitations
|
|
588
|
+
|
|
589
|
+
- Imported upstream skill; verify credentials, permissions, and safety boundaries before execution.
|
|
590
|
+
- Does not replace environment-specific validation, testing, or maintainer review.
|