feat: implement waterfall layout with smart image positioning and infinite scroll

- Add single-column layout for homepage articles
- Implement smart image positioning based on aspect ratio:
  * Landscape images (ratio > 1.2) displayed on top
  * Portrait/square images (ratio ≤ 1.2) displayed on left side
- Add infinite scroll with lazy loading
- Create new API endpoint /api/articles for pagination
- Add loading indicator and 'no more articles' message
- Optimize performance with image lazy loading and scroll throttling
- Add responsive layout for mobile devices

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 19:31:18 +08:00
co-authored by Claude Fable 5
parent 7047b33358
commit 5ec783e471
5 changed files with 576 additions and 40 deletions
+34
View File
@@ -1,6 +1,7 @@
package handlers
import (
"fmt"
"net/http"
"time"
@@ -33,6 +34,39 @@ func HomePage(db *gorm.DB) gin.HandlerFunc {
}
}
// HomeArticlesAPI returns articles in JSON format for infinite scroll.
func HomeArticlesAPI(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
page := 1
if p, ok := c.GetQuery("page"); ok {
var parsed int
if _, err := fmt.Sscanf(p, "%d", &parsed); err == nil && parsed > 0 {
page = parsed
}
}
pageSize := 10
offset := (page - 1) * pageSize
var articles []models.Article
db.Where("status = ?", models.ArticlePublished).
Order(publishedArticleOrder).
Limit(pageSize).
Offset(offset).
Find(&articles)
var total int64
db.Model(&models.Article{}).
Where("status = ?", models.ArticlePublished).
Count(&total)
c.JSON(http.StatusOK, gin.H{
"articles": articles,
"hasMore": int64(offset+len(articles)) < total,
})
}
}
// ArticleDetail renders a single published article by its slug.
func ArticleDetail(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {