Emit periodic events from the backend and listen to them in Gleam
This commit is contained in:
parent
3cd65e1094
commit
1ddd93a108
7 changed files with 100 additions and 11 deletions
|
@ -1,8 +1,26 @@
|
||||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||||
|
use tauri::EventTarget;
|
||||||
|
use tauri::Manager;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
|
.setup(|app| {
|
||||||
|
let app = app.handle().clone();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
// app.emit_all("event-name", Payload { message: "Tauri is awesome!".into() }).unwrap();
|
||||||
|
let now = SystemTime::now();
|
||||||
|
let duration = now.duration_since(UNIX_EPOCH).unwrap();
|
||||||
|
app.emit_to(EventTarget::any(), "tick", duration.as_secs())
|
||||||
|
.unwrap();
|
||||||
|
std::thread::sleep(Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
.invoke_handler(tauri::generate_handler![greet])
|
.invoke_handler(tauri::generate_handler![greet])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
@ -12,3 +30,16 @@ fn main() {
|
||||||
fn greet(name: &str) -> String {
|
fn greet(name: &str) -> String {
|
||||||
format!("Hello, {}!", name)
|
format!("Hello, {}!", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn clock(app: tauri::AppHandle) {
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
let now = SystemTime::now();
|
||||||
|
let duration = now.duration_since(UNIX_EPOCH).unwrap();
|
||||||
|
app.emit_to(EventTarget::any(), "tick", duration.as_secs())
|
||||||
|
.unwrap();
|
||||||
|
std::thread::sleep(Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
|
import { listen } from '@tauri-apps/api/event';
|
||||||
import { Ok, Error } from "../../build/dev/javascript/videopls/gleam.mjs"; // FIXME: Is this the right way to do this?
|
import { Ok, Error } from "../../build/dev/javascript/videopls/gleam.mjs"; // FIXME: Is this the right way to do this?
|
||||||
|
|
||||||
export async function greet(name) {
|
export async function greet(name) {
|
||||||
|
@ -8,3 +9,12 @@ export async function greet(name) {
|
||||||
return new Error(error.toString());
|
return new Error(error.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function listenForTick(handler) {
|
||||||
|
console.log("listenForTick");
|
||||||
|
await listen('tick', (event) => {
|
||||||
|
console.log(event.payload);
|
||||||
|
handler(event.payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
7
src/ffi/js_extra.js
Normal file
7
src/ffi/js_extra.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export function from_unix(timestamp) {
|
||||||
|
return new Date(timestamp * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function date_to_string(date) {
|
||||||
|
return date.toString();
|
||||||
|
}
|
|
@ -15,11 +15,11 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Model {
|
type Model {
|
||||||
Model(count: Int, greeting: String, name: String)
|
Model(count: Int, greeting: String, name: String, time: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(_) -> #(Model, Effect(Msg)) {
|
fn init(_) -> #(Model, Effect(Msg)) {
|
||||||
#(Model(0, "", ""), effect.none())
|
#(Model(0, "", "", 0), bind_clock())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Msg {
|
pub type Msg {
|
||||||
|
@ -28,6 +28,7 @@ pub type Msg {
|
||||||
Greet
|
Greet
|
||||||
GotGreeting(String)
|
GotGreeting(String)
|
||||||
UpdateName(String)
|
UpdateName(String)
|
||||||
|
Tick(Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
|
fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
|
||||||
|
@ -40,6 +41,7 @@ fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
|
||||||
effect.none(),
|
effect.none(),
|
||||||
)
|
)
|
||||||
UpdateName(name) -> #(Model(..model, name: name), effect.none())
|
UpdateName(name) -> #(Model(..model, name: name), effect.none())
|
||||||
|
Tick(time) -> #(Model(..model, time: time), effect.none())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,17 +63,50 @@ fn do_get_greeting(name: String, dispatch: fn(Msg) -> Nil) -> Nil {
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bind_clock() -> Effect(Msg) {
|
||||||
|
effect.from(fn(dispatch) {
|
||||||
|
listen_for_tick(fn(time) {
|
||||||
|
tick(time)
|
||||||
|
|> 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))
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
fn update_name(text: String) -> Msg {
|
fn update_name(text: String) -> Msg {
|
||||||
UpdateName(text)
|
UpdateName(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tick(time: Int) -> Msg {
|
||||||
|
Tick(time)
|
||||||
|
}
|
||||||
|
|
||||||
// -- VIEW
|
// -- VIEW
|
||||||
|
|
||||||
fn view(model: Model) -> Element(Msg) {
|
fn view(model: Model) -> Element(Msg) {
|
||||||
let count = int.to_string(model.count)
|
let count = int.to_string(model.count)
|
||||||
|
let time =
|
||||||
|
model.time
|
||||||
|
|> new_date
|
||||||
|
|> date_to_string
|
||||||
|
|
||||||
html.div([], [
|
html.div([], [
|
||||||
html.h1([], [element.text("Gleam + Vite + Tauri")]),
|
html.h1([], [element.text("Gleam + Vite + Tauri")]),
|
||||||
|
@ -92,5 +127,8 @@ fn view(model: Model) -> Element(Msg) {
|
||||||
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")]),
|
||||||
]),
|
]),
|
||||||
|
html.div([attr.class("clock text-center")], [
|
||||||
|
element.text("Clock: " <> time),
|
||||||
|
]),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,9 @@ h1 {
|
||||||
.field {
|
.field {
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
.clock {
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
.text-center {
|
.text-center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue