From 9a0cb7ed91851d969066aad7e0bb05d211c97d99 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sat, 4 Jan 2020 01:05:40 +0100 Subject: [PATCH 01/12] Fix examples/tests to work with `web_sys`. --- ci/check_examples.sh | 8 +-- ci/run_tests.sh | 0 examples/build_all.sh | 64 ++++++++++++++++--- examples/counter/Cargo.toml | 7 +- examples/counter/src/lib.rs | 12 +++- examples/crm/Cargo.toml | 4 ++ examples/custom_components/Cargo.toml | 4 ++ examples/dashboard/Cargo.toml | 4 ++ examples/file_upload/Cargo.toml | 5 ++ examples/file_upload/src/lib.rs | 6 ++ examples/fragments/Cargo.toml | 4 ++ examples/futures/Cargo.toml | 6 +- examples/futures/README.md | 4 +- examples/futures/index.html | 10 --- examples/futures/main.js | 6 -- examples/futures/src/lib.rs | 2 +- examples/game_of_life/Cargo.toml | 8 ++- examples/inner_html/Cargo.toml | 7 +- examples/inner_html/src/lib.rs | 23 ++++++- examples/js_callback/Cargo.toml | 6 +- examples/js_callback/src/lib.rs | 24 +++++++ examples/large_table/Cargo.toml | 4 ++ examples/minimal/Cargo.toml | 4 ++ examples/mount_point/Cargo.toml | 20 +++++- examples/mount_point/src/main.rs | 45 +++++++++++-- examples/multi_thread/Cargo.toml | 7 +- examples/multi_thread/README.md | 8 ++- examples/multi_thread/src/bin/main.rs | 3 + .../multi_thread/src/bin/native_worker.rs | 3 + examples/nested_list/Cargo.toml | 4 ++ examples/node_refs/Cargo.toml | 7 +- examples/node_refs/src/lib.rs | 16 +++-- examples/npm_and_rest/Cargo.toml | 9 ++- examples/npm_and_rest/src/ccxt.rs | 38 ++++++++++- examples/npm_and_rest/src/lib.rs | 1 + examples/showcase/Cargo.toml | 40 +++++++++++- examples/static/.gitignore | 3 + examples/static/index.html | 12 ++++ examples/textarea/Cargo.toml | 4 ++ examples/timer/Cargo.toml | 4 ++ examples/todomvc/Cargo.toml | 4 ++ examples/todomvc/src/lib.rs | 17 +++-- examples/two_apps/Cargo.toml | 7 +- examples/two_apps/src/main.rs | 9 ++- tests/vtag_test.rs | 1 - 45 files changed, 416 insertions(+), 68 deletions(-) mode change 100755 => 100644 ci/run_tests.sh delete mode 100644 examples/futures/index.html delete mode 100644 examples/futures/main.js create mode 100644 examples/static/.gitignore create mode 100644 examples/static/index.html diff --git a/ci/check_examples.sh b/ci/check_examples.sh index 7b46284a6c1..686788cdc3f 100755 --- a/ci/check_examples.sh +++ b/ci/check_examples.sh @@ -10,12 +10,12 @@ cd examples/showcase if [ "$emscripten_supported" == "0" ]; then # TODO - Emscripten builds are broken on rustc > 1.39.0 - cargo web build --target asmjs-unknown-emscripten - cargo web build --target wasm32-unknown-emscripten + cargo web build --target asmjs-unknown-emscripten --features std_web + cargo web build --target wasm32-unknown-emscripten --features std_web fi -# TODO showcase doesn't support wasm-bindgen yet -cargo web build --target wasm32-unknown-unknown +cargo web build --target wasm32-unknown-unknown --features std_web +cargo build --target wasm32-unknown-unknown --features web_sys # Reset cwd cd ../.. diff --git a/ci/run_tests.sh b/ci/run_tests.sh old mode 100755 new mode 100644 diff --git a/examples/build_all.sh b/examples/build_all.sh index bd074fa57d5..ecaa91d8ef7 100755 --- a/examples/build_all.sh +++ b/examples/build_all.sh @@ -7,11 +7,14 @@ function ctrl_c() { kill $PID } -function build() { +function build_std_web() { for example in */ ; do if [[ $example == server* ]]; then continue fi + if [[ $example == static* ]]; then + continue + fi echo "Building: $example" cd $example cargo update @@ -20,12 +23,32 @@ function build() { done } -function run() { +function build_web_sys() { + for example in */ ; do + if [[ $example == server* ]]; then + continue + fi + if [[ $example == static* ]]; then + continue + fi + echo "Building: $example" + cd $example + cargo update + cargo build --target wasm32-unknown-unknown + wasm-bindgen --target web --no-typescript --out-dir ../static/ --out-name wasm ../target/wasm32-unknown-unknown/debug/$example.wasm + cd .. + done +} + +function run_std_web() { trap ctrl_c INT for example in */ ; do if [[ $example == server* ]]; then continue fi + if [[ $example == static* ]]; then + continue + fi echo "Running: $example" cd $example cargo web start --target wasm32-unknown-unknown & @@ -35,6 +58,26 @@ function run() { done } +function run_web_sys() { + trap ctrl_c INT + for example in */ ; do + if [[ $example == server* ]]; then + continue + fi + if [[ $example == static* ]]; then + continue + fi + echo "Running: $example" + cd $example + cargo build --target wasm32-unknown-unknown + wasm-bindgen --target web --no-typescript --out-dir ../static/ --out-name wasm ../target/wasm32-unknown-unknown/debug/$example.wasm + http -r ../static/ + PID=$! + wait $PID + cd .. + done +} + function clean() { trap ctrl_c INT for example in */ ; do @@ -51,16 +94,19 @@ case "$1" in --help) echo "Available commands: build, run, clean" ;; - build) - build + build_std_web) + build_std_web + ;; + build_web_sys) + build_web_sys ;; - run) - run + run_std_web) + run_std_web + ;; + run_web_sys) + run_web_sys ;; clean) clean ;; - *) - build - ;; esac diff --git a/examples/counter/Cargo.toml b/examples/counter/Cargo.toml index 22272744d51..a4991e81139 100644 --- a/examples/counter/Cargo.toml +++ b/examples/counter/Cargo.toml @@ -5,5 +5,10 @@ authors = ["Denis Kolodin "] edition = "2018" [dependencies] -stdweb = "0.4.20" +js-sys = { version = "0.3", optional = true } +stdweb = { version = "0.4.20", optional = true } yew = { path = "../.." } + +[features] +std_web = ["stdweb", "yew/std_web"] +web_sys = ["js-sys", "yew/web_sys"] diff --git a/examples/counter/src/lib.rs b/examples/counter/src/lib.rs index fa9d33de841..bbb4551269f 100644 --- a/examples/counter/src/lib.rs +++ b/examples/counter/src/lib.rs @@ -1,5 +1,8 @@ -#![recursion_limit = "128"] +#![recursion_limit = "512"] +#[cfg(feature = "web_sys")] +use js_sys::Date; +#[cfg(feature = "std_web")] use stdweb::web::Date; use yew::services::ConsoleService; use yew::{html, Component, ComponentLink, Html, ShouldRender}; @@ -63,7 +66,12 @@ impl Component for Model {

{ self.value }

-

{ Date::new().to_string() }

+

