fix(toolbar): watch active ref for always-mounted views (AgentsView, ViewerView)
Views mounted via v-if+CSS-hide never unmount, so onMounted/onUnmounted only fire once. When a RouterView (Tests) unmounts it clears _config, and the always-mounted view never restores it. Fix: provideToolbar accepts optional active ref and uses watch() instead of lifecycle hooks for those views. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9d0012edad
commit
d48612665b
@ -9,7 +9,7 @@
|
|||||||
* Views that don't provide → toolbar shows nothing (login, home).
|
* Views that don't provide → toolbar shows nothing (login, home).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { onMounted, onUnmounted, ref, type Ref } from 'vue';
|
import { onMounted, onUnmounted, ref, watch, type Ref } from 'vue';
|
||||||
|
|
||||||
// --- Types ---
|
// --- Types ---
|
||||||
|
|
||||||
@ -35,16 +35,24 @@ export interface ToolbarConfig {
|
|||||||
const _config = ref<ToolbarConfig | null>(null);
|
const _config = ref<ToolbarConfig | null>(null);
|
||||||
let _mountVersion = 0;
|
let _mountVersion = 0;
|
||||||
|
|
||||||
export function provideToolbar(config: ToolbarConfig) {
|
/**
|
||||||
|
* Register toolbar config for the active view.
|
||||||
|
*
|
||||||
|
* Pass `active` for always-mounted views (v-if + CSS hide, e.g. AgentsView, ViewerView).
|
||||||
|
* Omit `active` for route-mounted views (RouterView) — uses onMounted/onUnmounted.
|
||||||
|
*/
|
||||||
|
export function provideToolbar(config: ToolbarConfig, active?: Ref<boolean>) {
|
||||||
let myVersion = 0;
|
let myVersion = 0;
|
||||||
onMounted(() => {
|
|
||||||
myVersion = ++_mountVersion;
|
function activate() { myVersion = ++_mountVersion; _config.value = config; }
|
||||||
_config.value = config;
|
function deactivate() { if (myVersion === _mountVersion) _config.value = null; }
|
||||||
});
|
|
||||||
onUnmounted(() => {
|
if (active !== undefined) {
|
||||||
// Only clear if no newer component has taken ownership since we mounted.
|
watch(active, (isActive) => { isActive ? activate() : deactivate(); }, { immediate: true });
|
||||||
if (myVersion === _mountVersion) _config.value = null;
|
} else {
|
||||||
});
|
onMounted(activate);
|
||||||
|
onUnmounted(deactivate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function injectToolbar(): Ref<ToolbarConfig | null> {
|
export function injectToolbar(): Ref<ToolbarConfig | null> {
|
||||||
|
|||||||
@ -98,7 +98,8 @@ const { connected, send: wsSend } = ws;
|
|||||||
const { isLoggedIn } = auth;
|
const { isLoggedIn } = auth;
|
||||||
const { selectedAgent, selectedMode, filteredAgents, defaultAgent, allAgents } = agents;
|
const { selectedAgent, selectedMode, filteredAgents, defaultAgent, allAgents } = agents;
|
||||||
|
|
||||||
// Toolbar — wrap chatStore state into ToolbarConnection shape
|
// Toolbar — always-mounted view: pass viewActive so config tracks route, not lifecycle
|
||||||
|
const viewActive = computed(() => agentsRoute.name === 'nyx');
|
||||||
const chatStore = useChatStore();
|
const chatStore = useChatStore();
|
||||||
provideToolbar({
|
provideToolbar({
|
||||||
groups: ['quad-view', 'themes', 'panels'],
|
groups: ['quad-view', 'themes', 'panels'],
|
||||||
@ -119,7 +120,7 @@ provideToolbar({
|
|||||||
Mode: selectedMode.value,
|
Mode: selectedMode.value,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
});
|
}, viewActive);
|
||||||
|
|
||||||
// Agent picker — disabled for now (auto-select default agent)
|
// Agent picker — disabled for now (auto-select default agent)
|
||||||
// TODO: re-enable when multi-agent UX is designed
|
// TODO: re-enable when multi-agent UX is designed
|
||||||
@ -160,8 +161,6 @@ watch(
|
|||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
const viewActive = computed(() => agentsRoute.name === 'nyx');
|
|
||||||
|
|
||||||
// HUD state from ChatPane (for debug panels)
|
// HUD state from ChatPane (for debug panels)
|
||||||
const hudState = ref({ hudTree: [] as any[], hudVersion: 0, connected: false });
|
const hudState = ref({ hudTree: [] as any[], hudVersion: 0, connected: false });
|
||||||
function onHudUpdate(payload: { hudTree: any[]; hudVersion: number; connected: boolean }) {
|
function onHudUpdate(payload: { hudTree: any[]; hudVersion: number; connected: boolean }) {
|
||||||
|
|||||||
@ -88,8 +88,11 @@ import { useViewer } from '../composables/useViewer';
|
|||||||
import { provideToolbar } from '../composables/useToolbar';
|
import { provideToolbar } from '../composables/useToolbar';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
provideToolbar({ groups: ['themes'] });
|
import { useRoute } from 'vue-router';
|
||||||
import { getApiBase } from '../utils/apiBase';
|
import { getApiBase } from '../utils/apiBase';
|
||||||
|
const _route = useRoute();
|
||||||
|
const _viewActive = computed(() => _route.name === 'viewer');
|
||||||
|
provideToolbar({ groups: ['themes'] }, _viewActive);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
fstoken, viewerRoots, currentPath,
|
fstoken, viewerRoots, currentPath,
|
||||||
|
|||||||
Reference in New Issue
Block a user