fix(app-tauri,frontend): le panneau MCP se détache en fenêtre OS — #299 (cause: enum Rust ViewPanel sans variante Mcp, open_view_window("mcp") rejetait INVALID et detachPanel ne touchait le placement qu'en cas de succès donc aucun effet visible ni message; fix: variante ViewPanel::Mcp avec parse/as_str/title "MCP" + contrat stable label view-mcp / url index.html?panel=mcp / decodage view_panel_from_window_label, identite persistee des fenetres view-mcp acceptee a la restauration #50, et ProjectsView surface desormais un echec de detachement via alerte role=alert avec bouton Reessayer au lieu de l'echec silencieux — placement conserve tant que la fenetre OS ne s'ouvre pas; QA verte reconfirmee par Git: rustup run stable cargo fmt --all -- --check, git diff --check, cargo test -p app-tauri view_window_tests 9/9 dont mcp_view_window_contract_is_stable, persisted_identity_accepts_mcp_view_label 1/1, npm test 22/22 sur ViewWindow/ProjectsView.detach/viewPlacement, npm run build tsc+vite OK; fichiers tickets/296/*, tickets/299/, scripts/ et sync counter/index hors perimetre; aucun push)
This commit is contained in:
@ -246,6 +246,7 @@ export function ProjectsView() {
|
||||
const [pendingConversationOpen, setPendingConversationOpen] =
|
||||
useState<PendingConversationOpen | null>(null);
|
||||
const [taskToasts, setTaskToasts] = useState<BackgroundTaskToast[]>([]);
|
||||
const [detachErrorPanel, setDetachErrorPanel] = useState<PanelId | null>(null);
|
||||
|
||||
const active = vm.openTabs.find((t) => t.id === vm.activeTabId) ?? null;
|
||||
const activeViewerConversation =
|
||||
@ -446,11 +447,17 @@ export function ProjectsView() {
|
||||
// shell. On failure the placement is left untouched (no ghost "detached" slot).
|
||||
function detachPanel(panel: PanelId) {
|
||||
if (!active) return;
|
||||
setDetachErrorPanel(null);
|
||||
void windowGateway
|
||||
.openViewWindow(panel)
|
||||
.then(() => setPlacement(panel, "detached"))
|
||||
.then(() => {
|
||||
setDetachErrorPanel(null);
|
||||
setPlacement(panel, "detached");
|
||||
})
|
||||
.catch(() => {
|
||||
/* window failed to open; keep the current placement */
|
||||
// Keep the current placement (no ghost detached slot), but surface the
|
||||
// failure so the action never appears to do nothing (#299).
|
||||
setDetachErrorPanel(panel);
|
||||
});
|
||||
}
|
||||
|
||||
@ -868,6 +875,20 @@ export function ProjectsView() {
|
||||
{vm.error}
|
||||
</p>
|
||||
)}
|
||||
{detachErrorPanel && (
|
||||
<div
|
||||
role="alert"
|
||||
className="mx-4 mt-2 flex shrink-0 items-center justify-between gap-3 rounded-md border border-danger/40 bg-danger/10 px-3 py-2 text-sm text-danger"
|
||||
>
|
||||
<span>
|
||||
Le panneau {PANEL_TITLE[detachErrorPanel]} ne peut pas être détaché
|
||||
pour le moment.
|
||||
</span>
|
||||
<Button size="sm" onClick={() => detachPanel(detachErrorPanel)}>
|
||||
Réessayer
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ── Project tab bar (#26): tabs = open projects, "+" opens Projects ── */}
|
||||
<ProjectTabs
|
||||
|
||||
Reference in New Issue
Block a user