1#![allow(unexpected_cfgs)]
2
3use anyhow::Result;
4use fission_core::{Action, ActionId, AppState, Env, Widget};
5use fission_shell::async_host::AsyncRegistry;
6use fission_shell_winit::WinitApp;
7
8pub use fission_shell_winit::{
9 test_control, BarcodeScannerHost, BiometricHost, BluetoothHost, CameraHost, ClipboardHost,
10 GeolocationHost, HapticHost, InvalidationSet, MemoryBarcodeScannerHost, MemoryBiometricHost,
11 MemoryBluetoothHost, MemoryCameraHost, MemoryClipboardHost, MemoryGeolocationHost,
12 MemoryHapticHost, MemoryMicrophoneHost, MemoryNfcHost, MemoryNotificationHost,
13 MemoryPasskeyHost, MemoryVolumeHost, MemoryWifiHost, MicrophoneHost, NfcHost, NotificationHost,
14 PasskeyHost, Pipeline, UnsupportedBarcodeScannerHost, UnsupportedBiometricHost,
15 UnsupportedBluetoothHost, UnsupportedCameraHost, UnsupportedGeolocationHost,
16 UnsupportedHapticHost, UnsupportedMicrophoneHost, UnsupportedNfcHost,
17 UnsupportedNotificationHost, UnsupportedPasskeyHost, UnsupportedVolumeHost,
18 UnsupportedWifiHost, VolumeHost, WifiHost,
19};
20#[cfg(feature = "tray")]
21pub use fission_shell_winit::{
22 TrayActivateBehavior, TrayConfig, TrayHostAction, TrayIconSource, TrayMenu, TrayMenuAction,
23 TrayMenuEntry, TrayMenuItem, TrayMenuWidget, WindowCloseBehavior,
24};
25
26pub struct DesktopApp<S: AppState, W: Widget<S>> {
27 inner: WinitApp<S, W>,
28}
29
30impl<S: AppState + Default, W: Widget<S> + 'static> DesktopApp<S, W> {
31 pub fn new(root_widget: W) -> Self {
32 Self {
33 inner: WinitApp::new(root_widget),
34 }
35 }
36
37 pub fn with_key_handler<F>(mut self, handler: F) -> Self
38 where
39 F: Fn(&mut S, &fission_core::KeyCode, u8) -> bool + Send + Sync + 'static,
40 {
41 self.inner = self.inner.with_key_handler(handler);
42 self
43 }
44
45 pub fn with_title(mut self, title: impl Into<String>) -> Self {
46 self.inner = self.inner.with_title(title);
47 self
48 }
49
50 pub fn with_test_control_port(mut self, port: u16) -> Self {
51 self.inner = self.inner.with_test_control_port(port);
52 self
53 }
54
55 pub fn with_state_init<F>(mut self, init: F) -> Self
56 where
57 F: FnOnce(&mut S),
58 {
59 self.inner = self.inner.with_state_init(init);
60 self
61 }
62
63 pub fn with_env(mut self, env: Env) -> Self {
64 self.inner = self.inner.with_env(env);
65 self
66 }
67
68 pub fn with_design_system<D: fission_theme::DesignSystem>(
69 mut self,
70 mode: fission_theme::DesignMode,
71 ) -> Self {
72 self.inner = self.inner.with_design_system::<D>(mode);
73 self
74 }
75
76 pub fn with_sync_env<F>(mut self, f: F) -> Self
77 where
78 F: Fn(&S, &mut Env) + Send + Sync + 'static,
79 {
80 self.inner = self.inner.with_sync_env(f);
81 self
82 }
83
84 pub fn with_frame_hook<F>(mut self, f: F) -> Self
85 where
86 F: Fn(&mut S) -> bool + Send + Sync + 'static,
87 {
88 self.inner = self.inner.with_frame_hook(f);
89 self
90 }
91
92 pub fn with_async<F>(mut self, configure: F) -> Self
93 where
94 F: FnOnce(&mut AsyncRegistry),
95 {
96 self.inner = self.inner.with_async(configure);
97 self
98 }
99
100 pub fn with_notification_host<H>(mut self, host: H) -> Self
101 where
102 H: NotificationHost,
103 {
104 self.inner = self.inner.with_notification_host(host);
105 self
106 }
107
108 pub fn with_nfc_host<H>(mut self, host: H) -> Self
109 where
110 H: NfcHost,
111 {
112 self.inner = self.inner.with_nfc_host(host);
113 self
114 }
115
116 pub fn with_biometric_host<H>(mut self, host: H) -> Self
117 where
118 H: BiometricHost,
119 {
120 self.inner = self.inner.with_biometric_host(host);
121 self
122 }
123
124 pub fn with_passkey_host<H>(mut self, host: H) -> Self
125 where
126 H: PasskeyHost,
127 {
128 self.inner = self.inner.with_passkey_host(host);
129 self
130 }
131
132 pub fn with_bluetooth_host<H>(mut self, host: H) -> Self
133 where
134 H: BluetoothHost,
135 {
136 self.inner = self.inner.with_bluetooth_host(host);
137 self
138 }
139
140 pub fn with_barcode_scanner_host<H>(mut self, host: H) -> Self
141 where
142 H: BarcodeScannerHost,
143 {
144 self.inner = self.inner.with_barcode_scanner_host(host);
145 self
146 }
147
148 pub fn with_camera_host<H>(mut self, host: H) -> Self
149 where
150 H: CameraHost,
151 {
152 self.inner = self.inner.with_camera_host(host);
153 self
154 }
155
156 pub fn with_clipboard_host<H>(mut self, host: H) -> Self
157 where
158 H: ClipboardHost,
159 {
160 self.inner = self.inner.with_clipboard_host(host);
161 self
162 }
163
164 pub fn with_geolocation_host<H>(mut self, host: H) -> Self
165 where
166 H: GeolocationHost,
167 {
168 self.inner = self.inner.with_geolocation_host(host);
169 self
170 }
171
172 pub fn with_haptic_host<H>(mut self, host: H) -> Self
173 where
174 H: HapticHost,
175 {
176 self.inner = self.inner.with_haptic_host(host);
177 self
178 }
179
180 pub fn with_microphone_host<H>(mut self, host: H) -> Self
181 where
182 H: MicrophoneHost,
183 {
184 self.inner = self.inner.with_microphone_host(host);
185 self
186 }
187
188 pub fn with_wifi_host<H>(mut self, host: H) -> Self
189 where
190 H: WifiHost,
191 {
192 self.inner = self.inner.with_wifi_host(host);
193 self
194 }
195
196 pub fn with_volume_host<H>(mut self, host: H) -> Self
197 where
198 H: VolumeHost,
199 {
200 self.inner = self.inner.with_volume_host(host);
201 self
202 }
203
204 pub fn with_startup_action<A: Action>(mut self, action: A) -> Self {
205 self.inner = self.inner.with_startup_action(action);
206 self
207 }
208
209 #[cfg(feature = "tray")]
210 pub fn with_tray(mut self, config: TrayConfig<S>) -> Self {
211 self.inner = self.inner.with_tray(config);
212 self
213 }
214
215 pub fn with_deep_link_config(mut self, config: fission_core::DeepLinkConfig) -> Self {
216 self.inner = self.inner.with_deep_link_config(config);
217 self
218 }
219
220 pub fn with_deep_link_scheme(mut self, scheme: impl Into<String>) -> Self {
221 self.inner = self.inner.with_deep_link_scheme(scheme);
222 self
223 }
224
225 pub fn with_deep_link_domain(mut self, domain: impl Into<String>) -> Self {
226 self.inner = self.inner.with_deep_link_domain(domain);
227 self
228 }
229
230 pub fn with_startup_deep_link(mut self, link: fission_core::DeepLink) -> Self {
231 self.inner = self.inner.with_startup_deep_link(link);
232 self
233 }
234
235 pub fn with_startup_notification_response(
236 mut self,
237 response: fission_core::NotificationResponse,
238 ) -> Self {
239 self.inner = self.inner.with_startup_notification_response(response);
240 self
241 }
242
243 pub fn on_deep_link<H>(mut self, handler: H) -> Self
244 where
245 H: fission_core::registry::IntoHandler<S, fission_core::DeepLinkReceived>
246 + Send
247 + Sync
248 + 'static,
249 {
250 self.inner = self.inner.on_deep_link(handler);
251 self
252 }
253
254 pub fn on_notification_response<H>(mut self, handler: H) -> Self
255 where
256 H: fission_core::registry::IntoHandler<S, fission_core::NotificationResponseReceived>
257 + Send
258 + Sync
259 + 'static,
260 {
261 self.inner = self.inner.on_notification_response(handler);
262 self
263 }
264
265 pub fn register_reducer(
266 &mut self,
267 action_id: ActionId,
268 reducer: fn(&mut S, &fission_core::ActionEnvelope, fission_core::NodeId) -> Result<()>,
269 ) -> Result<()> {
270 self.inner.register_reducer(action_id, reducer)
271 }
272
273 pub fn absorb_registry(&mut self, registry: fission_core::ActionRegistry<S>) {
274 self.inner.absorb_registry(registry);
275 }
276
277 pub fn run(self) -> Result<()> {
278 self.inner.run()
279 }
280
281 #[cfg(target_os = "android")]
282 pub fn run_with_android_app(
283 self,
284 android_app: winit::platform::android::activity::AndroidApp,
285 ) -> Result<()> {
286 self.inner.run_with_android_app(android_app)
287 }
288}