From b430c800008a8f57aa88cd494b4b275e47f05acf223cc02d68492afea21ef0b1 Mon Sep 17 00:00:00 2001 From: Evan Carroll Date: Wed, 14 Jan 2026 12:53:16 -0600 Subject: [PATCH] fix: scaling, and chat * Chat ergonomics vastly improved. * Scaling now done through client side settings --- .../src/pages/scene_detail.rs | 156 +--- .../src/pages/scene_new.rs | 104 +-- crates/chattyness-user-ui/src/components.rs | 4 + .../chattyness-user-ui/src/components/chat.rs | 399 ++++++++-- .../src/components/scene_viewer.rs | 718 ++++++++++++++---- .../src/components/settings.rs | 179 +++++ .../src/components/settings_popup.rs | 280 +++++++ crates/chattyness-user-ui/src/pages/realm.rs | 163 +++- 8 files changed, 1564 insertions(+), 439 deletions(-) create mode 100644 crates/chattyness-user-ui/src/components/settings.rs create mode 100644 crates/chattyness-user-ui/src/components/settings_popup.rs diff --git a/crates/chattyness-admin-ui/src/pages/scene_detail.rs b/crates/chattyness-admin-ui/src/pages/scene_detail.rs index a43c049..dabd5fc 100644 --- a/crates/chattyness-admin-ui/src/pages/scene_detail.rs +++ b/crates/chattyness-admin-ui/src/pages/scene_detail.rs @@ -134,7 +134,7 @@ fn SceneDetailView( let (show_delete_confirm, set_show_delete_confirm) = signal(false); let (show_image_modal, set_show_image_modal) = signal(false); - // Parse dimensions from bounds_wkt + // Parse dimensions from bounds_wkt for display let (initial_width, initial_height) = parse_bounds_wkt(&scene.bounds_wkt); // Clone scene data for view (to avoid move issues) @@ -145,7 +145,6 @@ fn SceneDetailView( let scene_background_image_path = scene.background_image_path.clone(); let scene_background_image_path_for_modal = scene.background_image_path.clone(); let scene_background_image_path_for_check = scene.background_image_path.clone(); - let scene_background_image_path_for_dimensions = scene.background_image_path.clone(); let scene_background_color_display = scene.background_color.clone(); let scene_created_at = scene.created_at.clone(); let scene_updated_at = scene.updated_at.clone(); @@ -158,42 +157,32 @@ fn SceneDetailView( ); let (background_image_url, set_background_image_url) = signal(String::new()); let (clear_background_image, set_clear_background_image) = signal(false); - let (infer_dimensions, set_infer_dimensions) = signal(false); - let (width, set_width) = signal(initial_width); - let (height, set_height) = signal(initial_height); - let (dimension_mode, set_dimension_mode) = signal(scene.dimension_mode.clone()); let (sort_order, set_sort_order) = signal(scene.sort_order); let (is_entry_point, set_is_entry_point) = signal(scene.is_entry_point); let (is_hidden, set_is_hidden) = signal(scene.is_hidden); - // UI state for dimension fetching + // UI state for dimension detection (read-only display) let (fetching_dimensions, set_fetching_dimensions) = signal(false); - let (dimension_message, set_dimension_message) = signal(Option::<(String, bool)>::None); + let (detected_dimensions, set_detected_dimensions) = signal(Option::<(u32, u32)>::None); let fetch_dimensions = move |_: leptos::ev::MouseEvent| { let url = background_image_url.get(); if url.is_empty() { - set_dimension_message.set(Some(("Please enter an image URL first".to_string(), false))); return; } set_fetching_dimensions.set(true); - set_dimension_message.set(None); + set_detected_dimensions.set(None); #[cfg(feature = "hydrate")] { fetch_image_dimensions_client( url, move |w, h| { - set_width.set(w as i32); - set_height.set(h as i32); - set_dimension_message.set(Some(( - format!("Dimensions: {}x{}", w, h), - true, - ))); + set_detected_dimensions.set(Some((w, h))); }, - move |err| { - set_dimension_message.set(Some((err, false))); + move |_err| { + set_detected_dimensions.set(None); }, set_fetching_dimensions, ); @@ -210,17 +199,11 @@ fn SceneDetailView( use gloo_net::http::Request; let id = scene_id.clone(); - // Build bounds WKT from width/height - let w = width.get(); - let h = height.get(); - let bounds_wkt = format!("POLYGON((0 0, {} 0, {} {}, 0 {}, 0 0))", w, w, h, h); let mut data = serde_json::json!({ "name": name.get(), "description": if description.get().is_empty() { None:: } else { Some(description.get()) }, "background_color": if background_color.get().is_empty() { None:: } else { Some(background_color.get()) }, - "bounds_wkt": bounds_wkt, - "dimension_mode": dimension_mode.get(), "sort_order": sort_order.get(), "is_entry_point": is_entry_point.get(), "is_hidden": is_hidden.get() @@ -230,10 +213,8 @@ fn SceneDetailView( let bg_url = background_image_url.get(); if !bg_url.is_empty() { data["background_image_url"] = serde_json::json!(bg_url); - // Include infer dimensions flag when uploading new image - if infer_dimensions.get() { - data["infer_dimensions_from_image"] = serde_json::json!(true); - } + // Always infer dimensions from new image + data["infer_dimensions_from_image"] = serde_json::json!(true); } // Include clear flag if set @@ -447,35 +428,19 @@ fn SceneDetailView( - // Dimension fetch message - + // Show detected dimensions (read-only feedback for new images) + {move || { - let (msg, is_success) = dimension_message.get().unwrap_or_default(); - let class = if is_success { "alert alert-success" } else { "alert alert-error" }; + let (w, h) = detected_dimensions.get().unwrap_or((0, 0)); view! { -