Fix windows open log viewer
- There was tendency where webview would just freeze on windows, lets ensure this doesn't happen.
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
// Log webview emit chain: keep `cfg(not(windows))` here aligned with
|
||||
// `platform_constants::SECONDARY_LOG_WEBVIEW_SUPPORTED` (compile-time strip on Windows).
|
||||
use fern::colors::{Color, ColoredLevelConfig};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use serde::Serialize;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use tauri::{Emitter, Manager};
|
||||
use time::{format_description, OffsetDateTime};
|
||||
|
||||
@@ -23,7 +28,9 @@ fn formatted_time() -> String {
|
||||
_now.format(&format).unwrap()
|
||||
}
|
||||
|
||||
#[cfg_attr(target_os = "windows", allow(unused_variables))]
|
||||
pub fn setup_logging(app_handle: tauri::AppHandle) -> Result<(), log::SetLoggerError> {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let log_window_app = app_handle.clone();
|
||||
let colors = ColoredLevelConfig::new()
|
||||
.trace(Color::Magenta)
|
||||
@@ -48,6 +55,7 @@ pub fn setup_logging(app_handle: tauri::AppHandle) -> Result<(), log::SetLoggerE
|
||||
})
|
||||
.chain(std::io::stdout());
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let tauri_event_config = fern::Dispatch::new()
|
||||
.format(move |out, message, record| {
|
||||
out.finish(format_args!(
|
||||
@@ -76,10 +84,12 @@ pub fn setup_logging(app_handle: tauri::AppHandle) -> Result<(), log::SetLoggerE
|
||||
}
|
||||
}));
|
||||
|
||||
base_config
|
||||
.chain(stdout_config)
|
||||
.chain(tauri_event_config)
|
||||
.apply()
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let dispatch = base_config.chain(stdout_config).chain(tauri_event_config);
|
||||
#[cfg(target_os = "windows")]
|
||||
let dispatch = base_config.chain(stdout_config);
|
||||
|
||||
dispatch.apply()
|
||||
}
|
||||
|
||||
trait FernExt {
|
||||
@@ -118,13 +128,14 @@ fn global_level() -> log::LevelFilter {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[derive(Debug, Serialize, Clone)]
|
||||
struct LogMessage {
|
||||
message: String,
|
||||
level: LogLevel,
|
||||
}
|
||||
|
||||
// Serialize to u16 instead of strings.
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
|
||||
#[repr(u16)]
|
||||
enum LogLevel {
|
||||
@@ -135,6 +146,7 @@ enum LogLevel {
|
||||
Error,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
impl From<log::Level> for LogLevel {
|
||||
fn from(level: log::Level) -> Self {
|
||||
match level {
|
||||
|
||||
@@ -213,6 +213,7 @@ fn main() {
|
||||
signatures::ed25519_signing_payload::generate_nym_node_bonding_msg_payload,
|
||||
signatures::ed25519_signing_payload::vesting_generate_gateway_bonding_msg_payload,
|
||||
help::log::help_log_toggle_window,
|
||||
help::log::log_viewer_window_supported,
|
||||
app::window::create_main_window,
|
||||
app::window::create_auth_window,
|
||||
app::react::set_react_state,
|
||||
@@ -221,7 +222,9 @@ fn main() {
|
||||
.menu(menu::build_app_menu)
|
||||
.on_menu_event(|app, event| {
|
||||
if event.id() == SHOW_LOG_WINDOW {
|
||||
let _r = help::log::help_log_toggle_window(app.app_handle().clone());
|
||||
if let Err(err) = help::log::help_log_toggle_window(app.app_handle().clone()) {
|
||||
::log::warn!("Show logs menu action failed: {err}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.setup(|app| Ok(log::setup_logging(app.app_handle().clone())?))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use tauri::menu::{Menu, MenuBuilder, MenuItemBuilder, SubmenuBuilder};
|
||||
use tauri::{AppHandle, Runtime};
|
||||
|
||||
use crate::platform_constants::SECONDARY_LOG_WEBVIEW_SUPPORTED;
|
||||
|
||||
pub const SHOW_LOG_WINDOW: &str = "show_log_window";
|
||||
|
||||
pub fn build_app_menu<R: Runtime>(app: &AppHandle<R>) -> tauri::Result<Menu<R>> {
|
||||
@@ -13,7 +15,7 @@ pub fn build_app_menu<R: Runtime>(app: &AppHandle<R>) -> tauri::Result<Menu<R>>
|
||||
|
||||
let mut menu_builder = MenuBuilder::new(app).item(&edit_submenu);
|
||||
|
||||
if std::env::var("NYM_WALLET_ENABLE_LOG").is_ok() {
|
||||
if std::env::var("NYM_WALLET_ENABLE_LOG").is_ok() && SECONDARY_LOG_WEBVIEW_SUPPORTED {
|
||||
let help_text = MenuItemBuilder::with_id(SHOW_LOG_WINDOW, "Show logs").build(app)?;
|
||||
|
||||
let help_submenu = SubmenuBuilder::new(app, "Help")
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
use crate::error::BackendError;
|
||||
use crate::platform_constants::SECONDARY_LOG_WEBVIEW_SUPPORTED;
|
||||
use crate::webview_theme::NYM_WALLET_WEBVIEW_BG;
|
||||
use tauri::webview::PageLoadEvent;
|
||||
use tauri::Manager;
|
||||
|
||||
/// Separate log viewer window is disabled on Windows due to WebView2 freezes / "(Not Responding)".
|
||||
#[tauri::command]
|
||||
#[must_use]
|
||||
pub fn log_viewer_window_supported() -> bool {
|
||||
SECONDARY_LOG_WEBVIEW_SUPPORTED
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn help_log_toggle_window(app_handle: tauri::AppHandle) -> Result<(), BackendError> {
|
||||
if let Some(current_log_window) = app_handle.get_webview_window("log") {
|
||||
@@ -13,41 +21,50 @@ pub fn help_log_toggle_window(app_handle: tauri::AppHandle) -> Result<(), Backen
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
log::info!("Creating log window...");
|
||||
match tauri::WebviewWindowBuilder::new(
|
||||
&app_handle,
|
||||
"log",
|
||||
tauri::WebviewUrl::App("log.html".into()),
|
||||
)
|
||||
.title("Nym Wallet Logs")
|
||||
.background_color(NYM_WALLET_WEBVIEW_BG)
|
||||
.use_https_scheme(true)
|
||||
.on_page_load(|window, payload| match payload.event() {
|
||||
PageLoadEvent::Started => {
|
||||
log::debug!("Log webview load started: {}", payload.url());
|
||||
}
|
||||
PageLoadEvent::Finished => {
|
||||
log::info!("Log webview load finished: {}", payload.url());
|
||||
if std::env::var("NYM_WALLET_LOG_WEBVIEW_DEVTOOLS")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1")
|
||||
{
|
||||
window.open_devtools();
|
||||
}
|
||||
}
|
||||
})
|
||||
.build()
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
Ok(window) => {
|
||||
if let Err(err) = window.set_focus() {
|
||||
log::error!("Unable to focus log window: {err}");
|
||||
log::info!("Log viewer window is disabled on Windows; use stdout or RUST_LOG.");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
log::info!("Creating log window...");
|
||||
match tauri::WebviewWindowBuilder::new(
|
||||
&app_handle,
|
||||
"log",
|
||||
tauri::WebviewUrl::App("log.html".into()),
|
||||
)
|
||||
.title("Nym Wallet Logs")
|
||||
.background_color(NYM_WALLET_WEBVIEW_BG)
|
||||
.use_https_scheme(true)
|
||||
.on_page_load(|window, payload| match payload.event() {
|
||||
PageLoadEvent::Started => {
|
||||
log::debug!("Log webview load started: {}", payload.url());
|
||||
}
|
||||
PageLoadEvent::Finished => {
|
||||
log::info!("Log webview load finished: {}", payload.url());
|
||||
if std::env::var("NYM_WALLET_LOG_WEBVIEW_DEVTOOLS")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1")
|
||||
{
|
||||
window.open_devtools();
|
||||
}
|
||||
}
|
||||
})
|
||||
.build()
|
||||
{
|
||||
Ok(window) => {
|
||||
if let Err(err) = window.set_focus() {
|
||||
log::error!("Unable to focus log window: {err}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("Unable to create log window: {err}");
|
||||
Err(BackendError::NewWindowError)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("Unable to create log window: {err}");
|
||||
Err(BackendError::NewWindowError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/// Secondary log viewer `WebviewWindow` is disabled on Windows due to WebView2 freezes.
|
||||
pub const SECONDARY_LOG_WEBVIEW_SUPPORTED: bool = cfg!(not(target_os = "windows"));
|
||||
|
||||
pub const CONFIG_DIR_NAME: &str = "nym-wallet";
|
||||
pub const CONFIG_FILENAME: &str = "config.toml";
|
||||
pub const STORAGE_DIR_NAME: &str = "nym-wallet";
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
import React, { useContext } from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { Box, Button, Divider, Stack, Typography } from '@mui/material';
|
||||
import { helpLogToggleWindow } from '../../requests';
|
||||
import { helpLogToggleWindow, logViewerWindowSupported } from '../../requests';
|
||||
import { AppContext } from '../../context';
|
||||
import { config } from '../../config';
|
||||
import SelectValidator from '../../components/Settings/SelectValidator';
|
||||
|
||||
const AdvancedSettings = () => {
|
||||
const { handleShowTerminal, appEnv } = useContext(AppContext);
|
||||
const [logViewerOk, setLogViewerOk] = useState<boolean | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
logViewerWindowSupported()
|
||||
.then((ok) => {
|
||||
if (!cancelled) setLogViewerOk(ok);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) setLogViewerOk(false);
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box pb={3}>
|
||||
@@ -28,20 +43,28 @@ const AdvancedSettings = () => {
|
||||
<Divider />
|
||||
</>
|
||||
)}
|
||||
<Stack direction="row" justifyContent="space-between" padding={3}>
|
||||
<Stack direction="column" gap={1}>
|
||||
<Typography variant="h6">Logs</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
Open logs to monitor all actions in the wallet
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Box alignSelf="flex-end">
|
||||
<Button variant="text" onClick={() => helpLogToggleWindow()}>
|
||||
Open logs
|
||||
</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Divider />
|
||||
{logViewerOk !== null && (
|
||||
<>
|
||||
<Stack direction="row" justifyContent="space-between" padding={3}>
|
||||
<Stack direction="column" gap={1}>
|
||||
<Typography variant="h6">Logs</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
{logViewerOk
|
||||
? 'Open logs to monitor all actions in the wallet'
|
||||
: 'The in-app log viewer window is not available on Windows. Run the wallet from a terminal or set RUST_LOG to capture logs on stdout.'}
|
||||
</Typography>
|
||||
</Stack>
|
||||
{logViewerOk ? (
|
||||
<Box alignSelf="flex-end">
|
||||
<Button variant="text" onClick={() => helpLogToggleWindow()}>
|
||||
Open logs
|
||||
</Button>
|
||||
</Box>
|
||||
) : null}
|
||||
</Stack>
|
||||
<Divider />
|
||||
</>
|
||||
)}
|
||||
<SelectValidator />
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { invokeWrapper } from './wrapper';
|
||||
|
||||
export const helpLogToggleWindow = async () => invokeWrapper<void>('help_log_toggle_window', {});
|
||||
|
||||
export const logViewerWindowSupported = async () =>
|
||||
invokeWrapper<boolean>('log_viewer_window_supported', {});
|
||||
|
||||
Reference in New Issue
Block a user