Skip to content

Instantly share code, notes, and snippets.

@ntr-808
Created September 5, 2018 11:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ntr-808/eb805124d55a0adba2b95ff1428fba76 to your computer and use it in GitHub Desktop.
Save ntr-808/eb805124d55a0adba2b95ff1428fba76 to your computer and use it in GitHub Desktop.
extern crate failure;
#[macro_use]
extern crate serde_derive;
extern crate serde_cbor;
#[macro_use]
extern crate yew;
use failure::Error;
use yew::prelude::*;
use yew::services::Task;
// use yew::services::fetch::{FetchTask, Request, Response};
use yew::format::{Nothing, Json, Cbor};
use yew::services::websocket::{WebSocketService, WebSocketTask, WebSocketStatus};
use yew::services::ConsoleService;
use serde_cbor::{Value,to_value};
struct Cryp {
name: String,
}
pub struct Model {
ws_service: WebSocketService,
link: ComponentLink<Model>,
data: Option<Value>,
ws: Option<WebSocketTask>,
console: ConsoleService,
}
pub enum WsAction {
Connect,
SendData,
Disconnect,
Lost,
}
pub enum Msg {
WsAction(WsAction),
WsReady(Result<WsResponse, Error>),
Ignore,
}
impl From<WsAction> for Msg {
fn from(action: WsAction) -> Self {
Msg::WsAction(action)
}
}
/// This type is used as a request which sent to websocket connection.
#[derive(Serialize, Debug)]
struct WsRequest {
value: u32,
}
/// This type is an expected response from a websocket connection.
#[derive(Deserialize, Debug)]
pub struct WsResponse {
value: Vec<u8>,
}
impl Component for Model {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
Model {
ws_service: WebSocketService::new(),
console: ConsoleService::new(),
link,
data: None,
ws: None,
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::WsAction(action) => {
match action {
WsAction::Connect => {
self.console.log("connecting");
let callback = self.link.send_back(|Cbor(data)| Msg::WsReady(data));
let notification = self.link.send_back(|status| {
match status {
WebSocketStatus::Opened => Msg::Ignore,
WebSocketStatus::Closed | WebSocketStatus::Error => WsAction::Lost.into(),
}
}) ;
let task = self.ws_service.connect("ws://localhost:40000/", callback, notification);
self.ws = Some(task);
}
WsAction::SendData => {
let request = WsRequest {
value: 321,
};
self.ws.as_mut().unwrap().send_binary(Cbor(&request));
}
WsAction::Disconnect => {
self.ws.take().unwrap().cancel();
}
WsAction::Lost => {
self.ws = None;
}
}
}
Msg::WsReady(response) => {
self.console.log("ready");
self.data = match response {
Ok(v) => {
self.console.log("yay");
Some(to_value(v.value).unwrap())
},
Err(e) => {
self.console.log("there was an error");
None
},
}
}
Msg::Ignore => {
return false;
}
}
true
}
}
impl Renderable<Model> for Model {
fn view(&self) -> Html<Self> {
html! {
<div>
<nav class="menu",>
{ self.view_data() }
<button disabled=self.ws.is_some(),
onclick=|_| WsAction::Connect.into(),>{ "Connect To WebSocket" }</button>
<button disabled=self.ws.is_none(),
onclick=|_| WsAction::SendData.into(),>{ "Send To WebSocket" }</button>
<button disabled=self.ws.is_none(),
onclick=|_| WsAction::Disconnect.into(),>{ "Close WebSocket connection" }</button>
</nav>
</div>
}
}
}
impl Model {
fn view_data(&self) -> Html<Model> {
if let Some(value) = self.data.clone() {
html! {
<p>{ "Got a value" }</p>
}
} else {
html! {
<p>{ "Data hasn't fetched yet." }</p>
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment