mirror of https://github.com/stashapp/stash.git
Support Javascript injection (#3132)
This commit is contained in:
parent
3a63f1f9b7
commit
ca9c8e0a34
|
@ -63,6 +63,8 @@ fragment ConfigInterfaceData on ConfigInterfaceResult {
|
|||
showStudioAsText
|
||||
css
|
||||
cssEnabled
|
||||
javascript
|
||||
javascriptEnabled
|
||||
customLocales
|
||||
customLocalesEnabled
|
||||
language
|
||||
|
|
|
@ -264,6 +264,10 @@ input ConfigInterfaceInput {
|
|||
css: String
|
||||
cssEnabled: Boolean
|
||||
|
||||
"""Custom Javascript"""
|
||||
javascript: String
|
||||
javascriptEnabled: Boolean
|
||||
|
||||
"""Custom Locales"""
|
||||
customLocales: String
|
||||
customLocalesEnabled: Boolean
|
||||
|
@ -330,6 +334,10 @@ type ConfigInterfaceResult {
|
|||
css: String
|
||||
cssEnabled: Boolean
|
||||
|
||||
"""Custom Javascript"""
|
||||
javascript: String
|
||||
javascriptEnabled: Boolean
|
||||
|
||||
"""Custom Locales"""
|
||||
customLocales: String
|
||||
customLocalesEnabled: Boolean
|
||||
|
|
|
@ -365,6 +365,12 @@ func (r *mutationResolver) ConfigureInterface(ctx context.Context, input ConfigI
|
|||
|
||||
setBool(config.CSSEnabled, input.CSSEnabled)
|
||||
|
||||
if input.Javascript != nil {
|
||||
c.SetJavascript(*input.Javascript)
|
||||
}
|
||||
|
||||
setBool(config.JavascriptEnabled, input.JavascriptEnabled)
|
||||
|
||||
if input.CustomLocales != nil {
|
||||
c.SetCustomLocales(*input.CustomLocales)
|
||||
}
|
||||
|
|
|
@ -142,6 +142,8 @@ func makeConfigInterfaceResult() *ConfigInterfaceResult {
|
|||
showStudioAsText := config.GetShowStudioAsText()
|
||||
css := config.GetCSS()
|
||||
cssEnabled := config.GetCSSEnabled()
|
||||
javascript := config.GetJavascript()
|
||||
javascriptEnabled := config.GetJavascriptEnabled()
|
||||
customLocales := config.GetCustomLocales()
|
||||
customLocalesEnabled := config.GetCustomLocalesEnabled()
|
||||
language := config.GetLanguage()
|
||||
|
@ -166,6 +168,8 @@ func makeConfigInterfaceResult() *ConfigInterfaceResult {
|
|||
ContinuePlaylistDefault: &continuePlaylistDefault,
|
||||
CSS: &css,
|
||||
CSSEnabled: &cssEnabled,
|
||||
Javascript: &javascript,
|
||||
JavascriptEnabled: &javascriptEnabled,
|
||||
CustomLocales: &customLocales,
|
||||
CustomLocalesEnabled: &customLocalesEnabled,
|
||||
Language: &language,
|
||||
|
|
|
@ -181,6 +181,21 @@ func Start() error {
|
|||
|
||||
http.ServeFile(w, r, fn)
|
||||
})
|
||||
r.HandleFunc("/javascript", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/javascript")
|
||||
if !c.GetJavascriptEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
// search for custom.js in current directory, then $HOME/.stash
|
||||
fn := c.GetJavascriptPath()
|
||||
exists, _ := fsutil.FileExists(fn)
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
|
||||
http.ServeFile(w, r, fn)
|
||||
})
|
||||
r.HandleFunc("/customlocales", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if c.GetCustomLocalesEnabled() {
|
||||
|
|
|
@ -139,6 +139,7 @@ const (
|
|||
ContinuePlaylistDefault = "continue_playlist_default"
|
||||
ShowStudioAsText = "show_studio_as_text"
|
||||
CSSEnabled = "cssEnabled"
|
||||
JavascriptEnabled = "javascriptEnabled"
|
||||
CustomLocalesEnabled = "customLocalesEnabled"
|
||||
|
||||
ShowScrubber = "show_scrubber"
|
||||
|
@ -1077,6 +1078,49 @@ func (i *Instance) GetCSSEnabled() bool {
|
|||
return i.getBool(CSSEnabled)
|
||||
}
|
||||
|
||||
func (i *Instance) GetJavascriptPath() string {
|
||||
// use custom.js in the same directory as the config file
|
||||
configFileUsed := i.GetConfigFile()
|
||||
configDir := filepath.Dir(configFileUsed)
|
||||
|
||||
fn := filepath.Join(configDir, "custom.js")
|
||||
|
||||
return fn
|
||||
}
|
||||
|
||||
func (i *Instance) GetJavascript() string {
|
||||
fn := i.GetJavascriptPath()
|
||||
|
||||
exists, _ := fsutil.FileExists(fn)
|
||||
if !exists {
|
||||
return ""
|
||||
}
|
||||
|
||||
buf, err := os.ReadFile(fn)
|
||||
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
func (i *Instance) SetJavascript(javascript string) {
|
||||
fn := i.GetJavascriptPath()
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
buf := []byte(javascript)
|
||||
|
||||
if err := os.WriteFile(fn, buf, 0777); err != nil {
|
||||
logger.Warnf("error while writing %v bytes to %v: %v", len(buf), fn, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Instance) GetJavascriptEnabled() bool {
|
||||
return i.getBool(JavascriptEnabled)
|
||||
}
|
||||
|
||||
func (i *Instance) GetCustomLocalesPath() string {
|
||||
// use custom-locales.json in the same directory as the config file
|
||||
configFileUsed := i.GetConfigFile()
|
||||
|
|
|
@ -86,6 +86,8 @@ func TestConcurrentConfigAccess(t *testing.T) {
|
|||
i.Set(ImageLightboxSlideshowDelay, *i.GetImageLightboxOptions().SlideshowDelay)
|
||||
i.GetCSSPath()
|
||||
i.GetCSS()
|
||||
i.GetJavascriptPath()
|
||||
i.GetJavascript()
|
||||
i.GetCustomLocalesPath()
|
||||
i.GetCustomLocales()
|
||||
i.Set(CSSEnabled, i.GetCSSEnabled())
|
||||
|
|
|
@ -510,6 +510,36 @@ export const SettingsInterfacePanel: React.FC = () => {
|
|||
}}
|
||||
/>
|
||||
</SettingSection>
|
||||
<SettingSection headingID="config.ui.custom_javascript.heading">
|
||||
<BooleanSetting
|
||||
id="custom-javascript-enabled"
|
||||
headingID="config.ui.custom_javascript.option_label"
|
||||
checked={iface.javascriptEnabled ?? undefined}
|
||||
onChange={(v) => saveInterface({ javascriptEnabled: v })}
|
||||
/>
|
||||
|
||||
<ModalSetting<string>
|
||||
id="custom-javascript"
|
||||
headingID="config.ui.custom_javascript.heading"
|
||||
subHeadingID="config.ui.custom_javascript.description"
|
||||
value={iface.javascript ?? undefined}
|
||||
onChange={(v) => saveInterface({ javascript: v })}
|
||||
renderField={(value, setValue) => (
|
||||
<Form.Control
|
||||
as="textarea"
|
||||
value={value}
|
||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
|
||||
setValue(e.currentTarget.value)
|
||||
}
|
||||
rows={16}
|
||||
className="text-input code"
|
||||
/>
|
||||
)}
|
||||
renderValue={() => {
|
||||
return <></>;
|
||||
}}
|
||||
/>
|
||||
</SettingSection>
|
||||
<SettingSection headingID="config.ui.custom_locales.heading">
|
||||
<BooleanSetting
|
||||
id="custom-locales-enabled"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
### ✨ New Features
|
||||
* Added custom javascript option. ([#3132](https://github.com/stashapp/stash/pull/3132))
|
||||
* Added ability to select rating system in the Interface settings, allowing 5 stars with full-, half- or quarter-stars, or numeric score out of 10 with one decimal point. ([#2830](https://github.com/stashapp/stash/pull/2830))
|
||||
* Added filter criteria for Birthdate, Death Date, Date, Created At and Updated At fields. ([#2834](https://github.com/stashapp/stash/pull/2834))
|
||||
* Support creation of scenes without files. ([#3006](https://github.com/stashapp/stash/pull/3006))
|
||||
|
|
|
@ -26,6 +26,10 @@ The stash UI can be customised using custom CSS. See [here](https://github.com/s
|
|||
|
||||
[Stash Plex Theme](https://github.com/stashapp/stash/wiki/Theme-Plex) is a community created theme inspired by the popular Plex interface.
|
||||
|
||||
## Custom Javascript
|
||||
|
||||
Stash supports the injection of custom javascript to assist with theming or adding additional functionality. Be aware that bad Javascript could break the UI or worse.
|
||||
|
||||
## Custom Locales
|
||||
|
||||
The localisation strings can be customised. The master list of default (en-GB) locale strings can be found [here](https://github.com/stashapp/stash/blob/develop/ui/v2.5/src/locales/en-GB.json). The custom locale format is the same as this json file.
|
||||
|
|
|
@ -20,6 +20,10 @@ ReactDOM.render(
|
|||
document.getElementById("root")
|
||||
);
|
||||
|
||||
const script = document.createElement("script");
|
||||
script.src = `${getPlatformURL()}javascript`;
|
||||
document.body.appendChild(script);
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: http://bit.ly/CRA-PWA
|
||||
|
|
|
@ -435,6 +435,11 @@
|
|||
"heading": "Custom CSS",
|
||||
"option_label": "Custom CSS enabled"
|
||||
},
|
||||
"custom_javascript": {
|
||||
"description": "Page must be reloaded for changes to take effect.",
|
||||
"heading": "Custom Javascript",
|
||||
"option_label": "Custom Javascript enabled"
|
||||
},
|
||||
"custom_locales": {
|
||||
"description": "Override individual locale strings. See https://github.com/stashapp/stash/blob/develop/ui/v2.5/src/locales/en-GB.json for the master list. Page must be reloaded for changes to take effect.",
|
||||
"heading": "Custom localisation",
|
||||
|
|
Loading…
Reference in New Issue