Adds ability to configure sort order for DLNA videos (#3645)

This commit is contained in:
CJ
2023-05-02 20:33:32 -07:00
committed by GitHub
parent 55e0d5c82f
commit d6b4d16ff4
11 changed files with 83 additions and 5 deletions

View File

@@ -99,6 +99,7 @@ fragment ConfigDLNAData on ConfigDLNAResult {
enabled enabled
whitelistedIPs whitelistedIPs
interfaces interfaces
videoSortOrder
} }
fragment ConfigScrapingData on ConfigScrapingResult { fragment ConfigScrapingData on ConfigScrapingResult {

View File

@@ -431,6 +431,8 @@ input ConfigDLNAInput {
whitelistedIPs: [String!] whitelistedIPs: [String!]
"""List of interfaces to run DLNA on. Empty for all""" """List of interfaces to run DLNA on. Empty for all"""
interfaces: [String!] interfaces: [String!]
"""Order to sort videos"""
videoSortOrder: String
} }
type ConfigDLNAResult { type ConfigDLNAResult {
@@ -441,6 +443,8 @@ type ConfigDLNAResult {
whitelistedIPs: [String!]! whitelistedIPs: [String!]!
"""List of interfaces to run DLNA on. Empty for all""" """List of interfaces to run DLNA on. Empty for all"""
interfaces: [String!]! interfaces: [String!]!
"""Order to sort videos"""
videoSortOrder: String!
} }
input ConfigScrapingInput { input ConfigScrapingInput {

View File

@@ -493,6 +493,10 @@ func (r *mutationResolver) ConfigureDlna(ctx context.Context, input ConfigDLNAIn
c.Set(config.DLNADefaultIPWhitelist, input.WhitelistedIPs) c.Set(config.DLNADefaultIPWhitelist, input.WhitelistedIPs)
} }
if input.VideoSortOrder != nil {
c.Set(config.DLNAVideoSortOrder, input.VideoSortOrder)
}
currentDLNAEnabled := c.GetDLNADefaultEnabled() currentDLNAEnabled := c.GetDLNADefaultEnabled()
if input.Enabled != nil && *input.Enabled != currentDLNAEnabled { if input.Enabled != nil && *input.Enabled != currentDLNAEnabled {
c.Set(config.DLNADefaultEnabled, *input.Enabled) c.Set(config.DLNADefaultEnabled, *input.Enabled)

View File

@@ -202,6 +202,7 @@ func makeConfigDLNAResult() *ConfigDLNAResult {
Enabled: config.GetDLNADefaultEnabled(), Enabled: config.GetDLNADefaultEnabled(),
WhitelistedIPs: config.GetDLNADefaultIPWhitelist(), WhitelistedIPs: config.GetDLNADefaultIPWhitelist(),
Interfaces: config.GetDLNAInterfaces(), Interfaces: config.GetDLNAInterfaces(),
VideoSortOrder: config.GetVideoSortOrder(),
} }
} }

View File

@@ -444,10 +444,15 @@ func (me *contentDirectoryService) getVideos(sceneFilter *models.SceneFilterType
var objs []interface{} var objs []interface{}
if err := txn.WithReadTxn(context.TODO(), me.txnManager, func(ctx context.Context) error { if err := txn.WithReadTxn(context.TODO(), me.txnManager, func(ctx context.Context) error {
sort := "title" sort := me.VideoSortOrder
direction := models.SortDirectionEnumDesc
if sort == "title" {
direction = models.SortDirectionEnumAsc
}
findFilter := &models.FindFilterType{ findFilter := &models.FindFilterType{
PerPage: &pageSize, PerPage: &pageSize,
Sort: &sort, Sort: &sort,
Direction: &direction,
} }
scenes, total, err := scene.QueryWithCount(ctx, me.repository.SceneFinder, sceneFilter, findFilter) scenes, total, err := scene.QueryWithCount(ctx, me.repository.SceneFinder, sceneFilter, findFilter)

View File

@@ -276,6 +276,7 @@ type Server struct {
repository Repository repository Repository
sceneServer sceneServer sceneServer sceneServer
ipWhitelistManager *ipWhitelistManager ipWhitelistManager *ipWhitelistManager
VideoSortOrder string
} }
// UPnP SOAP service. // UPnP SOAP service.

View File

@@ -45,6 +45,7 @@ type dmsConfig struct {
LogHeaders bool LogHeaders bool
StallEventSubscribe bool StallEventSubscribe bool
NotifyInterval time.Duration NotifyInterval time.Duration
VideoSortOrder string
} }
type sceneServer interface { type sceneServer interface {
@@ -56,6 +57,7 @@ type Config interface {
GetDLNAInterfaces() []string GetDLNAInterfaces() []string
GetDLNAServerName() string GetDLNAServerName() string
GetDLNADefaultIPWhitelist() []string GetDLNADefaultIPWhitelist() []string
GetVideoSortOrder() string
} }
type Service struct { type Service struct {
@@ -123,6 +125,7 @@ func (s *Service) init() error {
FriendlyName: friendlyName, FriendlyName: friendlyName,
LogHeaders: false, LogHeaders: false,
NotifyInterval: 30 * time.Second, NotifyInterval: 30 * time.Second,
VideoSortOrder: s.config.GetVideoSortOrder(),
} }
interfaces, err := s.getInterfaces() interfaces, err := s.getInterfaces()
@@ -164,6 +167,7 @@ func (s *Service) init() error {
// }, // },
StallEventSubscribe: dmsConfig.StallEventSubscribe, StallEventSubscribe: dmsConfig.StallEventSubscribe,
NotifyInterval: dmsConfig.NotifyInterval, NotifyInterval: dmsConfig.NotifyInterval,
VideoSortOrder: dmsConfig.VideoSortOrder,
} }
return nil return nil

View File

@@ -210,6 +210,9 @@ const (
DLNADefaultIPWhitelist = "dlna.default_whitelist" DLNADefaultIPWhitelist = "dlna.default_whitelist"
DLNAInterfaces = "dlna.interfaces" DLNAInterfaces = "dlna.interfaces"
DLNAVideoSortOrder = "dlna.video_sort_order"
dlnaVideoSortOrderDefault = "title"
// Logging options // Logging options
LogFile = "logFile" LogFile = "logFile"
LogOut = "logOut" LogOut = "logOut"
@@ -1370,6 +1373,17 @@ func (i *Instance) GetDLNAInterfaces() []string {
return i.getStringSlice(DLNAInterfaces) return i.getStringSlice(DLNAInterfaces)
} }
// GetVideoSortOrder returns the sort order to display videos. If
// empty, videos will be sorted by titles.
func (i *Instance) GetVideoSortOrder() string {
ret := i.getString(DLNAVideoSortOrder)
if ret == "" {
ret = dlnaVideoSortOrderDefault
}
return ret
}
// GetLogFile returns the filename of the file to output logs to. // GetLogFile returns the filename of the file to output logs to.
// An empty string means that file logging will be disabled. // An empty string means that file logging will be disabled.
func (i *Instance) GetLogFile() string { func (i *Instance) GetLogFile() string {

View File

@@ -14,8 +14,17 @@ import { Icon } from "../Shared/Icon";
import { LoadingIndicator } from "../Shared/LoadingIndicator"; import { LoadingIndicator } from "../Shared/LoadingIndicator";
import { ModalComponent } from "../Shared/Modal"; import { ModalComponent } from "../Shared/Modal";
import { SettingSection } from "./SettingSection"; import { SettingSection } from "./SettingSection";
import { BooleanSetting, StringListSetting, StringSetting } from "./Inputs"; import {
BooleanSetting,
StringListSetting,
StringSetting,
SelectSetting,
} from "./Inputs";
import { SettingStateContext } from "./context"; import { SettingStateContext } from "./context";
import {
videoSortOrderIntlMap,
defaultVideoSort,
} from "src/utils/dlnaVideoSort";
import { import {
faClock, faClock,
faTimes, faTimes,
@@ -445,6 +454,22 @@ export const SettingsServicesPanel: React.FC = () => {
value={dlna.whitelistedIPs ?? undefined} value={dlna.whitelistedIPs ?? undefined}
onChange={(v) => saveDLNA({ whitelistedIPs: v })} onChange={(v) => saveDLNA({ whitelistedIPs: v })}
/> />
<SelectSetting
id="video-sort-order"
headingID="config.dlna.video_sort_order"
subHeadingID="config.dlna.video_sort_order_desc"
value={dlna.videoSortOrder ?? defaultVideoSort}
onChange={(v) => saveDLNA({ videoSortOrder: v })}
>
{Array.from(videoSortOrderIntlMap.entries()).map((v) => (
<option key={v[0]} value={v[0]}>
{intl.formatMessage({
id: v[1],
})}
</option>
))}
</SelectSetting>
</SettingSection> </SettingSection>
</> </>
); );

View File

@@ -234,7 +234,9 @@
"server_display_name": "Server Display Name", "server_display_name": "Server Display Name",
"server_display_name_desc": "Display name for the DLNA server. Defaults to {server_name} if empty.", "server_display_name_desc": "Display name for the DLNA server. Defaults to {server_name} if empty.",
"successfully_cancelled_temporary_behaviour": "Successfully cancelled temporary behaviour", "successfully_cancelled_temporary_behaviour": "Successfully cancelled temporary behaviour",
"until_restart": "until restart" "until_restart": "until restart",
"video_sort_order": "Default Video Sort Order",
"video_sort_order_desc": "Order to sort videos by default."
}, },
"general": { "general": {
"auth": { "auth": {

View File

@@ -0,0 +1,17 @@
export enum VideoSortOrder {
Created_At = "created_at",
Date = "date",
Random = "random",
Title = "title",
Updated_At = "updated_at",
}
export const defaultVideoSort = VideoSortOrder.Title;
export const videoSortOrderIntlMap = new Map<VideoSortOrder, string>([
[VideoSortOrder.Created_At, "created_at"],
[VideoSortOrder.Date, "date"],
[VideoSortOrder.Random, "random"],
[VideoSortOrder.Title, "title"],
[VideoSortOrder.Updated_At, "updated_at"],
]);