feat: complete AIUI integration — all 31 overnight tasks
- Protocol: 10 context categories (apps, system, network, bitcoin, media, files, notes, search, ai-local, wallet) - ContextBroker: real data wiring for all categories with sanitization - Permissions: user toggles for all categories in Settings - Nginx: Claude API, OpenRouter, SearXNG proxy pass-through - Actions: launch-app, search-web, install-app handlers - Chat.vue: loading state + connection indicator - Integration test page: test-aiui.html Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
81473db38b
commit
7b56927c3c
+80
-14
@@ -228,18 +228,40 @@
|
||||
</div>
|
||||
|
||||
<!-- Quick Start Goals - shown in Pro mode below the overview cards -->
|
||||
<div v-if="uiMode.isGamer" class="path-option-card cursor-default px-6 py-6">
|
||||
<h2 class="text-xl font-semibold text-white/96 mb-2">Quick Start Goals</h2>
|
||||
<p class="text-sm text-white/60 mb-4">Not sure where to start? Try a guided setup.</p>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||
<RouterLink
|
||||
v-for="goal in topGoals"
|
||||
:key="goal.id"
|
||||
:to="`/dashboard/goals/${goal.id}`"
|
||||
class="path-action-button path-action-button--continue flex items-center justify-center gap-3"
|
||||
>
|
||||
<span>{{ goal.title }}</span>
|
||||
</RouterLink>
|
||||
<div
|
||||
v-if="uiMode.isGamer && showQuickStart"
|
||||
class="home-card"
|
||||
:class="{ 'home-card-animate': animateCards }"
|
||||
style="--card-stagger: 4"
|
||||
>
|
||||
<div class="home-card-shell">
|
||||
<div class="home-card-inner px-6 py-6">
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold text-white/96 mb-1">Quick Start Goals</h2>
|
||||
<p class="text-sm text-white/60 mb-4">Not sure where to start? Try a guided setup.</p>
|
||||
</div>
|
||||
<button
|
||||
@click="dismissQuickStart"
|
||||
class="text-white/40 hover:text-white/80 transition-colors p-1 -mt-1 -mr-1"
|
||||
title="Dismiss"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||
<RouterLink
|
||||
v-for="goal in topGoals"
|
||||
:key="goal.id"
|
||||
:to="`/dashboard/goals/${goal.id}`"
|
||||
class="home-card-btn path-action-button path-action-button--continue flex items-center justify-center gap-3"
|
||||
>
|
||||
<span>{{ goal.title }}</span>
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -266,6 +288,11 @@ import EasyHome from '@/components/EasyHome.vue'
|
||||
const uiMode = useUIModeStore()
|
||||
const topGoals = GOALS.slice(0, 3)
|
||||
|
||||
// Apps required by the top 3 goals — if all installed, no need to show Quick Start
|
||||
const QUICK_START_APPS = [...new Set(topGoals.flatMap((g) => g.requiredApps))]
|
||||
const QUICK_START_KEY = 'archipelago-quick-start-dismissed'
|
||||
const QUICK_START_RESHOW_LOGINS = 5
|
||||
|
||||
const store = useAppStore()
|
||||
const loginTransition = useLoginTransitionStore()
|
||||
|
||||
@@ -333,9 +360,45 @@ watch(() => loginTransition.startWelcomeTyping, (shouldStart) => {
|
||||
const version = computed(() => store.serverInfo?.version || '0.0.0')
|
||||
const packages = computed(() => store.packages)
|
||||
const appCount = computed(() => Object.keys(packages.value).length)
|
||||
const runningCount = computed(() =>
|
||||
const runningCount = computed(() =>
|
||||
Object.values(packages.value).filter(pkg => pkg.state === PackageState.Running).length
|
||||
)
|
||||
|
||||
// Quick Start Goals dismiss logic
|
||||
const quickStartDismissed = ref(false)
|
||||
|
||||
const allQuickStartAppsInstalled = computed(() =>
|
||||
QUICK_START_APPS.every((appId) => Object.keys(packages.value).includes(appId))
|
||||
)
|
||||
|
||||
const showQuickStart = computed(() => {
|
||||
if (allQuickStartAppsInstalled.value) return false
|
||||
return !quickStartDismissed.value
|
||||
})
|
||||
|
||||
function loadQuickStartState() {
|
||||
try {
|
||||
const raw = localStorage.getItem(QUICK_START_KEY)
|
||||
if (!raw) { quickStartDismissed.value = false; return }
|
||||
const data = JSON.parse(raw) as { dismissed: boolean; loginCount: number }
|
||||
if (!data.dismissed) { quickStartDismissed.value = false; return }
|
||||
// Re-show every N logins
|
||||
const loginCount = (data.loginCount || 0) + 1
|
||||
localStorage.setItem(QUICK_START_KEY, JSON.stringify({ dismissed: true, loginCount }))
|
||||
quickStartDismissed.value = loginCount % QUICK_START_RESHOW_LOGINS !== 0
|
||||
} catch {
|
||||
quickStartDismissed.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function dismissQuickStart() {
|
||||
quickStartDismissed.value = true
|
||||
try {
|
||||
localStorage.setItem(QUICK_START_KEY, JSON.stringify({ dismissed: true, loginCount: 0 }))
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
loadQuickStartState()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -356,7 +419,7 @@ const runningCount = computed(() =>
|
||||
}
|
||||
|
||||
/* 2advanced-style card animation sequence */
|
||||
.home-card {
|
||||
.grid > .home-card {
|
||||
min-height: 280px;
|
||||
}
|
||||
|
||||
@@ -432,6 +495,9 @@ const runningCount = computed(() =>
|
||||
opacity: 0;
|
||||
transform: scale(0.5);
|
||||
border-color: transparent;
|
||||
min-height: 44px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.home-card-animate .home-card-btn {
|
||||
|
||||
Reference in New Issue
Block a user