mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
Add setting for showing scene scrubber by default (#2325)
This commit is contained in:
@@ -51,6 +51,7 @@ fragment ConfigInterfaceData on ConfigInterfaceResult {
|
|||||||
soundOnPreview
|
soundOnPreview
|
||||||
wallShowTitle
|
wallShowTitle
|
||||||
wallPlayback
|
wallPlayback
|
||||||
|
showScrubber
|
||||||
maximumLoopDuration
|
maximumLoopDuration
|
||||||
noBrowser
|
noBrowser
|
||||||
notificationsEnabled
|
notificationsEnabled
|
||||||
|
|||||||
@@ -208,6 +208,9 @@ input ConfigInterfaceInput {
|
|||||||
"""Wall playback type"""
|
"""Wall playback type"""
|
||||||
wallPlayback: String
|
wallPlayback: String
|
||||||
|
|
||||||
|
"""Show scene scrubber by default"""
|
||||||
|
showScrubber: Boolean
|
||||||
|
|
||||||
"""Maximum duration (in seconds) in which a scene video will loop in the scene player"""
|
"""Maximum duration (in seconds) in which a scene video will loop in the scene player"""
|
||||||
maximumLoopDuration: Int
|
maximumLoopDuration: Int
|
||||||
"""If true, video will autostart on load in the scene player"""
|
"""If true, video will autostart on load in the scene player"""
|
||||||
@@ -261,6 +264,9 @@ type ConfigInterfaceResult {
|
|||||||
"""Wall playback type"""
|
"""Wall playback type"""
|
||||||
wallPlayback: String
|
wallPlayback: String
|
||||||
|
|
||||||
|
"""Show scene scrubber by default"""
|
||||||
|
showScrubber: Boolean
|
||||||
|
|
||||||
"""Maximum duration (in seconds) in which a scene video will loop in the scene player"""
|
"""Maximum duration (in seconds) in which a scene video will loop in the scene player"""
|
||||||
maximumLoopDuration: Int
|
maximumLoopDuration: Int
|
||||||
"""True if we should not auto-open a browser window on startup"""
|
"""True if we should not auto-open a browser window on startup"""
|
||||||
|
|||||||
@@ -296,6 +296,8 @@ func (r *mutationResolver) ConfigureInterface(ctx context.Context, input models.
|
|||||||
|
|
||||||
setBool(config.NotificationsEnabled, input.NotificationsEnabled)
|
setBool(config.NotificationsEnabled, input.NotificationsEnabled)
|
||||||
|
|
||||||
|
setBool(config.ShowScrubber, input.ShowScrubber)
|
||||||
|
|
||||||
if input.WallPlayback != nil {
|
if input.WallPlayback != nil {
|
||||||
c.Set(config.WallPlayback, *input.WallPlayback)
|
c.Set(config.WallPlayback, *input.WallPlayback)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ func makeConfigInterfaceResult() *models.ConfigInterfaceResult {
|
|||||||
menuItems := config.GetMenuItems()
|
menuItems := config.GetMenuItems()
|
||||||
soundOnPreview := config.GetSoundOnPreview()
|
soundOnPreview := config.GetSoundOnPreview()
|
||||||
wallShowTitle := config.GetWallShowTitle()
|
wallShowTitle := config.GetWallShowTitle()
|
||||||
|
showScrubber := config.GetShowScrubber()
|
||||||
wallPlayback := config.GetWallPlayback()
|
wallPlayback := config.GetWallPlayback()
|
||||||
noBrowser := config.GetNoBrowser()
|
noBrowser := config.GetNoBrowser()
|
||||||
notificationsEnabled := config.GetNotificationsEnabled()
|
notificationsEnabled := config.GetNotificationsEnabled()
|
||||||
@@ -132,6 +133,7 @@ func makeConfigInterfaceResult() *models.ConfigInterfaceResult {
|
|||||||
SoundOnPreview: &soundOnPreview,
|
SoundOnPreview: &soundOnPreview,
|
||||||
WallShowTitle: &wallShowTitle,
|
WallShowTitle: &wallShowTitle,
|
||||||
WallPlayback: &wallPlayback,
|
WallPlayback: &wallPlayback,
|
||||||
|
ShowScrubber: &showScrubber,
|
||||||
MaximumLoopDuration: &maximumLoopDuration,
|
MaximumLoopDuration: &maximumLoopDuration,
|
||||||
NoBrowser: &noBrowser,
|
NoBrowser: &noBrowser,
|
||||||
NotificationsEnabled: ¬ificationsEnabled,
|
NotificationsEnabled: ¬ificationsEnabled,
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ const (
|
|||||||
ShowStudioAsText = "show_studio_as_text"
|
ShowStudioAsText = "show_studio_as_text"
|
||||||
CSSEnabled = "cssEnabled"
|
CSSEnabled = "cssEnabled"
|
||||||
|
|
||||||
|
ShowScrubber = "show_scrubber"
|
||||||
|
showScrubberDefault = true
|
||||||
|
|
||||||
WallPlayback = "wall_playback"
|
WallPlayback = "wall_playback"
|
||||||
defaultWallPlayback = "video"
|
defaultWallPlayback = "video"
|
||||||
|
|
||||||
@@ -395,6 +398,18 @@ func (i *Instance) getBool(key string) bool {
|
|||||||
return i.viper(key).GetBool(key)
|
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 {
|
func (i *Instance) getInt(key string) int {
|
||||||
i.RLock()
|
i.RLock()
|
||||||
defer i.RUnlock()
|
defer i.RUnlock()
|
||||||
@@ -559,16 +574,7 @@ func (i *Instance) GetScraperCDPPath() string {
|
|||||||
// GetScraperCertCheck returns true if the scraper should check for insecure
|
// GetScraperCertCheck returns true if the scraper should check for insecure
|
||||||
// certificates when fetching an image or a page.
|
// certificates when fetching an image or a page.
|
||||||
func (i *Instance) GetScraperCertCheck() bool {
|
func (i *Instance) GetScraperCertCheck() bool {
|
||||||
ret := true
|
return i.getBoolDefault(ScraperCertCheck, true)
|
||||||
i.RLock()
|
|
||||||
defer i.RUnlock()
|
|
||||||
|
|
||||||
v := i.viper(ScraperCertCheck)
|
|
||||||
if v.IsSet(ScraperCertCheck) {
|
|
||||||
ret = v.GetBool(ScraperCertCheck)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) GetScraperExcludeTagPatterns() []string {
|
func (i *Instance) GetScraperExcludeTagPatterns() []string {
|
||||||
@@ -848,6 +854,10 @@ func (i *Instance) GetWallPlayback() string {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Instance) GetShowScrubber() bool {
|
||||||
|
return i.getBoolDefault(ShowScrubber, showScrubberDefault)
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Instance) GetMaximumLoopDuration() int {
|
func (i *Instance) GetMaximumLoopDuration() int {
|
||||||
return i.getInt(MaximumLoopDuration)
|
return i.getInt(MaximumLoopDuration)
|
||||||
}
|
}
|
||||||
@@ -857,16 +867,7 @@ func (i *Instance) GetAutostartVideo() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) GetAutostartVideoOnPlaySelected() bool {
|
func (i *Instance) GetAutostartVideoOnPlaySelected() bool {
|
||||||
i.Lock()
|
return i.getBoolDefault(AutostartVideoOnPlaySelected, autostartVideoOnPlaySelectedDefault)
|
||||||
defer i.Unlock()
|
|
||||||
|
|
||||||
ret := autostartVideoOnPlaySelectedDefault
|
|
||||||
v := i.viper(AutostartVideoOnPlaySelected)
|
|
||||||
if v.IsSet(AutostartVideoOnPlaySelected) {
|
|
||||||
ret = v.GetBool(AutostartVideoOnPlaySelected)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) GetContinuePlaylistDefault() bool {
|
func (i *Instance) GetContinuePlaylistDefault() bool {
|
||||||
@@ -954,16 +955,7 @@ func (i *Instance) GetDeleteFileDefault() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) GetDeleteGeneratedDefault() bool {
|
func (i *Instance) GetDeleteGeneratedDefault() bool {
|
||||||
i.RLock()
|
return i.getBoolDefault(DeleteGeneratedDefault, deleteGeneratedDefaultDefault)
|
||||||
defer i.RUnlock()
|
|
||||||
ret := deleteGeneratedDefaultDefault
|
|
||||||
|
|
||||||
v := i.viper(DeleteGeneratedDefault)
|
|
||||||
if v.IsSet(DeleteGeneratedDefault) {
|
|
||||||
ret = v.GetBool(DeleteGeneratedDefault)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefaultIdentifySettings returns the default Identify task settings.
|
// 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
|
// in addition to writing to a log file. Logging will be output to the
|
||||||
// terminal if file logging is disabled. Defaults to true.
|
// terminal if file logging is disabled. Defaults to true.
|
||||||
func (i *Instance) GetLogOut() bool {
|
func (i *Instance) GetLogOut() bool {
|
||||||
i.RLock()
|
return i.getBoolDefault(LogOut, defaultLogOut)
|
||||||
defer i.RUnlock()
|
|
||||||
|
|
||||||
ret := defaultLogOut
|
|
||||||
v := i.viper(LogOut)
|
|
||||||
|
|
||||||
if v.IsSet(LogOut) {
|
|
||||||
ret = v.GetBool(LogOut)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogLevel returns the lowest log level to write to the log.
|
// 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.
|
// GetLogAccess returns true if http requests should be logged to the terminal.
|
||||||
// HTTP requests are not logged to the log file. Defaults to true.
|
// HTTP requests are not logged to the log file. Defaults to true.
|
||||||
func (i *Instance) GetLogAccess() bool {
|
func (i *Instance) GetLogAccess() bool {
|
||||||
i.RLock()
|
return i.getBoolDefault(LogAccess, defaultLogAccess)
|
||||||
defer i.RUnlock()
|
|
||||||
ret := defaultLogAccess
|
|
||||||
|
|
||||||
v := i.viper(LogAccess)
|
|
||||||
if v.IsSet(LogAccess) {
|
|
||||||
ret = v.GetBool(LogAccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Max allowed graphql upload size in megabytes
|
// Max allowed graphql upload size in megabytes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Tab, Nav, Dropdown, Button, ButtonGroup } from "react-bootstrap";
|
import { Tab, Nav, Dropdown, Button, ButtonGroup } from "react-bootstrap";
|
||||||
import queryString from "query-string";
|
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 { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { useParams, useLocation, useHistory, Link } from "react-router-dom";
|
import { useParams, useLocation, useHistory, Link } from "react-router-dom";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
@@ -39,6 +39,7 @@ import { DeleteScenesDialog } from "../DeleteScenesDialog";
|
|||||||
import { GenerateDialog } from "../../Dialogs/GenerateDialog";
|
import { GenerateDialog } from "../../Dialogs/GenerateDialog";
|
||||||
import { SceneVideoFilterPanel } from "./SceneVideoFilterPanel";
|
import { SceneVideoFilterPanel } from "./SceneVideoFilterPanel";
|
||||||
import { OrganizedButton } from "./OrganizedButton";
|
import { OrganizedButton } from "./OrganizedButton";
|
||||||
|
import { ConfigurationContext } from "src/hooks/Config";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
scene: GQL.SceneDataFragment;
|
scene: GQL.SceneDataFragment;
|
||||||
@@ -54,11 +55,14 @@ const ScenePage: React.FC<IProps> = ({ scene, refetch }) => {
|
|||||||
const [generateScreenshot] = useSceneGenerateScreenshot();
|
const [generateScreenshot] = useSceneGenerateScreenshot();
|
||||||
const [timestamp, setTimestamp] = useState<number>(getInitialTimestamp());
|
const [timestamp, setTimestamp] = useState<number>(getInitialTimestamp());
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
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 [showDraftModal, setShowDraftModal] = useState(false);
|
||||||
const boxes = data?.configuration?.general?.stashBoxes ?? [];
|
const boxes = configuration?.general?.stashBoxes ?? [];
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: sceneStreams,
|
data: sceneStreams,
|
||||||
|
|||||||
@@ -149,6 +149,12 @@ export const SettingsInterfacePanel: React.FC = () => {
|
|||||||
</SettingSection>
|
</SettingSection>
|
||||||
|
|
||||||
<SettingSection headingID="config.ui.scene_player.heading">
|
<SettingSection headingID="config.ui.scene_player.heading">
|
||||||
|
<BooleanSetting
|
||||||
|
id="show-scrubber"
|
||||||
|
headingID="config.ui.scene_player.options.show_scrubber"
|
||||||
|
checked={iface.showScrubber ?? undefined}
|
||||||
|
onChange={(v) => saveInterface({ showScrubber: v })}
|
||||||
|
/>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
id="auto-start-video"
|
id="auto-start-video"
|
||||||
headingID="config.ui.scene_player.options.auto_start_video"
|
headingID="config.ui.scene_player.options.auto_start_video"
|
||||||
|
|||||||
@@ -492,7 +492,8 @@
|
|||||||
"continue_playlist_default": {
|
"continue_playlist_default": {
|
||||||
"description": "Play next scene in queue when video finishes",
|
"description": "Play next scene in queue when video finishes",
|
||||||
"heading": "Continue playlist by default"
|
"heading": "Continue playlist by default"
|
||||||
}
|
},
|
||||||
|
"show_scrubber": "Show Scrubber"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scene_wall": {
|
"scene_wall": {
|
||||||
|
|||||||
Reference in New Issue
Block a user