<template>
<div class="chat-area">
<ChatHeader
@toggle-sidebar="emit('toggle-sidebar')"
@toggle-artifacts="emit('toggle-artifacts')"
/>
<!-- Reconnect toast (system-level, shown inline at top) -->
<Transition name="fade">
<div v-if="ws.reconnectFailed.value" class="reconnect-banner">
<i class="ph ph-wifi-slash"></i>
Connection lost. Retrying in background…
<GnIconButton icon="ph ph-arrows-clockwise" label="Retry" @click="retryNow" />
</div>
</Transition>
<template v-if="chat.currentId">
<MessageList />
<InputBar :ws="ws" />
</template>
<div v-else class="empty-chat">
<i class="ph ph-chat-dots empty-icon"></i>
<p>Select a conversation or start a new one</p>
</div>
</div>
</template>
<script setup>
import { watch, onUnmounted, provide } from 'vue'
import { useChatStore } from '@/stores/chat.js'
import { useWebSocket } from '@/composables/useWebSocket.js'
import ChatHeader from './ChatHeader.vue'
import MessageList from './MessageList.vue'
import InputBar from './InputBar.vue'
const emit = defineEmits(['toggle-sidebar', 'toggle-artifacts'])
const chat = useChatStore()
const ws = useWebSocket()
provide('wsSend', ws.send)
// Connect/reconnect WS when session changes
watch(
() => chat.currentId,
(id) => {
if (id) ws.connect(id)
else ws.disconnect()
},
{ immediate: true }
)
function retryNow() {
if (chat.currentId) ws.connect(chat.currentId)
}
onUnmounted(() => ws.disconnect())
</script>
<style scoped>
.reconnect-banner {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 16px;
background: rgba(224, 175, 104, 0.1);
border-bottom: 1px solid rgba(224, 175, 104, 0.3);
font-size: 13px;
color: var(--color-warning, #e0af68);
}
</style>