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).
|
||||
*/
|
||||
|
||||
import { onMounted, onUnmounted, ref, type Ref } from 'vue';
|
||||
import { onMounted, onUnmounted, ref, watch, type Ref } from 'vue';
|
||||
|
||||
// --- Types ---
|
||||
|
||||
@ -35,16 +35,24 @@ export interface ToolbarConfig {
|
||||
const _config = ref<ToolbarConfig | null>(null);
|
||||
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;
|
||||
onMounted(() => {
|
||||
myVersion = ++_mountVersion;
|
||||
_config.value = config;
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// Only clear if no newer component has taken ownership since we mounted.
|
||||
if (myVersion === _mountVersion) _config.value = null;
|
||||
});
|
||||
|
||||
function activate() { myVersion = ++_mountVersion; _config.value = config; }
|
||||
function deactivate() { if (myVersion === _mountVersion) _config.value = null; }
|
||||
|
||||
if (active !== undefined) {
|
||||
watch(active, (isActive) => { isActive ? activate() : deactivate(); }, { immediate: true });
|
||||
} else {
|
||||
onMounted(activate);
|
||||
onUnmounted(deactivate);
|
||||
}
|
||||
}
|
||||
|
||||
export function injectToolbar(): Ref<ToolbarConfig | null> {
|
||||
|
||||
@ -98,7 +98,8 @@ const { connected, send: wsSend } = ws;
|
||||
const { isLoggedIn } = auth;
|
||||
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();
|
||||
provideToolbar({
|
||||
groups: ['quad-view', 'themes', 'panels'],
|
||||
@ -119,7 +120,7 @@ provideToolbar({
|
||||
Mode: selectedMode.value,
|
||||
}),
|
||||
},
|
||||
});
|
||||
}, viewActive);
|
||||
|
||||
// Agent picker — disabled for now (auto-select default agent)
|
||||
// TODO: re-enable when multi-agent UX is designed
|
||||
@ -160,8 +161,6 @@ watch(
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
const viewActive = computed(() => agentsRoute.name === 'nyx');
|
||||
|
||||
// HUD state from ChatPane (for debug panels)
|
||||
const hudState = ref({ hudTree: [] as any[], hudVersion: 0, connected: false });
|
||||
function onHudUpdate(payload: { hudTree: any[]; hudVersion: number; connected: boolean }) {
|
||||
|
||||
@ -88,8 +88,11 @@ import { useViewer } from '../composables/useViewer';
|
||||
import { provideToolbar } from '../composables/useToolbar';
|
||||
import { computed } from 'vue';
|
||||
|
||||
provideToolbar({ groups: ['themes'] });
|
||||
import { useRoute } from 'vue-router';
|
||||
import { getApiBase } from '../utils/apiBase';
|
||||
const _route = useRoute();
|
||||
const _viewActive = computed(() => _route.name === 'viewer');
|
||||
provideToolbar({ groups: ['themes'] }, _viewActive);
|
||||
|
||||
const {
|
||||
fstoken, viewerRoots, currentPath,
|
||||
|
||||
Reference in New Issue
Block a user