mirror of
https://github.com/R0m1k3/FlowReader.git
synced 2026-10-11 17:28:05 +02:00
feat: improve article image extraction and display
This commit is contained in:
1 parent
007aec2094
commit
6fd38fbffd
3 files changed
+55
-3
No files matched your search
@@ -3,6 +3,7 @@ module github.com/michael/flowreader
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.8.0
|
||||
github.com/go-chi/chi/v5 v5.0.11
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
@@ -13,7 +14,6 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.8.0 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
|
||||
@@ -7,6 +7,9 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/google/uuid"
|
||||
"github.com/michael/flowreader/internal/domain"
|
||||
"github.com/mmcdole/gofeed"
|
||||
@@ -108,6 +111,8 @@ func (p *FeedParser) Parse(ctx context.Context, feedURL string, feedID uuid.UUID
|
||||
|
||||
if item.Image != nil && item.Image.URL != "" {
|
||||
article.ImageURL = item.Image.URL
|
||||
} else {
|
||||
article.ImageURL = findImage(item)
|
||||
}
|
||||
|
||||
if item.PublishedParsed != nil {
|
||||
@@ -134,3 +139,44 @@ func getGUID(item *gofeed.Item) string {
|
||||
}
|
||||
return item.Title // Last resort fallback
|
||||
}
|
||||
|
||||
// findImage attempts to find the best image for a feed item.
|
||||
func findImage(item *gofeed.Item) string {
|
||||
// 1. Check Enclosures
|
||||
for _, enc := range item.Enclosures {
|
||||
if strings.HasPrefix(enc.Type, "image/") {
|
||||
return enc.URL
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Check Media Extensions (media:content, media:thumbnail)
|
||||
if media, ok := item.Extensions["media"]; ok {
|
||||
if content, ok := media["content"]; ok && len(content) > 0 {
|
||||
if url := content[0].Attrs["url"]; url != "" {
|
||||
return url
|
||||
}
|
||||
}
|
||||
if thumbnail, ok := media["thumbnail"]; ok && len(thumbnail) > 0 {
|
||||
if url := thumbnail[0].Attrs["url"]; url != "" {
|
||||
return url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Extract from Content/Description as fallback
|
||||
htmlContent := item.Content
|
||||
if htmlContent == "" {
|
||||
htmlContent = item.Description
|
||||
}
|
||||
|
||||
if htmlContent != "" {
|
||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(htmlContent))
|
||||
if err == nil {
|
||||
if imgURL, exists := doc.Find("img").First().Attr("src"); exists {
|
||||
return imgURL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
@@ -16,8 +16,14 @@ export function ArticleCard({ article, onClick, onToggleRead, onToggleFavorite }
|
||||
<div className="aspect-[16/10] overflow-hidden rounded-xl bg-carbon-light relative mb-6">
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-carbon-dark/80 via-transparent to-transparent opacity-60 z-10"></div>
|
||||
|
||||
{/* Visual placeholder */}
|
||||
<div className="w-full h-full bg-[url('https://images.unsplash.com/photo-1586339949916-3e9457bef6d3?auto=format&fit=crop&q=80&w=800')] bg-cover bg-center transition-transform duration-700 group-hover:scale-105 opacity-40"></div>
|
||||
{/* Visual placeholder or real image */}
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center transition-transform duration-700 group-hover:scale-105 opacity-60"
|
||||
style={{
|
||||
backgroundImage: `url(${article.image_url || 'https://images.unsplash.com/photo-1586339949916-3e9457bef6d3?auto=format&fit=crop&q=80&w=800'})`,
|
||||
backgroundColor: '#1e1e1e'
|
||||
}}
|
||||
></div>
|
||||
|
||||
{/* Meta on top of image */}
|
||||
<div className="absolute bottom-4 left-4 right-4 z-20 flex justify-between items-end">
|
||||
|
||||
Reference in new issue
Block a user