mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Adds ability to configure sort order for DLNA videos (#3645)
This commit is contained in:
@@ -99,6 +99,7 @@ fragment ConfigDLNAData on ConfigDLNAResult {
|
|||||||
enabled
|
enabled
|
||||||
whitelistedIPs
|
whitelistedIPs
|
||||||
interfaces
|
interfaces
|
||||||
|
videoSortOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment ConfigScrapingData on ConfigScrapingResult {
|
fragment ConfigScrapingData on ConfigScrapingResult {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
|||||||
17
ui/v2.5/src/utils/dlnaVideoSort.ts
Normal file
17
ui/v2.5/src/utils/dlnaVideoSort.ts
Normal 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"],
|
||||||
|
]);
|
||||||
Reference in New Issue
Block a user