Make Command implementations platform-specific
This allows us to introduce a platform-specific `Action` to both `iced_native` and `iced_web` and remove the `Clipboard` from `Application::update` to maintain purity. Additionally, this should let us implement further actions to let users query and modify the shell environment (e.g. window, clipboard, and more!)
This commit is contained in:
parent
b7b7741578
commit
76698ff2b5
34 changed files with 363 additions and 342 deletions
|
|
@ -1,21 +0,0 @@
|
|||
/// A buffer for short-term storage and transfer within and between
|
||||
/// applications.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Clipboard;
|
||||
|
||||
impl Clipboard {
|
||||
/// Creates a new [`Clipboard`].
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
/// Reads the current content of the [`Clipboard`] as text.
|
||||
pub fn read(&self) -> Option<String> {
|
||||
unimplemented! {}
|
||||
}
|
||||
|
||||
/// Writes the given text contents to the [`Clipboard`].
|
||||
pub fn write(&mut self, _contents: String) {
|
||||
unimplemented! {}
|
||||
}
|
||||
}
|
||||
77
web/src/command.rs
Normal file
77
web/src/command.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
mod action;
|
||||
|
||||
pub use action::Action;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use std::future::Future;
|
||||
|
||||
/// A set of asynchronous actions to be performed by some runtime.
|
||||
pub enum Command<T> {
|
||||
None,
|
||||
Single(Action<T>),
|
||||
Batch(Vec<Action<T>>),
|
||||
}
|
||||
|
||||
impl<T> Command<T> {
|
||||
/// Creates an empty [`Command`].
|
||||
///
|
||||
/// In other words, a [`Command`] that does nothing.
|
||||
pub fn none() -> Self {
|
||||
Self::None
|
||||
}
|
||||
|
||||
/// Creates a [`Command`] that performs the action of the given future.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn perform<A>(
|
||||
future: impl Future<Output = T> + 'static,
|
||||
f: impl Fn(T) -> A + 'static + Send,
|
||||
) -> Command<A> {
|
||||
use iced_futures::futures::FutureExt;
|
||||
|
||||
Command::Single(Action::Future(Box::pin(future.map(f))))
|
||||
}
|
||||
|
||||
/// Applies a transformation to the result of a [`Command`].
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn map<A>(mut self, f: impl Fn(T) -> A + 'static + Clone) -> Command<A>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
match self {
|
||||
Self::None => Command::None,
|
||||
Self::Single(action) => Command::Single(action.map(f)),
|
||||
Self::Batch(batch) => Command::Batch(
|
||||
batch
|
||||
.into_iter()
|
||||
.map(|action| action.map(f.clone()))
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a [`Command`] that performs the actions of all the given
|
||||
/// commands.
|
||||
///
|
||||
/// Once this command is run, all the commands will be executed at once.
|
||||
pub fn batch(commands: impl IntoIterator<Item = Command<T>>) -> Self {
|
||||
let mut batch = Vec::new();
|
||||
|
||||
for command in commands {
|
||||
match command {
|
||||
Self::None => {}
|
||||
Self::Single(command) => batch.push(command),
|
||||
Self::Batch(commands) => batch.extend(commands),
|
||||
}
|
||||
}
|
||||
|
||||
Self::Batch(batch)
|
||||
}
|
||||
|
||||
pub fn actions(self) -> Vec<Action<T>> {
|
||||
match self {
|
||||
Self::None => Vec::new(),
|
||||
Self::Single(action) => vec![action],
|
||||
Self::Batch(batch) => batch,
|
||||
}
|
||||
}
|
||||
}
|
||||
18
web/src/command/action.rs
Normal file
18
web/src/command/action.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
pub enum Action<T> {
|
||||
Future(iced_futures::BoxFuture<T>),
|
||||
}
|
||||
|
||||
impl<T> Action<T> {
|
||||
/// Applies a transformation to the result of a [`Command`].
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn map<A>(self, f: impl Fn(T) -> A + 'static) -> Action<A>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
use iced_futures::futures::FutureExt;
|
||||
|
||||
match self {
|
||||
Self::Future(future) => Action::Future(Box::pin(future.map(f))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -50,8 +50,8 @@
|
|||
//! [`wasm-pack`]: https://github.com/rustwasm/wasm-pack
|
||||
//! [`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
|
||||
//! [`tour` example]: https://github.com/hecrj/iced/tree/0.3/examples/tour
|
||||
#![deny(missing_docs)]
|
||||
#![deny(missing_debug_implementations)]
|
||||
//#![deny(missing_docs)]
|
||||
//#![deny(missing_debug_implementations)]
|
||||
#![deny(unused_results)]
|
||||
#![forbid(unsafe_code)]
|
||||
#![forbid(rust_2018_idioms)]
|
||||
|
|
@ -59,7 +59,7 @@ use dodrio::bumpalo;
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
mod bus;
|
||||
mod clipboard;
|
||||
mod command;
|
||||
mod element;
|
||||
mod hasher;
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ pub mod subscription;
|
|||
pub mod widget;
|
||||
|
||||
pub use bus::Bus;
|
||||
pub use clipboard::Clipboard;
|
||||
pub use command::Command;
|
||||
pub use css::Css;
|
||||
pub use dodrio;
|
||||
pub use element::Element;
|
||||
|
|
@ -77,7 +77,7 @@ pub use iced_core::{
|
|||
keyboard, menu, mouse, Align, Background, Color, Font, HorizontalAlignment,
|
||||
Length, Menu, Padding, Point, Rectangle, Size, Vector, VerticalAlignment,
|
||||
};
|
||||
pub use iced_futures::{executor, futures, Command};
|
||||
pub use iced_futures::{executor, futures};
|
||||
pub use subscription::Subscription;
|
||||
|
||||
#[doc(no_inline)]
|
||||
|
|
@ -128,11 +128,7 @@ pub trait Application {
|
|||
/// this method.
|
||||
///
|
||||
/// Any [`Command`] returned will be executed immediately in the background.
|
||||
fn update(
|
||||
&mut self,
|
||||
message: Self::Message,
|
||||
clipboard: &mut Clipboard,
|
||||
) -> Command<Self::Message>;
|
||||
fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
|
||||
|
||||
/// Returns the widgets to display in the [`Application`].
|
||||
///
|
||||
|
|
@ -162,8 +158,6 @@ pub trait Application {
|
|||
let document = window.document().unwrap();
|
||||
let body = document.body().unwrap();
|
||||
|
||||
let mut clipboard = Clipboard::new();
|
||||
|
||||
let (sender, receiver) =
|
||||
iced_futures::futures::channel::mpsc::unbounded();
|
||||
|
||||
|
|
@ -177,7 +171,7 @@ pub trait Application {
|
|||
let mut title = app.title();
|
||||
document.set_title(&title);
|
||||
|
||||
runtime.spawn(command);
|
||||
run_command(command, &mut runtime);
|
||||
|
||||
let application = Rc::new(RefCell::new(app));
|
||||
|
||||
|
|
@ -190,8 +184,7 @@ pub trait Application {
|
|||
|
||||
let event_loop = receiver.for_each(move |message| {
|
||||
let (command, subscription) = runtime.enter(|| {
|
||||
let command =
|
||||
application.borrow_mut().update(message, &mut clipboard);
|
||||
let command = application.borrow_mut().update(message);
|
||||
let subscription = application.borrow().subscription();
|
||||
|
||||
(command, subscription)
|
||||
|
|
@ -199,7 +192,7 @@ pub trait Application {
|
|||
|
||||
let new_title = application.borrow().title();
|
||||
|
||||
runtime.spawn(command);
|
||||
run_command(command, &mut runtime);
|
||||
runtime.track(subscription);
|
||||
|
||||
if title != new_title {
|
||||
|
|
@ -350,8 +343,7 @@ pub trait Embedded {
|
|||
);
|
||||
|
||||
let (app, command) = runtime.enter(|| Self::new(flags));
|
||||
|
||||
runtime.spawn(command);
|
||||
run_command(command, &mut runtime);
|
||||
|
||||
let application = Rc::new(RefCell::new(app));
|
||||
|
||||
|
|
@ -370,7 +362,7 @@ pub trait Embedded {
|
|||
(command, subscription)
|
||||
});
|
||||
|
||||
runtime.spawn(command);
|
||||
run_command(command, &mut runtime);
|
||||
runtime.track(subscription);
|
||||
|
||||
vdom.weak().schedule_render();
|
||||
|
|
@ -382,6 +374,25 @@ pub trait Embedded {
|
|||
}
|
||||
}
|
||||
|
||||
fn run_command<Message: 'static + Send, E: Executor>(
|
||||
command: Command<Message>,
|
||||
runtime: &mut iced_futures::Runtime<
|
||||
Hasher,
|
||||
(),
|
||||
E,
|
||||
iced_futures::futures::channel::mpsc::UnboundedSender<Message>,
|
||||
Message,
|
||||
>,
|
||||
) {
|
||||
for action in command.actions() {
|
||||
match action {
|
||||
command::Action::Future(future) => {
|
||||
runtime.spawn(future);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EmbeddedInstance<A: Embedded> {
|
||||
application: Rc<RefCell<A>>,
|
||||
bus: Bus<A::Message>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue