moves log state up to App so it persists across route changes, moves wait during setup for webview to start to the async runtime so it doesn't block the setup fn from starting the webview.

This commit is contained in:
Automated Release Test 2024-03-05 20:42:25 -05:00
parent dd1744f326
commit f25e9d6286
4 changed files with 70 additions and 60 deletions

View File

@ -4,6 +4,7 @@ use std::{
io::{BufRead, BufReader},
path::PathBuf,
process::{Child, Command, Stdio},
time::Duration,
};
use tauri::{utils, AppHandle, Manager};
@ -94,8 +95,17 @@ pub fn run_zebrad() -> (Child, Receiver<String>) {
(zebrad_child, output_receiver)
}
pub fn spawn_logs_emitter(mut output_receiver: Receiver<String>, app_handle: AppHandle) {
pub fn spawn_logs_emitter(
mut output_receiver: Receiver<String>,
app_handle: AppHandle,
should_wait_for_webview: bool,
) {
tauri::async_runtime::spawn(async move {
// Wait for webview to start
if should_wait_for_webview {
tokio::time::sleep(Duration::from_secs(3)).await;
}
// Exit the task once the channel is closed and empty.
while let Some(output) = output_receiver.recv().await {
if let Err(error) = app_handle.emit("log", output) {

View File

@ -37,7 +37,7 @@ async fn save_config(app_handle: AppHandle, new_config: String) -> Result<String
app_handle
.state::<AppState>()
.insert_zebrad_child(zebrad_child);
spawn_logs_emitter(zebrad_output_receiver, app_handle);
spawn_logs_emitter(zebrad_output_receiver, app_handle, false);
Ok(old_config_contents)
}
@ -54,10 +54,7 @@ fn main() {
tauri::Builder::default()
.manage(AppState::new(zebrad_child))
.setup(|app| {
// Wait for webview to start
std::thread::sleep(Duration::from_secs(3));
spawn_logs_emitter(zebrad_output_receiver, app.handle().clone());
spawn_logs_emitter(zebrad_output_receiver, app.handle().clone(), true);
Ok(())
})
.invoke_handler(tauri::generate_handler![save_config, read_config])

View File

@ -1,6 +1,13 @@
import { Router, Route, RouteSectionProps, A, useMatch } from "@solidjs/router";
import { css, styled } from "solid-styled-components";
import { listen, Event, UnlistenFn } from "@tauri-apps/api/event";
import { createSignal, onCleanup, onMount } from "solid-js";
import { EXAMPLE_LOGS } from "./tests/example_data";
import { MAX_NUM_LOG_LINES } from "./constants";
import { NAVIGATION_BAR_HEIGHT } from "./constants";
import Logs from "./pages/Logs";
import Configuration from "./pages/Configure";
@ -68,9 +75,56 @@ const AppContainer = ({ children }: RouteSectionProps) => (
);
function App() {
const is_tauri_app = window.hasOwnProperty("__TAURI_INTERNALS__");
const [logs, set_logs] = createSignal<Array<string>>([]);
const is_at_bottom = () => {
const y_bottom = Math.ceil(window.scrollY) + window.innerHeight;
return y_bottom >= document.body.scrollHeight;
};
const scroll_to_bottom = () => {
window.scroll(0, document.body.scrollHeight);
};
if (is_tauri_app) {
let stop_listening: UnlistenFn;
onMount(async () => {
stop_listening = await listen("log", (event: Event<string>) => {
const was_at_bottom = is_at_bottom();
set_logs([...logs().slice(-MAX_NUM_LOG_LINES), event.payload]);
if (was_at_bottom) {
scroll_to_bottom();
}
});
});
onCleanup(() => stop_listening());
} else {
let example_log_index = 0;
setInterval(() => {
const was_at_bottom = is_at_bottom();
set_logs([
...logs().slice(-MAX_NUM_LOG_LINES),
EXAMPLE_LOGS[example_log_index],
]);
// TODO: check if it's the logs page? May be easier to do if this logic is moved to `AppContainer`.
if (was_at_bottom) {
scroll_to_bottom();
}
example_log_index = (example_log_index + 1) % EXAMPLE_LOGS.length;
}, 100);
}
return (
<Router root={AppContainer}>
<Route path="/" component={Logs} />
<Route path="/" component={() => <Logs logs={logs} />} />
<Route path="/configure" component={Configuration} />
</Router>
);

View File

@ -1,11 +1,6 @@
import { listen, Event, UnlistenFn } from "@tauri-apps/api/event";
import { createSignal, onCleanup, onMount, For } from "solid-js";
import { For, Accessor } from "solid-js";
import { styled } from "solid-styled-components";
import { EXAMPLE_LOGS } from "../tests/example_data";
import { MAX_NUM_LOG_LINES } from "../constants";
const LogContainer = styled("div")`
display: flex;
flex-grow: 1;
@ -68,53 +63,7 @@ const Log = ({ children }: { children: string }) => {
}
};
const Logs = () => {
const is_tauri_app = window.hasOwnProperty("__TAURI_INTERNALS__");
const [logs, set_logs] = createSignal<Array<string>>([]);
const is_at_bottom = () => {
const y_bottom = Math.ceil(window.scrollY) + window.innerHeight;
return y_bottom >= document.body.scrollHeight;
};
const scroll_to_bottom = () => {
window.scroll(0, document.body.scrollHeight);
};
if (is_tauri_app) {
let stop_listening: UnlistenFn;
onMount(async () => {
stop_listening = await listen("log", (event: Event<string>) => {
const was_at_bottom = is_at_bottom();
set_logs([...logs().slice(-MAX_NUM_LOG_LINES), event.payload]);
if (was_at_bottom) {
scroll_to_bottom();
}
});
});
onCleanup(() => stop_listening());
} else {
let example_log_index = 0;
setInterval(() => {
const was_at_bottom = is_at_bottom();
set_logs([
...logs().slice(-MAX_NUM_LOG_LINES),
EXAMPLE_LOGS[example_log_index],
]);
if (was_at_bottom) {
scroll_to_bottom();
}
example_log_index = (example_log_index + 1) % EXAMPLE_LOGS.length;
}, 100);
}
const Logs = ({ logs }: { logs: Accessor<string[]> }) => {
return (
<LogContainer>
<For each={logs()} fallback={<Log>Waiting for zebrad to start...</Log>}>