{ + #[cfg(feature = "std_web")] + { Date::new().to_string() } + #[cfg(feature = "web_sys")] + Date::new_0().to_string().as_string().unwrap() + }

} } diff --git a/examples/crm/Cargo.toml b/examples/crm/Cargo.toml index 85a4e28e8d8..248a56c9238 100644 --- a/examples/crm/Cargo.toml +++ b/examples/crm/Cargo.toml @@ -9,3 +9,7 @@ serde = "1" serde_derive = "1" yew = { path = "../.." } pulldown-cmark = "0.1.2" + +[features] +std_web = ["yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/custom_components/Cargo.toml b/examples/custom_components/Cargo.toml index 0e50867b039..9c8843fc883 100644 --- a/examples/custom_components/Cargo.toml +++ b/examples/custom_components/Cargo.toml @@ -6,3 +6,7 @@ edition = "2018" [dependencies] yew = { path = "../.." } + +[features] +std_web = ["yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/dashboard/Cargo.toml b/examples/dashboard/Cargo.toml index f4e0ddb55fd..88d57d1f47b 100644 --- a/examples/dashboard/Cargo.toml +++ b/examples/dashboard/Cargo.toml @@ -9,3 +9,7 @@ anyhow = "1" serde = "1" serde_derive = "1" yew = { path = "../..", features = ["toml"] } + +[features] +std_web = ["yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/file_upload/Cargo.toml b/examples/file_upload/Cargo.toml index 84d09fe47cc..95789571280 100644 --- a/examples/file_upload/Cargo.toml +++ b/examples/file_upload/Cargo.toml @@ -5,4 +5,9 @@ authors = ["Denis Kolodin "] edition = "2018" [dependencies] +js-sys = { version = "0.3", optional = true } yew = { path = "../.." } + +[features] +std_web = ["yew/std_web"] +web_sys = ["js-sys", "yew/web_sys"] diff --git a/examples/file_upload/src/lib.rs b/examples/file_upload/src/lib.rs index 9f909331434..70a9e3c2905 100644 --- a/examples/file_upload/src/lib.rs +++ b/examples/file_upload/src/lib.rs @@ -73,6 +73,12 @@ impl Component for Model { - - - - Yew • Futures - - - - - \ No newline at end of file diff --git a/examples/futures/main.js b/examples/futures/main.js deleted file mode 100644 index cce343c6215..00000000000 --- a/examples/futures/main.js +++ /dev/null @@ -1,6 +0,0 @@ -import init, { run_app } from './pkg/futures.js'; -async function main() { - await init('./pkg/futures_bg.wasm'); - run_app(); -} -main() \ No newline at end of file diff --git a/examples/futures/src/lib.rs b/examples/futures/src/lib.rs index fc6ed10ed58..a7d25723703 100644 --- a/examples/futures/src/lib.rs +++ b/examples/futures/src/lib.rs @@ -136,7 +136,7 @@ impl Component for Model { } } -#[wasm_bindgen] +#[wasm_bindgen(start)] pub fn run_app() { yew::start_app::(); } diff --git a/examples/game_of_life/Cargo.toml b/examples/game_of_life/Cargo.toml index 26677bce28c..691193aa23f 100644 --- a/examples/game_of_life/Cargo.toml +++ b/examples/game_of_life/Cargo.toml @@ -7,7 +7,11 @@ authors = ["Diego Cardoso ", edition = "2018" [dependencies] -rand = { version = "0.6.5", features = ["stdweb"] } +rand = { version = "0.6.5" } log = "0.4" -web_logger = "0.1" +web_logger = "0.2" yew = { path = "../.." } + +[features] +std_web = ["rand/stdweb", "yew/std_web"] +web_sys = ["rand/wasm-bindgen", "yew/web_sys"] diff --git a/examples/inner_html/Cargo.toml b/examples/inner_html/Cargo.toml index 37c92c05b64..a90d3ec32fb 100644 --- a/examples/inner_html/Cargo.toml +++ b/examples/inner_html/Cargo.toml @@ -5,5 +5,10 @@ authors = ["Garrett Berg "] edition = "2018" [dependencies] -stdweb = "0.4.20" +stdweb = { version = "0.4.20", optional = true } +web-sys = { version = "0.3", optional = true, features = ["console", "Document", "Element", "Node", "Window"] } yew = { path = "../.." } + +[features] +std_web = ["stdweb", "yew/std_web"] +web_sys = ["web-sys", "yew/web_sys"] diff --git a/examples/inner_html/src/lib.rs b/examples/inner_html/src/lib.rs index 1427fc88fde..53f9c40397e 100644 --- a/examples/inner_html/src/lib.rs +++ b/examples/inner_html/src/lib.rs @@ -1,9 +1,12 @@ #![recursion_limit = "512"] +#[cfg(feature = "std_web")] #[macro_use] extern crate stdweb; -use stdweb::unstable::TryFrom; -use stdweb::web::Node; +#[cfg(feature = "std_web")] +use stdweb::{unstable::TryFrom, web::Node}; +#[cfg(feature = "web_sys")] +use web_sys::{console, Node}; use yew::virtual_dom::VNode; use yew::{Component, ComponentLink, Html, ShouldRender}; @@ -34,14 +37,30 @@ impl Component for Model { } fn view(&self) -> Html { + #[cfg(feature = "std_web")] let js_svg = js! { var div = document.createElement("div"); div.innerHTML = @{SVG.to_string()}; console.log(div); return div; }; + #[cfg(feature = "web_sys")] + let js_svg = { + let div = web_sys::window() + .unwrap() + .document() + .unwrap() + .create_element("div") + .unwrap(); + div.set_inner_html(SVG); + console::log_1(&div); + div + }; eprintln!("js_svg: {:?}", js_svg); + #[cfg(feature = "std_web")] let node = Node::try_from(js_svg).expect("convert js_svg"); + #[cfg(feature = "web_sys")] + let node = Node::from(js_svg); let vnode = VNode::VRef(node); eprintln!("svg: {:?}", vnode); vnode diff --git a/examples/js_callback/Cargo.toml b/examples/js_callback/Cargo.toml index 242701f9958..f9be3a4291d 100644 --- a/examples/js_callback/Cargo.toml +++ b/examples/js_callback/Cargo.toml @@ -6,7 +6,11 @@ edition = "2018" [dependencies] yew = { path = "../.." } -stdweb = "^0.4.20" +stdweb = { version = "^0.4.20", optional = true } [target.'cfg(all(target_arch = "wasm32", not(cargo_web)))'.dependencies] wasm-bindgen = "0.2.58" + +[features] +std_web = ["stdweb", "yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/js_callback/src/lib.rs b/examples/js_callback/src/lib.rs index c30d31eb9d2..8c9efb7abe1 100644 --- a/examples/js_callback/src/lib.rs +++ b/examples/js_callback/src/lib.rs @@ -1,8 +1,11 @@ #![recursion_limit = "128"] #![deny(warnings)] +#[cfg(feature = "std_web")] #[allow(unused_imports)] use stdweb::{_js_impl, js}; +#[cfg(feature = "web_sys")] +use wasm_bindgen::{closure::Closure, prelude::wasm_bindgen, JsValue}; use yew::prelude::*; pub struct Model { @@ -82,10 +85,18 @@ where String::from(string).replace(' ', "\u{00a0}") } +#[cfg(feature = "std_web")] fn get_payload() -> String { (js! { return window.get_payload() }).into_string().unwrap() } +#[cfg(feature = "web_sys")] +#[wasm_bindgen] +extern "C" { + fn get_payload() -> String; +} + +#[cfg(feature = "std_web")] fn get_payload_later(payload_callback: Callback) { let callback = move |payload: String| payload_callback.emit(payload); js! { @@ -98,3 +109,16 @@ fn get_payload_later(payload_callback: Callback) { }); }; } + +#[cfg(feature = "web_sys")] +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_name = "get_payload_later")] + fn get_payload_later_js(payload_callback: JsValue); +} + +#[cfg(feature = "web_sys")] +fn get_payload_later(payload_callback: Callback) { + let callback = Closure::once_into_js(move |payload: String| payload_callback.emit(payload)); + get_payload_later_js(callback); +} diff --git a/examples/large_table/Cargo.toml b/examples/large_table/Cargo.toml index 67d7196cede..b62c39ea019 100644 --- a/examples/large_table/Cargo.toml +++ b/examples/large_table/Cargo.toml @@ -6,3 +6,7 @@ edition = "2018" [dependencies] yew = { path = "../.." } + +[features] +std_web = ["yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/minimal/Cargo.toml b/examples/minimal/Cargo.toml index ce3b9cdc1dc..be969b88ecb 100644 --- a/examples/minimal/Cargo.toml +++ b/examples/minimal/Cargo.toml @@ -6,3 +6,7 @@ edition = "2018" [dependencies] yew = { path = "../.." } + +[features] +std_web = ["yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/mount_point/Cargo.toml b/examples/mount_point/Cargo.toml index 675b6281a5b..3d988d52c02 100644 --- a/examples/mount_point/Cargo.toml +++ b/examples/mount_point/Cargo.toml @@ -5,5 +5,23 @@ authors = ["Ben Berman "] edition = "2018" [dependencies] -stdweb = "0.4.20" +stdweb = { version = "0.4.20", optional = true } +wasm-bindgen = { version = "0.2", optional = true } yew = { path = "../.." } + +[dependencies.web-sys] +version = "0.3" +optional = true +features = [ + "CanvasRenderingContext2d", + "Document", + "DomTokenList", + "Element", + "HtmlCanvasElement", + "Node", + "Window" +] + +[features] +std_web = ["stdweb", "yew/std_web"] +web_sys = ["wasm-bindgen", "web-sys", "yew/web_sys"] diff --git a/examples/mount_point/src/main.rs b/examples/mount_point/src/main.rs index 2253a36f26d..200d2b17bda 100644 --- a/examples/mount_point/src/main.rs +++ b/examples/mount_point/src/main.rs @@ -1,18 +1,33 @@ +#[cfg(feature = "std_web")] #[macro_use] extern crate stdweb; use mount_point::Model; +#[cfg(feature = "std_web")] use stdweb::web::{document, IElement, INode, IParentNode}; use yew::App; +#[cfg(feature = "web_sys")] +use ::{ + wasm_bindgen::JsValue, + web_sys::{CanvasRenderingContext2d, HtmlCanvasElement}, +}; fn main() { yew::initialize(); - let body = document().query_selector("body").unwrap().unwrap(); + #[cfg(feature = "std_web")] + let document = document(); + #[cfg(feature = "web_sys")] + let document = web_sys::window().unwrap().document().unwrap(); + let body = document.query_selector("body").unwrap().unwrap(); // This canvas won't be overwritten by yew! - let canvas = document().create_element("canvas").unwrap(); - body.append_child(&canvas); + let canvas = document.create_element("canvas").unwrap(); + #[cfg_attr(feature = "std_web", allow(unused_variables))] + let result = body.append_child(&canvas); + #[cfg(feature = "web_sys")] + result.unwrap(); + #[cfg(feature = "std_web")] js! { const canvas = document.querySelector("canvas"); canvas.width = 100; @@ -21,11 +36,29 @@ fn main() { ctx.fillStyle = "green"; ctx.fillRect(10, 10, 50, 50); }; + #[cfg(feature = "web_sys")] + { + let canvas = HtmlCanvasElement::from(JsValue::from(canvas)); + canvas.set_width(100); + canvas.set_height(100); + let ctx = CanvasRenderingContext2d::from(JsValue::from( + canvas.get_context("2d").unwrap().unwrap(), + )); + ctx.set_fill_style(&JsValue::from_str("green")); + ctx.fill_rect(10., 10., 50., 50.); + } let mount_class = "mount-point"; - let mount_point = document().create_element("div").unwrap(); - mount_point.class_list().add(mount_class).unwrap(); - body.append_child(&mount_point); + let mount_point = document.create_element("div").unwrap(); + let class_list = mount_point.class_list(); + #[cfg(feature = "std_web")] + class_list.add(mount_class).unwrap(); + #[cfg(feature = "web_sys")] + class_list.add_1(mount_class).unwrap(); + #[cfg_attr(feature = "std_web", allow(unused_variables))] + let result = body.append_child(&mount_point); + #[cfg(feature = "web_sys")] + result.unwrap(); App::::new().mount(mount_point); yew::run_loop(); diff --git a/examples/multi_thread/Cargo.toml b/examples/multi_thread/Cargo.toml index 1841175d9b6..6faf24b7a4b 100644 --- a/examples/multi_thread/Cargo.toml +++ b/examples/multi_thread/Cargo.toml @@ -14,7 +14,12 @@ path = "src/bin/native_worker.rs" [dependencies] log = "0.4" -web_logger = "0.1" +wasm-logger = { version = "0.2", optional = true } +web_logger = { version = "0.2", optional = true } serde = "1.0" serde_derive = "1.0" yew = { path = "../.." } + +[features] +std_web = ["web_logger", "yew/std_web"] +web_sys = ["wasm-logger", "yew/web_sys"] diff --git a/examples/multi_thread/README.md b/examples/multi_thread/README.md index 32da696e6c6..6a12b961ff3 100644 --- a/examples/multi_thread/README.md +++ b/examples/multi_thread/README.md @@ -3,5 +3,11 @@ You should compile a worker which have to be spawned in a separate thread: ```sh -cargo web build --bin native_worker --release +cargo web build --bin native_worker --release --features std_web +``` + +For `web-sys` support, use `no-modules` output. + +```sh +wasm-pack build --target no-modules --release -- --features web_sys --bin native_worker ``` diff --git a/examples/multi_thread/src/bin/main.rs b/examples/multi_thread/src/bin/main.rs index 1a699be56aa..28e93e8d54a 100644 --- a/examples/multi_thread/src/bin/main.rs +++ b/examples/multi_thread/src/bin/main.rs @@ -1,4 +1,7 @@ fn main() { + #[cfg(feature = "std_web")] web_logger::init(); + #[cfg(feature = "web_sys")] + wasm_logger::init(wasm_logger::Config::default()); yew::start_app::(); } diff --git a/examples/multi_thread/src/bin/native_worker.rs b/examples/multi_thread/src/bin/native_worker.rs index f4343ca2755..f1f40be3413 100644 --- a/examples/multi_thread/src/bin/native_worker.rs +++ b/examples/multi_thread/src/bin/native_worker.rs @@ -1,7 +1,10 @@ use yew::agent::Threaded; fn main() { + #[cfg(feature = "std_web")] web_logger::init(); + #[cfg(feature = "web_sys")] + wasm_logger::init(wasm_logger::Config::default()); yew::initialize(); multi_thread::native_worker::Worker::register(); yew::run_loop(); diff --git a/examples/nested_list/Cargo.toml b/examples/nested_list/Cargo.toml index 744148fd54b..6dc090c3555 100644 --- a/examples/nested_list/Cargo.toml +++ b/examples/nested_list/Cargo.toml @@ -8,3 +8,7 @@ edition = "2018" log = "0.4" web_logger = "0.2" yew = { path = "../.." } + +[features] +std_web = ["yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/node_refs/Cargo.toml b/examples/node_refs/Cargo.toml index 2cb0ce4acfd..4c5bc794722 100644 --- a/examples/node_refs/Cargo.toml +++ b/examples/node_refs/Cargo.toml @@ -6,4 +6,9 @@ edition = "2018" [dependencies] yew = { path = "../.." } -stdweb = "0.4.20" +stdweb = { version = "0.4.20", optional = true } +web-sys = { version = "0.3", optional = true, features = ["HtmlElement", "HtmlInputElement", "Node"] } + +[features] +std_web = ["stdweb", "yew/std_web"] +web_sys = ["web-sys", "yew/web_sys"] diff --git a/examples/node_refs/src/lib.rs b/examples/node_refs/src/lib.rs index a40b5e09a65..97faee7cba9 100644 --- a/examples/node_refs/src/lib.rs +++ b/examples/node_refs/src/lib.rs @@ -3,8 +3,10 @@ mod input; use input::InputComponent; -use stdweb::web::html_element::InputElement; -use stdweb::web::IHtmlElement; +#[cfg(feature = "std_web")] +use stdweb::web::{html_element::InputElement, IHtmlElement}; +#[cfg(feature = "web_sys")] +use web_sys::HtmlInputElement as InputElement; use yew::prelude::*; pub struct Model { @@ -31,7 +33,10 @@ impl Component for Model { fn mounted(&mut self) -> ShouldRender { if let Some(input) = self.refs[self.focus_index].try_into::() { - input.focus(); + #[cfg_attr(feature = "std_web", allow(unused_variables))] + let result = input.focus(); + #[cfg(feature = "web_sys")] + result.unwrap(); } false } @@ -41,7 +46,10 @@ impl Component for Model { Msg::HoverIndex(index) => self.focus_index = index, } if let Some(input) = self.refs[self.focus_index].try_into::() { - input.focus(); + #[cfg_attr(feature = "std_web", allow(unused_variables))] + let result = input.focus(); + #[cfg(feature = "web_sys")] + result.unwrap(); } true } diff --git a/examples/npm_and_rest/Cargo.toml b/examples/npm_and_rest/Cargo.toml index 146b3b7a753..4caac1b6e6e 100644 --- a/examples/npm_and_rest/Cargo.toml +++ b/examples/npm_and_rest/Cargo.toml @@ -6,7 +6,14 @@ edition = "2018" [dependencies] anyhow = "1" +js-sys = { version = "0.3", optional = true } serde = "1" serde_derive = "1" -stdweb = "0.4.20" +stdweb = { version = "0.4.20", optional = true } +wasm-bindgen = { version = "0.2", optional = true } +web-sys = { version = "0.3", optional = true, features = ["console"] } yew = { path = "../.." } + +[features] +std_web = ["stdweb", "yew/std_web"] +web_sys = ["js-sys", "wasm-bindgen", "web-sys", "yew/web_sys"] diff --git a/examples/npm_and_rest/src/ccxt.rs b/examples/npm_and_rest/src/ccxt.rs index b19d9d77190..238d91a44f7 100644 --- a/examples/npm_and_rest/src/ccxt.rs +++ b/examples/npm_and_rest/src/ccxt.rs @@ -1,25 +1,57 @@ -use stdweb::unstable::TryInto; -use stdweb::Value; +#[cfg(feature = "std_web")] +use stdweb::{unstable::TryInto, Value}; +#[cfg(feature = "web_sys")] +use ::{ + js_sys::{Array, Reflect}, + wasm_bindgen::{prelude::wasm_bindgen, JsValue}, + web_sys::console, +}; #[derive(Default)] -pub struct CcxtService(Option); +pub struct CcxtService( + #[cfg(feature = "std_web")] Option, + #[cfg(feature = "web_sys")] Option<&'static JsValue>, +); + +#[cfg(feature = "web_sys")] +#[wasm_bindgen] +extern "C" { + static ccxt: JsValue; +} impl CcxtService { pub fn new() -> Self { + #[cfg(feature = "std_web")] let lib = js! { return ccxt; }; + #[cfg(feature = "web_sys")] + let lib: &JsValue = &ccxt; CcxtService(Some(lib)) } pub fn exchanges(&mut self) -> Vec { let lib = self.0.as_ref().expect("ccxt library object lost"); + #[cfg(feature = "std_web")] let v: Value = js! { var ccxt = @{lib}; console.log(ccxt.exchanges); return ccxt.exchanges; }; + #[cfg(feature = "web_sys")] + let v = { + let exchanges = Reflect::get(lib, &JsValue::from_str("exchanges")).unwrap(); + console::log_1(&exchanges); + exchanges + }; + #[cfg(feature = "std_web")] let v: Vec = v.try_into().expect("can't extract exchanges"); + #[cfg(feature = "web_sys")] + let v: Vec = Array::from(&v) + .to_vec() + .into_iter() + .map(|v| v.as_string().expect("can't extract exchanges")) + .collect(); v } } diff --git a/examples/npm_and_rest/src/lib.rs b/examples/npm_and_rest/src/lib.rs index 27d646ae315..9135f03142b 100644 --- a/examples/npm_and_rest/src/lib.rs +++ b/examples/npm_and_rest/src/lib.rs @@ -1,5 +1,6 @@ #![recursion_limit = "128"] +#[cfg(feature = "std_web")] #[macro_use] extern crate stdweb; diff --git a/examples/showcase/Cargo.toml b/examples/showcase/Cargo.toml index b9acad62070..0019cfda866 100644 --- a/examples/showcase/Cargo.toml +++ b/examples/showcase/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] log = "0.4" -web_logger = "0.1" +web_logger = "0.2" strum = "0.13" strum_macros = "0.13" yew = { path = "../.." } @@ -25,3 +25,41 @@ textarea = { path = "../textarea" } timer = { path = "../timer" } todomvc = { path = "../todomvc" } two_apps = { path = "../two_apps" } + +[features] +std_web = [ + "yew/std_web", + "counter/std_web", + "crm/std_web", + "custom_components/std_web", + "dashboard/std_web", + "node_refs/std_web", + "fragments/std_web", + "game_of_life/std_web", + "inner_html/std_web", + "large_table/std_web", + "mount_point/std_web", + "npm_and_rest/std_web", + "textarea/std_web", + "timer/std_web", + "todomvc/std_web", + "two_apps/std_web", +] +web_sys = [ + "yew/web_sys", + "counter/web_sys", + "crm/web_sys", + "custom_components/web_sys", + "dashboard/web_sys", + "node_refs/web_sys", + "fragments/web_sys", + "game_of_life/web_sys", + "inner_html/web_sys", + "large_table/web_sys", + "mount_point/web_sys", + "npm_and_rest/web_sys", + "textarea/web_sys", + "timer/web_sys", + "todomvc/web_sys", + "two_apps/web_sys", +] diff --git a/examples/static/.gitignore b/examples/static/.gitignore new file mode 100644 index 00000000000..7ad566ec26a --- /dev/null +++ b/examples/static/.gitignore @@ -0,0 +1,3 @@ +*.wasm +*.js +snippets/ diff --git a/examples/static/index.html b/examples/static/index.html new file mode 100644 index 00000000000..e1925eb8819 --- /dev/null +++ b/examples/static/index.html @@ -0,0 +1,12 @@ + + + + + Yew example + + + + diff --git a/examples/textarea/Cargo.toml b/examples/textarea/Cargo.toml index 2f892e7bed5..00e96d6494a 100644 --- a/examples/textarea/Cargo.toml +++ b/examples/textarea/Cargo.toml @@ -6,3 +6,7 @@ edition = "2018" [dependencies] yew = { path = "../.." } + +[features] +std_web = ["yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/timer/Cargo.toml b/examples/timer/Cargo.toml index 8d1e74d3df2..ca417b914c5 100644 --- a/examples/timer/Cargo.toml +++ b/examples/timer/Cargo.toml @@ -6,3 +6,7 @@ edition = "2018" [dependencies] yew = { path = "../.." } + +[features] +std_web = ["yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/todomvc/Cargo.toml b/examples/todomvc/Cargo.toml index 9b71961e468..6921fe9dbb4 100644 --- a/examples/todomvc/Cargo.toml +++ b/examples/todomvc/Cargo.toml @@ -10,3 +10,7 @@ strum_macros = "0.13" serde = "1" serde_derive = "1" yew = { path = "../.." } + +[features] +std_web = ["yew/std_web"] +web_sys = ["yew/web_sys"] diff --git a/examples/todomvc/src/lib.rs b/examples/todomvc/src/lib.rs index 71113feef31..b1d3f53dbce 100644 --- a/examples/todomvc/src/lib.rs +++ b/examples/todomvc/src/lib.rs @@ -3,10 +3,13 @@ use serde_derive::{Deserialize, Serialize}; use strum::IntoEnumIterator; use strum_macros::{EnumIter, ToString}; -use yew::events::IKeyboardEvent; +#[cfg(feature = "web_sys")] +use yew::events::KeyboardEvent; use yew::format::Json; use yew::services::storage::{Area, StorageService}; -use yew::{html, Component, ComponentLink, Href, Html, InputData, KeyPressEvent, ShouldRender}; +#[cfg(feature = "std_web")] +use yew::{events::IKeyboardEvent, KeyPressEvent}; +use yew::{html, Component, ComponentLink, Href, Html, InputData, ShouldRender}; const KEY: &'static str = "yew.todomvc.self"; @@ -184,7 +187,10 @@ impl Model { placeholder="What needs to be done?" value=&self.state.value oninput=self.link.callback(|e: InputData| Msg::Update(e.value)) - onkeypress=self.link.callback(|e: KeyPressEvent| { + onkeypress=self.link.callback(| + #[cfg(feature = "std_web")] e: KeyPressEvent, + #[cfg(feature = "web_sys")] e: KeyboardEvent + | { if e.key() == "Enter" { Msg::Add } else { Msg::Nope } }) /> /* Or multiline: @@ -227,7 +233,10 @@ impl Model { value=&entry.description oninput=self.link.callback(|e: InputData| Msg::UpdateEdit(e.value)) onblur=self.link.callback(move |_| Msg::Edit(idx)) - onkeypress=self.link.callback(move |e: KeyPressEvent| { + onkeypress=self.link.callback(move | + #[cfg(feature = "std_web")] e: KeyPressEvent, + #[cfg(feature = "web_sys")] e: KeyboardEvent + | { if e.key() == "Enter" { Msg::Edit(idx) } else { Msg::Nope } }) /> } diff --git a/examples/two_apps/Cargo.toml b/examples/two_apps/Cargo.toml index d080b683938..2d04113470c 100644 --- a/examples/two_apps/Cargo.toml +++ b/examples/two_apps/Cargo.toml @@ -5,5 +5,10 @@ authors = ["Denis Kolodin "] edition = "2018" [dependencies] -stdweb = "0.4.20" +stdweb = { version = "0.4.20", optional = true } +web-sys = { version = "0.3", optional = true, features = ["Document", "Window"] } yew = { path = "../.." } + +[features] +std_web = ["stdweb", "yew/std_web"] +web_sys = ["web-sys", "yew/web_sys"] diff --git a/examples/two_apps/src/main.rs b/examples/two_apps/src/main.rs index c306990c97b..e70814bc4e0 100644 --- a/examples/two_apps/src/main.rs +++ b/examples/two_apps/src/main.rs @@ -1,10 +1,15 @@ +#[cfg(feature = "std_web")] use stdweb::web::{document, IParentNode}; use two_apps::{Model, Msg}; use yew::html::Scope; use yew::App; fn mount_app(selector: &'static str, app: App) -> Scope { - let element = document().query_selector(selector).unwrap().unwrap(); + #[cfg(feature = "std_web")] + let document = document(); + #[cfg(feature = "web_sys")] + let document = web_sys::window().unwrap().document().unwrap(); + let element = document.query_selector(selector).unwrap().unwrap(); app.mount(element) } @@ -12,7 +17,9 @@ fn main() { yew::initialize(); let first_app = App::new(); let second_app = App::new(); + #[cfg_attr(feature = "web_sys", allow(unused_mut))] let mut to_first = mount_app(".first-app", first_app); + #[cfg_attr(feature = "web_sys", allow(unused_mut))] let mut to_second = mount_app(".second-app", second_app); to_first.send_message(Msg::SetScope(to_second.clone())); to_second.send_message(Msg::SetScope(to_first.clone())); diff --git a/tests/vtag_test.rs b/tests/vtag_test.rs index 8b5daf35ce2..96c75d4d30b 100644 --- a/tests/vtag_test.rs +++ b/tests/vtag_test.rs @@ -1,5 +1,4 @@ #![recursion_limit = "128"] - #[cfg(feature = "std_web")] use stdweb::web::{document, IElement}; #[cfg(feature = "wasm_test")] From fcf3505f0614796adcc615409907f8268122479c Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 9 Jan 2020 15:56:54 +0100 Subject: [PATCH 02/12] Update `StorageService` usage. --- examples/crm/src/lib.rs | 2 +- examples/todomvc/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/crm/src/lib.rs b/examples/crm/src/lib.rs index 227feef5bbe..4a9fafe4ea8 100644 --- a/examples/crm/src/lib.rs +++ b/examples/crm/src/lib.rs @@ -64,7 +64,7 @@ impl Component for Model { type Properties = (); fn create(_: Self::Properties, link: ComponentLink) -> Self { - let storage = StorageService::new(Area::Local); + let storage = StorageService::new(Area::Local).expect("storage was disabled by the user"); let Json(database) = storage.restore(KEY); let database = database.unwrap_or_else(|_| Database { clients: Vec::new(), diff --git a/examples/todomvc/src/lib.rs b/examples/todomvc/src/lib.rs index b1d3f53dbce..6db115f978c 100644 --- a/examples/todomvc/src/lib.rs +++ b/examples/todomvc/src/lib.rs @@ -53,7 +53,7 @@ impl Component for Model { type Properties = (); fn create(_: Self::Properties, link: ComponentLink) -> Self { - let storage = StorageService::new(Area::Local); + let storage = StorageService::new(Area::Local).expect("storage was disabled by the user"); let entries = { if let Json(Ok(restored_model)) = storage.restore(KEY) { restored_model From 827584e1c5a774ca4585813e3a658c30c16e08b1 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 12 Jan 2020 15:38:39 +0100 Subject: [PATCH 03/12] Split `stdweb` and `web-sys` examples. --- examples/Cargo.toml | 30 +- examples/counter/Cargo.toml | 14 - examples/counter/src/main.rs | 3 - examples/file_upload/Cargo.toml | 13 - examples/file_upload/src/main.rs | 3 - examples/futures/Cargo.toml | 2 +- examples/game_of_life/Cargo.toml | 2 +- examples/inner_html/Cargo.toml | 14 - examples/mount_point/src/main.rs | 65 ---- examples/multi_thread/static/bin | 1 - examples/node_refs/Cargo.toml | 14 - examples/node_refs/src/main.rs | 3 - examples/npm_and_rest/Cargo.toml | 19 - examples/npm_and_rest/src/ccxt.rs | 57 --- examples/npm_and_rest/src/main.rs | 3 - examples/showcase/Cargo.toml | 50 ++- examples/showcase/src/main.rs | 20 + examples/std_web/counter/Cargo.toml | 9 + examples/{ => std_web}/counter/src/lib.rs | 12 +- examples/std_web/counter/src/main.rs | 3 + examples/std_web/file_upload/Cargo.toml | 8 + examples/std_web/file_upload/src/lib.rs | 99 +++++ examples/std_web/file_upload/src/main.rs | 3 + examples/std_web/inner_html/Cargo.toml | 12 + examples/std_web/inner_html/src/lib.rs | 49 +++ examples/{ => std_web}/inner_html/src/main.rs | 0 examples/std_web/js_callback/Cargo.toml | 12 + examples/std_web/js_callback/README.md | 8 + examples/std_web/js_callback/src/lib.rs | 100 +++++ examples/std_web/js_callback/src/main.rs | 3 + .../js_callback/static/get-payload-script.js | 9 + .../std_web/js_callback/static/index.html | 11 + examples/std_web/mount_point/Cargo.toml | 12 + examples/{ => std_web}/mount_point/src/lib.rs | 0 examples/std_web/mount_point/src/main.rs | 32 ++ .../{ => std_web}/multi_thread/Cargo.toml | 11 +- examples/std_web/multi_thread/README.md | 7 + examples/{ => std_web}/multi_thread/Web.toml | 0 examples/std_web/multi_thread/src/bin/main.rs | 4 + .../multi_thread/src/bin/native_worker.rs | 8 + .../{ => std_web}/multi_thread/src/context.rs | 0 .../{ => std_web}/multi_thread/src/job.rs | 0 .../{ => std_web}/multi_thread/src/lib.rs | 0 .../multi_thread/src/native_worker.rs | 0 examples/std_web/multi_thread/static/bin | 1 + .../multi_thread/static/index.html | 0 examples/std_web/node_refs/Cargo.toml | 9 + examples/{ => std_web}/node_refs/src/input.rs | 0 examples/std_web/node_refs/src/lib.rs | 75 ++++ examples/std_web/node_refs/src/main.rs | 3 + examples/std_web/npm_and_rest/Cargo.toml | 15 + examples/std_web/npm_and_rest/src/ccxt.rs | 25 ++ .../npm_and_rest/src/gravatar.rs | 0 .../{ => std_web}/npm_and_rest/src/lib.rs | 1 - examples/std_web/npm_and_rest/src/main.rs | 3 + .../npm_and_rest/static/index.html | 0 examples/{ => std_web}/todomvc/Cargo.toml | 8 +- examples/{ => std_web}/todomvc/README.md | 0 examples/std_web/todomvc/src/lib.rs | 358 ++++++++++++++++++ examples/std_web/todomvc/src/main.rs | 3 + .../{ => std_web}/todomvc/static/index.html | 0 examples/std_web/two_apps/Cargo.toml | 9 + examples/{ => std_web}/two_apps/src/lib.rs | 0 examples/std_web/two_apps/src/main.rs | 21 + .../{ => std_web}/two_apps/static/index.html | 0 examples/todomvc/src/main.rs | 3 - examples/two_apps/Cargo.toml | 14 - examples/two_apps/src/main.rs | 27 -- examples/web_sys/counter/Cargo.toml | 9 + examples/web_sys/counter/src/lib.rs | 70 ++++ examples/web_sys/counter/src/main.rs | 3 + examples/web_sys/file_upload/Cargo.toml | 9 + examples/{ => web_sys}/file_upload/src/lib.rs | 1 - examples/web_sys/file_upload/src/main.rs | 3 + examples/web_sys/inner_html/Cargo.toml | 9 + examples/{ => web_sys}/inner_html/src/lib.rs | 17 - examples/web_sys/inner_html/src/main.rs | 3 + examples/web_sys/js_callback/Cargo.toml | 11 + examples/web_sys/js_callback/README.md | 8 + examples/web_sys/js_callback/src/lib.rs | 98 +++++ examples/web_sys/js_callback/src/main.rs | 3 + .../js_callback/static/get-payload-script.js | 9 + .../web_sys/js_callback/static/index.html | 11 + examples/{ => web_sys}/mount_point/Cargo.toml | 12 +- examples/web_sys/mount_point/src/lib.rs | 42 ++ examples/web_sys/mount_point/src/main.rs | 31 ++ examples/web_sys/multi_thread/Cargo.toml | 20 + examples/{ => web_sys}/multi_thread/README.md | 6 - examples/web_sys/multi_thread/Web.toml | 1 + .../multi_thread/src/bin/main.rs | 0 .../multi_thread/src/bin/native_worker.rs | 0 examples/web_sys/multi_thread/src/context.rs | 66 ++++ examples/web_sys/multi_thread/src/job.rs | 66 ++++ examples/web_sys/multi_thread/src/lib.rs | 82 ++++ .../web_sys/multi_thread/src/native_worker.rs | 70 ++++ examples/web_sys/multi_thread/static/bin | 1 + .../web_sys/multi_thread/static/index.html | 11 + examples/web_sys/node_refs/Cargo.toml | 9 + examples/web_sys/node_refs/src/input.rs | 43 +++ examples/{ => web_sys}/node_refs/src/lib.rs | 13 +- examples/web_sys/node_refs/src/main.rs | 3 + examples/web_sys/npm_and_rest/Cargo.toml | 14 + examples/web_sys/npm_and_rest/src/ccxt.rs | 34 ++ examples/web_sys/npm_and_rest/src/gravatar.rs | 51 +++ examples/web_sys/npm_and_rest/src/lib.rs | 83 ++++ examples/web_sys/npm_and_rest/src/main.rs | 3 + .../web_sys/npm_and_rest/static/index.html | 12 + examples/web_sys/todomvc/Cargo.toml | 12 + examples/web_sys/todomvc/README.md | 6 + examples/{ => web_sys}/todomvc/src/lib.rs | 13 +- examples/web_sys/todomvc/src/main.rs | 3 + examples/web_sys/todomvc/static/index.html | 13 + examples/web_sys/two_apps/Cargo.toml | 9 + examples/web_sys/two_apps/src/lib.rs | 83 ++++ examples/web_sys/two_apps/src/main.rs | 20 + examples/web_sys/two_apps/static/index.html | 14 + 116 files changed, 2044 insertions(+), 366 deletions(-) delete mode 100644 examples/counter/Cargo.toml delete mode 100644 examples/counter/src/main.rs delete mode 100644 examples/file_upload/Cargo.toml delete mode 100644 examples/file_upload/src/main.rs delete mode 100644 examples/inner_html/Cargo.toml delete mode 100644 examples/mount_point/src/main.rs delete mode 120000 examples/multi_thread/static/bin delete mode 100644 examples/node_refs/Cargo.toml delete mode 100644 examples/node_refs/src/main.rs delete mode 100644 examples/npm_and_rest/Cargo.toml delete mode 100644 examples/npm_and_rest/src/ccxt.rs delete mode 100644 examples/npm_and_rest/src/main.rs create mode 100644 examples/std_web/counter/Cargo.toml rename examples/{ => std_web}/counter/src/lib.rs (83%) create mode 100644 examples/std_web/counter/src/main.rs create mode 100644 examples/std_web/file_upload/Cargo.toml create mode 100644 examples/std_web/file_upload/src/lib.rs create mode 100644 examples/std_web/file_upload/src/main.rs create mode 100644 examples/std_web/inner_html/Cargo.toml create mode 100644 examples/std_web/inner_html/src/lib.rs rename examples/{ => std_web}/inner_html/src/main.rs (100%) create mode 100644 examples/std_web/js_callback/Cargo.toml create mode 100644 examples/std_web/js_callback/README.md create mode 100644 examples/std_web/js_callback/src/lib.rs create mode 100644 examples/std_web/js_callback/src/main.rs create mode 100644 examples/std_web/js_callback/static/get-payload-script.js create mode 100644 examples/std_web/js_callback/static/index.html create mode 100644 examples/std_web/mount_point/Cargo.toml rename examples/{ => std_web}/mount_point/src/lib.rs (100%) create mode 100644 examples/std_web/mount_point/src/main.rs rename examples/{ => std_web}/multi_thread/Cargo.toml (53%) create mode 100644 examples/std_web/multi_thread/README.md rename examples/{ => std_web}/multi_thread/Web.toml (100%) create mode 100644 examples/std_web/multi_thread/src/bin/main.rs create mode 100644 examples/std_web/multi_thread/src/bin/native_worker.rs rename examples/{ => std_web}/multi_thread/src/context.rs (100%) rename examples/{ => std_web}/multi_thread/src/job.rs (100%) rename examples/{ => std_web}/multi_thread/src/lib.rs (100%) rename examples/{ => std_web}/multi_thread/src/native_worker.rs (100%) create mode 100644 examples/std_web/multi_thread/static/bin rename examples/{ => std_web}/multi_thread/static/index.html (100%) create mode 100644 examples/std_web/node_refs/Cargo.toml rename examples/{ => std_web}/node_refs/src/input.rs (100%) create mode 100644 examples/std_web/node_refs/src/lib.rs create mode 100644 examples/std_web/node_refs/src/main.rs create mode 100644 examples/std_web/npm_and_rest/Cargo.toml create mode 100644 examples/std_web/npm_and_rest/src/ccxt.rs rename examples/{ => std_web}/npm_and_rest/src/gravatar.rs (100%) rename examples/{ => std_web}/npm_and_rest/src/lib.rs (98%) create mode 100644 examples/std_web/npm_and_rest/src/main.rs rename examples/{ => std_web}/npm_and_rest/static/index.html (100%) rename examples/{ => std_web}/todomvc/Cargo.toml (63%) rename examples/{ => std_web}/todomvc/README.md (100%) create mode 100644 examples/std_web/todomvc/src/lib.rs create mode 100644 examples/std_web/todomvc/src/main.rs rename examples/{ => std_web}/todomvc/static/index.html (100%) create mode 100644 examples/std_web/two_apps/Cargo.toml rename examples/{ => std_web}/two_apps/src/lib.rs (100%) create mode 100644 examples/std_web/two_apps/src/main.rs rename examples/{ => std_web}/two_apps/static/index.html (100%) delete mode 100644 examples/todomvc/src/main.rs delete mode 100644 examples/two_apps/Cargo.toml delete mode 100644 examples/two_apps/src/main.rs create mode 100644 examples/web_sys/counter/Cargo.toml create mode 100644 examples/web_sys/counter/src/lib.rs create mode 100644 examples/web_sys/counter/src/main.rs create mode 100644 examples/web_sys/file_upload/Cargo.toml rename examples/{ => web_sys}/file_upload/src/lib.rs (98%) create mode 100644 examples/web_sys/file_upload/src/main.rs create mode 100644 examples/web_sys/inner_html/Cargo.toml rename examples/{ => web_sys}/inner_html/src/lib.rs (68%) create mode 100644 examples/web_sys/inner_html/src/main.rs create mode 100644 examples/web_sys/js_callback/Cargo.toml create mode 100644 examples/web_sys/js_callback/README.md create mode 100644 examples/web_sys/js_callback/src/lib.rs create mode 100644 examples/web_sys/js_callback/src/main.rs create mode 100644 examples/web_sys/js_callback/static/get-payload-script.js create mode 100644 examples/web_sys/js_callback/static/index.html rename examples/{ => web_sys}/mount_point/Cargo.toml (51%) create mode 100644 examples/web_sys/mount_point/src/lib.rs create mode 100644 examples/web_sys/mount_point/src/main.rs create mode 100644 examples/web_sys/multi_thread/Cargo.toml rename examples/{ => web_sys}/multi_thread/README.md (60%) create mode 100644 examples/web_sys/multi_thread/Web.toml rename examples/{ => web_sys}/multi_thread/src/bin/main.rs (100%) rename examples/{ => web_sys}/multi_thread/src/bin/native_worker.rs (100%) create mode 100644 examples/web_sys/multi_thread/src/context.rs create mode 100644 examples/web_sys/multi_thread/src/job.rs create mode 100644 examples/web_sys/multi_thread/src/lib.rs create mode 100644 examples/web_sys/multi_thread/src/native_worker.rs create mode 100644 examples/web_sys/multi_thread/static/bin create mode 100644 examples/web_sys/multi_thread/static/index.html create mode 100644 examples/web_sys/node_refs/Cargo.toml create mode 100644 examples/web_sys/node_refs/src/input.rs rename examples/{ => web_sys}/node_refs/src/lib.rs (81%) create mode 100644 examples/web_sys/node_refs/src/main.rs create mode 100644 examples/web_sys/npm_and_rest/Cargo.toml create mode 100644 examples/web_sys/npm_and_rest/src/ccxt.rs create mode 100644 examples/web_sys/npm_and_rest/src/gravatar.rs create mode 100644 examples/web_sys/npm_and_rest/src/lib.rs create mode 100644 examples/web_sys/npm_and_rest/src/main.rs create mode 100644 examples/web_sys/npm_and_rest/static/index.html create mode 100644 examples/web_sys/todomvc/Cargo.toml create mode 100644 examples/web_sys/todomvc/README.md rename examples/{ => web_sys}/todomvc/src/lib.rs (95%) create mode 100644 examples/web_sys/todomvc/src/main.rs create mode 100644 examples/web_sys/todomvc/static/index.html create mode 100644 examples/web_sys/two_apps/Cargo.toml create mode 100644 examples/web_sys/two_apps/src/lib.rs create mode 100644 examples/web_sys/two_apps/src/main.rs create mode 100644 examples/web_sys/two_apps/static/index.html diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 2492b0e90b8..320738eecec 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -1,26 +1,36 @@ [workspace] members = [ - "counter", "crm", "custom_components", "dashboard", - "node_refs", - "file_upload", "fragments", "futures", "game_of_life", - "inner_html", - "js_callback", "large_table", "minimal", - "mount_point", - "multi_thread", "nested_list", - "npm_and_rest", "server", "showcase", "textarea", "timer", - "todomvc", - "two_apps", + "std_web/counter", + "std_web/file_upload", + "std_web/inner_html", + "std_web/js_callback", + "std_web/mount_point", + "std_web/multi_thread", + "std_web/node_refs", + "std_web/npm_and_rest", + "std_web/todomvc", + "std_web/two_apps", + "web_sys/counter", + "web_sys/file_upload", + "web_sys/inner_html", + "web_sys/js_callback", + "web_sys/mount_point", + "web_sys/multi_thread", + "web_sys/node_refs", + "web_sys/npm_and_rest", + "web_sys/todomvc", + "web_sys/two_apps", ] diff --git a/examples/counter/Cargo.toml b/examples/counter/Cargo.toml deleted file mode 100644 index a4991e81139..00000000000 --- a/examples/counter/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "counter" -version = "0.1.1" -authors = ["Denis Kolodin "] -edition = "2018" - -[dependencies] -js-sys = { version = "0.3", optional = true } -stdweb = { version = "0.4.20", optional = true } -yew = { path = "../.." } - -[features] -std_web = ["stdweb", "yew/std_web"] -web_sys = ["js-sys", "yew/web_sys"] diff --git a/examples/counter/src/main.rs b/examples/counter/src/main.rs deleted file mode 100644 index fa550b8b389..00000000000 --- a/examples/counter/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - yew::start_app::(); -} diff --git a/examples/file_upload/Cargo.toml b/examples/file_upload/Cargo.toml deleted file mode 100644 index 95789571280..00000000000 --- a/examples/file_upload/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "file_upload" -version = "0.1.0" -authors = ["Denis Kolodin "] -edition = "2018" - -[dependencies] -js-sys = { version = "0.3", optional = true } -yew = { path = "../.." } - -[features] -std_web = ["yew/std_web"] -web_sys = ["js-sys", "yew/web_sys"] diff --git a/examples/file_upload/src/main.rs b/examples/file_upload/src/main.rs deleted file mode 100644 index 405b924110c..00000000000 --- a/examples/file_upload/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - yew::start_app::(); -} diff --git a/examples/futures/Cargo.toml b/examples/futures/Cargo.toml index 2901d56107f..dfb5f10d24d 100644 --- a/examples/futures/Cargo.toml +++ b/examples/futures/Cargo.toml @@ -15,7 +15,7 @@ yew = { path = "../.." } wasm-bindgen-futures = "0.4.3" [dependencies.web-sys] -version = "0.3.33" +version = "0.3.35" features = [ 'Headers', 'Request', diff --git a/examples/game_of_life/Cargo.toml b/examples/game_of_life/Cargo.toml index 691193aa23f..8c82e077545 100644 --- a/examples/game_of_life/Cargo.toml +++ b/examples/game_of_life/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Diego Cardoso ", edition = "2018" [dependencies] -rand = { version = "0.6.5" } +rand = { version = "0.6.5", features = ["wasm-bindgen"] } log = "0.4" web_logger = "0.2" yew = { path = "../.." } diff --git a/examples/inner_html/Cargo.toml b/examples/inner_html/Cargo.toml deleted file mode 100644 index a90d3ec32fb..00000000000 --- a/examples/inner_html/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "inner_html" -version = "0.1.0" -authors = ["Garrett Berg "] -edition = "2018" - -[dependencies] -stdweb = { version = "0.4.20", optional = true } -web-sys = { version = "0.3", optional = true, features = ["console", "Document", "Element", "Node", "Window"] } -yew = { path = "../.." } - -[features] -std_web = ["stdweb", "yew/std_web"] -web_sys = ["web-sys", "yew/web_sys"] diff --git a/examples/mount_point/src/main.rs b/examples/mount_point/src/main.rs deleted file mode 100644 index 200d2b17bda..00000000000 --- a/examples/mount_point/src/main.rs +++ /dev/null @@ -1,65 +0,0 @@ -#[cfg(feature = "std_web")] -#[macro_use] -extern crate stdweb; - -use mount_point::Model; -#[cfg(feature = "std_web")] -use stdweb::web::{document, IElement, INode, IParentNode}; -use yew::App; -#[cfg(feature = "web_sys")] -use ::{ - wasm_bindgen::JsValue, - web_sys::{CanvasRenderingContext2d, HtmlCanvasElement}, -}; - -fn main() { - yew::initialize(); - #[cfg(feature = "std_web")] - let document = document(); - #[cfg(feature = "web_sys")] - let document = web_sys::window().unwrap().document().unwrap(); - let body = document.query_selector("body").unwrap().unwrap(); - - // This canvas won't be overwritten by yew! - let canvas = document.create_element("canvas").unwrap(); - #[cfg_attr(feature = "std_web", allow(unused_variables))] - let result = body.append_child(&canvas); - #[cfg(feature = "web_sys")] - result.unwrap(); - - #[cfg(feature = "std_web")] - js! { - const canvas = document.querySelector("canvas"); - canvas.width = 100; - canvas.height = 100; - const ctx = canvas.getContext("2d"); - ctx.fillStyle = "green"; - ctx.fillRect(10, 10, 50, 50); - }; - #[cfg(feature = "web_sys")] - { - let canvas = HtmlCanvasElement::from(JsValue::from(canvas)); - canvas.set_width(100); - canvas.set_height(100); - let ctx = CanvasRenderingContext2d::from(JsValue::from( - canvas.get_context("2d").unwrap().unwrap(), - )); - ctx.set_fill_style(&JsValue::from_str("green")); - ctx.fill_rect(10., 10., 50., 50.); - } - - let mount_class = "mount-point"; - let mount_point = document.create_element("div").unwrap(); - let class_list = mount_point.class_list(); - #[cfg(feature = "std_web")] - class_list.add(mount_class).unwrap(); - #[cfg(feature = "web_sys")] - class_list.add_1(mount_class).unwrap(); - #[cfg_attr(feature = "std_web", allow(unused_variables))] - let result = body.append_child(&mount_point); - #[cfg(feature = "web_sys")] - result.unwrap(); - - App::::new().mount(mount_point); - yew::run_loop(); -} diff --git a/examples/multi_thread/static/bin b/examples/multi_thread/static/bin deleted file mode 120000 index 4a2105e009b..00000000000 --- a/examples/multi_thread/static/bin +++ /dev/null @@ -1 +0,0 @@ -../../../target/wasm32-unknown-unknown/release \ No newline at end of file diff --git a/examples/node_refs/Cargo.toml b/examples/node_refs/Cargo.toml deleted file mode 100644 index 4c5bc794722..00000000000 --- a/examples/node_refs/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "node_refs" -version = "0.1.0" -authors = ["Justin Starry "] -edition = "2018" - -[dependencies] -yew = { path = "../.." } -stdweb = { version = "0.4.20", optional = true } -web-sys = { version = "0.3", optional = true, features = ["HtmlElement", "HtmlInputElement", "Node"] } - -[features] -std_web = ["stdweb", "yew/std_web"] -web_sys = ["web-sys", "yew/web_sys"] diff --git a/examples/node_refs/src/main.rs b/examples/node_refs/src/main.rs deleted file mode 100644 index 63360e2c5d9..00000000000 --- a/examples/node_refs/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - yew::start_app::(); -} diff --git a/examples/npm_and_rest/Cargo.toml b/examples/npm_and_rest/Cargo.toml deleted file mode 100644 index 4caac1b6e6e..00000000000 --- a/examples/npm_and_rest/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "npm_and_rest" -version = "0.1.0" -authors = ["Denis Kolodin "] -edition = "2018" - -[dependencies] -anyhow = "1" -js-sys = { version = "0.3", optional = true } -serde = "1" -serde_derive = "1" -stdweb = { version = "0.4.20", optional = true } -wasm-bindgen = { version = "0.2", optional = true } -web-sys = { version = "0.3", optional = true, features = ["console"] } -yew = { path = "../.." } - -[features] -std_web = ["stdweb", "yew/std_web"] -web_sys = ["js-sys", "wasm-bindgen", "web-sys", "yew/web_sys"] diff --git a/examples/npm_and_rest/src/ccxt.rs b/examples/npm_and_rest/src/ccxt.rs deleted file mode 100644 index 238d91a44f7..00000000000 --- a/examples/npm_and_rest/src/ccxt.rs +++ /dev/null @@ -1,57 +0,0 @@ -#[cfg(feature = "std_web")] -use stdweb::{unstable::TryInto, Value}; -#[cfg(feature = "web_sys")] -use ::{ - js_sys::{Array, Reflect}, - wasm_bindgen::{prelude::wasm_bindgen, JsValue}, - web_sys::console, -}; - -#[derive(Default)] -pub struct CcxtService( - #[cfg(feature = "std_web")] Option, - #[cfg(feature = "web_sys")] Option<&'static JsValue>, -); - -#[cfg(feature = "web_sys")] -#[wasm_bindgen] -extern "C" { - static ccxt: JsValue; -} - -impl CcxtService { - pub fn new() -> Self { - #[cfg(feature = "std_web")] - let lib = js! { - return ccxt; - }; - #[cfg(feature = "web_sys")] - let lib: &JsValue = &ccxt; - CcxtService(Some(lib)) - } - - pub fn exchanges(&mut self) -> Vec { - let lib = self.0.as_ref().expect("ccxt library object lost"); - #[cfg(feature = "std_web")] - let v: Value = js! { - var ccxt = @{lib}; - console.log(ccxt.exchanges); - return ccxt.exchanges; - }; - #[cfg(feature = "web_sys")] - let v = { - let exchanges = Reflect::get(lib, &JsValue::from_str("exchanges")).unwrap(); - console::log_1(&exchanges); - exchanges - }; - #[cfg(feature = "std_web")] - let v: Vec = v.try_into().expect("can't extract exchanges"); - #[cfg(feature = "web_sys")] - let v: Vec = Array::from(&v) - .to_vec() - .into_iter() - .map(|v| v.as_string().expect("can't extract exchanges")) - .collect(); - v - } -} diff --git a/examples/npm_and_rest/src/main.rs b/examples/npm_and_rest/src/main.rs deleted file mode 100644 index 8e3af40a3a9..00000000000 --- a/examples/npm_and_rest/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - yew::start_app::(); -} diff --git a/examples/showcase/Cargo.toml b/examples/showcase/Cargo.toml index 0019cfda866..eb6c311f2b4 100644 --- a/examples/showcase/Cargo.toml +++ b/examples/showcase/Cargo.toml @@ -5,61 +5,69 @@ authors = ["Denis Kolodin ", "Limira"] edition = "2018" [dependencies] +cfg-if = "0.1" log = "0.4" web_logger = "0.2" strum = "0.13" strum_macros = "0.13" yew = { path = "../.." } -counter = { path = "../counter" } +counter_std_web = { path = "../std_web/counter", optional = true } +counter_web_sys = { path = "../web_sys/counter", optional = true } crm = { path = "../crm" } custom_components = { path = "../custom_components" } dashboard = { path = "../dashboard" } -node_refs = { path = "../node_refs" } +node_refs_std_web = { path = "../std_web/node_refs", optional = true } +node_refs_web_sys = { path = "../web_sys/node_refs", optional = true } fragments = { path = "../fragments" } game_of_life = { path = "../game_of_life" } -inner_html = { path = "../inner_html" } +inner_html_std_web = { path = "../std_web/inner_html", optional = true } +inner_html_web_sys = { path = "../web_sys/inner_html", optional = true } large_table = { path = "../large_table" } -mount_point = { path = "../mount_point" } -npm_and_rest = { path = "../npm_and_rest" } +mount_point_std_web = { path = "../std_web/mount_point", optional = true } +mount_point_web_sys = { path = "../web_sys/mount_point", optional = true } +npm_and_rest_std_web = { path = "../std_web/npm_and_rest", optional = true } +npm_and_rest_web_sys = { path = "../web_sys/npm_and_rest", optional = true } textarea = { path = "../textarea" } timer = { path = "../timer" } -todomvc = { path = "../todomvc" } -two_apps = { path = "../two_apps" } +todomvc_std_web = { path = "../std_web/todomvc", optional = true } +todomvc_web_sys = { path = "../web_sys/todomvc", optional = true } +two_apps_std_web = { path = "../std_web/two_apps", optional = true } +two_apps_web_sys = { path = "../web_sys/two_apps", optional = true } [features] std_web = [ "yew/std_web", - "counter/std_web", + "counter_std_web", "crm/std_web", "custom_components/std_web", "dashboard/std_web", - "node_refs/std_web", + "node_refs_std_web", "fragments/std_web", "game_of_life/std_web", - "inner_html/std_web", + "inner_html_std_web", "large_table/std_web", - "mount_point/std_web", - "npm_and_rest/std_web", + "mount_point_std_web", + "npm_and_rest_std_web", "textarea/std_web", "timer/std_web", - "todomvc/std_web", - "two_apps/std_web", + "todomvc_std_web", + "two_apps_std_web", ] web_sys = [ "yew/web_sys", - "counter/web_sys", + "counter_web_sys", "crm/web_sys", "custom_components/web_sys", "dashboard/web_sys", - "node_refs/web_sys", + "node_refs_web_sys", "fragments/web_sys", "game_of_life/web_sys", - "inner_html/web_sys", + "inner_html_web_sys", "large_table/web_sys", - "mount_point/web_sys", - "npm_and_rest/web_sys", + "mount_point_web_sys", + "npm_and_rest_web_sys", "textarea/web_sys", "timer/web_sys", - "todomvc/web_sys", - "two_apps/web_sys", + "todomvc_web_sys", + "two_apps_web_sys", ] diff --git a/examples/showcase/src/main.rs b/examples/showcase/src/main.rs index d2b0329fd7b..d4b31da07e0 100644 --- a/examples/showcase/src/main.rs +++ b/examples/showcase/src/main.rs @@ -1,5 +1,25 @@ #![recursion_limit = "128"] +cfg_if::cfg_if! { + if #[cfg(feature = "std_web")] { + use counter_std_web as counter; + use inner_html_std_web as inner_html; + use mount_point_std_web as mount_point; + use node_refs_std_web as node_refs; + use npm_and_rest_std_web as npm_and_rest; + use todomvc_std_web as todomvc; + use two_apps_std_web as two_apps; + } else if #[cfg(feature = "web_sys")] { + use counter_web_sys as counter; + use inner_html_web_sys as inner_html; + use mount_point_web_sys as mount_point; + use node_refs_web_sys as node_refs; + use npm_and_rest_web_sys as npm_and_rest; + use todomvc_web_sys as todomvc; + use two_apps_web_sys as two_apps; + } +} + use counter::Model as Counter; use crm::Model as Crm; use custom_components::Model as CustomComponents; diff --git a/examples/std_web/counter/Cargo.toml b/examples/std_web/counter/Cargo.toml new file mode 100644 index 00000000000..e98688967f8 --- /dev/null +++ b/examples/std_web/counter/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "counter_std_web" +version = "0.1.1" +authors = ["Denis Kolodin "] +edition = "2018" + +[dependencies] +stdweb = "0.4.20" +yew = { path = "../../..", features = ["std_web"] } diff --git a/examples/counter/src/lib.rs b/examples/std_web/counter/src/lib.rs similarity index 83% rename from examples/counter/src/lib.rs rename to examples/std_web/counter/src/lib.rs index bbb4551269f..430d9e6ad9e 100644 --- a/examples/counter/src/lib.rs +++ b/examples/std_web/counter/src/lib.rs @@ -1,8 +1,5 @@ -#![recursion_limit = "512"] +#![recursion_limit = "256"] -#[cfg(feature = "web_sys")] -use js_sys::Date; -#[cfg(feature = "std_web")] use stdweb::web::Date; use yew::services::ConsoleService; use yew::{html, Component, ComponentLink, Html, ShouldRender}; @@ -66,12 +63,7 @@ impl Component for Model {

{ self.value }

-

{ - #[cfg(feature = "std_web")] - { Date::new().to_string() } - #[cfg(feature = "web_sys")] - Date::new_0().to_string().as_string().unwrap() - }

+

{ Date::new().to_string() }

} } diff --git a/examples/std_web/counter/src/main.rs b/examples/std_web/counter/src/main.rs new file mode 100644 index 00000000000..e3193531fdf --- /dev/null +++ b/examples/std_web/counter/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/std_web/file_upload/Cargo.toml b/examples/std_web/file_upload/Cargo.toml new file mode 100644 index 00000000000..2a2c8bc7564 --- /dev/null +++ b/examples/std_web/file_upload/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "file_upload_std_web" +version = "0.1.0" +authors = ["Denis Kolodin "] +edition = "2018" + +[dependencies] +yew = { path = "../../..", features = ["std_web"] } diff --git a/examples/std_web/file_upload/src/lib.rs b/examples/std_web/file_upload/src/lib.rs new file mode 100644 index 00000000000..9f909331434 --- /dev/null +++ b/examples/std_web/file_upload/src/lib.rs @@ -0,0 +1,99 @@ +#![recursion_limit = "256"] + +use yew::services::reader::{File, FileChunk, FileData, ReaderService, ReaderTask}; +use yew::{html, ChangeData, Component, ComponentLink, Html, ShouldRender}; + +pub struct Model { + link: ComponentLink, + reader: ReaderService, + tasks: Vec, + files: Vec, + by_chunks: bool, +} + +type Chunks = bool; + +pub enum Msg { + Loaded(FileData), + Chunk(FileChunk), + Files(Vec, Chunks), + ToggleByChunks, +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + Model { + reader: ReaderService::new(), + link, + tasks: vec![], + files: vec![], + by_chunks: false, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::Loaded(file) => { + let info = format!("file: {:?}", file); + self.files.push(info); + } + Msg::Chunk(chunk) => { + let info = format!("chunk: {:?}", chunk); + self.files.push(info); + } + Msg::Files(files, chunks) => { + for file in files.into_iter() { + let task = { + if chunks { + let callback = self.link.callback(Msg::Chunk); + self.reader.read_file_by_chunks(file, callback, 10) + } else { + let callback = self.link.callback(Msg::Loaded); + self.reader.read_file(file, callback) + } + }; + self.tasks.push(task); + } + } + Msg::ToggleByChunks => { + self.by_chunks = !self.by_chunks; + } + } + true + } + + fn view(&self) -> Html { + let flag = self.by_chunks; + html! { +
+
+ +
+
+ + +
+
    + { for self.files.iter().map(|f| self.view_file(f)) } +
+
+ } + } +} + +impl Model { + fn view_file(&self, data: &str) -> Html { + html! { +
  • { data }
  • + } + } +} diff --git a/examples/std_web/file_upload/src/main.rs b/examples/std_web/file_upload/src/main.rs new file mode 100644 index 00000000000..c5578f8e78d --- /dev/null +++ b/examples/std_web/file_upload/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/std_web/inner_html/Cargo.toml b/examples/std_web/inner_html/Cargo.toml new file mode 100644 index 00000000000..05d0ec776c2 --- /dev/null +++ b/examples/std_web/inner_html/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "inner_html_std_web" +version = "0.1.0" +authors = ["Garrett Berg "] +edition = "2018" + +[dependencies] +stdweb = "0.4.20" +yew = { path = "../../..", features = ["std_web"] } + +[target.'cfg(all(target_arch = "wasm32", not(target_os="wasi"), not(cargo_web)))'.dependencies] +wasm-bindgen = "0.2.58" diff --git a/examples/std_web/inner_html/src/lib.rs b/examples/std_web/inner_html/src/lib.rs new file mode 100644 index 00000000000..1427fc88fde --- /dev/null +++ b/examples/std_web/inner_html/src/lib.rs @@ -0,0 +1,49 @@ +#![recursion_limit = "512"] +#[macro_use] +extern crate stdweb; + +use stdweb::unstable::TryFrom; +use stdweb::web::Node; +use yew::virtual_dom::VNode; +use yew::{Component, ComponentLink, Html, ShouldRender}; + +const SVG: &str = r#" +

    Inline SVG or any HTML:

    + + + Sorry, your browser does not support inline SVG. + +"#; + +pub struct Model { + pub value: i64, +} + +pub enum Msg {} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, _: ComponentLink) -> Self { + Model { value: 0 } + } + + fn update(&mut self, _: Self::Message) -> ShouldRender { + true + } + + fn view(&self) -> Html { + let js_svg = js! { + var div = document.createElement("div"); + div.innerHTML = @{SVG.to_string()}; + console.log(div); + return div; + }; + eprintln!("js_svg: {:?}", js_svg); + let node = Node::try_from(js_svg).expect("convert js_svg"); + let vnode = VNode::VRef(node); + eprintln!("svg: {:?}", vnode); + vnode + } +} diff --git a/examples/inner_html/src/main.rs b/examples/std_web/inner_html/src/main.rs similarity index 100% rename from examples/inner_html/src/main.rs rename to examples/std_web/inner_html/src/main.rs diff --git a/examples/std_web/js_callback/Cargo.toml b/examples/std_web/js_callback/Cargo.toml new file mode 100644 index 00000000000..e1d0d931bb0 --- /dev/null +++ b/examples/std_web/js_callback/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "js_callback_std_web" +version = "0.1.0" +authors = ["Scott Steele "] +edition = "2018" + +[dependencies] +yew = { path = "../../..", features = ["std_web"] } +stdweb = "^0.4.20" + +[target.'cfg(all(target_arch = "wasm32", not(cargo_web)))'.dependencies] +wasm-bindgen = "0.2.58" diff --git a/examples/std_web/js_callback/README.md b/examples/std_web/js_callback/README.md new file mode 100644 index 00000000000..027f020adec --- /dev/null +++ b/examples/std_web/js_callback/README.md @@ -0,0 +1,8 @@ +(Asynchronous) callback from Javascript +======================================= + +The purpose of this example is to demonstrate a simple case of asynchronously +sending a message back into the component update loop. + +See https://github.com/yewstack/yew/issues/316 for discussion on what +motivated this example. diff --git a/examples/std_web/js_callback/src/lib.rs b/examples/std_web/js_callback/src/lib.rs new file mode 100644 index 00000000000..c30d31eb9d2 --- /dev/null +++ b/examples/std_web/js_callback/src/lib.rs @@ -0,0 +1,100 @@ +#![recursion_limit = "128"] +#![deny(warnings)] + +#[allow(unused_imports)] +use stdweb::{_js_impl, js}; +use yew::prelude::*; + +pub struct Model { + payload: String, + // Pointless field just to have something that's been manipulated + debugged_payload: String, + link: ComponentLink, +} + +pub enum Msg { + Payload(String), + AsyncPayload, +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + let payload = String::default(); + let debugged_payload = format!("{:?}", payload); + Self { + payload, + debugged_payload, + link, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + use Msg::*; + match msg { + Payload(payload) => { + if payload != self.payload { + self.debugged_payload = format!("{:?}", payload); + self.payload = payload; + true + } else { + false + } + } + AsyncPayload => { + get_payload_later(self.link.callback(Msg::Payload)); + false + } + } + } + + fn change(&mut self, _: Self::Properties) -> ShouldRender { + false + } + + fn view(&self) -> Html { + html! { +
    + + + +

    + { nbsp(self.debugged_payload.as_str()) } +

    +
    + } + } +} + +fn nbsp(string: T) -> String +where + String: From, +{ + String::from(string).replace(' ', "\u{00a0}") +} + +fn get_payload() -> String { + (js! { return window.get_payload() }).into_string().unwrap() +} + +fn get_payload_later(payload_callback: Callback) { + let callback = move |payload: String| payload_callback.emit(payload); + js! { + // Note: The semi-colons appear to be strictly necessary here due to + // how the interpolation is implemented + var callback = @{callback}; + window.get_payload_later(function(payload) { + callback(payload); + callback.drop(); + }); + }; +} diff --git a/examples/std_web/js_callback/src/main.rs b/examples/std_web/js_callback/src/main.rs new file mode 100644 index 00000000000..1c4ab7f0979 --- /dev/null +++ b/examples/std_web/js_callback/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/std_web/js_callback/static/get-payload-script.js b/examples/std_web/js_callback/static/get-payload-script.js new file mode 100644 index 00000000000..2735ee185c3 --- /dev/null +++ b/examples/std_web/js_callback/static/get-payload-script.js @@ -0,0 +1,9 @@ +function get_payload() { + return (new Date()).toString() +} + +function get_payload_later(callback) { + setTimeout(() => { + callback(get_payload()) + }, 1000) +} diff --git a/examples/std_web/js_callback/static/index.html b/examples/std_web/js_callback/static/index.html new file mode 100644 index 00000000000..8e47c484fcc --- /dev/null +++ b/examples/std_web/js_callback/static/index.html @@ -0,0 +1,11 @@ + + + + + (Asynchronous) callback from JavaScript + + + + + + diff --git a/examples/std_web/mount_point/Cargo.toml b/examples/std_web/mount_point/Cargo.toml new file mode 100644 index 00000000000..e3cb5a7bd56 --- /dev/null +++ b/examples/std_web/mount_point/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "mount_point_std_web" +version = "0.1.0" +authors = ["Ben Berman "] +edition = "2018" + +[dependencies] +stdweb = "0.4.20" +yew = { path = "../../..", features = ["std_web"] } + +[target.'cfg(all(target_arch = "wasm32", not(target_os="wasi"), not(cargo_web)))'.dependencies] +wasm-bindgen = "0.2.58" diff --git a/examples/mount_point/src/lib.rs b/examples/std_web/mount_point/src/lib.rs similarity index 100% rename from examples/mount_point/src/lib.rs rename to examples/std_web/mount_point/src/lib.rs diff --git a/examples/std_web/mount_point/src/main.rs b/examples/std_web/mount_point/src/main.rs new file mode 100644 index 00000000000..57c144ea65f --- /dev/null +++ b/examples/std_web/mount_point/src/main.rs @@ -0,0 +1,32 @@ +#[macro_use] +extern crate stdweb; + +use mount_point_std_web::Model; +use stdweb::web::{document, IElement, INode, IParentNode}; +use yew::App; + +fn main() { + yew::initialize(); + let body = document().query_selector("body").unwrap().unwrap(); + + // This canvas won't be overwritten by yew! + let canvas = document().create_element("canvas").unwrap(); + body.append_child(&canvas); + + js! { + const canvas = document.querySelector("canvas"); + canvas.width = 100; + canvas.height = 100; + const ctx = canvas.getContext("2d"); + ctx.fillStyle = "green"; + ctx.fillRect(10, 10, 50, 50); + }; + + let mount_class = "mount-point"; + let mount_point = document().create_element("div").unwrap(); + mount_point.class_list().add(mount_class).unwrap(); + body.append_child(&mount_point); + + App::::new().mount(mount_point); + yew::run_loop(); +} diff --git a/examples/multi_thread/Cargo.toml b/examples/std_web/multi_thread/Cargo.toml similarity index 53% rename from examples/multi_thread/Cargo.toml rename to examples/std_web/multi_thread/Cargo.toml index 6faf24b7a4b..89d9ebe3f39 100644 --- a/examples/multi_thread/Cargo.toml +++ b/examples/std_web/multi_thread/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "multi_thread" +name = "multi_thread_std_web" version = "0.1.0" authors = ["Denis Kolodin "] edition = "2018" @@ -14,12 +14,7 @@ path = "src/bin/native_worker.rs" [dependencies] log = "0.4" -wasm-logger = { version = "0.2", optional = true } -web_logger = { version = "0.2", optional = true } +web_logger = "0.2" serde = "1.0" serde_derive = "1.0" -yew = { path = "../.." } - -[features] -std_web = ["web_logger", "yew/std_web"] -web_sys = ["wasm-logger", "yew/web_sys"] +yew = { path = "../../..", features = ["std_web"] } diff --git a/examples/std_web/multi_thread/README.md b/examples/std_web/multi_thread/README.md new file mode 100644 index 00000000000..79abcf6516d --- /dev/null +++ b/examples/std_web/multi_thread/README.md @@ -0,0 +1,7 @@ +### multi_thread + +You should compile a worker which have to be spawned in a separate thread: + +```sh +cargo web build --bin native_worker --release --features std_web +``` diff --git a/examples/multi_thread/Web.toml b/examples/std_web/multi_thread/Web.toml similarity index 100% rename from examples/multi_thread/Web.toml rename to examples/std_web/multi_thread/Web.toml diff --git a/examples/std_web/multi_thread/src/bin/main.rs b/examples/std_web/multi_thread/src/bin/main.rs new file mode 100644 index 00000000000..c06e491d700 --- /dev/null +++ b/examples/std_web/multi_thread/src/bin/main.rs @@ -0,0 +1,4 @@ +fn main() { + web_logger::init(); + yew::start_app::(); +} diff --git a/examples/std_web/multi_thread/src/bin/native_worker.rs b/examples/std_web/multi_thread/src/bin/native_worker.rs new file mode 100644 index 00000000000..9886831fc6d --- /dev/null +++ b/examples/std_web/multi_thread/src/bin/native_worker.rs @@ -0,0 +1,8 @@ +use yew::agent::Threaded; + +fn main() { + web_logger::init(); + yew::initialize(); + multi_thread_std_web::native_worker::Worker::register(); + yew::run_loop(); +} diff --git a/examples/multi_thread/src/context.rs b/examples/std_web/multi_thread/src/context.rs similarity index 100% rename from examples/multi_thread/src/context.rs rename to examples/std_web/multi_thread/src/context.rs diff --git a/examples/multi_thread/src/job.rs b/examples/std_web/multi_thread/src/job.rs similarity index 100% rename from examples/multi_thread/src/job.rs rename to examples/std_web/multi_thread/src/job.rs diff --git a/examples/multi_thread/src/lib.rs b/examples/std_web/multi_thread/src/lib.rs similarity index 100% rename from examples/multi_thread/src/lib.rs rename to examples/std_web/multi_thread/src/lib.rs diff --git a/examples/multi_thread/src/native_worker.rs b/examples/std_web/multi_thread/src/native_worker.rs similarity index 100% rename from examples/multi_thread/src/native_worker.rs rename to examples/std_web/multi_thread/src/native_worker.rs diff --git a/examples/std_web/multi_thread/static/bin b/examples/std_web/multi_thread/static/bin new file mode 100644 index 00000000000..4a2105e009b --- /dev/null +++ b/examples/std_web/multi_thread/static/bin @@ -0,0 +1 @@ +../../../target/wasm32-unknown-unknown/release \ No newline at end of file diff --git a/examples/multi_thread/static/index.html b/examples/std_web/multi_thread/static/index.html similarity index 100% rename from examples/multi_thread/static/index.html rename to examples/std_web/multi_thread/static/index.html diff --git a/examples/std_web/node_refs/Cargo.toml b/examples/std_web/node_refs/Cargo.toml new file mode 100644 index 00000000000..1ecf044a350 --- /dev/null +++ b/examples/std_web/node_refs/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "node_refs_std_web" +version = "0.1.0" +authors = ["Justin Starry "] +edition = "2018" + +[dependencies] +yew = { path = "../../..", features = ["std_web"] } +stdweb = "0.4.20" diff --git a/examples/node_refs/src/input.rs b/examples/std_web/node_refs/src/input.rs similarity index 100% rename from examples/node_refs/src/input.rs rename to examples/std_web/node_refs/src/input.rs diff --git a/examples/std_web/node_refs/src/lib.rs b/examples/std_web/node_refs/src/lib.rs new file mode 100644 index 00000000000..a40b5e09a65 --- /dev/null +++ b/examples/std_web/node_refs/src/lib.rs @@ -0,0 +1,75 @@ +#![recursion_limit = "256"] + +mod input; + +use input::InputComponent; +use stdweb::web::html_element::InputElement; +use stdweb::web::IHtmlElement; +use yew::prelude::*; + +pub struct Model { + link: ComponentLink, + refs: Vec, + focus_index: usize, +} + +pub enum Msg { + HoverIndex(usize), +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + Model { + link, + focus_index: 0, + refs: vec![NodeRef::default(), NodeRef::default()], + } + } + + fn mounted(&mut self) -> ShouldRender { + if let Some(input) = self.refs[self.focus_index].try_into::() { + input.focus(); + } + false + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::HoverIndex(index) => self.focus_index = index, + } + if let Some(input) = self.refs[self.focus_index].try_into::() { + input.focus(); + } + true + } + + fn view(&self) -> Html { + html! { +
    +

    { "Node Refs Demo" }

    +

    { "Refs can be used to access and manipulate DOM elements directly" }

    +
      +
    • { "First input will focus on mount" }
    • +
    • { "Each input will focus on hover" }
    • +
    +
    + + +
    +
    + + +
    +
    + } + } +} diff --git a/examples/std_web/node_refs/src/main.rs b/examples/std_web/node_refs/src/main.rs new file mode 100644 index 00000000000..9c0f53346bf --- /dev/null +++ b/examples/std_web/node_refs/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/std_web/npm_and_rest/Cargo.toml b/examples/std_web/npm_and_rest/Cargo.toml new file mode 100644 index 00000000000..d1759f348e7 --- /dev/null +++ b/examples/std_web/npm_and_rest/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "npm_and_rest_std_web" +version = "0.1.0" +authors = ["Denis Kolodin "] +edition = "2018" + +[dependencies] +failure = "0.1" +serde = "1" +serde_derive = "1" +stdweb = "0.4.20" +yew = { path = "../../..", features = ["std_web"] } + +[target.'cfg(all(target_arch = "wasm32", not(target_os="wasi"), not(cargo_web)))'.dependencies] +wasm-bindgen = "0.2.58" \ No newline at end of file diff --git a/examples/std_web/npm_and_rest/src/ccxt.rs b/examples/std_web/npm_and_rest/src/ccxt.rs new file mode 100644 index 00000000000..b19d9d77190 --- /dev/null +++ b/examples/std_web/npm_and_rest/src/ccxt.rs @@ -0,0 +1,25 @@ +use stdweb::unstable::TryInto; +use stdweb::Value; + +#[derive(Default)] +pub struct CcxtService(Option); + +impl CcxtService { + pub fn new() -> Self { + let lib = js! { + return ccxt; + }; + CcxtService(Some(lib)) + } + + pub fn exchanges(&mut self) -> Vec { + let lib = self.0.as_ref().expect("ccxt library object lost"); + let v: Value = js! { + var ccxt = @{lib}; + console.log(ccxt.exchanges); + return ccxt.exchanges; + }; + let v: Vec = v.try_into().expect("can't extract exchanges"); + v + } +} diff --git a/examples/npm_and_rest/src/gravatar.rs b/examples/std_web/npm_and_rest/src/gravatar.rs similarity index 100% rename from examples/npm_and_rest/src/gravatar.rs rename to examples/std_web/npm_and_rest/src/gravatar.rs diff --git a/examples/npm_and_rest/src/lib.rs b/examples/std_web/npm_and_rest/src/lib.rs similarity index 98% rename from examples/npm_and_rest/src/lib.rs rename to examples/std_web/npm_and_rest/src/lib.rs index 9135f03142b..27d646ae315 100644 --- a/examples/npm_and_rest/src/lib.rs +++ b/examples/std_web/npm_and_rest/src/lib.rs @@ -1,6 +1,5 @@ #![recursion_limit = "128"] -#[cfg(feature = "std_web")] #[macro_use] extern crate stdweb; diff --git a/examples/std_web/npm_and_rest/src/main.rs b/examples/std_web/npm_and_rest/src/main.rs new file mode 100644 index 00000000000..267c8afdfcf --- /dev/null +++ b/examples/std_web/npm_and_rest/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/npm_and_rest/static/index.html b/examples/std_web/npm_and_rest/static/index.html similarity index 100% rename from examples/npm_and_rest/static/index.html rename to examples/std_web/npm_and_rest/static/index.html diff --git a/examples/todomvc/Cargo.toml b/examples/std_web/todomvc/Cargo.toml similarity index 63% rename from examples/todomvc/Cargo.toml rename to examples/std_web/todomvc/Cargo.toml index 6921fe9dbb4..a230bebe475 100644 --- a/examples/todomvc/Cargo.toml +++ b/examples/std_web/todomvc/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "todomvc" +name = "todomvc_std_web" version = "0.1.0" authors = ["Denis Kolodin "] edition = "2018" @@ -9,8 +9,4 @@ strum = "0.13" strum_macros = "0.13" serde = "1" serde_derive = "1" -yew = { path = "../.." } - -[features] -std_web = ["yew/std_web"] -web_sys = ["yew/web_sys"] +yew = { path = "../../..", features = ["std_web"] } diff --git a/examples/todomvc/README.md b/examples/std_web/todomvc/README.md similarity index 100% rename from examples/todomvc/README.md rename to examples/std_web/todomvc/README.md diff --git a/examples/std_web/todomvc/src/lib.rs b/examples/std_web/todomvc/src/lib.rs new file mode 100644 index 00000000000..dffea6676e1 --- /dev/null +++ b/examples/std_web/todomvc/src/lib.rs @@ -0,0 +1,358 @@ +#![recursion_limit = "512"] + +use serde_derive::{Deserialize, Serialize}; +use strum::IntoEnumIterator; +use strum_macros::{EnumIter, ToString}; +use yew::events::IKeyboardEvent; +use yew::format::Json; +use yew::services::storage::{Area, StorageService}; +use yew::{html, Component, ComponentLink, Href, Html, InputData, KeyPressEvent, ShouldRender}; + +const KEY: &'static str = "yew.todomvc.self"; + +pub struct Model { + link: ComponentLink, + storage: StorageService, + state: State, +} + +#[derive(Serialize, Deserialize)] +pub struct State { + entries: Vec, + filter: Filter, + value: String, + edit_value: String, +} + +#[derive(Serialize, Deserialize)] +struct Entry { + description: String, + completed: bool, + editing: bool, +} + +pub enum Msg { + Add, + Edit(usize), + Update(String), + UpdateEdit(String), + Remove(usize), + SetFilter(Filter), + ToggleAll, + ToggleEdit(usize), + Toggle(usize), + ClearCompleted, + Nope, +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + let storage = StorageService::new(Area::Local).expect("storage was disabled by the user"); + let entries = { + if let Json(Ok(restored_model)) = storage.restore(KEY) { + restored_model + } else { + Vec::new() + } + }; + let state = State { + entries, + filter: Filter::All, + value: "".into(), + edit_value: "".into(), + }; + Model { + link, + storage, + state, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::Add => { + let entry = Entry { + description: self.state.value.clone(), + completed: false, + editing: false, + }; + self.state.entries.push(entry); + self.state.value = "".to_string(); + } + Msg::Edit(idx) => { + let edit_value = self.state.edit_value.clone(); + self.state.complete_edit(idx, edit_value); + self.state.edit_value = "".to_string(); + } + Msg::Update(val) => { + println!("Input: {}", val); + self.state.value = val; + } + Msg::UpdateEdit(val) => { + println!("Input: {}", val); + self.state.edit_value = val; + } + Msg::Remove(idx) => { + self.state.remove(idx); + } + Msg::SetFilter(filter) => { + self.state.filter = filter; + } + Msg::ToggleEdit(idx) => { + self.state.edit_value = self.state.entries[idx].description.clone(); + self.state.toggle_edit(idx); + } + Msg::ToggleAll => { + let status = !self.state.is_all_completed(); + self.state.toggle_all(status); + } + Msg::Toggle(idx) => { + self.state.toggle(idx); + } + Msg::ClearCompleted => { + self.state.clear_completed(); + } + Msg::Nope => {} + } + self.storage.store(KEY, Json(&self.state.entries)); + true + } + + fn view(&self) -> Html { + html! { +
    +
    +
    +

    { "todos" }

    + { self.view_input() } +
    +
    + +
      + { for self.state.entries.iter().filter(|e| self.state.filter.fit(e)).enumerate().map(|e| self.view_entry(e)) } +
    +
    +
    + + { self.state.total() } + { " item(s) left" } + +
      + { for Filter::iter().map(|flt| self.view_filter(flt)) } +
    + +
    +
    + +
    + } + } +} + +impl Model { + fn view_filter(&self, filter: Filter) -> Html { + let flt = filter.clone(); + html! { +
  • + + { filter } + +
  • + } + } + + fn view_input(&self) -> Html { + html! { + // You can use standard Rust comments. One line: + //
  • + + /* Or multiline: +
      +
    • +
    + */ + } + } + + fn view_entry(&self, (idx, entry): (usize, &Entry)) -> Html { + let mut class = "todo".to_string(); + if entry.editing { + class.push_str(" editing"); + } + if entry.completed { + class.push_str(" completed"); + } + html! { +
  • +
    + + +
    + { self.view_entry_edit_input((idx, &entry)) } +
  • + } + } + + fn view_entry_edit_input(&self, (idx, entry): (usize, &Entry)) -> Html { + if entry.editing { + html! { + + } + } else { + html! { } + } + } +} + +#[derive(EnumIter, ToString, Clone, PartialEq, Serialize, Deserialize)] +pub enum Filter { + All, + Active, + Completed, +} + +impl<'a> Into for &'a Filter { + fn into(self) -> Href { + match *self { + Filter::All => "#/".into(), + Filter::Active => "#/active".into(), + Filter::Completed => "#/completed".into(), + } + } +} + +impl Filter { + fn fit(&self, entry: &Entry) -> bool { + match *self { + Filter::All => true, + Filter::Active => !entry.completed, + Filter::Completed => entry.completed, + } + } +} + +impl State { + fn total(&self) -> usize { + self.entries.len() + } + + fn total_completed(&self) -> usize { + self.entries + .iter() + .filter(|e| Filter::Completed.fit(e)) + .count() + } + + fn is_all_completed(&self) -> bool { + let mut filtered_iter = self + .entries + .iter() + .filter(|e| self.filter.fit(e)) + .peekable(); + + if filtered_iter.peek().is_none() { + return false; + } + + filtered_iter.all(|e| e.completed) + } + + fn toggle_all(&mut self, value: bool) { + for entry in self.entries.iter_mut() { + if self.filter.fit(entry) { + entry.completed = value; + } + } + } + + fn clear_completed(&mut self) { + let entries = self + .entries + .drain(..) + .filter(|e| Filter::Active.fit(e)) + .collect(); + self.entries = entries; + } + + fn toggle(&mut self, idx: usize) { + let filter = self.filter.clone(); + let mut entries = self + .entries + .iter_mut() + .filter(|e| filter.fit(e)) + .collect::>(); + let entry = entries.get_mut(idx).unwrap(); + entry.completed = !entry.completed; + } + + fn toggle_edit(&mut self, idx: usize) { + let filter = self.filter.clone(); + let mut entries = self + .entries + .iter_mut() + .filter(|e| filter.fit(e)) + .collect::>(); + let entry = entries.get_mut(idx).unwrap(); + entry.editing = !entry.editing; + } + + fn complete_edit(&mut self, idx: usize, val: String) { + let filter = self.filter.clone(); + let mut entries = self + .entries + .iter_mut() + .filter(|e| filter.fit(e)) + .collect::>(); + let entry = entries.get_mut(idx).unwrap(); + entry.description = val; + entry.editing = !entry.editing; + } + + fn remove(&mut self, idx: usize) { + let idx = { + let filter = self.filter.clone(); + let entries = self + .entries + .iter() + .enumerate() + .filter(|&(_, e)| filter.fit(e)) + .collect::>(); + let &(idx, _) = entries.get(idx).unwrap(); + idx + }; + self.entries.remove(idx); + } +} diff --git a/examples/std_web/todomvc/src/main.rs b/examples/std_web/todomvc/src/main.rs new file mode 100644 index 00000000000..acea50454b1 --- /dev/null +++ b/examples/std_web/todomvc/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/todomvc/static/index.html b/examples/std_web/todomvc/static/index.html similarity index 100% rename from examples/todomvc/static/index.html rename to examples/std_web/todomvc/static/index.html diff --git a/examples/std_web/two_apps/Cargo.toml b/examples/std_web/two_apps/Cargo.toml new file mode 100644 index 00000000000..65effeeee88 --- /dev/null +++ b/examples/std_web/two_apps/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "two_apps_std_web" +version = "0.1.0" +authors = ["Denis Kolodin "] +edition = "2018" + +[dependencies] +stdweb = "0.4.20" +yew = { path = "../../..", features = ["std_web"] } diff --git a/examples/two_apps/src/lib.rs b/examples/std_web/two_apps/src/lib.rs similarity index 100% rename from examples/two_apps/src/lib.rs rename to examples/std_web/two_apps/src/lib.rs diff --git a/examples/std_web/two_apps/src/main.rs b/examples/std_web/two_apps/src/main.rs new file mode 100644 index 00000000000..c7176a9369d --- /dev/null +++ b/examples/std_web/two_apps/src/main.rs @@ -0,0 +1,21 @@ +use stdweb::web::IParentNode; +use two_apps_std_web::{Model, Msg}; +use yew::html::Scope; +use yew::App; + +fn mount_app(selector: &'static str, app: App) -> Scope { + let document = yew::utils::document(); + let element = document.query_selector(selector).unwrap().unwrap(); + app.mount(element) +} + +fn main() { + yew::initialize(); + let first_app = App::new(); + let second_app = App::new(); + let to_first = mount_app(".first-app", first_app); + let to_second = mount_app(".second-app", second_app); + to_first.send_message(Msg::SetScope(to_second.clone())); + to_second.send_message(Msg::SetScope(to_first.clone())); + yew::run_loop(); +} diff --git a/examples/two_apps/static/index.html b/examples/std_web/two_apps/static/index.html similarity index 100% rename from examples/two_apps/static/index.html rename to examples/std_web/two_apps/static/index.html diff --git a/examples/todomvc/src/main.rs b/examples/todomvc/src/main.rs deleted file mode 100644 index c45e29a36fa..00000000000 --- a/examples/todomvc/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - yew::start_app::(); -} diff --git a/examples/two_apps/Cargo.toml b/examples/two_apps/Cargo.toml deleted file mode 100644 index 2d04113470c..00000000000 --- a/examples/two_apps/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "two_apps" -version = "0.1.0" -authors = ["Denis Kolodin "] -edition = "2018" - -[dependencies] -stdweb = { version = "0.4.20", optional = true } -web-sys = { version = "0.3", optional = true, features = ["Document", "Window"] } -yew = { path = "../.." } - -[features] -std_web = ["stdweb", "yew/std_web"] -web_sys = ["web-sys", "yew/web_sys"] diff --git a/examples/two_apps/src/main.rs b/examples/two_apps/src/main.rs deleted file mode 100644 index e70814bc4e0..00000000000 --- a/examples/two_apps/src/main.rs +++ /dev/null @@ -1,27 +0,0 @@ -#[cfg(feature = "std_web")] -use stdweb::web::{document, IParentNode}; -use two_apps::{Model, Msg}; -use yew::html::Scope; -use yew::App; - -fn mount_app(selector: &'static str, app: App) -> Scope { - #[cfg(feature = "std_web")] - let document = document(); - #[cfg(feature = "web_sys")] - let document = web_sys::window().unwrap().document().unwrap(); - let element = document.query_selector(selector).unwrap().unwrap(); - app.mount(element) -} - -fn main() { - yew::initialize(); - let first_app = App::new(); - let second_app = App::new(); - #[cfg_attr(feature = "web_sys", allow(unused_mut))] - let mut to_first = mount_app(".first-app", first_app); - #[cfg_attr(feature = "web_sys", allow(unused_mut))] - let mut to_second = mount_app(".second-app", second_app); - to_first.send_message(Msg::SetScope(to_second.clone())); - to_second.send_message(Msg::SetScope(to_first.clone())); - yew::run_loop(); -} diff --git a/examples/web_sys/counter/Cargo.toml b/examples/web_sys/counter/Cargo.toml new file mode 100644 index 00000000000..c75e76b899f --- /dev/null +++ b/examples/web_sys/counter/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "counter_web_sys" +version = "0.1.1" +authors = ["Denis Kolodin "] +edition = "2018" + +[dependencies] +js-sys = "0.3" +yew = { path = "../../..", features = ["web_sys"] } diff --git a/examples/web_sys/counter/src/lib.rs b/examples/web_sys/counter/src/lib.rs new file mode 100644 index 00000000000..7bf99358801 --- /dev/null +++ b/examples/web_sys/counter/src/lib.rs @@ -0,0 +1,70 @@ +#![recursion_limit = "256"] + +use js_sys::Date; +use yew::services::ConsoleService; +use yew::{html, Component, ComponentLink, Html, ShouldRender}; + +pub struct Model { + link: ComponentLink, + console: ConsoleService, + value: i64, +} + +pub enum Msg { + Increment, + Decrement, + Bulk(Vec), +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + Model { + link, + console: ConsoleService::new(), + value: 0, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::Increment => { + self.value = self.value + 1; + self.console.log("plus one"); + } + Msg::Decrement => { + self.value = self.value - 1; + self.console.log("minus one"); + } + Msg::Bulk(list) => { + for msg in list { + self.update(msg); + self.console.log("Bulk action"); + } + } + } + true + } + + fn view(&self) -> Html { + html! { +
    + +

    { self.value }

    +

    { Date::new_0().to_string().as_string().unwrap() }

    +
    + } + } +} diff --git a/examples/web_sys/counter/src/main.rs b/examples/web_sys/counter/src/main.rs new file mode 100644 index 00000000000..88e374caeca --- /dev/null +++ b/examples/web_sys/counter/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/web_sys/file_upload/Cargo.toml b/examples/web_sys/file_upload/Cargo.toml new file mode 100644 index 00000000000..afee9936ec6 --- /dev/null +++ b/examples/web_sys/file_upload/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "file_upload_web_sys" +version = "0.1.0" +authors = ["Denis Kolodin "] +edition = "2018" + +[dependencies] +js-sys = "0.3" +yew = { path = "../../..", features = ["web_sys"] } diff --git a/examples/file_upload/src/lib.rs b/examples/web_sys/file_upload/src/lib.rs similarity index 98% rename from examples/file_upload/src/lib.rs rename to examples/web_sys/file_upload/src/lib.rs index 70a9e3c2905..86f1c66f64b 100644 --- a/examples/file_upload/src/lib.rs +++ b/examples/web_sys/file_upload/src/lib.rs @@ -73,7 +73,6 @@ impl Component for Model { (); +} diff --git a/examples/web_sys/inner_html/Cargo.toml b/examples/web_sys/inner_html/Cargo.toml new file mode 100644 index 00000000000..70d8a952bcc --- /dev/null +++ b/examples/web_sys/inner_html/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "inner_html_web_sys" +version = "0.1.0" +authors = ["Garrett Berg "] +edition = "2018" + +[dependencies] +web-sys = { version = "0.3", features = ["console", "Document", "Element", "Node", "Window"] } +yew = { path = "../../..", features = ["web_sys"] } diff --git a/examples/inner_html/src/lib.rs b/examples/web_sys/inner_html/src/lib.rs similarity index 68% rename from examples/inner_html/src/lib.rs rename to examples/web_sys/inner_html/src/lib.rs index 53f9c40397e..160290adafe 100644 --- a/examples/inner_html/src/lib.rs +++ b/examples/web_sys/inner_html/src/lib.rs @@ -1,11 +1,5 @@ #![recursion_limit = "512"] -#[cfg(feature = "std_web")] -#[macro_use] -extern crate stdweb; -#[cfg(feature = "std_web")] -use stdweb::{unstable::TryFrom, web::Node}; -#[cfg(feature = "web_sys")] use web_sys::{console, Node}; use yew::virtual_dom::VNode; use yew::{Component, ComponentLink, Html, ShouldRender}; @@ -37,14 +31,6 @@ impl Component for Model { } fn view(&self) -> Html { - #[cfg(feature = "std_web")] - let js_svg = js! { - var div = document.createElement("div"); - div.innerHTML = @{SVG.to_string()}; - console.log(div); - return div; - }; - #[cfg(feature = "web_sys")] let js_svg = { let div = web_sys::window() .unwrap() @@ -57,9 +43,6 @@ impl Component for Model { div }; eprintln!("js_svg: {:?}", js_svg); - #[cfg(feature = "std_web")] - let node = Node::try_from(js_svg).expect("convert js_svg"); - #[cfg(feature = "web_sys")] let node = Node::from(js_svg); let vnode = VNode::VRef(node); eprintln!("svg: {:?}", vnode); diff --git a/examples/web_sys/inner_html/src/main.rs b/examples/web_sys/inner_html/src/main.rs new file mode 100644 index 00000000000..e5c55fd9b98 --- /dev/null +++ b/examples/web_sys/inner_html/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/web_sys/js_callback/Cargo.toml b/examples/web_sys/js_callback/Cargo.toml new file mode 100644 index 00000000000..91413b7eb4c --- /dev/null +++ b/examples/web_sys/js_callback/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "js_callback_web_sys" +version = "0.1.0" +authors = ["Scott Steele "] +edition = "2018" + +[dependencies] +yew = { path = "../../..", features = ["web_sys"] } + +[target.'cfg(all(target_arch = "wasm32", not(cargo_web)))'.dependencies] +wasm-bindgen = "0.2.58" diff --git a/examples/web_sys/js_callback/README.md b/examples/web_sys/js_callback/README.md new file mode 100644 index 00000000000..027f020adec --- /dev/null +++ b/examples/web_sys/js_callback/README.md @@ -0,0 +1,8 @@ +(Asynchronous) callback from Javascript +======================================= + +The purpose of this example is to demonstrate a simple case of asynchronously +sending a message back into the component update loop. + +See https://github.com/yewstack/yew/issues/316 for discussion on what +motivated this example. diff --git a/examples/web_sys/js_callback/src/lib.rs b/examples/web_sys/js_callback/src/lib.rs new file mode 100644 index 00000000000..d6e5bb73400 --- /dev/null +++ b/examples/web_sys/js_callback/src/lib.rs @@ -0,0 +1,98 @@ +#![recursion_limit = "128"] +#![deny(warnings)] + +use wasm_bindgen::{closure::Closure, prelude::wasm_bindgen, JsValue}; +use yew::prelude::*; + +pub struct Model { + payload: String, + // Pointless field just to have something that's been manipulated + debugged_payload: String, + link: ComponentLink, +} + +pub enum Msg { + Payload(String), + AsyncPayload, +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + let payload = String::default(); + let debugged_payload = format!("{:?}", payload); + Self { + payload, + debugged_payload, + link, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + use Msg::*; + match msg { + Payload(payload) => { + if payload != self.payload { + self.debugged_payload = format!("{:?}", payload); + self.payload = payload; + true + } else { + false + } + } + AsyncPayload => { + get_payload_later(self.link.callback(Msg::Payload)); + false + } + } + } + + fn change(&mut self, _: Self::Properties) -> ShouldRender { + false + } + + fn view(&self) -> Html { + html! { +
    + + + +

    + { nbsp(self.debugged_payload.as_str()) } +

    +
    + } + } +} + +fn nbsp(string: T) -> String +where + String: From, +{ + String::from(string).replace(' ', "\u{00a0}") +} + +#[wasm_bindgen] +extern "C" { + fn get_payload() -> String; +} + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_name = "get_payload_later")] + fn get_payload_later_js(payload_callback: JsValue); +} + +fn get_payload_later(payload_callback: Callback) { + let callback = Closure::once_into_js(move |payload: String| payload_callback.emit(payload)); + get_payload_later_js(callback); +} diff --git a/examples/web_sys/js_callback/src/main.rs b/examples/web_sys/js_callback/src/main.rs new file mode 100644 index 00000000000..db451555d85 --- /dev/null +++ b/examples/web_sys/js_callback/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/web_sys/js_callback/static/get-payload-script.js b/examples/web_sys/js_callback/static/get-payload-script.js new file mode 100644 index 00000000000..2735ee185c3 --- /dev/null +++ b/examples/web_sys/js_callback/static/get-payload-script.js @@ -0,0 +1,9 @@ +function get_payload() { + return (new Date()).toString() +} + +function get_payload_later(callback) { + setTimeout(() => { + callback(get_payload()) + }, 1000) +} diff --git a/examples/web_sys/js_callback/static/index.html b/examples/web_sys/js_callback/static/index.html new file mode 100644 index 00000000000..8e47c484fcc --- /dev/null +++ b/examples/web_sys/js_callback/static/index.html @@ -0,0 +1,11 @@ + + + + + (Asynchronous) callback from JavaScript + + + + + + diff --git a/examples/mount_point/Cargo.toml b/examples/web_sys/mount_point/Cargo.toml similarity index 51% rename from examples/mount_point/Cargo.toml rename to examples/web_sys/mount_point/Cargo.toml index 3d988d52c02..83688ddc4b3 100644 --- a/examples/mount_point/Cargo.toml +++ b/examples/web_sys/mount_point/Cargo.toml @@ -1,17 +1,15 @@ [package] -name = "mount_point" +name = "mount_point_web_sys" version = "0.1.0" authors = ["Ben Berman "] edition = "2018" [dependencies] -stdweb = { version = "0.4.20", optional = true } -wasm-bindgen = { version = "0.2", optional = true } -yew = { path = "../.." } +wasm-bindgen = "0.2" +yew = { path = "../../..", features = ["web_sys"] } [dependencies.web-sys] version = "0.3" -optional = true features = [ "CanvasRenderingContext2d", "Document", @@ -21,7 +19,3 @@ features = [ "Node", "Window" ] - -[features] -std_web = ["stdweb", "yew/std_web"] -web_sys = ["wasm-bindgen", "web-sys", "yew/web_sys"] diff --git a/examples/web_sys/mount_point/src/lib.rs b/examples/web_sys/mount_point/src/lib.rs new file mode 100644 index 00000000000..29c728b1ba3 --- /dev/null +++ b/examples/web_sys/mount_point/src/lib.rs @@ -0,0 +1,42 @@ +use yew::{html, Component, ComponentLink, Html, InputData, ShouldRender}; + +pub struct Model { + link: ComponentLink, + name: String, +} + +pub enum Msg { + UpdateName(String), +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + Model { + link, + name: "Reversed".to_owned(), + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::UpdateName(new_name) => { + self.name = new_name; + } + } + true + } + + fn view(&self) -> Html { + html! { +
    + +

    { self.name.chars().rev().collect::() }

    +
    + } + } +} diff --git a/examples/web_sys/mount_point/src/main.rs b/examples/web_sys/mount_point/src/main.rs new file mode 100644 index 00000000000..484d88d4403 --- /dev/null +++ b/examples/web_sys/mount_point/src/main.rs @@ -0,0 +1,31 @@ +use mount_point_web_sys::Model; +use wasm_bindgen::JsValue; +use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement}; +use yew::App; + +fn main() { + yew::initialize(); + let document = yew::utils::document(); + let body = document.query_selector("body").unwrap().unwrap(); + + // This canvas won't be overwritten by yew! + let canvas = document.create_element("canvas").unwrap(); + body.append_child(&canvas).unwrap(); + + let canvas = HtmlCanvasElement::from(JsValue::from(canvas)); + canvas.set_width(100); + canvas.set_height(100); + let ctx = + CanvasRenderingContext2d::from(JsValue::from(canvas.get_context("2d").unwrap().unwrap())); + ctx.set_fill_style(&JsValue::from_str("green")); + ctx.fill_rect(10., 10., 50., 50.); + + let mount_class = "mount-point"; + let mount_point = document.create_element("div").unwrap(); + let class_list = mount_point.class_list(); + class_list.add_1(mount_class).unwrap(); + body.append_child(&mount_point).unwrap(); + + App::::new().mount(mount_point); + yew::run_loop(); +} diff --git a/examples/web_sys/multi_thread/Cargo.toml b/examples/web_sys/multi_thread/Cargo.toml new file mode 100644 index 00000000000..dc2db7632b2 --- /dev/null +++ b/examples/web_sys/multi_thread/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "multi_thread_web_sys" +version = "0.1.0" +authors = ["Denis Kolodin "] +edition = "2018" + +[[bin]] +name = "main" +path = "src/bin/main.rs" + +[[bin]] +name = "native_worker" +path = "src/bin/native_worker.rs" + +[dependencies] +log = "0.4" +wasm-logger = "0.2" +serde = "1.0" +serde_derive = "1.0" +yew = { path = "../../..", features = ["web_sys"]} diff --git a/examples/multi_thread/README.md b/examples/web_sys/multi_thread/README.md similarity index 60% rename from examples/multi_thread/README.md rename to examples/web_sys/multi_thread/README.md index 6a12b961ff3..efe100aad0d 100644 --- a/examples/multi_thread/README.md +++ b/examples/web_sys/multi_thread/README.md @@ -2,12 +2,6 @@ You should compile a worker which have to be spawned in a separate thread: -```sh -cargo web build --bin native_worker --release --features std_web -``` - -For `web-sys` support, use `no-modules` output. - ```sh wasm-pack build --target no-modules --release -- --features web_sys --bin native_worker ``` diff --git a/examples/web_sys/multi_thread/Web.toml b/examples/web_sys/multi_thread/Web.toml new file mode 100644 index 00000000000..813e27393a9 --- /dev/null +++ b/examples/web_sys/multi_thread/Web.toml @@ -0,0 +1 @@ +default-target = "wasm32-unknown-unknown" diff --git a/examples/multi_thread/src/bin/main.rs b/examples/web_sys/multi_thread/src/bin/main.rs similarity index 100% rename from examples/multi_thread/src/bin/main.rs rename to examples/web_sys/multi_thread/src/bin/main.rs diff --git a/examples/multi_thread/src/bin/native_worker.rs b/examples/web_sys/multi_thread/src/bin/native_worker.rs similarity index 100% rename from examples/multi_thread/src/bin/native_worker.rs rename to examples/web_sys/multi_thread/src/bin/native_worker.rs diff --git a/examples/web_sys/multi_thread/src/context.rs b/examples/web_sys/multi_thread/src/context.rs new file mode 100644 index 00000000000..c93a9461cb8 --- /dev/null +++ b/examples/web_sys/multi_thread/src/context.rs @@ -0,0 +1,66 @@ +use log::info; +use serde_derive::{Deserialize, Serialize}; +use std::time::Duration; +use yew::worker::*; +// TODO use yew::services::{IntervalService, FetchService, Task}; +use yew::services::fetch::FetchService; +use yew::services::interval::IntervalService; +use yew::services::Task; + +#[derive(Serialize, Deserialize, Debug)] +pub enum Request { + GetDataFromServer, +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum Response { + DataFetched, +} + +pub enum Msg { + Updating, +} + +pub struct Worker { + link: AgentLink, + interval: IntervalService, + task: Box, + fetch: FetchService, +} + +impl Agent for Worker { + type Reach = Context; + type Message = Msg; + type Input = Request; + type Output = Response; + + fn create(link: AgentLink) -> Self { + let mut interval = IntervalService::new(); + let duration = Duration::from_secs(3); + let callback = link.callback(|_| Msg::Updating); + let task = interval.spawn(duration, callback); + Worker { + link, + interval, + task: Box::new(task), + fetch: FetchService::new(), + } + } + + fn update(&mut self, msg: Self::Message) { + match msg { + Msg::Updating => { + info!("Tick..."); + } + } + } + + fn handle_input(&mut self, msg: Self::Input, who: HandlerId) { + info!("Request: {:?}", msg); + match msg { + Request::GetDataFromServer => { + self.link.respond(who, Response::DataFetched); + } + } + } +} diff --git a/examples/web_sys/multi_thread/src/job.rs b/examples/web_sys/multi_thread/src/job.rs new file mode 100644 index 00000000000..a9d21aa4144 --- /dev/null +++ b/examples/web_sys/multi_thread/src/job.rs @@ -0,0 +1,66 @@ +use log::info; +use serde_derive::{Deserialize, Serialize}; +use std::time::Duration; +use yew::worker::*; +// TODO use yew::services::{IntervalService, FetchService, Task}; +use yew::services::fetch::FetchService; +use yew::services::interval::IntervalService; +use yew::services::Task; + +#[derive(Serialize, Deserialize, Debug)] +pub enum Request { + GetDataFromServer, +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum Response { + DataFetched, +} + +pub enum Msg { + Updating, +} + +pub struct Worker { + link: AgentLink, + interval: IntervalService, + task: Box, + fetch: FetchService, +} + +impl Agent for Worker { + type Reach = Job; + type Message = Msg; + type Input = Request; + type Output = Response; + + fn create(link: AgentLink) -> Self { + let mut interval = IntervalService::new(); + let duration = Duration::from_secs(3); + let callback = link.callback(|_| Msg::Updating); + let task = interval.spawn(duration, callback); + Worker { + link, + interval, + task: Box::new(task), + fetch: FetchService::new(), + } + } + + fn update(&mut self, msg: Self::Message) { + match msg { + Msg::Updating => { + info!("Tick..."); + } + } + } + + fn handle_input(&mut self, msg: Self::Input, who: HandlerId) { + info!("Request: {:?}", msg); + match msg { + Request::GetDataFromServer => { + self.link.respond(who, Response::DataFetched); + } + } + } +} diff --git a/examples/web_sys/multi_thread/src/lib.rs b/examples/web_sys/multi_thread/src/lib.rs new file mode 100644 index 00000000000..e86645d0332 --- /dev/null +++ b/examples/web_sys/multi_thread/src/lib.rs @@ -0,0 +1,82 @@ +#![recursion_limit = "128"] + +pub mod context; +pub mod job; +pub mod native_worker; + +use log::info; +use yew::worker::*; +use yew::{html, Component, ComponentLink, Html, ShouldRender}; + +pub struct Model { + link: ComponentLink, + worker: Box>, + job: Box>, + context: Box>, + context_2: Box>, +} + +pub enum Msg { + SendToWorker, + SendToJob, + SendToContext, + DataReceived, +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + let callback = link.callback(|_| Msg::DataReceived); + let worker = native_worker::Worker::bridge(callback); + + let callback = link.callback(|_| Msg::DataReceived); + let job = job::Worker::bridge(callback); + + let callback = link.callback(|_| Msg::DataReceived); + let context = context::Worker::bridge(callback); + + let callback = link.callback(|_| Msg::DataReceived); + let context_2 = context::Worker::bridge(callback); + + Model { + link, + worker, + job, + context, + context_2, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::SendToWorker => { + self.worker.send(native_worker::Request::GetDataFromServer); + } + Msg::SendToJob => { + self.job.send(job::Request::GetDataFromServer); + } + Msg::SendToContext => { + self.context.send(context::Request::GetDataFromServer); + self.context_2.send(context::Request::GetDataFromServer); + } + Msg::DataReceived => { + info!("DataReceived"); + } + } + true + } + + fn view(&self) -> Html { + html! { +
    + +
    + } + } +} diff --git a/examples/web_sys/multi_thread/src/native_worker.rs b/examples/web_sys/multi_thread/src/native_worker.rs new file mode 100644 index 00000000000..723d54cec46 --- /dev/null +++ b/examples/web_sys/multi_thread/src/native_worker.rs @@ -0,0 +1,70 @@ +use log::info; +use serde_derive::{Deserialize, Serialize}; +use std::time::Duration; +use yew::worker::*; +// TODO use yew::services::{IntervalService, FetchService, Task}; +use yew::services::fetch::FetchService; +use yew::services::interval::IntervalService; +use yew::services::Task; + +#[derive(Serialize, Deserialize, Debug)] +pub enum Request { + GetDataFromServer, +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum Response { + DataFetched, +} + +pub enum Msg { + Updating, +} + +pub struct Worker { + link: AgentLink, + interval: IntervalService, + task: Box, + fetch: FetchService, +} + +impl Agent for Worker { + type Reach = Public; + type Message = Msg; + type Input = Request; + type Output = Response; + + fn create(link: AgentLink) -> Self { + let mut interval = IntervalService::new(); + let duration = Duration::from_secs(3); + let callback = link.callback(|_| Msg::Updating); + let task = interval.spawn(duration, callback); + Worker { + link, + interval, + task: Box::new(task), + fetch: FetchService::new(), + } + } + + fn update(&mut self, msg: Self::Message) { + match msg { + Msg::Updating => { + info!("Tick..."); + } + } + } + + fn handle_input(&mut self, msg: Self::Input, who: HandlerId) { + info!("Request: {:?}", msg); + match msg { + Request::GetDataFromServer => { + self.link.respond(who, Response::DataFetched); + } + } + } + + fn name_of_resource() -> &'static str { + "bin/native_worker.js" + } +} diff --git a/examples/web_sys/multi_thread/static/bin b/examples/web_sys/multi_thread/static/bin new file mode 100644 index 00000000000..4a2105e009b --- /dev/null +++ b/examples/web_sys/multi_thread/static/bin @@ -0,0 +1 @@ +../../../target/wasm32-unknown-unknown/release \ No newline at end of file diff --git a/examples/web_sys/multi_thread/static/index.html b/examples/web_sys/multi_thread/static/index.html new file mode 100644 index 00000000000..11845751fc2 --- /dev/null +++ b/examples/web_sys/multi_thread/static/index.html @@ -0,0 +1,11 @@ + + + + + Yew • Multi-Thread + + + + + + diff --git a/examples/web_sys/node_refs/Cargo.toml b/examples/web_sys/node_refs/Cargo.toml new file mode 100644 index 00000000000..e6617be1864 --- /dev/null +++ b/examples/web_sys/node_refs/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "node_refs_web_sys" +version = "0.1.0" +authors = ["Justin Starry "] +edition = "2018" + +[dependencies] +yew = { path = "../../..", features = ["web_sys"] } +web-sys = { version = "0.3", features = ["HtmlElement", "HtmlInputElement", "Node"] } diff --git a/examples/web_sys/node_refs/src/input.rs b/examples/web_sys/node_refs/src/input.rs new file mode 100644 index 00000000000..e26f27c4ad4 --- /dev/null +++ b/examples/web_sys/node_refs/src/input.rs @@ -0,0 +1,43 @@ +use yew::prelude::*; + +pub struct InputComponent { + props: Props, + link: ComponentLink, +} + +#[derive(Clone, Properties)] +pub struct Props { + #[props(required)] + pub on_hover: Callback<()>, +} + +pub enum Msg { + Hover, +} + +impl Component for InputComponent { + type Message = Msg; + type Properties = Props; + + fn create(props: Self::Properties, link: ComponentLink) -> Self { + InputComponent { props, link } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::Hover => { + self.props.on_hover.emit(()); + } + } + false + } + + fn view(&self) -> Html { + html! { + + } + } +} diff --git a/examples/node_refs/src/lib.rs b/examples/web_sys/node_refs/src/lib.rs similarity index 81% rename from examples/node_refs/src/lib.rs rename to examples/web_sys/node_refs/src/lib.rs index 97faee7cba9..472f52c0fa8 100644 --- a/examples/node_refs/src/lib.rs +++ b/examples/web_sys/node_refs/src/lib.rs @@ -3,9 +3,6 @@ mod input; use input::InputComponent; -#[cfg(feature = "std_web")] -use stdweb::web::{html_element::InputElement, IHtmlElement}; -#[cfg(feature = "web_sys")] use web_sys::HtmlInputElement as InputElement; use yew::prelude::*; @@ -33,10 +30,7 @@ impl Component for Model { fn mounted(&mut self) -> ShouldRender { if let Some(input) = self.refs[self.focus_index].try_into::() { - #[cfg_attr(feature = "std_web", allow(unused_variables))] - let result = input.focus(); - #[cfg(feature = "web_sys")] - result.unwrap(); + input.focus().unwrap(); } false } @@ -46,10 +40,7 @@ impl Component for Model { Msg::HoverIndex(index) => self.focus_index = index, } if let Some(input) = self.refs[self.focus_index].try_into::() { - #[cfg_attr(feature = "std_web", allow(unused_variables))] - let result = input.focus(); - #[cfg(feature = "web_sys")] - result.unwrap(); + input.focus().unwrap(); } true } diff --git a/examples/web_sys/node_refs/src/main.rs b/examples/web_sys/node_refs/src/main.rs new file mode 100644 index 00000000000..f771d6d5dad --- /dev/null +++ b/examples/web_sys/node_refs/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/web_sys/npm_and_rest/Cargo.toml b/examples/web_sys/npm_and_rest/Cargo.toml new file mode 100644 index 00000000000..900658035cd --- /dev/null +++ b/examples/web_sys/npm_and_rest/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "npm_and_rest_web_sys" +version = "0.1.0" +authors = ["Denis Kolodin "] +edition = "2018" + +[dependencies] +failure = "0.1" +js-sys = "0.3" +serde = "1" +serde_derive = "1" +wasm-bindgen = "0.2" +web-sys = { version = "0.3", features = ["console"] } +yew = { path = "../../..", features = ["web_sys"] } diff --git a/examples/web_sys/npm_and_rest/src/ccxt.rs b/examples/web_sys/npm_and_rest/src/ccxt.rs new file mode 100644 index 00000000000..ae3f9de2b32 --- /dev/null +++ b/examples/web_sys/npm_and_rest/src/ccxt.rs @@ -0,0 +1,34 @@ +use js_sys::{Array, Reflect}; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; +use web_sys::console; + +#[derive(Default)] +pub struct CcxtService(Option<&'static JsValue>); + +#[wasm_bindgen] +extern "C" { + static ccxt: JsValue; +} + +impl CcxtService { + pub fn new() -> Self { + let lib: &JsValue = &ccxt; + CcxtService(Some(lib)) + } + + pub fn exchanges(&mut self) -> Vec { + let lib = self.0.as_ref().expect("ccxt library object lost"); + let v = { + let exchanges = Reflect::get(lib, &JsValue::from_str("exchanges")).unwrap(); + console::log_1(&exchanges); + exchanges + }; + let v: Vec = Array::from(&v) + .to_vec() + .into_iter() + .map(|v| v.as_string().expect("can't extract exchanges")) + .collect(); + v + } +} diff --git a/examples/web_sys/npm_and_rest/src/gravatar.rs b/examples/web_sys/npm_and_rest/src/gravatar.rs new file mode 100644 index 00000000000..6b8b0401b78 --- /dev/null +++ b/examples/web_sys/npm_and_rest/src/gravatar.rs @@ -0,0 +1,51 @@ +use failure::{format_err, Error}; +use serde_derive::Deserialize; +use yew::callback::Callback; +use yew::format::{Json, Nothing}; +use yew::services::fetch::{FetchService, FetchTask, Request, Response}; + +#[derive(Deserialize, Debug)] +pub struct Profile { + entry: Vec, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Entry { + id: String, + hash: String, + request_hash: String, + profile_url: String, + preferred_username: String, +} + +#[derive(Default)] +pub struct GravatarService { + web: FetchService, +} + +impl GravatarService { + pub fn new() -> Self { + Self { + web: FetchService::new(), + } + } + + pub fn profile(&mut self, hash: &str, callback: Callback>) -> FetchTask { + let url = format!("https://en.gravatar.com/{}.json", hash); + let handler = move |response: Response>>| { + let (meta, Json(data)) = response.into_parts(); + if meta.status.is_success() { + callback.emit(data) + } else { + // format_err! is a macro in crate `failure` + callback.emit(Err(format_err!( + "{}: error getting profile https://gravatar.com/", + meta.status + ))) + } + }; + let request = Request::get(url.as_str()).body(Nothing).unwrap(); + self.web.fetch(request, handler.into()) + } +} diff --git a/examples/web_sys/npm_and_rest/src/lib.rs b/examples/web_sys/npm_and_rest/src/lib.rs new file mode 100644 index 00000000000..c6eeff55915 --- /dev/null +++ b/examples/web_sys/npm_and_rest/src/lib.rs @@ -0,0 +1,83 @@ +#![recursion_limit = "128"] + +// Own services implementation +pub mod ccxt; +pub mod gravatar; + +use failure::Error; +use yew::services::fetch::FetchTask; +use yew::{html, Callback, Component, ComponentLink, Html, ShouldRender}; + +use ccxt::CcxtService; +use gravatar::{GravatarService, Profile}; + +pub struct Model { + link: ComponentLink, + gravatar: GravatarService, + ccxt: CcxtService, + callback: Callback>, + profile: Option, + exchanges: Vec, + task: Option, +} + +pub enum Msg { + Gravatar, + GravatarReady(Result), + Exchanges, +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + Model { + link: link.clone(), + gravatar: GravatarService::new(), + ccxt: CcxtService::new(), + callback: link.callback(Msg::GravatarReady), + profile: None, + exchanges: Vec::new(), + task: None, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::Gravatar => { + let task = self + .gravatar + .profile("205e460b479e2e5b48aec07710c08d50", self.callback.clone()); + self.task = Some(task); + } + Msg::GravatarReady(Ok(profile)) => { + self.profile = Some(profile); + } + Msg::GravatarReady(Err(_)) => { + // Can't load gravatar profile + } + Msg::Exchanges => { + self.exchanges = self.ccxt.exchanges(); + } + } + true + } + + fn view(&self) -> Html { + let view_exchange = |exchange| { + html! { +
  • { exchange }
  • + } + }; + html! { +
    + + +
      + { for self.exchanges.iter().map(view_exchange) } +
    +
    + } + } +} diff --git a/examples/web_sys/npm_and_rest/src/main.rs b/examples/web_sys/npm_and_rest/src/main.rs new file mode 100644 index 00000000000..d9c7a9efb69 --- /dev/null +++ b/examples/web_sys/npm_and_rest/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/web_sys/npm_and_rest/static/index.html b/examples/web_sys/npm_and_rest/static/index.html new file mode 100644 index 00000000000..a0e34651c2b --- /dev/null +++ b/examples/web_sys/npm_and_rest/static/index.html @@ -0,0 +1,12 @@ + + + + + Yew • npm and REST + + + + + + + diff --git a/examples/web_sys/todomvc/Cargo.toml b/examples/web_sys/todomvc/Cargo.toml new file mode 100644 index 00000000000..0af8a7727ba --- /dev/null +++ b/examples/web_sys/todomvc/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "todomvc_web_sys" +version = "0.1.0" +authors = ["Denis Kolodin "] +edition = "2018" + +[dependencies] +strum = "0.13" +strum_macros = "0.13" +serde = "1" +serde_derive = "1" +yew = { path = "../../..", features = ["web_sys"] } diff --git a/examples/web_sys/todomvc/README.md b/examples/web_sys/todomvc/README.md new file mode 100644 index 00000000000..5249541a236 --- /dev/null +++ b/examples/web_sys/todomvc/README.md @@ -0,0 +1,6 @@ +## Yew TodoMVC Demo + +This it an implementationt of [TodoMVC](http://todomvc.com/) app. + +Unlike other implementations, this stores the full state of the model, +including: all entries, entered text and chosen filter. diff --git a/examples/todomvc/src/lib.rs b/examples/web_sys/todomvc/src/lib.rs similarity index 95% rename from examples/todomvc/src/lib.rs rename to examples/web_sys/todomvc/src/lib.rs index 6db115f978c..fb0760ab248 100644 --- a/examples/todomvc/src/lib.rs +++ b/examples/web_sys/todomvc/src/lib.rs @@ -3,12 +3,9 @@ use serde_derive::{Deserialize, Serialize}; use strum::IntoEnumIterator; use strum_macros::{EnumIter, ToString}; -#[cfg(feature = "web_sys")] use yew::events::KeyboardEvent; use yew::format::Json; use yew::services::storage::{Area, StorageService}; -#[cfg(feature = "std_web")] -use yew::{events::IKeyboardEvent, KeyPressEvent}; use yew::{html, Component, ComponentLink, Href, Html, InputData, ShouldRender}; const KEY: &'static str = "yew.todomvc.self"; @@ -187,10 +184,7 @@ impl Model { placeholder="What needs to be done?" value=&self.state.value oninput=self.link.callback(|e: InputData| Msg::Update(e.value)) - onkeypress=self.link.callback(| - #[cfg(feature = "std_web")] e: KeyPressEvent, - #[cfg(feature = "web_sys")] e: KeyboardEvent - | { + onkeypress=self.link.callback(|e: KeyboardEvent| { if e.key() == "Enter" { Msg::Add } else { Msg::Nope } }) /> /* Or multiline: @@ -233,10 +227,7 @@ impl Model { value=&entry.description oninput=self.link.callback(|e: InputData| Msg::UpdateEdit(e.value)) onblur=self.link.callback(move |_| Msg::Edit(idx)) - onkeypress=self.link.callback(move | - #[cfg(feature = "std_web")] e: KeyPressEvent, - #[cfg(feature = "web_sys")] e: KeyboardEvent - | { + onkeypress=self.link.callback(move |e: KeyboardEvent| { if e.key() == "Enter" { Msg::Edit(idx) } else { Msg::Nope } }) /> } diff --git a/examples/web_sys/todomvc/src/main.rs b/examples/web_sys/todomvc/src/main.rs new file mode 100644 index 00000000000..ba7deffbd24 --- /dev/null +++ b/examples/web_sys/todomvc/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + yew::start_app::(); +} diff --git a/examples/web_sys/todomvc/static/index.html b/examples/web_sys/todomvc/static/index.html new file mode 100644 index 00000000000..4f2cf27d37f --- /dev/null +++ b/examples/web_sys/todomvc/static/index.html @@ -0,0 +1,13 @@ + + + + + Yew • TodoMVC + + + + + + + + diff --git a/examples/web_sys/two_apps/Cargo.toml b/examples/web_sys/two_apps/Cargo.toml new file mode 100644 index 00000000000..36ff90bd306 --- /dev/null +++ b/examples/web_sys/two_apps/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "two_apps_web_sys" +version = "0.1.0" +authors = ["Denis Kolodin "] +edition = "2018" + +[dependencies] +stdweb = "0.4.20" +yew = { path = "../../..", features = ["web_sys"] } diff --git a/examples/web_sys/two_apps/src/lib.rs b/examples/web_sys/two_apps/src/lib.rs new file mode 100644 index 00000000000..232ad785fd4 --- /dev/null +++ b/examples/web_sys/two_apps/src/lib.rs @@ -0,0 +1,83 @@ +#![recursion_limit = "256"] + +use yew::html::Scope; +/// This example demonstrates low-level usage of scopes. +use yew::{html, Component, ComponentLink, Html, ShouldRender}; + +pub struct Model { + link: ComponentLink, + scope: Option>, + selector: &'static str, + title: String, +} + +pub enum Msg { + SetScope(Scope), + SendToOpposite(String), + SetTitle(String), +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + Model { + link, + scope: None, + selector: "", + title: "Nothing".into(), + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::SetScope(scope) => { + self.scope = Some(scope); + } + Msg::SendToOpposite(title) => { + self.scope + .as_mut() + .unwrap() + .send_message(Msg::SetTitle(title)); + } + Msg::SetTitle(title) => { + match title.as_ref() { + "Ping" => { + self.scope + .as_mut() + .unwrap() + .send_message(Msg::SetTitle("Pong".into())); + } + "Pong" => { + self.scope + .as_mut() + .unwrap() + .send_message(Msg::SetTitle("Pong Done".into())); + } + "Pong Done" => { + self.scope + .as_mut() + .unwrap() + .send_message(Msg::SetTitle("Ping Done".into())); + } + _ => {} + } + self.title = title; + } + } + true + } + + fn view(&self) -> Html { + html! { +
    +

    { format!("{} received <{}>", self.selector, self.title) }

    + + + + +
    + } + } +} diff --git a/examples/web_sys/two_apps/src/main.rs b/examples/web_sys/two_apps/src/main.rs new file mode 100644 index 00000000000..a0f3cc8018c --- /dev/null +++ b/examples/web_sys/two_apps/src/main.rs @@ -0,0 +1,20 @@ +use two_apps_web_sys::{Model, Msg}; +use yew::html::Scope; +use yew::App; + +fn mount_app(selector: &'static str, app: App) -> Scope { + let document = yew::utils::document(); + let element = document.query_selector(selector).unwrap().unwrap(); + app.mount(element) +} + +fn main() { + yew::initialize(); + let first_app = App::new(); + let second_app = App::new(); + let to_first = mount_app(".first-app", first_app); + let to_second = mount_app(".second-app", second_app); + to_first.send_message(Msg::SetScope(to_second.clone())); + to_second.send_message(Msg::SetScope(to_first.clone())); + yew::run_loop(); +} diff --git a/examples/web_sys/two_apps/static/index.html b/examples/web_sys/two_apps/static/index.html new file mode 100644 index 00000000000..c01b03cda9c --- /dev/null +++ b/examples/web_sys/two_apps/static/index.html @@ -0,0 +1,14 @@ + + + + + Yew • Two Apps + + + +
    +
    + + + + From 32811a3b3e3fb18795440649242357fc39d6e01b Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 12 Jan 2020 15:46:12 +0100 Subject: [PATCH 04/12] Fixing the shell script. --- examples/build_all.sh | 78 +++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/examples/build_all.sh b/examples/build_all.sh index ecaa91d8ef7..15696561fe3 100755 --- a/examples/build_all.sh +++ b/examples/build_all.sh @@ -15,11 +15,18 @@ function build_std_web() { if [[ $example == static* ]]; then continue fi - echo "Building: $example" - cd $example - cargo update - cargo web build --target wasm32-unknown-unknown - cd .. + if [[ $example == web_sys* ]]; then + continue + fi + if [[ $example == std_web* ]]; then + build_std_web() + else + echo "Building: $example" + cd $example + cargo update + cargo web build --target wasm32-unknown-unknown + cd .. + fi done } @@ -31,12 +38,19 @@ function build_web_sys() { if [[ $example == static* ]]; then continue fi - echo "Building: $example" - cd $example - cargo update - cargo build --target wasm32-unknown-unknown - wasm-bindgen --target web --no-typescript --out-dir ../static/ --out-name wasm ../target/wasm32-unknown-unknown/debug/$example.wasm - cd .. + if [[ $example == std_web* ]]; then + continue + fi + if [[ $example == web_sys* ]]; then + build_web_sys() + else + echo "Building: $example" + cd $example + cargo update + cargo build --target wasm32-unknown-unknown + wasm-bindgen --target web --no-typescript --out-dir ../static/ --out-name wasm ../target/wasm32-unknown-unknown/debug/$example.wasm + cd .. + fi done } @@ -49,12 +63,19 @@ function run_std_web() { if [[ $example == static* ]]; then continue fi - echo "Running: $example" - cd $example - cargo web start --target wasm32-unknown-unknown & - PID=$! - wait $PID - cd .. + if [[ $example == web_sys* ]]; then + continue + fi + if [[ $example == std_web* ]]; then + run_std_web() + else + echo "Running: $example" + cd $example + cargo web start --target wasm32-unknown-unknown & + PID=$! + wait $PID + cd .. + fi done } @@ -67,14 +88,21 @@ function run_web_sys() { if [[ $example == static* ]]; then continue fi - echo "Running: $example" - cd $example - cargo build --target wasm32-unknown-unknown - wasm-bindgen --target web --no-typescript --out-dir ../static/ --out-name wasm ../target/wasm32-unknown-unknown/debug/$example.wasm - http -r ../static/ - PID=$! - wait $PID - cd .. + if [[ $example == std_web* ]]; then + continue + fi + if [[ $example == web_sys* ]]; then + run_web_sys() + else + echo "Running: $example" + cd $example + cargo build --target wasm32-unknown-unknown + wasm-bindgen --target web --no-typescript --out-dir ../static/ --out-name wasm ../target/wasm32-unknown-unknown/debug/$example.wasm + http -r ../static/ + PID=$! + wait $PID + cd .. + fi done } From 6073cd3915214684f3f3229d0161a9b6afb7d7ff Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 15 Jan 2020 14:21:21 +0100 Subject: [PATCH 05/12] Trying to reset file permissions. --- ci/run_tests.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 ci/run_tests.sh diff --git a/ci/run_tests.sh b/ci/run_tests.sh old mode 100644 new mode 100755 From 1175704192cdc1099403b55b356c75856c5e0b95 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 19 Jan 2020 12:28:28 +0100 Subject: [PATCH 06/12] Update to new reader API. --- examples/std_web/file_upload/src/lib.rs | 4 ++-- examples/web_sys/file_upload/src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/std_web/file_upload/src/lib.rs b/examples/std_web/file_upload/src/lib.rs index 9f909331434..b0eee363402 100644 --- a/examples/std_web/file_upload/src/lib.rs +++ b/examples/std_web/file_upload/src/lib.rs @@ -49,10 +49,10 @@ impl Component for Model { let task = { if chunks { let callback = self.link.callback(Msg::Chunk); - self.reader.read_file_by_chunks(file, callback, 10) + self.reader.read_file_by_chunks(file, callback, 10).unwrap() } else { let callback = self.link.callback(Msg::Loaded); - self.reader.read_file(file, callback) + self.reader.read_file(file, callback).unwrap() } }; self.tasks.push(task); diff --git a/examples/web_sys/file_upload/src/lib.rs b/examples/web_sys/file_upload/src/lib.rs index 86f1c66f64b..5d1dcd005c8 100644 --- a/examples/web_sys/file_upload/src/lib.rs +++ b/examples/web_sys/file_upload/src/lib.rs @@ -49,10 +49,10 @@ impl Component for Model { let task = { if chunks { let callback = self.link.callback(Msg::Chunk); - self.reader.read_file_by_chunks(file, callback, 10) + self.reader.read_file_by_chunks(file, callback, 10).unwrap() } else { let callback = self.link.callback(Msg::Loaded); - self.reader.read_file(file, callback) + self.reader.read_file(file, callback).unwrap() } }; self.tasks.push(task); From 79e259a90c4bcb03290408eb0c76e8da430d6729 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 23 Jan 2020 16:38:41 +0100 Subject: [PATCH 07/12] Update to new fetch API. --- examples/dashboard/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/dashboard/src/lib.rs b/examples/dashboard/src/lib.rs index 971903e4eb6..6916363c628 100644 --- a/examples/dashboard/src/lib.rs +++ b/examples/dashboard/src/lib.rs @@ -92,9 +92,9 @@ impl Model { ); let request = Request::get("/data.json").body(Nothing).unwrap(); if binary { - self.fetch_service.fetch_binary(request, callback) + self.fetch_service.fetch_binary(request, callback).unwrap() } else { - self.fetch_service.fetch(request, callback) + self.fetch_service.fetch(request, callback).unwrap() } } @@ -112,9 +112,9 @@ impl Model { ); let request = Request::get("/data.toml").body(Nothing).unwrap(); if binary { - self.fetch_service.fetch_binary(request, callback) + self.fetch_service.fetch_binary(request, callback).unwrap() } else { - self.fetch_service.fetch(request, callback) + self.fetch_service.fetch(request, callback).unwrap() } } } From b0d8179a2daf8485cfd690f08a06629821fc73d7 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 23 Jan 2020 18:24:33 +0100 Subject: [PATCH 08/12] Update to new fetch API. --- examples/std_web/npm_and_rest/src/gravatar.rs | 2 +- examples/web_sys/npm_and_rest/src/gravatar.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/std_web/npm_and_rest/src/gravatar.rs b/examples/std_web/npm_and_rest/src/gravatar.rs index 2dafae95aa6..72c035852ad 100644 --- a/examples/std_web/npm_and_rest/src/gravatar.rs +++ b/examples/std_web/npm_and_rest/src/gravatar.rs @@ -45,6 +45,6 @@ impl GravatarService { } }; let request = Request::get(url.as_str()).body(Nothing).unwrap(); - self.web.fetch(request, handler.into()) + self.web.fetch(request, handler.into()).unwrap() } } diff --git a/examples/web_sys/npm_and_rest/src/gravatar.rs b/examples/web_sys/npm_and_rest/src/gravatar.rs index 6b8b0401b78..1c504c0586e 100644 --- a/examples/web_sys/npm_and_rest/src/gravatar.rs +++ b/examples/web_sys/npm_and_rest/src/gravatar.rs @@ -46,6 +46,6 @@ impl GravatarService { } }; let request = Request::get(url.as_str()).body(Nothing).unwrap(); - self.web.fetch(request, handler.into()) + self.web.fetch(request, handler.into()).unwrap() } } From 1a749259891495debc63c0285a4596793e00ba04 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 23 Jan 2020 19:27:45 +0100 Subject: [PATCH 09/12] Re-enable examples CI. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0524efc1ad1..b4971cd63b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,4 +41,4 @@ install: script: - ./ci/run_checks.sh - CHROMEDRIVER=$(pwd)/chromedriver ./ci/run_tests.sh - # - CHROMEDRIVER=$(pwd)/chromedriver ./ci/check_examples.sh + - CHROMEDRIVER=$(pwd)/chromedriver ./ci/check_examples.sh From 673b4252eef91e893cd586eb397280a387307e08 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 27 Jan 2020 17:26:34 +0100 Subject: [PATCH 10/12] Deleted duplicate example. --- examples/js_callback/Cargo.toml | 16 --- examples/js_callback/README.md | 8 -- examples/js_callback/src/lib.rs | 124 ------------------ examples/js_callback/src/main.rs | 3 - .../js_callback/static/get-payload-script.js | 9 -- examples/js_callback/static/index.html | 11 -- 6 files changed, 171 deletions(-) delete mode 100644 examples/js_callback/Cargo.toml delete mode 100644 examples/js_callback/README.md delete mode 100644 examples/js_callback/src/lib.rs delete mode 100644 examples/js_callback/src/main.rs delete mode 100644 examples/js_callback/static/get-payload-script.js delete mode 100644 examples/js_callback/static/index.html diff --git a/examples/js_callback/Cargo.toml b/examples/js_callback/Cargo.toml deleted file mode 100644 index f9be3a4291d..00000000000 --- a/examples/js_callback/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "js_callback" -version = "0.1.0" -authors = ["Scott Steele "] -edition = "2018" - -[dependencies] -yew = { path = "../.." } -stdweb = { version = "^0.4.20", optional = true } - -[target.'cfg(all(target_arch = "wasm32", not(cargo_web)))'.dependencies] -wasm-bindgen = "0.2.58" - -[features] -std_web = ["stdweb", "yew/std_web"] -web_sys = ["yew/web_sys"] diff --git a/examples/js_callback/README.md b/examples/js_callback/README.md deleted file mode 100644 index 027f020adec..00000000000 --- a/examples/js_callback/README.md +++ /dev/null @@ -1,8 +0,0 @@ -(Asynchronous) callback from Javascript -======================================= - -The purpose of this example is to demonstrate a simple case of asynchronously -sending a message back into the component update loop. - -See https://github.com/yewstack/yew/issues/316 for discussion on what -motivated this example. diff --git a/examples/js_callback/src/lib.rs b/examples/js_callback/src/lib.rs deleted file mode 100644 index 8c9efb7abe1..00000000000 --- a/examples/js_callback/src/lib.rs +++ /dev/null @@ -1,124 +0,0 @@ -#![recursion_limit = "128"] -#![deny(warnings)] - -#[cfg(feature = "std_web")] -#[allow(unused_imports)] -use stdweb::{_js_impl, js}; -#[cfg(feature = "web_sys")] -use wasm_bindgen::{closure::Closure, prelude::wasm_bindgen, JsValue}; -use yew::prelude::*; - -pub struct Model { - payload: String, - // Pointless field just to have something that's been manipulated - debugged_payload: String, - link: ComponentLink, -} - -pub enum Msg { - Payload(String), - AsyncPayload, -} - -impl Component for Model { - type Message = Msg; - type Properties = (); - - fn create(_: Self::Properties, link: ComponentLink) -> Self { - let payload = String::default(); - let debugged_payload = format!("{:?}", payload); - Self { - payload, - debugged_payload, - link, - } - } - - fn update(&mut self, msg: Self::Message) -> ShouldRender { - use Msg::*; - match msg { - Payload(payload) => { - if payload != self.payload { - self.debugged_payload = format!("{:?}", payload); - self.payload = payload; - true - } else { - false - } - } - AsyncPayload => { - get_payload_later(self.link.callback(Msg::Payload)); - false - } - } - } - - fn change(&mut self, _: Self::Properties) -> ShouldRender { - false - } - - fn view(&self) -> Html { - html! { -
    - - - -

    - { nbsp(self.debugged_payload.as_str()) } -

    -
    - } - } -} - -fn nbsp(string: T) -> String -where - String: From, -{ - String::from(string).replace(' ', "\u{00a0}") -} - -#[cfg(feature = "std_web")] -fn get_payload() -> String { - (js! { return window.get_payload() }).into_string().unwrap() -} - -#[cfg(feature = "web_sys")] -#[wasm_bindgen] -extern "C" { - fn get_payload() -> String; -} - -#[cfg(feature = "std_web")] -fn get_payload_later(payload_callback: Callback) { - let callback = move |payload: String| payload_callback.emit(payload); - js! { - // Note: The semi-colons appear to be strictly necessary here due to - // how the interpolation is implemented - var callback = @{callback}; - window.get_payload_later(function(payload) { - callback(payload); - callback.drop(); - }); - }; -} - -#[cfg(feature = "web_sys")] -#[wasm_bindgen] -extern "C" { - #[wasm_bindgen(js_name = "get_payload_later")] - fn get_payload_later_js(payload_callback: JsValue); -} - -#[cfg(feature = "web_sys")] -fn get_payload_later(payload_callback: Callback) { - let callback = Closure::once_into_js(move |payload: String| payload_callback.emit(payload)); - get_payload_later_js(callback); -} diff --git a/examples/js_callback/src/main.rs b/examples/js_callback/src/main.rs deleted file mode 100644 index b03f7331e40..00000000000 --- a/examples/js_callback/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - yew::start_app::(); -} diff --git a/examples/js_callback/static/get-payload-script.js b/examples/js_callback/static/get-payload-script.js deleted file mode 100644 index 2735ee185c3..00000000000 --- a/examples/js_callback/static/get-payload-script.js +++ /dev/null @@ -1,9 +0,0 @@ -function get_payload() { - return (new Date()).toString() -} - -function get_payload_later(callback) { - setTimeout(() => { - callback(get_payload()) - }, 1000) -} diff --git a/examples/js_callback/static/index.html b/examples/js_callback/static/index.html deleted file mode 100644 index 8e47c484fcc..00000000000 --- a/examples/js_callback/static/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - (Asynchronous) callback from JavaScript - - - - - - From 6b4ec4335859a4d304c306ac45e5c6c581fb3738 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 27 Jan 2020 18:20:26 +0100 Subject: [PATCH 11/12] Some fixes. --- examples/std_web/counter/Cargo.toml | 2 +- examples/std_web/npm_and_rest/Cargo.toml | 2 +- examples/web_sys/counter/Cargo.toml | 2 +- examples/web_sys/npm_and_rest/Cargo.toml | 2 +- examples/web_sys/npm_and_rest/src/gravatar.rs | 4 ++-- examples/web_sys/npm_and_rest/src/lib.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/std_web/counter/Cargo.toml b/examples/std_web/counter/Cargo.toml index e98688967f8..0c6e1418de9 100644 --- a/examples/std_web/counter/Cargo.toml +++ b/examples/std_web/counter/Cargo.toml @@ -6,4 +6,4 @@ edition = "2018" [dependencies] stdweb = "0.4.20" -yew = { path = "../../..", features = ["std_web"] } +yew = { path = "../../..", features = ["services", "std_web"] } diff --git a/examples/std_web/npm_and_rest/Cargo.toml b/examples/std_web/npm_and_rest/Cargo.toml index d1759f348e7..fcfcf3f49d6 100644 --- a/examples/std_web/npm_and_rest/Cargo.toml +++ b/examples/std_web/npm_and_rest/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Denis Kolodin "] edition = "2018" [dependencies] -failure = "0.1" +anyhow = "1" serde = "1" serde_derive = "1" stdweb = "0.4.20" diff --git a/examples/web_sys/counter/Cargo.toml b/examples/web_sys/counter/Cargo.toml index c75e76b899f..3e687d650a1 100644 --- a/examples/web_sys/counter/Cargo.toml +++ b/examples/web_sys/counter/Cargo.toml @@ -6,4 +6,4 @@ edition = "2018" [dependencies] js-sys = "0.3" -yew = { path = "../../..", features = ["web_sys"] } +yew = { path = "../../..", features = ["services", "web_sys"] } diff --git a/examples/web_sys/npm_and_rest/Cargo.toml b/examples/web_sys/npm_and_rest/Cargo.toml index 900658035cd..7b44cfe7131 100644 --- a/examples/web_sys/npm_and_rest/Cargo.toml +++ b/examples/web_sys/npm_and_rest/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Denis Kolodin "] edition = "2018" [dependencies] -failure = "0.1" +anyhow = "1" js-sys = "0.3" serde = "1" serde_derive = "1" diff --git a/examples/web_sys/npm_and_rest/src/gravatar.rs b/examples/web_sys/npm_and_rest/src/gravatar.rs index 1c504c0586e..845a9d71785 100644 --- a/examples/web_sys/npm_and_rest/src/gravatar.rs +++ b/examples/web_sys/npm_and_rest/src/gravatar.rs @@ -1,4 +1,4 @@ -use failure::{format_err, Error}; +use anyhow::{anyhow, Error}; use serde_derive::Deserialize; use yew::callback::Callback; use yew::format::{Json, Nothing}; @@ -39,7 +39,7 @@ impl GravatarService { callback.emit(data) } else { // format_err! is a macro in crate `failure` - callback.emit(Err(format_err!( + callback.emit(Err(anyhow!( "{}: error getting profile https://gravatar.com/", meta.status ))) diff --git a/examples/web_sys/npm_and_rest/src/lib.rs b/examples/web_sys/npm_and_rest/src/lib.rs index c6eeff55915..97b6a16c116 100644 --- a/examples/web_sys/npm_and_rest/src/lib.rs +++ b/examples/web_sys/npm_and_rest/src/lib.rs @@ -4,7 +4,7 @@ pub mod ccxt; pub mod gravatar; -use failure::Error; +use anyhow::Error; use yew::services::fetch::FetchTask; use yew::{html, Callback, Component, ComponentLink, Html, ShouldRender}; From 3c03fe56564783eb1eb03ccecee33d75f5e65a0a Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 27 Jan 2020 18:37:24 +0100 Subject: [PATCH 12/12] Fix rand build. --- examples/game_of_life/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/game_of_life/Cargo.toml b/examples/game_of_life/Cargo.toml index 8c82e077545..a67d8ed4d0e 100644 --- a/examples/game_of_life/Cargo.toml +++ b/examples/game_of_life/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Diego Cardoso ", edition = "2018" [dependencies] -rand = { version = "0.6.5", features = ["wasm-bindgen"] } +rand = "0.6.5" log = "0.4" web_logger = "0.2" yew = { path = "../.." }