Add settings page, model management, and chat UX improvements
- Settings infrastructure: key-value settings table, GET/PUT API, Pinia store - Configurable assistant name (default "Fable") in settings and LLM system prompt - Model catalog with 18 models in 3 categories (General Purpose, Coding, Uncensored / Creative Writing) with download/select/remove functionality - Move Ollama status indicator from chat views to global nav bar - Chat bubble layout: user messages right-aligned, assistant left-aligned - Floating dark input bar with auto-focus and circular send button - Fix HTML entity rendering (' apostrophe issue in marked/DOMPurify pipeline) - Fix new chat button navigation (fetchConversation before router.push) - Recent chats section on home page with "New Chat" button - Update summary.md with Phase 4.5 changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useTheme } from "@/composables/useTheme";
|
||||
import { useChatStore } from "@/stores/chat";
|
||||
|
||||
const { theme, toggleTheme } = useTheme();
|
||||
const chatStore = useChatStore();
|
||||
|
||||
const emit = defineEmits<{
|
||||
toggleChatPanel: [];
|
||||
}>();
|
||||
|
||||
const statusLabel = computed(() => {
|
||||
if (chatStore.ollamaStatus === "unavailable") return "Ollama unavailable";
|
||||
if (chatStore.modelStatus === "not_found") return "Model downloading...";
|
||||
if (chatStore.chatReady) return "Connected";
|
||||
return "Checking...";
|
||||
});
|
||||
|
||||
const statusClass = computed(() => {
|
||||
if (chatStore.ollamaStatus === "unavailable") return "status-red";
|
||||
if (chatStore.modelStatus === "not_found") return "status-yellow";
|
||||
if (chatStore.chatReady) return "status-green";
|
||||
return "status-yellow";
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -16,6 +33,10 @@ const emit = defineEmits<{
|
||||
<router-link to="/notes" class="nav-link">Notes</router-link>
|
||||
<router-link to="/tasks" class="nav-link">Tasks</router-link>
|
||||
<router-link to="/chat" class="nav-link">Chat</router-link>
|
||||
<router-link to="/settings" class="nav-link">Settings</router-link>
|
||||
<span class="status-indicator" :class="statusClass" :title="statusLabel">
|
||||
<span class="status-dot"></span>
|
||||
</span>
|
||||
<button class="btn-chat-panel" @click="emit('toggleChatPanel')" title="Open chat panel">
|
||||
💬
|
||||
</button>
|
||||
@@ -59,6 +80,30 @@ const emit = defineEmits<{
|
||||
.nav-link:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
.status-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.status-green .status-dot {
|
||||
background: #22c55e;
|
||||
}
|
||||
.status-yellow .status-dot {
|
||||
background: #eab308;
|
||||
animation: pulse-dot 2s infinite;
|
||||
}
|
||||
.status-red .status-dot {
|
||||
background: #ef4444;
|
||||
}
|
||||
@keyframes pulse-dot {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.4; }
|
||||
}
|
||||
.btn-chat-panel {
|
||||
background: none;
|
||||
border: 1px solid var(--color-border);
|
||||
|
||||
Reference in New Issue
Block a user