plushie_renderer_lib/effects/mod.rs
1//! Platform abstraction for side effects.
2//!
3//! The renderer needs to perform platform-specific operations (file
4//! dialogs, clipboard, notifications) that differ between native and
5//! WASM targets. The [`EffectHandler`] trait abstracts these so
6//! plushie-renderer can compile to both targets.
7
8use std::future::Future;
9use std::pin::Pin;
10
11use plushie_core::ops::EffectRequest;
12use plushie_widget_sdk::protocol::EffectResponse;
13
14#[cfg(not(target_arch = "wasm32"))]
15pub mod native;
16
17#[cfg(not(target_arch = "wasm32"))]
18pub use native::NativeEffectHandler;
19
20/// Handler for platform-specific side effects.
21///
22/// Native implementations use rfd (file dialogs), arboard (clipboard),
23/// and notify-rust (notifications). WASM implementations stub or use
24/// web platform APIs.
25///
26/// Handlers produce data (EffectResponse). The caller (App::execute)
27/// is responsible for emitting the response through the EventSink.
28/// This keeps handlers decoupled from the emission mechanism.
29///
30/// The `Send + 'static` bound is required because iced's daemon holds
31/// the App across async boundaries and may move it between executor
32/// contexts on native (tokio). On wasm32, `Send` is trivially satisfied.
33pub trait EffectHandler: Send + 'static {
34 /// Handle a synchronous effect. Returns `Some(response)` for effects
35 /// that complete immediately (clipboard, notifications).
36 ///
37 /// Returns `None` only if the request is completely unrecognized.
38 fn handle_sync(&self, id: &str, request: &EffectRequest) -> Option<EffectResponse>;
39
40 /// Handle an async effect, returning a future that resolves to the
41 /// response. Used for operations that must not block the event loop
42 /// (file dialogs on native).
43 fn handle_async(
44 &self,
45 id: String,
46 request: EffectRequest,
47 ) -> Pin<Box<dyn Future<Output = EffectResponse> + Send>>;
48
49 /// Returns true if the given request should be handled async.
50 fn is_async(&self, request: &EffectRequest) -> bool;
51}