Files
archy/packages/app/src/components/chat/PromptIndex.vue
T
DorianandClaude Opus 4.6 ad63a7b1af feat(content): add TV Series content type with TMDB integration
Add complete TV series content surface: extraction from AI responses,
grid/detail views, TMDB TV search endpoint, and panel tab integration.
Includes film_ext-to-TV-series conversion for backward compatibility
and AI prompt instructions for [[tv_ext:...]] tags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 06:50:03 +00:00

114 lines
3.4 KiB
Vue

<template>
<div class="flex-1 min-h-0 overflow-y-auto scrollbar-hide p-3 space-y-1">
<div v-if="promptPairs.length === 0" class="flex items-center justify-center h-full">
<p class="text-xs" :class="isDark ? 'text-white/30' : 'text-gray-400'">
No prompts yet
</p>
</div>
<button
v-for="(pair, i) in promptPairs"
:key="pair.userMsg.id"
class="w-full text-left px-3 py-2.5 rounded-xl transition-all duration-150 group"
:class="[
activeIndex === i
? 'path-glass-bubble-user'
: isDark
? 'hover:bg-white/5'
: 'hover:bg-black/3'
]"
@click="selectPrompt(pair, i)"
>
<p class="text-sm leading-snug truncate"
:class="isDark ? 'text-white/90' : 'text-gray-800'">
{{ pair.userMsg.content }}
</p>
<div class="flex items-center gap-1.5 mt-1">
<span class="text-[10px]"
:class="isDark ? 'text-white/30' : 'text-gray-400'">
{{ formatTime(pair.userMsg.timestamp) }}
</span>
<span
v-for="badge in pair.badges"
:key="badge"
class="text-[9px] px-1.5 py-0.5 rounded-md"
:class="isDark
? 'bg-white/8 text-white/40'
: 'bg-black/5 text-gray-500'"
>
{{ badge }}
</span>
</div>
</button>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import type { Message } from '@aiui/core/types/message'
import { useTheme } from '@/composables/useTheme'
import { useContentPanel } from '@/composables/useContentPanel'
interface PromptPair {
userMsg: Message
assistantMsg: Message | null
badges: string[]
}
const props = defineProps<{
messages: Message[]
}>()
const emit = defineEmits<{
select: [userMsg: Message, assistantMsg: Message | null]
}>()
const { isDark } = useTheme()
const { getContextualInlineContent } = useContentPanel()
const activeIndex = ref<number | null>(null)
const promptPairs = computed<PromptPair[]>(() => {
const pairs: PromptPair[] = []
const msgs = props.messages
for (let i = 0; i < msgs.length; i++) {
if (msgs[i].role !== 'user') continue
const userMsg = msgs[i]
const assistantMsg = (i + 1 < msgs.length && msgs[i + 1].role === 'assistant')
? msgs[i + 1]
: null
const badges: string[] = []
if (assistantMsg && assistantMsg.content) {
const content = getContextualInlineContent(
assistantMsg.content,
userMsg.content,
assistantMsg.webResults ?? [],
)
if (content.films.length > 0) badges.push('Films')
if ((content.books?.length ?? 0) > 0) badges.push('Books')
if ((content.tvSeries?.length ?? 0) > 0) badges.push('TV')
if (content.songs.length > 0) badges.push('Music')
if (content.podcasts.length > 0) badges.push('Podcasts')
if (content.magazineSections.length > 0) badges.push('Magazine')
if ((content.newsLinks?.length ?? 0) > 0) badges.push('News')
if ((content.websitesLinks?.length ?? 0) > 0) badges.push('Web')
}
pairs.push({ userMsg, assistantMsg, badges })
}
return pairs
})
function selectPrompt(pair: PromptPair, index: number) {
activeIndex.value = index
emit('select', pair.userMsg, pair.assistantMsg)
}
function formatTime(ts: number): string {
return new Date(ts).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
}
</script>