Optimize chat rendering & add web session activity tracking (#214)
* feat: add chat virtualization and turn grouping infrastructure Implement VirtualMessageList with virtualization and overscan for smooth scrolling Refactor MessageList to render only visible messages and pass scroll refs Introduce TurnGroupingContext and provider to stabilize per-turn rendering and reduce re-renders * feat: add web server session activity endpoint for visibility restore Add /api/session-activity endpoint to expose tracked session activity Use web server activity first when restoring visibility, with fallback to global status Update server SSE to set session phase on activity events * feat(chat): split TurnGroupingContext into UI/Streaming contexts Add separate UI state and streaming contexts to reduce re-renders. Skip animations for items visible in collapsed view when expanding. Track shown parts in collapsed mode to fade in progressively * feat(ui): cache turn groups with expand state and guard web activity Add isExpanded to the turn cache key to trigger updates correctly Expose isGroupExpanded from UI state so groups reflect expand/collapse Limit web server session activity fetch to web runtime only
This commit is contained in:
committed by
GitHub
parent
adbc5af95f
commit
f34027df10
Generated
+21
-18
@@ -2882,6 +2882,17 @@ dependencies = [
|
||||
"objc2-foundation 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-metal"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2 0.6.3",
|
||||
"objc2-foundation 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-osa-kit"
|
||||
version = "0.3.2"
|
||||
@@ -2904,7 +2915,7 @@ dependencies = [
|
||||
"block2 0.5.1",
|
||||
"objc2 0.5.2",
|
||||
"objc2-foundation 0.2.2",
|
||||
"objc2-metal",
|
||||
"objc2-metal 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2914,8 +2925,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2 0.6.2",
|
||||
"libc",
|
||||
"objc2 0.6.3",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-video",
|
||||
"objc2-foundation 0.3.2",
|
||||
"objc2-metal 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2991,7 +3008,9 @@ dependencies = [
|
||||
"nix 0.28.0",
|
||||
"objc",
|
||||
"objc2 0.6.3",
|
||||
"objc2-app-kit",
|
||||
"objc2-foundation 0.3.2",
|
||||
"objc2-quartz-core 0.3.2",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"portable-pty",
|
||||
@@ -3016,7 +3035,6 @@ dependencies = [
|
||||
"url",
|
||||
"urlencoding",
|
||||
"uuid",
|
||||
"window-vibrancy 0.7.1",
|
||||
"zip 2.4.2",
|
||||
]
|
||||
|
||||
@@ -4756,7 +4774,7 @@ dependencies = [
|
||||
"url",
|
||||
"webkit2gtk",
|
||||
"webview2-com",
|
||||
"window-vibrancy 0.6.0",
|
||||
"window-vibrancy",
|
||||
"windows",
|
||||
]
|
||||
|
||||
@@ -6006,21 +6024,6 @@ dependencies = [
|
||||
"windows-version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "window-vibrancy"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "010797bd7c40396fbc59d3105089fed0885fe267a0ef4a0a4646df54e28647f6"
|
||||
dependencies = [
|
||||
"objc2 0.6.3",
|
||||
"objc2-app-kit",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation 0.3.2",
|
||||
"raw-window-handle",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.61.3"
|
||||
|
||||
@@ -59,4 +59,5 @@ zip = "2.1"
|
||||
tauri-build = { version = "2.5.3", features = [] }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
window-vibrancy = "0.7.1"
|
||||
objc2-app-kit = { version = "0.3.2", features = ["NSView", "NSResponder"] }
|
||||
objc2-quartz-core = { version = "0.3.2", features = ["CALayer"] }
|
||||
|
||||
@@ -88,8 +88,7 @@ use window_state::{load_window_state, persist_window_state, WindowStateManager};
|
||||
#[cfg(target_os = "macos")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use window_vibrancy::{apply_vibrancy, NSVisualEffectMaterial};
|
||||
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
static NEEDS_TRAFFIC_LIGHT_FIX: AtomicBool = AtomicBool::new(false);
|
||||
@@ -352,6 +351,41 @@ fn adjust_traffic_lights_position<R: tauri::Runtime>(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn optimize_webview_layer<R: tauri::Runtime>(window: &tauri::WebviewWindow<R>) {
|
||||
use objc2::msg_send;
|
||||
use objc2::runtime::AnyObject;
|
||||
|
||||
if let Ok(ns_view) = window.ns_view() {
|
||||
unsafe {
|
||||
let view: *mut AnyObject = ns_view.cast();
|
||||
if view.is_null() {
|
||||
warn!("[macos:layer] NSView is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable layer-backing for GPU compositing
|
||||
let _: () = msg_send![view, setWantsLayer: true];
|
||||
|
||||
// Get the layer
|
||||
let layer: *mut AnyObject = msg_send![view, layer];
|
||||
if !layer.is_null() {
|
||||
// Enable asynchronous drawing for better scroll performance
|
||||
let _: () = msg_send![layer, setDrawsAsynchronously: true];
|
||||
|
||||
// Disable implicit animations that can cause jitter
|
||||
let _: () = msg_send![layer, setActions: std::ptr::null::<AnyObject>()];
|
||||
|
||||
info!("[macos:layer] WebView layer optimizations applied");
|
||||
} else {
|
||||
warn!("[macos:layer] Layer is null after setWantsLayer");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("[macos:layer] Failed to get NSView");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn prevent_app_nap() {
|
||||
use objc2_foundation::{NSActivityOptions, NSProcessInfo, NSString};
|
||||
@@ -681,28 +715,13 @@ fn main() {
|
||||
let macos_version = get_macos_major_version();
|
||||
info!("[macos] Detected macOS version: {}", macos_version);
|
||||
|
||||
let corner_radius = if macos_version >= 26 { 24.0 } else { 10.0 };
|
||||
if let Err(error) = apply_vibrancy(
|
||||
&window,
|
||||
NSVisualEffectMaterial::Sidebar,
|
||||
None,
|
||||
Some(corner_radius),
|
||||
) {
|
||||
warn!(
|
||||
"[desktop:vibrancy] Failed to apply macOS vibrancy: {}",
|
||||
error
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
"[desktop:vibrancy] Applied macOS Sidebar vibrancy with radius {}",
|
||||
corner_radius
|
||||
);
|
||||
}
|
||||
|
||||
if macos_version < 26 {
|
||||
NEEDS_TRAFFIC_LIGHT_FIX.store(true, Ordering::SeqCst);
|
||||
adjust_traffic_lights_position(&window, 17.0, 16.0);
|
||||
}
|
||||
|
||||
// Apply layer optimizations for smoother scrolling
|
||||
optimize_webview_layer(&window);
|
||||
}
|
||||
|
||||
if let Some(saved) = &stored_state {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
{
|
||||
"label": "main",
|
||||
"title": "OpenChamber",
|
||||
"transparent": true,
|
||||
"transparent": false,
|
||||
"width": 1280,
|
||||
"height": 800,
|
||||
"resizable": true,
|
||||
|
||||
Reference in New Issue
Block a user