diff --git a/src/data_processing.rs b/src/data_processing.rs index 6f65a4f0..fc571f20 100644 --- a/src/data_processing.rs +++ b/src/data_processing.rs @@ -6,6 +6,7 @@ use crate::element_processing::*; use crate::ground::Ground; use crate::osm_parser::ProcessedElement; use crate::progress::emit_gui_progress_update; +use crate::telemetry::{send_log, LogLevel}; use crate::world_editor::WorldEditor; use colored::Colorize; use indicatif::{ProgressBar, ProgressStyle}; @@ -250,7 +251,9 @@ pub fn generate_world( args.scale, &ground, ) { - eprintln!("Warning: Failed to update spawn point Y coordinate: {e}"); + let warning_msg = format!("Failed to update spawn point Y coordinate: {}", e); + eprintln!("Warning: {}", warning_msg); + send_log(LogLevel::Warning, &warning_msg); } } diff --git a/src/elevation_data.rs b/src/elevation_data.rs index 455e9e18..0c033b88 100644 --- a/src/elevation_data.rs +++ b/src/elevation_data.rs @@ -1,4 +1,5 @@ use crate::coordinate_system::{geographic::LLBBox, transformation::geo_distance}; +use crate::telemetry::{send_log, LogLevel}; use image::Rgb; use std::path::Path; @@ -109,8 +110,15 @@ pub fn fetch_elevation_data( }; if file_size < 1000 { - eprintln!("Warning: Cached tile at {} appears to be too small ({} bytes). Refetching tile.", - tile_path.display(), file_size); + eprintln!( + "Warning: Cached tile at {} appears to be too small ({} bytes). Refetching tile.", + tile_path.display(), + file_size + ); + send_log( + LogLevel::Warning, + "Cached tile appears to be too small. Refetching tile.", + ); // Remove the potentially corrupted file if let Err(remove_err) = std::fs::remove_file(&tile_path) { @@ -118,6 +126,10 @@ pub fn fetch_elevation_data( "Warning: Failed to remove corrupted tile file: {}", remove_err ); + send_log( + LogLevel::Warning, + "Failed to remove corrupted tile file during refetching.", + ); } // Re-download the tile @@ -132,7 +144,15 @@ pub fn fetch_elevation_data( match image::open(&tile_path) { Ok(img) => img.to_rgb8(), Err(e) => { - eprintln!("Warning: Cached tile at {} is corrupted or invalid: {}. Re-downloading...", tile_path.display(), e); + eprintln!( + "Cached tile at {} is corrupted or invalid: {}. Re-downloading...", + tile_path.display(), + e + ); + send_log( + LogLevel::Warning, + "Cached tile is corrupted or invalid. Re-downloading...", + ); // Remove the corrupted file if let Err(remove_err) = std::fs::remove_file(&tile_path) { @@ -140,6 +160,10 @@ pub fn fetch_elevation_data( "Warning: Failed to remove corrupted tile file: {}", remove_err ); + send_log( + LogLevel::Warning, + "Failed to remove corrupted tile file during re-download.", + ); } // Re-download the tile diff --git a/src/gui.rs b/src/gui.rs index 2eff3964..4460ec0d 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -8,15 +8,16 @@ use crate::map_transformation; use crate::osm_parser; use crate::progress; use crate::retrieve_data; +use crate::telemetry::{self, send_log, LogLevel}; use crate::version_check; use fastnbt::Value; use flate2::read::GzDecoder; use fs2::FileExt; -use log::{error, LevelFilter}; +use log::LevelFilter; use rfd::FileDialog; use std::io::Read; use std::path::{Path, PathBuf}; -use std::{env, fs, io::Write, panic}; +use std::{env, fs, io::Write}; use tauri_plugin_log::{Builder as LogBuilder, Target, TargetKind}; /// Manages the session.lock file for a Minecraft world directory @@ -63,12 +64,8 @@ pub fn run_gui() { // Launch the UI println!("Launching UI..."); - // Set a custom panic hook to log panic information - panic::set_hook(Box::new(|panic_info| { - let message = format!("Application panicked: {panic_info:?}"); - error!("{message}"); - std::process::exit(1); - })); + // Install panic hook for crash reporting + telemetry::install_panic_hook(); // Workaround WebKit2GTK issue with NVIDIA drivers and graphics issues // Source: https://github.com/tauri-apps/tauri/issues/10702 @@ -400,6 +397,10 @@ fn add_localized_world_name(world_path: PathBuf, bbox: &LLBBox) -> PathBuf { if let Ok(compressed_data) = encoder.finish() { if let Err(e) = std::fs::write(&level_path, compressed_data) { eprintln!("Failed to update level.dat with area name: {e}"); + send_log( + LogLevel::Warning, + "Failed to update level.dat with area name", + ); } } } @@ -678,10 +679,17 @@ fn gui_start_generation( fillground_enabled: bool, is_new_world: bool, spawn_point: Option<(f64, f64)>, + telemetry_consent: bool, ) -> Result<(), String> { use progress::emit_gui_error; use LLBBox; + // Store telemetry consent for crash reporting + telemetry::set_telemetry_consent(telemetry_consent); + + // Send generation click telemetry + telemetry::send_generation_click(); + // If spawn point was chosen and the world is new, check and set the spawn point if is_new_world && spawn_point.is_some() { // Verify the spawn point is within bounds @@ -810,6 +818,7 @@ fn gui_start_generation( &mut xzbbox, &mut ground, ); + send_log(LogLevel::Info, "Map transformation completed."); let _ = data_processing::generate_world( parsed_elements, diff --git a/src/gui/css/styles.css b/src/gui/css/styles.css index c2a5a5d5..864cd3ea 100644 --- a/src/gui/css/styles.css +++ b/src/gui/css/styles.css @@ -63,6 +63,7 @@ a:hover { justify-content: center; align-items: stretch; margin-top: 5px; + min-height: 60vh; } .section { @@ -79,6 +80,12 @@ a:hover { padding: 20px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + display: flex; + flex-direction: column; +} + +.map-box { + min-height: 400px; } .controls-content { @@ -94,6 +101,8 @@ a:hover { .map-container { border: 2px solid #e0e0e0; border-radius: 8px; + flex-grow: 1; + min-height: 300px; } .section h2 { @@ -249,6 +258,33 @@ button:hover { color: #ffffff; } +/* Modal actions/buttons */ +.modal-actions { + display: flex; + justify-content: flex-end; + gap: 10px; +} + +.btn-primary { + background-color: var(--primary-accent); + color: #1a1a1a; +} + +.btn-primary:hover { + background-color: var(--primary-accent-dark); +} + +.btn-secondary { + background-color: #e0e0e0; +} + +@media (prefers-color-scheme: dark) { + .btn-secondary { + background-color: #3a3a3a; + color: #ffffff; + } +} + #terrain-toggle { accent-color: #fecc44; } @@ -281,6 +317,10 @@ button:hover { margin: 15px 0; } +#telemetry-toggle { + accent-color: #fecc44; +} + .scale-slider-container label { display: block; margin-bottom: 5px; @@ -306,7 +346,7 @@ button:hover { #bbox-coords { width: 100%; - padding: 8px; + padding: 5px; border: 1px solid #fecc44; border-radius: 4px; font-size: 14px; @@ -353,7 +393,7 @@ button:hover { .license-button-row { justify-content: center; - margin-top: 10px; + margin-top: 5px; } .license-button { @@ -393,7 +433,7 @@ button:hover { .generation-mode-dropdown { width: 100%; max-width: 180px; - padding: 5px 8px; + padding: 3px 8px; border-radius: 4px; border: 1px solid #fecc44; background-color: #ffffff; @@ -421,7 +461,7 @@ button:hover { .language-dropdown { width: 100%; max-width: 180px; - padding: 5px 8px; + padding: 3px 8px; border-radius: 4px; border: 1px solid #fecc44; background-color: #ffffff; @@ -449,7 +489,7 @@ button:hover { .theme-dropdown { width: 100%; max-width: 180px; - padding: 5px 8px; + padding: 3px 8px; border-radius: 4px; border: 1px solid #fecc44; background-color: #ffffff; diff --git a/src/gui/index.html b/src/gui/index.html index 0ed78ef8..a216db1f 100644 --- a/src/gui/index.html +++ b/src/gui/index.html @@ -186,6 +186,14 @@