Invoke Tauri command from Gleam

This commit is contained in:
Wesley Moore 2024-02-18 14:45:10 +10:00
parent 9ae2a39dd7
commit eb555aab3b
No known key found for this signature in database
2 changed files with 66 additions and 25 deletions

View file

@ -1,62 +1,93 @@
import gleam/int import gleam/int
import gleam/javascript/promise.{type Promise} import gleam/javascript/promise.{type Promise}
import gleam/io
import lustre import lustre
import lustre/attribute import lustre/attribute as attr
import lustre/element.{type Element} import lustre/element.{type Element}
import lustre/element/html import lustre/element/html
import lustre/event import lustre/event
import lustre/effect.{type Effect}
pub fn main() { pub fn main() {
let app = lustre.simple(init, update, view) let app = lustre.application(init, update, view)
let assert Ok(dispatch) = lustre.start(app, "#app", Nil) let assert Ok(dispatch) = lustre.start(app, "#app", Nil)
dispatch dispatch
} }
type Model = type Model {
Int Model(count: Int, greeting: String, name: String)
}
fn init(_) -> Model { fn init(_) -> #(Model, Effect(Msg)) {
0 #(Model(0, "", ""), effect.none())
} }
pub type Msg { pub type Msg {
Increment Increment
Decrement Decrement
Greet Greet
GotGreeting(String)
UpdateName(String)
} }
fn update(model: Model, msg: Msg) -> Model { fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
case msg { case msg {
Increment -> model + 1 Increment -> #(Model(..model, count: model.count + 1), effect.none())
Decrement -> model - 1 Decrement -> #(Model(..model, count: model.count - 1), effect.none())
Greet -> { Greet -> #(model, get_greeting(model.name))
{ GotGreeting(greeting) -> #(
use greeting <- promise.await(greet("Gleam")) Model(..model, greeting: greeting),
case greeting { effect.none(),
Ok(g) -> io.print(g) )
Error(e) -> io.print("greeting err: " <> e) UpdateName(name) -> #(Model(..model, name: name), effect.none())
}
promise.resolve(#())
}
model
}
} }
} }
fn get_greeting(name: String) -> Effect(Msg) {
effect.from(do_get_greeting(name, _))
}
fn do_get_greeting(name: String, dispatch: fn(Msg) -> Nil) -> Nil {
greet(name)
// |> promise.await()
|> promise.map(fn(response) {
case response {
Ok(greeting) -> GotGreeting(greeting)
Error(err) -> GotGreeting("Error: " <> err)
}
})
|> promise.tap(dispatch)
Nil
}
@external(javascript, "./ffi/commands.js", "greet") @external(javascript, "./ffi/commands.js", "greet")
pub fn greet(name: String) -> Promise(Result(String, String)) pub fn greet(name: String) -> Promise(Result(String, String))
fn update_name(text: String) -> Msg {
UpdateName(text)
}
// -- VIEW
fn view(model: Model) -> Element(Msg) { fn view(model: Model) -> Element(Msg) {
let count = int.to_string(model) let count = int.to_string(model.count)
html.div([], [ html.div([], [
html.h1([], [element.text("Gleam + Vite + Tauri")]), html.h1([], [element.text("Gleam + Vite + Tauri")]),
html.p([attribute.style([#("text-align", "center")])], [ html.div([attr.class("field text-center")], [
element.text("Gleam counter " <> count <> ""), html.label([attr.for("greet_name")], [element.text("Name")]),
element.text(" "),
html.input([
attr.type_("text"),
attr.name("greet_name"),
event.on_input(update_name),
]),
]), ]),
html.p([attribute.style([#("text-align", "center")])], [ html.p([attr.class("text-center")], [
element.text(model.greeting <> " " <> count <> ""),
]),
html.div([attr.class("text-center")], [
html.button([event.on_click(Decrement)], [element.text("-")]), html.button([event.on_click(Decrement)], [element.text("-")]),
html.button([event.on_click(Increment)], [element.text("+")]), html.button([event.on_click(Increment)], [element.text("+")]),
html.button([event.on_click(Greet)], [element.text("Greet")]), html.button([event.on_click(Greet)], [element.text("Greet")]),

View file

@ -64,6 +64,13 @@ h1 {
color: #888; color: #888;
} }
.field {
margin-top: 0.5em;
}
.text-center {
text-align: center;
}
button { button {
border-radius: 8px; border-radius: 8px;
border: 1px solid transparent; border: 1px solid transparent;
@ -83,6 +90,9 @@ button:focus,
button:focus-visible { button:focus-visible {
outline: 4px auto -webkit-focus-ring-color; outline: 4px auto -webkit-focus-ring-color;
} }
label {
font-weight: bold;
}
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
:root { :root {