2024-02-18 01:48:10 +00:00
|
|
|
import gleam/int
|
2024-02-18 02:49:50 +00:00
|
|
|
import gleam/javascript/promise.{type Promise}
|
2024-02-18 01:48:10 +00:00
|
|
|
import lustre
|
2024-02-18 04:45:10 +00:00
|
|
|
import lustre/attribute as attr
|
2024-02-18 01:48:10 +00:00
|
|
|
import lustre/element.{type Element}
|
|
|
|
import lustre/element/html
|
|
|
|
import lustre/event
|
2024-02-18 04:45:10 +00:00
|
|
|
import lustre/effect.{type Effect}
|
2024-02-18 01:48:10 +00:00
|
|
|
|
|
|
|
pub fn main() {
|
2024-02-18 04:45:10 +00:00
|
|
|
let app = lustre.application(init, update, view)
|
2024-02-18 01:48:10 +00:00
|
|
|
let assert Ok(dispatch) = lustre.start(app, "#app", Nil)
|
|
|
|
|
|
|
|
dispatch
|
|
|
|
}
|
|
|
|
|
2024-02-18 04:45:10 +00:00
|
|
|
type Model {
|
2024-02-18 06:59:48 +00:00
|
|
|
Model(count: Int, greeting: String, name: String, time: Int)
|
2024-02-18 04:45:10 +00:00
|
|
|
}
|
2024-02-18 01:48:10 +00:00
|
|
|
|
2024-02-18 04:45:10 +00:00
|
|
|
fn init(_) -> #(Model, Effect(Msg)) {
|
2024-02-18 06:59:48 +00:00
|
|
|
#(Model(0, "", "", 0), bind_clock())
|
2024-02-18 01:48:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub type Msg {
|
|
|
|
Increment
|
|
|
|
Decrement
|
2024-02-18 02:49:50 +00:00
|
|
|
Greet
|
2024-02-18 04:45:10 +00:00
|
|
|
GotGreeting(String)
|
|
|
|
UpdateName(String)
|
2024-02-18 06:59:48 +00:00
|
|
|
Tick(Int)
|
2024-02-18 01:48:10 +00:00
|
|
|
}
|
|
|
|
|
2024-02-18 04:45:10 +00:00
|
|
|
fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
|
2024-02-18 01:48:10 +00:00
|
|
|
case msg {
|
2024-02-18 04:45:10 +00:00
|
|
|
Increment -> #(Model(..model, count: model.count + 1), effect.none())
|
|
|
|
Decrement -> #(Model(..model, count: model.count - 1), effect.none())
|
|
|
|
Greet -> #(model, get_greeting(model.name))
|
|
|
|
GotGreeting(greeting) -> #(
|
|
|
|
Model(..model, greeting: greeting),
|
|
|
|
effect.none(),
|
|
|
|
)
|
|
|
|
UpdateName(name) -> #(Model(..model, name: name), effect.none())
|
2024-02-18 06:59:48 +00:00
|
|
|
Tick(time) -> #(Model(..model, time: time), effect.none())
|
2024-02-18 01:48:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-18 04:45:10 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-02-18 06:59:48 +00:00
|
|
|
fn bind_clock() -> Effect(Msg) {
|
|
|
|
effect.from(fn(dispatch) {
|
|
|
|
listen_for_tick(fn(time) {
|
|
|
|
tick(time)
|
|
|
|
|> dispatch
|
|
|
|
})
|
|
|
|
|
|
|
|
Nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-02-18 02:49:50 +00:00
|
|
|
@external(javascript, "./ffi/commands.js", "greet")
|
|
|
|
pub fn greet(name: String) -> Promise(Result(String, String))
|
|
|
|
|
2024-02-18 06:59:48 +00:00
|
|
|
type UnlistenFn =
|
|
|
|
fn() -> Nil
|
|
|
|
|
|
|
|
@external(javascript, "./ffi/commands.js", "listenForTick")
|
|
|
|
pub fn listen_for_tick(handler: fn(Int) -> Nil) -> Promise(UnlistenFn)
|
|
|
|
|
|
|
|
pub type Date
|
|
|
|
|
|
|
|
@external(javascript, "./ffi/js_extra.js", "from_unix")
|
|
|
|
pub fn new_date(timestamp: Int) -> Date
|
|
|
|
|
|
|
|
@external(javascript, "./ffi/js_extra.js", "date_to_string")
|
|
|
|
pub fn date_to_string(date: Date) -> String
|
|
|
|
|
2024-02-18 04:45:10 +00:00
|
|
|
fn update_name(text: String) -> Msg {
|
|
|
|
UpdateName(text)
|
|
|
|
}
|
|
|
|
|
2024-02-18 06:59:48 +00:00
|
|
|
fn tick(time: Int) -> Msg {
|
|
|
|
Tick(time)
|
|
|
|
}
|
|
|
|
|
2024-02-18 04:45:10 +00:00
|
|
|
// -- VIEW
|
|
|
|
|
2024-02-18 01:48:10 +00:00
|
|
|
fn view(model: Model) -> Element(Msg) {
|
2024-02-18 04:45:10 +00:00
|
|
|
let count = int.to_string(model.count)
|
2024-02-18 06:59:48 +00:00
|
|
|
let time =
|
|
|
|
model.time
|
|
|
|
|> new_date
|
|
|
|
|> date_to_string
|
2024-02-18 01:48:10 +00:00
|
|
|
|
2024-02-18 02:49:50 +00:00
|
|
|
html.div([], [
|
|
|
|
html.h1([], [element.text("Gleam + Vite + Tauri")]),
|
2024-02-18 04:45:10 +00:00
|
|
|
html.div([attr.class("field text-center")], [
|
|
|
|
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([attr.class("text-center")], [
|
|
|
|
element.text(model.greeting <> " " <> count <> " ✨"),
|
2024-02-18 02:49:50 +00:00
|
|
|
]),
|
2024-02-18 04:45:10 +00:00
|
|
|
html.div([attr.class("text-center")], [
|
2024-02-18 02:49:50 +00:00
|
|
|
html.button([event.on_click(Decrement)], [element.text("-")]),
|
|
|
|
html.button([event.on_click(Increment)], [element.text("+")]),
|
|
|
|
html.button([event.on_click(Greet)], [element.text("Greet")]),
|
|
|
|
]),
|
2024-02-18 06:59:48 +00:00
|
|
|
html.div([attr.class("clock text-center")], [
|
|
|
|
element.text("Clock: " <> time),
|
|
|
|
]),
|
2024-02-18 02:49:50 +00:00
|
|
|
])
|
2024-02-18 01:48:10 +00:00
|
|
|
}
|