feat(corp/tvixbolt): persist state in tvixbolt's URL

This makes it possible to enter something into tvixbolt and then share
the link with someone else.

Suggested by Profpatsch originally.

Change-Id: I9886e76a7b821070f13ea7005df09188821e091d
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6636
Tested-by: BuildkiteCI
Reviewed-by: Profpatsch <mail@profpatsch.de>
This commit is contained in:
Vincent Ambo 2022-09-18 19:23:22 +03:00 committed by tazjin
parent 993c22de59
commit bb47baf638
3 changed files with 23 additions and 10 deletions

View file

@ -592,6 +592,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"codemap", "codemap",
"rnix", "rnix",
"serde",
"serde_urlencoded", "serde_urlencoded",
"tvix-eval", "tvix-eval",
"wasm-bindgen", "wasm-bindgen",

View file

@ -22,3 +22,7 @@ rev = "7d0d929c22ad27bdcc0779afe445b541d3ce9631"
[dependencies.tvix-eval] [dependencies.tvix-eval]
path = "../../tvix/eval" path = "../../tvix/eval"
default-features = false default-features = false
[dependencies.serde]
version = "*" # pinned by yew
features = [ "derive" ]

View file

@ -1,5 +1,6 @@
use std::fmt::Write; use std::fmt::Write;
use serde::{Deserialize, Serialize};
use std::rc::Rc; use std::rc::Rc;
use tvix_eval::observer::TracingObserver; use tvix_eval::observer::TracingObserver;
use tvix_eval::observer::{DisassemblingObserver, NoOpObserver}; use tvix_eval::observer::{DisassemblingObserver, NoOpObserver};
@ -7,12 +8,14 @@ use web_sys::HtmlInputElement;
use web_sys::HtmlTextAreaElement; use web_sys::HtmlTextAreaElement;
use yew::prelude::*; use yew::prelude::*;
use yew::TargetCast; use yew::TargetCast;
use yew_router::{prelude::*, AnyRoute};
enum Msg { enum Msg {
CodeChange(String), CodeChange(String),
ToggleTrace(bool), ToggleTrace(bool),
} }
#[derive(Clone, Serialize, Deserialize)]
struct Model { struct Model {
code: String, code: String,
trace: bool, trace: bool,
@ -87,25 +90,30 @@ impl Component for Model {
type Message = Msg; type Message = Msg;
type Properties = (); type Properties = ();
fn create(_ctx: &Context<Self>) -> Self { fn create(_: &Context<Self>) -> Self {
Self { BrowserHistory::new()
code: String::new(), .location()
trace: false, .query::<Self>()
} .unwrap_or_else(|_| Self {
code: String::new(),
trace: false,
})
} }
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool { fn update(&mut self, _: &Context<Self>, msg: Self::Message) -> bool {
match msg { match msg {
Msg::ToggleTrace(trace) => { Msg::ToggleTrace(trace) => {
self.trace = trace; self.trace = trace;
true
} }
Msg::CodeChange(new_code) => { Msg::CodeChange(new_code) => {
self.code = new_code; self.code = new_code;
true
} }
} }
let _ = BrowserHistory::new().replace_with_query(AnyRoute::new("/"), self.clone());
true
} }
fn view(&self, ctx: &Context<Self>) -> Html { fn view(&self, ctx: &Context<Self>) -> Html {
@ -128,8 +136,8 @@ impl Component for Model {
Msg::CodeChange(ta) Msg::CodeChange(ta)
})} })}
id="code" cols="30" rows="10"> id="code" cols="30" rows="10" value={self.code.clone()}>
</textarea> </textarea>
</div> </div>
<div class="form-group"> <div class="form-group">