mirror of
https://github.com/zaphar/kitchen.git
synced 2025-07-22 19:40:14 -04:00
LinearSignal as a helper type
This commit is contained in:
parent
b496cf9568
commit
2ea0339ad1
@ -99,6 +99,7 @@ impl LocalStore {
|
|||||||
.expect("Failed to set our app state");
|
.expect("Failed to set our app state");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(jwall): Is this never used?
|
||||||
pub fn fetch_app_state(&self) -> Option<AppState> {
|
pub fn fetch_app_state(&self) -> Option<AppState> {
|
||||||
self.store.get("app_state").map_or(None, |val| {
|
self.store.get("app_state").map_or(None, |val| {
|
||||||
val.map(|s| from_str(&s).expect("Failed to deserialize app state"))
|
val.map(|s| from_str(&s).expect("Failed to deserialize app state"))
|
||||||
|
@ -28,7 +28,7 @@ use wasm_bindgen::throw_str;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{HttpStore, LocalStore},
|
api::{HttpStore, LocalStore},
|
||||||
components,
|
components, linear::LinearSignal,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
@ -166,9 +166,7 @@ impl StateMachine {
|
|||||||
original: &Signal<AppState>,
|
original: &Signal<AppState>,
|
||||||
) -> Result<(), crate::api::Error> {
|
) -> Result<(), crate::api::Error> {
|
||||||
// TODO(jwall): Load plan state from local_store first.
|
// TODO(jwall): Load plan state from local_store first.
|
||||||
if let Some(app_state) = local_store.fetch_app_state() {
|
let original: LinearSignal<AppState> = original.into();
|
||||||
original.set_silent(app_state);
|
|
||||||
}
|
|
||||||
let mut state = original.get().as_ref().clone();
|
let mut state = original.get().as_ref().clone();
|
||||||
info!("Synchronizing Recipes");
|
info!("Synchronizing Recipes");
|
||||||
let recipe_entries = &store.fetch_recipes().await?;
|
let recipe_entries = &store.fetch_recipes().await?;
|
||||||
@ -282,7 +280,7 @@ impl StateMachine {
|
|||||||
}
|
}
|
||||||
// Finally we store all of this app state back to our localstore
|
// Finally we store all of this app state back to our localstore
|
||||||
local_store.store_app_state(&state);
|
local_store.store_app_state(&state);
|
||||||
original.set(state);
|
original.update(state);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,17 +307,15 @@ impl MessageMapper<Message, AppState> for StateMachine {
|
|||||||
Message::RemoveExtra(idx) => {
|
Message::RemoveExtra(idx) => {
|
||||||
original_copy.extras.remove(idx);
|
original_copy.extras.remove(idx);
|
||||||
}
|
}
|
||||||
Message::UpdateExtra(idx, amt, name) => {
|
Message::UpdateExtra(idx, amt, name) => match original_copy.extras.get_mut(idx) {
|
||||||
match original_copy.extras.get_mut(idx) {
|
Some(extra) => {
|
||||||
Some(extra) => {
|
extra.0 = amt;
|
||||||
extra.0 = amt;
|
extra.1 = name;
|
||||||
extra.1 = name;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
throw_str("Attempted to remove extra that didn't exist");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
None => {
|
||||||
|
throw_str("Attempted to remove extra that didn't exist");
|
||||||
|
}
|
||||||
|
},
|
||||||
Message::SaveRecipe(entry, callback) => {
|
Message::SaveRecipe(entry, callback) => {
|
||||||
let recipe =
|
let recipe =
|
||||||
parse::as_recipe(entry.recipe_text()).expect("Failed to parse RecipeEntry");
|
parse::as_recipe(entry.recipe_text()).expect("Failed to parse RecipeEntry");
|
||||||
@ -429,7 +425,8 @@ impl MessageMapper<Message, AppState> for StateMachine {
|
|||||||
let local_store = self.local_store.clone();
|
let local_store = self.local_store.clone();
|
||||||
debug!("Loading user state.");
|
debug!("Loading user state.");
|
||||||
spawn_local_scoped(cx, async move {
|
spawn_local_scoped(cx, async move {
|
||||||
if let Err(err) = Self::load_state(&store, &local_store, original).await {
|
if let Err(err) = Self::load_state(&store, &local_store, original.clone()).await
|
||||||
|
{
|
||||||
error!(?err, "Failed to load user state");
|
error!(?err, "Failed to load user state");
|
||||||
components::toast::error_message(cx, "Failed to load_state.", None);
|
components::toast::error_message(cx, "Failed to load_state.", None);
|
||||||
} else {
|
} else {
|
||||||
@ -454,7 +451,7 @@ impl MessageMapper<Message, AppState> for StateMachine {
|
|||||||
}
|
}
|
||||||
Message::SelectPlanDate(date, callback) => {
|
Message::SelectPlanDate(date, callback) => {
|
||||||
let store = self.store.clone();
|
let store = self.store.clone();
|
||||||
let local_store = self.local_store.clone();
|
let local_store = self.local_store.clone();
|
||||||
spawn_local_scoped(cx, async move {
|
spawn_local_scoped(cx, async move {
|
||||||
if let Some(mut plan) = store
|
if let Some(mut plan) = store
|
||||||
.fetch_plan_for_date(&date)
|
.fetch_plan_for_date(&date)
|
||||||
@ -491,7 +488,7 @@ impl MessageMapper<Message, AppState> for StateMachine {
|
|||||||
}
|
}
|
||||||
Message::DeletePlan(date, callback) => {
|
Message::DeletePlan(date, callback) => {
|
||||||
let store = self.store.clone();
|
let store = self.store.clone();
|
||||||
let local_store = self.local_store.clone();
|
let local_store = self.local_store.clone();
|
||||||
spawn_local_scoped(cx, async move {
|
spawn_local_scoped(cx, async move {
|
||||||
if let Err(err) = store.delete_plan_for_date(&date).await {
|
if let Err(err) = store.delete_plan_for_date(&date).await {
|
||||||
components::toast::error_message(
|
components::toast::error_message(
|
||||||
|
@ -18,6 +18,7 @@ mod js_lib;
|
|||||||
mod pages;
|
mod pages;
|
||||||
mod routing;
|
mod routing;
|
||||||
mod web;
|
mod web;
|
||||||
|
mod linear;
|
||||||
|
|
||||||
use sycamore::prelude::*;
|
use sycamore::prelude::*;
|
||||||
use wasm_bindgen::prelude::wasm_bindgen;
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
51
web/src/linear.rs
Normal file
51
web/src/linear.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2022 Jeremy Wall
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
use std::convert::Into;
|
||||||
|
use std::ops::Drop;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use sycamore::prelude::*;
|
||||||
|
|
||||||
|
pub struct LinearSignal<'ctx, Payload> {
|
||||||
|
pub signal: &'ctx Signal<Payload>,
|
||||||
|
nv: Option<Payload>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ctx, Payload> Into<LinearSignal<'ctx, Payload>> for &'ctx Signal<Payload> {
|
||||||
|
fn into(self) -> LinearSignal<'ctx, Payload> {
|
||||||
|
LinearSignal { signal: self, nv: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ctx, Payload> LinearSignal<'ctx, Payload> {
|
||||||
|
pub fn update(mut self, payload: Payload) -> Self {
|
||||||
|
self.nv = Some(payload);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&'ctx self) -> Rc<Payload> {
|
||||||
|
self.signal.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ctx, Payload> Drop for LinearSignal<'ctx, Payload> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.nv.is_some() {
|
||||||
|
let mut val: Option<Payload> = None;
|
||||||
|
std::mem::swap(&mut val, &mut self.nv);
|
||||||
|
let payload = val.unwrap();
|
||||||
|
self.signal.set(payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user