Skip to content

Instantly share code, notes, and snippets.

@MartinKavik
Created Aug 16, 2019
Embed
What would you like to do?
Toy seed app refactored
// Replace *lib.rs* in the seed-quickstart project with this file,
// then run `cargo make build && cargo make serve`.
#[macro_use]
extern crate seed;
use seed::prelude::*;
// Model
enum AuthModel {
Unknown,
Unauthenticated,
Authenticated(String),
}
enum StuffModel {
Disconnected,
Connected(String),
}
struct Model {
auth_model: AuthModel,
stuff_model: StuffModel,
}
impl Default for Model {
fn default() -> Self {
Self {
auth_model: AuthModel::Unknown,
stuff_model: StuffModel::Disconnected,
}
}
}
// Update
#[derive(Clone, Debug)]
enum Msg {
WhoAmI,
Auth(AuthMsg),
Stuff(StuffMsg),
}
#[derive(Clone, Debug)]
enum AuthMsg {
Login(Option<String>),
}
#[derive(Clone, Debug)]
enum StuffMsg {
Connect(String),
}
fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
log!("update fn handling msg:", msg);
match msg {
Msg::Auth(msg) => {
update_auth(msg, &mut model.auth_model, &mut orders.proxy(Msg::Auth));
orders.send_msg(Msg::WhoAmI);
}
Msg::Stuff(msg) => {
update_stuff(msg, &mut model.stuff_model, &mut orders.proxy(Msg::Stuff));
}
Msg::WhoAmI => {
if let AuthModel::Authenticated(user) = &model.auth_model {
update_stuff(
StuffMsg::Connect(user.clone()),
&mut model.stuff_model,
&mut orders.proxy(Msg::Stuff),
);
}
}
}
}
fn update_auth(msg: AuthMsg, model: &mut AuthModel, _orders: &mut impl Orders<AuthMsg>) {
log!("update auth fn handling msg:", msg);
match msg {
AuthMsg::Login(res) => {
log!("updating login with res:", res);
match res {
Some(user) => *model = AuthModel::Authenticated(user),
None => *model = AuthModel::Unauthenticated,
}
}
}
}
fn update_stuff(msg: StuffMsg, model: &mut StuffModel, _orders: &mut impl Orders<StuffMsg>) {
log!("update stuff fn handling msg:", msg);
match msg {
StuffMsg::Connect(user) => {
*model = StuffModel::Connected(user);
},
}
}
// View
fn view(model: &Model) -> impl View<Msg> {
match &model.auth_model {
AuthModel::Unknown | AuthModel::Unauthenticated => {
view_auth(&model.auth_model).els().map_message(Msg::Auth)
}
AuthModel::Authenticated(_) => view_stuff(&model.stuff_model).els().map_message(Msg::Stuff),
}
}
fn view_auth(model: &AuthModel) -> impl View<AuthMsg> {
match model {
AuthModel::Unknown => div![
"auth state is unknown",
],
AuthModel::Unauthenticated => div![
// login form goes here
"log in as Alice",
button![
"I am Alice",
simple_ev(Ev::Click, AuthMsg::Login(Some("Alice".to_string()))),
],
],
AuthModel::Authenticated(_) => {
error!("Uh oh, authenticated model should never be handled by auth view fn");
div!["If you're seeing this, there is a big problem!!!"]
}
}
}
fn view_stuff(model: &StuffModel) -> impl View<StuffMsg> {
match model {
StuffModel::Disconnected => div![
div![
"not yet connected",
],
],
StuffModel::Connected(user) => div![format!("Connected as {}", user),],
}
}
fn init(_: Url, orders: &mut impl Orders<Msg>) -> Model {
// check browser cookie cache
orders.send_msg(Msg::Auth(AuthMsg::Login(None)));
Model::default()
}
#[wasm_bindgen(start)]
pub fn render() {
seed::App::build(init, update, view)
.finish()
.run();
}
@MartinKavik
Copy link
Author

MartinKavik commented Aug 16, 2019

Based on https://gist.github.com/wayeast/59b510f5163ca78273c413c34d9b2b12.

Changes:

  • no did_mount
  • no seed::update => no need to use serde and trigger_update_handler (and there are better alternatives when you want to call update)
  • "cookie check" moved into fn init
  • Msg::WhoAmI is sent in Msg::Auth handler

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment