hul ignennem
This commit is contained in:
@@ -13,3 +13,6 @@ common.workspace = true
|
||||
futures = "0.3.28"
|
||||
wasm-bindgen-futures = "0.4.36"
|
||||
reqwasm = "0.5.0"
|
||||
yew-agent = "0.2.0"
|
||||
serde.workspace = true
|
||||
serde_json = "1.0.96"
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Achievements</title>
|
||||
<link data-trunk rel="rust" href="Cargo.toml" data-bin="app" data-type="main" />
|
||||
<link data-trunk rel="rust" href="Cargo.toml" data-bin="event_bus" data-type="worker" />
|
||||
</head>
|
||||
</html>
|
||||
|
||||
4
crates/frontend/src/bin/app.rs
Normal file
4
crates/frontend/src/bin/app.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
wasm_logger::init(wasm_logger::Config::default());
|
||||
yew::Renderer::<frontend::App>::new().render();
|
||||
}
|
||||
6
crates/frontend/src/bin/event_bus.rs
Normal file
6
crates/frontend/src/bin/event_bus.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
use frontend::event_bus::EventBus;
|
||||
use yew_agent::PublicWorker;
|
||||
|
||||
fn main() {
|
||||
EventBus::register();
|
||||
}
|
||||
@@ -1,26 +1,75 @@
|
||||
use crate::event_bus::EventBus;
|
||||
use crate::services::websocket::WebsocketService;
|
||||
use crate::AppState;
|
||||
use crate::Route;
|
||||
use common::Achievement;
|
||||
use std::rc::Rc;
|
||||
use yew::functional::*;
|
||||
use yew::prelude::*;
|
||||
use yew_agent::Bridge;
|
||||
use yew_agent::Bridged;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
#[function_component(Root)]
|
||||
pub fn root() -> Html {
|
||||
let app_state = use_context::<crate::AppState>().expect("no context found");
|
||||
pub struct Root {
|
||||
wss: WebsocketService,
|
||||
_producer: Box<dyn Bridge<EventBus>>,
|
||||
achievements: Vec<Achievement>,
|
||||
}
|
||||
|
||||
let achievements = app_state
|
||||
.state
|
||||
.achievements
|
||||
.iter()
|
||||
.map(|a| {
|
||||
html! {
|
||||
<p>{format!("{}", a.goal)}</p>
|
||||
pub enum Msg {
|
||||
HandleMsg(String),
|
||||
}
|
||||
|
||||
impl Component for Root {
|
||||
type Message = Msg;
|
||||
|
||||
type Properties = ();
|
||||
|
||||
fn create(ctx: &Context<Self>) -> Self {
|
||||
// let ctx_link = ctx
|
||||
// .link()
|
||||
// .context::<AppState>(Callback::noop())
|
||||
// .expect("context to be set");
|
||||
|
||||
let wss = WebsocketService::new();
|
||||
|
||||
let cb = {
|
||||
let link = ctx.link().clone();
|
||||
move |e| link.send_message(Msg::HandleMsg(e))
|
||||
};
|
||||
|
||||
Self {
|
||||
wss,
|
||||
_producer: EventBus::bridge(Rc::new(cb)),
|
||||
achievements: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||
match msg {
|
||||
Msg::HandleMsg(s) => {
|
||||
let msg: common::WebSocketMessage = serde_json::from_str(&s).unwrap();
|
||||
self.achievements = msg.achievements;
|
||||
true
|
||||
}
|
||||
})
|
||||
.collect::<Html>();
|
||||
}
|
||||
}
|
||||
|
||||
html! {
|
||||
<div>
|
||||
{achievements}
|
||||
</div>
|
||||
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||
let achievements = self
|
||||
.achievements
|
||||
.iter()
|
||||
.map(|a| {
|
||||
html! {
|
||||
<p>{format!("{}", a.goal)}</p>
|
||||
}
|
||||
})
|
||||
.collect::<Html>();
|
||||
|
||||
html! {
|
||||
<div>
|
||||
{achievements}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
54
crates/frontend/src/event_bus.rs
Normal file
54
crates/frontend/src/event_bus.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::collections::HashSet;
|
||||
use yew_agent::HandlerId;
|
||||
use yew_agent::Public;
|
||||
use yew_agent::WorkerLink;
|
||||
|
||||
pub struct EventBus {
|
||||
link: WorkerLink<Self>,
|
||||
subscribers: HashSet<HandlerId>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum EventBusInput {
|
||||
EventBusMsg(String),
|
||||
}
|
||||
|
||||
impl yew_agent::Worker for EventBus {
|
||||
type Reach = Public<Self>;
|
||||
type Input = EventBusInput;
|
||||
type Output = String;
|
||||
type Message = ();
|
||||
|
||||
fn create(link: WorkerLink<Self>) -> Self {
|
||||
Self {
|
||||
link,
|
||||
subscribers: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) {}
|
||||
|
||||
fn handle_input(&mut self, msg: Self::Input, id: HandlerId) {
|
||||
match msg {
|
||||
EventBusInput::EventBusMsg(s) => {
|
||||
for sub in &self.subscribers {
|
||||
self.link.respond(*sub, s.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn connected(&mut self, id: HandlerId) {
|
||||
self.subscribers.insert(id);
|
||||
}
|
||||
|
||||
fn disconnected(&mut self, id: HandlerId) {
|
||||
self.subscribers.remove(&id);
|
||||
}
|
||||
|
||||
fn name_of_resource() -> &'static str {
|
||||
"event_bus.js"
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use yew_router::Routable;
|
||||
use yew_router::Switch;
|
||||
|
||||
mod components;
|
||||
pub mod event_bus;
|
||||
mod services;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Routable)]
|
||||
@@ -35,16 +36,7 @@ struct AppStateInner {
|
||||
type AppState = Rc<AppStateInner>;
|
||||
|
||||
#[function_component]
|
||||
fn App() -> Html {
|
||||
// let counter = use_state(|| 0);
|
||||
// let onclick = {
|
||||
// let counter = counter.clone();
|
||||
// move |_| {
|
||||
// let value = *counter + 1;
|
||||
// counter.set(value);
|
||||
// }
|
||||
// };
|
||||
|
||||
pub fn App() -> Html {
|
||||
let ctx = use_state(|| Rc::new(AppStateInner::default()));
|
||||
|
||||
html! {
|
||||
@@ -57,8 +49,3 @@ fn App() -> Html {
|
||||
</ContextProvider<AppState>>
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
wasm_logger::init(wasm_logger::Config::default());
|
||||
yew::Renderer::<App>::new().render();
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
use crate::event_bus::EventBus;
|
||||
use crate::event_bus::EventBusInput;
|
||||
use futures::channel::mpsc::Sender;
|
||||
use futures::SinkExt;
|
||||
use futures::StreamExt;
|
||||
use reqwasm::websocket::futures::WebSocket;
|
||||
use reqwasm::websocket::Message;
|
||||
use wasm_bindgen_futures::spawn_local;
|
||||
use yew_agent::Dispatched;
|
||||
|
||||
pub struct WebsocketService {
|
||||
pub tx: Sender<String>,
|
||||
@@ -11,11 +14,12 @@ pub struct WebsocketService {
|
||||
|
||||
impl WebsocketService {
|
||||
pub fn new() -> Self {
|
||||
let ws = WebSocket::open("ws://127.0.0.1:4000").unwrap();
|
||||
let ws = WebSocket::open("ws://127.0.0.1:4000/ws").unwrap();
|
||||
|
||||
let (mut write, mut read) = ws.split();
|
||||
|
||||
let (in_tx, mut in_rx) = futures::channel::mpsc::channel::<String>(1000);
|
||||
let mut event_bus = EventBus::dispatcher();
|
||||
|
||||
spawn_local(async move {
|
||||
while let Some(s) = in_rx.next().await {
|
||||
@@ -29,15 +33,17 @@ impl WebsocketService {
|
||||
match msg {
|
||||
Ok(Message::Text(data)) => {
|
||||
log::debug!("from websocket: {}", data);
|
||||
event_bus.send(EventBusInput::EventBusMsg(data));
|
||||
}
|
||||
Ok(Message::Bytes(b)) => {
|
||||
let decoded = std::str::from_utf8(&b);
|
||||
if let Ok(val) = decoded {
|
||||
log::debug!("from websocket: {}", val);
|
||||
event_bus.send(EventBusInput::EventBusMsg(val.into()));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("ws: {:?}", e)
|
||||
log::error!("ws: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user