mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-06 13:26:38 +08:00
feat: honor pinned libraries in Emby client Views order (#24)
Sort /Users/.../Views so libraries the user pinned on the web appear first for Infuse/Emby/Jellyfin clients. Unpinned libraries keep their existing sort_order / remote-mount order. Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: truewhile <truewhile@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -125,7 +126,8 @@ func (e *EmbyService) userPayload(u *model.User) map[string]any {
|
||||
}
|
||||
|
||||
// Views 返回 Emby 中"虚拟根目录"——每个 library 一个条目,外加所有启用的
|
||||
// 远程 Emby 挂载的媒体库(联邦聚合)。
|
||||
// 远程 Emby 挂载的媒体库(联邦聚合)。顺序遵循用户置顶偏好:置顶库靠前,
|
||||
// 未置顶保持原有 sort_order / 远程挂载顺序。
|
||||
func (e *EmbyService) Views(ctx context.Context, userID string) (map[string]any, error) {
|
||||
libs, err := e.repo.Library.List(ctx)
|
||||
if err != nil {
|
||||
@@ -143,9 +145,54 @@ func (e *EmbyService) Views(ctx context.Context, userID string) (map[string]any,
|
||||
for _, remote := range e.remoteViews(ctx) {
|
||||
items = append(items, remote)
|
||||
}
|
||||
items = sortViewItemsByPinnedIDs(items, e.pinnedLibraryIDsForUser(ctx, userID))
|
||||
return map[string]any{"Items": items, "TotalRecordCount": len(items), "StartIndex": 0}, nil
|
||||
}
|
||||
|
||||
func (e *EmbyService) pinnedLibraryIDsForUser(ctx context.Context, userID string) []string {
|
||||
if e == nil || e.repo == nil || e.repo.User == nil || strings.TrimSpace(userID) == "" {
|
||||
return nil
|
||||
}
|
||||
user, err := e.repo.User.FindByID(ctx, userID)
|
||||
if err != nil || user == nil {
|
||||
return nil
|
||||
}
|
||||
return user.DecodePinnedLibraryIDs()
|
||||
}
|
||||
|
||||
func sortViewItemsByPinnedIDs(items []map[string]any, pinnedIDs []string) []map[string]any {
|
||||
if len(items) < 2 || len(pinnedIDs) == 0 {
|
||||
return items
|
||||
}
|
||||
rank := make(map[string]int, len(pinnedIDs))
|
||||
for i, id := range pinnedIDs {
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
if _, exists := rank[id]; !exists {
|
||||
rank[id] = i
|
||||
}
|
||||
}
|
||||
if len(rank) == 0 {
|
||||
return items
|
||||
}
|
||||
sorted := append([]map[string]any(nil), items...)
|
||||
sort.SliceStable(sorted, func(i, j int) bool {
|
||||
iID, _ := sorted[i]["Id"].(string)
|
||||
jID, _ := sorted[j]["Id"].(string)
|
||||
iRank, iPinned := rank[iID]
|
||||
jRank, jPinned := rank[jID]
|
||||
if iPinned != jPinned {
|
||||
return iPinned
|
||||
}
|
||||
if iPinned && jPinned {
|
||||
return iRank < jRank
|
||||
}
|
||||
return false
|
||||
})
|
||||
return sorted
|
||||
}
|
||||
|
||||
// remoteViews 返回全部启用挂载的远程媒体库视图(只有显式挂载的库才出现)。
|
||||
func (e *EmbyService) remoteViews(ctx context.Context) []map[string]any {
|
||||
if e == nil || e.remote == nil {
|
||||
|
||||
Reference in New Issue
Block a user