diff --git a/graphql/documents/data/config.graphql b/graphql/documents/data/config.graphql index 2003e4650..2421bdb2f 100644 --- a/graphql/documents/data/config.graphql +++ b/graphql/documents/data/config.graphql @@ -51,6 +51,7 @@ fragment ConfigInterfaceData on ConfigInterfaceResult { soundOnPreview wallShowTitle wallPlayback + showScrubber maximumLoopDuration noBrowser notificationsEnabled diff --git a/graphql/schema/types/config.graphql b/graphql/schema/types/config.graphql index 04450462e..2b6fdbd5d 100644 --- a/graphql/schema/types/config.graphql +++ b/graphql/schema/types/config.graphql @@ -207,6 +207,9 @@ input ConfigInterfaceInput { wallShowTitle: Boolean """Wall playback type""" wallPlayback: String + + """Show scene scrubber by default""" + showScrubber: Boolean """Maximum duration (in seconds) in which a scene video will loop in the scene player""" maximumLoopDuration: Int @@ -261,6 +264,9 @@ type ConfigInterfaceResult { """Wall playback type""" wallPlayback: String + """Show scene scrubber by default""" + showScrubber: Boolean + """Maximum duration (in seconds) in which a scene video will loop in the scene player""" maximumLoopDuration: Int """True if we should not auto-open a browser window on startup""" diff --git a/pkg/api/resolver_mutation_configure.go b/pkg/api/resolver_mutation_configure.go index 3c8f58788..6e78220c8 100644 --- a/pkg/api/resolver_mutation_configure.go +++ b/pkg/api/resolver_mutation_configure.go @@ -296,6 +296,8 @@ func (r *mutationResolver) ConfigureInterface(ctx context.Context, input models. setBool(config.NotificationsEnabled, input.NotificationsEnabled) + setBool(config.ShowScrubber, input.ShowScrubber) + if input.WallPlayback != nil { c.Set(config.WallPlayback, *input.WallPlayback) } diff --git a/pkg/api/resolver_query_configuration.go b/pkg/api/resolver_query_configuration.go index 7a9d71d94..1383e9b62 100644 --- a/pkg/api/resolver_query_configuration.go +++ b/pkg/api/resolver_query_configuration.go @@ -109,6 +109,7 @@ func makeConfigInterfaceResult() *models.ConfigInterfaceResult { menuItems := config.GetMenuItems() soundOnPreview := config.GetSoundOnPreview() wallShowTitle := config.GetWallShowTitle() + showScrubber := config.GetShowScrubber() wallPlayback := config.GetWallPlayback() noBrowser := config.GetNoBrowser() notificationsEnabled := config.GetNotificationsEnabled() @@ -132,6 +133,7 @@ func makeConfigInterfaceResult() *models.ConfigInterfaceResult { SoundOnPreview: &soundOnPreview, WallShowTitle: &wallShowTitle, WallPlayback: &wallPlayback, + ShowScrubber: &showScrubber, MaximumLoopDuration: &maximumLoopDuration, NoBrowser: &noBrowser, NotificationsEnabled: ¬ificationsEnabled, diff --git a/pkg/manager/config/config.go b/pkg/manager/config/config.go index 6e02dad4a..07780db8c 100644 --- a/pkg/manager/config/config.go +++ b/pkg/manager/config/config.go @@ -135,6 +135,9 @@ const ( ShowStudioAsText = "show_studio_as_text" CSSEnabled = "cssEnabled" + ShowScrubber = "show_scrubber" + showScrubberDefault = true + WallPlayback = "wall_playback" defaultWallPlayback = "video" @@ -395,6 +398,18 @@ func (i *Instance) getBool(key string) bool { return i.viper(key).GetBool(key) } +func (i *Instance) getBoolDefault(key string, def bool) bool { + i.RLock() + defer i.RUnlock() + + ret := def + v := i.viper(key) + if v.IsSet(key) { + ret = v.GetBool(key) + } + return ret +} + func (i *Instance) getInt(key string) int { i.RLock() defer i.RUnlock() @@ -559,16 +574,7 @@ func (i *Instance) GetScraperCDPPath() string { // GetScraperCertCheck returns true if the scraper should check for insecure // certificates when fetching an image or a page. func (i *Instance) GetScraperCertCheck() bool { - ret := true - i.RLock() - defer i.RUnlock() - - v := i.viper(ScraperCertCheck) - if v.IsSet(ScraperCertCheck) { - ret = v.GetBool(ScraperCertCheck) - } - - return ret + return i.getBoolDefault(ScraperCertCheck, true) } func (i *Instance) GetScraperExcludeTagPatterns() []string { @@ -848,6 +854,10 @@ func (i *Instance) GetWallPlayback() string { return ret } +func (i *Instance) GetShowScrubber() bool { + return i.getBoolDefault(ShowScrubber, showScrubberDefault) +} + func (i *Instance) GetMaximumLoopDuration() int { return i.getInt(MaximumLoopDuration) } @@ -857,16 +867,7 @@ func (i *Instance) GetAutostartVideo() bool { } func (i *Instance) GetAutostartVideoOnPlaySelected() bool { - i.Lock() - defer i.Unlock() - - ret := autostartVideoOnPlaySelectedDefault - v := i.viper(AutostartVideoOnPlaySelected) - if v.IsSet(AutostartVideoOnPlaySelected) { - ret = v.GetBool(AutostartVideoOnPlaySelected) - } - - return ret + return i.getBoolDefault(AutostartVideoOnPlaySelected, autostartVideoOnPlaySelectedDefault) } func (i *Instance) GetContinuePlaylistDefault() bool { @@ -954,16 +955,7 @@ func (i *Instance) GetDeleteFileDefault() bool { } func (i *Instance) GetDeleteGeneratedDefault() bool { - i.RLock() - defer i.RUnlock() - ret := deleteGeneratedDefaultDefault - - v := i.viper(DeleteGeneratedDefault) - if v.IsSet(DeleteGeneratedDefault) { - ret = v.GetBool(DeleteGeneratedDefault) - } - - return ret + return i.getBoolDefault(DeleteGeneratedDefault, deleteGeneratedDefaultDefault) } // GetDefaultIdentifySettings returns the default Identify task settings. @@ -1088,17 +1080,7 @@ func (i *Instance) GetLogFile() string { // in addition to writing to a log file. Logging will be output to the // terminal if file logging is disabled. Defaults to true. func (i *Instance) GetLogOut() bool { - i.RLock() - defer i.RUnlock() - - ret := defaultLogOut - v := i.viper(LogOut) - - if v.IsSet(LogOut) { - ret = v.GetBool(LogOut) - } - - return ret + return i.getBoolDefault(LogOut, defaultLogOut) } // GetLogLevel returns the lowest log level to write to the log. @@ -1115,16 +1097,7 @@ func (i *Instance) GetLogLevel() string { // GetLogAccess returns true if http requests should be logged to the terminal. // HTTP requests are not logged to the log file. Defaults to true. func (i *Instance) GetLogAccess() bool { - i.RLock() - defer i.RUnlock() - ret := defaultLogAccess - - v := i.viper(LogAccess) - if v.IsSet(LogAccess) { - ret = v.GetBool(LogAccess) - } - - return ret + return i.getBoolDefault(LogAccess, defaultLogAccess) } // Max allowed graphql upload size in megabytes diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx index ccf744818..5c9046093 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/Scene.tsx @@ -1,6 +1,6 @@ import { Tab, Nav, Dropdown, Button, ButtonGroup } from "react-bootstrap"; import queryString from "query-string"; -import React, { useEffect, useState, useMemo } from "react"; +import React, { useEffect, useState, useMemo, useContext } from "react"; import { FormattedMessage, useIntl } from "react-intl"; import { useParams, useLocation, useHistory, Link } from "react-router-dom"; import { Helmet } from "react-helmet"; @@ -39,6 +39,7 @@ import { DeleteScenesDialog } from "../DeleteScenesDialog"; import { GenerateDialog } from "../../Dialogs/GenerateDialog"; import { SceneVideoFilterPanel } from "./SceneVideoFilterPanel"; import { OrganizedButton } from "./OrganizedButton"; +import { ConfigurationContext } from "src/hooks/Config"; interface IProps { scene: GQL.SceneDataFragment; @@ -54,11 +55,14 @@ const ScenePage: React.FC = ({ scene, refetch }) => { const [generateScreenshot] = useSceneGenerateScreenshot(); const [timestamp, setTimestamp] = useState(getInitialTimestamp()); const [collapsed, setCollapsed] = useState(false); - const [showScrubber, setShowScrubber] = useState(true); - const { data } = GQL.useConfigurationQuery(); + const { configuration } = useContext(ConfigurationContext); + + const [showScrubber, setShowScrubber] = useState( + configuration?.interface.showScrubber ?? true + ); const [showDraftModal, setShowDraftModal] = useState(false); - const boxes = data?.configuration?.general?.stashBoxes ?? []; + const boxes = configuration?.general?.stashBoxes ?? []; const { data: sceneStreams, diff --git a/ui/v2.5/src/components/Settings/SettingsInterfacePanel/SettingsInterfacePanel.tsx b/ui/v2.5/src/components/Settings/SettingsInterfacePanel/SettingsInterfacePanel.tsx index 5d8b23cde..c4cbe38da 100644 --- a/ui/v2.5/src/components/Settings/SettingsInterfacePanel/SettingsInterfacePanel.tsx +++ b/ui/v2.5/src/components/Settings/SettingsInterfacePanel/SettingsInterfacePanel.tsx @@ -149,6 +149,12 @@ export const SettingsInterfacePanel: React.FC = () => { + saveInterface({ showScrubber: v })} + />