feat(content): add Images content type with masonry grid layout
Extract markdown images and raw image URLs from AI responses into a browsable image gallery. Masonry (columns) layout in the grid, full-size detail view with source links. Also fix ContextLoader to accept all content types for loading state display. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
1973b24eaa
commit
e8ebe56d9e
@@ -99,6 +99,13 @@
|
||||
>
|
||||
View all {{ inlineTVSeries.length }} series →
|
||||
</button>
|
||||
<button
|
||||
v-else-if="inlineImages.length > 1"
|
||||
class="text-[10px] text-accent/70 hover:text-accent transition-colors"
|
||||
@click.stop="openPanel"
|
||||
>
|
||||
View all {{ inlineImages.length }} images →
|
||||
</button>
|
||||
<button
|
||||
v-else-if="inlineSongs.length > 1"
|
||||
class="text-[10px] text-accent/70 hover:text-accent transition-colors"
|
||||
@@ -142,7 +149,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { Message, WebSearchResult } from '@aiui/core/types/message'
|
||||
import type { Film, Song, Podcast, Book, TVSeries } from '@aiui/core/types/content'
|
||||
import type { Film, Song, Podcast, Book, TVSeries, ImageItem } from '@aiui/core/types/content'
|
||||
import { useTheme } from '@/composables/useTheme'
|
||||
import { useContentPanel, type MagazineSection } from '@/composables/useContentPanel'
|
||||
import { useArticleOverlayStore } from '@/stores/articleOverlay'
|
||||
@@ -163,13 +170,13 @@ const props = withDefaults(
|
||||
)
|
||||
|
||||
const { isDark } = useTheme()
|
||||
const { getContextualInlineContent, stripContentTags, stripMarkdownLinks, updatePanelFromText, openFilmDetail, openBookDetail, openTVSeriesDetail, openSongDetail, openPodcastDetail, openArticleDetail, closeFilmDetail, closeBookDetail, closeTVSeriesDetail, closeSongDetail, closePodcastDetail } = useContentPanel()
|
||||
const { getContextualInlineContent, stripContentTags, stripMarkdownLinks, updatePanelFromText, openFilmDetail, openBookDetail, openTVSeriesDetail, openImageDetail, openSongDetail, openPodcastDetail, openArticleDetail, closeFilmDetail, closeBookDetail, closeTVSeriesDetail, closeImageDetail, closeSongDetail, closePodcastDetail } = useContentPanel()
|
||||
const overlayStore = useArticleOverlayStore()
|
||||
|
||||
const isUser = computed(() => props.message.role === 'user')
|
||||
|
||||
const inlineContent = computed(() => {
|
||||
if (isUser.value) return { films: [] as Film[], books: [] as Book[], tvSeries: [] as TVSeries[], songs: [] as Song[], podcasts: [] as Podcast[], newsLinks: [] as WebSearchResult[], websitesLinks: [] as WebSearchResult[], magazineSections: [] as MagazineSection[] }
|
||||
if (isUser.value) return { films: [] as Film[], books: [] as Book[], tvSeries: [] as TVSeries[], images: [] as ImageItem[], songs: [] as Song[], podcasts: [] as Podcast[], newsLinks: [] as WebSearchResult[], websitesLinks: [] as WebSearchResult[], magazineSections: [] as MagazineSection[] }
|
||||
return getContextualInlineContent(props.message.content, props.triggeringQuery, props.message.webResults ?? [])
|
||||
})
|
||||
|
||||
@@ -182,6 +189,7 @@ const bubbleClasses = computed(() =>
|
||||
const inlineFilms = computed(() => inlineContent.value.films)
|
||||
const inlineBooks = computed(() => inlineContent.value.books ?? [])
|
||||
const inlineTVSeries = computed(() => inlineContent.value.tvSeries ?? [])
|
||||
const inlineImages = computed(() => inlineContent.value.images ?? [])
|
||||
const inlineSongs = computed(() => inlineContent.value.songs)
|
||||
const inlinePodcasts = computed(() => inlineContent.value.podcasts)
|
||||
const inlineNewsLinks = computed(() => inlineContent.value.newsLinks ?? [])
|
||||
@@ -192,6 +200,7 @@ const hasContext = computed(() => !isUser.value && (
|
||||
inlineFilms.value.length > 0 ||
|
||||
inlineBooks.value.length > 0 ||
|
||||
inlineTVSeries.value.length > 0 ||
|
||||
inlineImages.value.length > 0 ||
|
||||
inlineSongs.value.length > 0 ||
|
||||
inlinePodcasts.value.length > 0 ||
|
||||
inlineNewsLinks.value.length > 0 ||
|
||||
|
||||
Reference in New Issue
Block a user