fix(windows): restauration panel-only des fenêtres détachées suivant le projet en focus (#47)
Partie backend. Les fenêtres/panneaux détachés étaient restaurés avec un project_id figé au moment du détachement, si bien qu'ils restaient collés à un projet mort ou incohérent après redémarrage. Ils sont désormais restaurés en mode panel-only, sans project_id figé, et suivent le projet en focus de la fenêtre principale via un event focused-project exposé par la couche fenêtre. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -262,6 +262,8 @@ pub fn run() {
|
||||
commands::read_memory_index,
|
||||
commands::recall_memory,
|
||||
commands::resolve_memory_links,
|
||||
commands::set_focused_project,
|
||||
commands::get_focused_project,
|
||||
commands::open_view_window,
|
||||
commands::close_view_window,
|
||||
commands::move_tab_to_new_window,
|
||||
@ -351,25 +353,26 @@ fn persisted_window_identity(
|
||||
return Some((PersistedWindowKind::Main, None, None, None));
|
||||
}
|
||||
|
||||
let (panel, project_id) = persisted_view_identity_from_label(label)?;
|
||||
let panel = persisted_view_identity_from_label(label)?;
|
||||
Some((
|
||||
PersistedWindowKind::View,
|
||||
Some(panel.as_str().to_owned()),
|
||||
Some(project_id),
|
||||
Some(commands::view_window_url(panel, project_id)),
|
||||
None,
|
||||
Some(commands::view_window_url(panel)),
|
||||
))
|
||||
}
|
||||
|
||||
fn persisted_view_identity_from_label(label: &str) -> Option<(commands::ViewPanel, ProjectId)> {
|
||||
fn persisted_view_identity_from_label(label: &str) -> Option<commands::ViewPanel> {
|
||||
let rest = label.strip_prefix("view-")?;
|
||||
let (panel, project_id) = rest.rsplit_once('-')?;
|
||||
if project_id.len() != 32 {
|
||||
return None;
|
||||
if let Ok(panel) = commands::ViewPanel::parse(rest) {
|
||||
return Some(panel);
|
||||
}
|
||||
|
||||
let panel = commands::ViewPanel::parse(panel).ok()?;
|
||||
let project_id = ProjectId::from_uuid(Uuid::parse_str(project_id).ok()?);
|
||||
Some((panel, project_id))
|
||||
let (panel, project_id) = rest.rsplit_once('-')?;
|
||||
if project_id.len() != 32 || Uuid::parse_str(project_id).is_err() {
|
||||
return None;
|
||||
}
|
||||
commands::ViewPanel::parse(panel).ok()
|
||||
}
|
||||
|
||||
fn restore_open_webview_windows(handle: &tauri::AppHandle) {
|
||||
@ -396,30 +399,21 @@ fn restore_open_webview_windows(handle: &tauri::AppHandle) {
|
||||
}
|
||||
|
||||
fn restore_view_window(handle: &tauri::AppHandle, state: &PersistedWindowState) {
|
||||
if handle.get_webview_window(&state.label).is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(panel) = state
|
||||
.panel
|
||||
.as_deref()
|
||||
.and_then(|raw| commands::ViewPanel::parse(raw).ok())
|
||||
.or_else(|| persisted_view_identity_from_label(&state.label))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(project_id) = state.project_id else {
|
||||
return;
|
||||
};
|
||||
let expected_label = commands::view_window_label(panel, project_id);
|
||||
if expected_label != state.label {
|
||||
let label = commands::view_window_label(panel);
|
||||
if handle.get_webview_window(&label).is_some() {
|
||||
return;
|
||||
}
|
||||
let url = state
|
||||
.url
|
||||
.clone()
|
||||
.unwrap_or_else(|| commands::view_window_url(panel, project_id));
|
||||
let url = commands::view_window_url(panel);
|
||||
|
||||
let Ok(window) = WebviewWindowBuilder::new(handle, &state.label, WebviewUrl::App(url.into()))
|
||||
let Ok(window) = WebviewWindowBuilder::new(handle, &label, WebviewUrl::App(url.into()))
|
||||
.title(format!("IdeA - {}", panel.title()))
|
||||
.inner_size(1120.0, 760.0)
|
||||
.min_inner_size(720.0, 480.0)
|
||||
@ -435,21 +429,15 @@ fn restore_view_window(handle: &tauri::AppHandle, state: &PersistedWindowState)
|
||||
};
|
||||
|
||||
let event_app = handle.clone();
|
||||
let event_label = state.label.clone();
|
||||
let event_label = label.clone();
|
||||
window.on_window_event(move |event| {
|
||||
if let tauri::WindowEvent::CloseRequested { .. } = event {
|
||||
commands::emit_view_window_lifecycle(
|
||||
&event_app,
|
||||
"closed",
|
||||
panel,
|
||||
project_id,
|
||||
&event_label,
|
||||
);
|
||||
commands::emit_view_window_lifecycle(&event_app, "closed", panel, &event_label);
|
||||
}
|
||||
});
|
||||
|
||||
apply_persisted_window_state(handle, &window, state);
|
||||
commands::emit_view_window_lifecycle(handle, "opened", panel, project_id, &state.label);
|
||||
commands::emit_view_window_lifecycle(handle, "opened", panel, &label);
|
||||
}
|
||||
|
||||
fn apply_persisted_window_state(
|
||||
@ -541,17 +529,30 @@ mod tests {
|
||||
assert!(project_id.is_none());
|
||||
assert!(url.is_none());
|
||||
|
||||
let (panel, project_id) =
|
||||
persisted_view_identity_from_label("view-tickets-0000000000000000000000000000002a")
|
||||
.unwrap();
|
||||
let (kind, panel, project_id, url) =
|
||||
persisted_window_identity("view-tickets-0000000000000000000000000000002a").unwrap();
|
||||
|
||||
assert_eq!(panel.as_str(), "tickets");
|
||||
assert_eq!(kind, PersistedWindowKind::View);
|
||||
assert_eq!(panel.as_deref(), Some("tickets"));
|
||||
assert!(project_id.is_none());
|
||||
assert_eq!(url.as_deref(), Some("index.html?panel=tickets"));
|
||||
assert_eq!(
|
||||
project_id.to_string(),
|
||||
"00000000-0000-0000-0000-00000000002a"
|
||||
persisted_view_identity_from_label("view-tickets-0000000000000000000000000000002a")
|
||||
.unwrap()
|
||||
.as_str(),
|
||||
"tickets"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persisted_identity_accepts_new_panel_only_view_labels() {
|
||||
let (kind, panel, project_id, url) = persisted_window_identity("view-agents").unwrap();
|
||||
assert_eq!(kind, PersistedWindowKind::View);
|
||||
assert_eq!(panel.as_deref(), Some("agents"));
|
||||
assert!(project_id.is_none());
|
||||
assert_eq!(url.as_deref(), Some("index.html?panel=agents"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persisted_identity_filters_unknown_or_headless_labels() {
|
||||
assert!(persisted_window_identity("mcp-server").is_none());
|
||||
|
||||
Reference in New Issue
Block a user