Merge branch 'develop' of https://github.com/Darklyter/stash into develop

This commit is contained in:
Darklyter 2024-08-21 00:46:18 -04:00
commit 7db01e15ac
6 changed files with 886 additions and 876 deletions

View file

@ -192,7 +192,7 @@ func (me *contentDirectoryService) Handle(action string, argsXML []byte, r *http
obj, err := me.objectFromID(browse.ObjectID) obj, err := me.objectFromID(browse.ObjectID)
if err != nil { if err != nil {
return nil, upnp.Errorf(upnpav.NoSuchObjectErrorCode, err.Error()) return nil, upnp.Errorf(upnpav.NoSuchObjectErrorCode, "cannot find object with id %q: %v", browse.ObjectID, err.Error())
} }
switch browse.BrowseFlag { switch browse.BrowseFlag {

View file

@ -76,7 +76,7 @@ func (t *rawPluginTask) Start() error {
if err != nil { if err != nil {
logger.Warnf("error marshalling raw command input") logger.Warnf("error marshalling raw command input")
} }
if k, err := io.WriteString(stdin, string(inBytes)); err != nil { if k, err := stdin.Write(inBytes); err != nil {
logger.Warnf("error writing input to plugins stdin (wrote %v bytes out of %v): %v", k, len(string(inBytes)), err) logger.Warnf("error writing input to plugins stdin (wrote %v bytes out of %v): %v", k, len(string(inBytes)), err)
} }
}() }()

View file

@ -1338,7 +1338,7 @@ func (c *Client) submitDraft(ctx context.Context, query string, input interface{
return fmt.Errorf("failed to decode data %s: %w", string(responseBytes), err) return fmt.Errorf("failed to decode data %s: %w", string(responseBytes), err)
} }
if respGQL.Errors != nil && len(respGQL.Errors) > 0 { if len(respGQL.Errors) > 0 {
// try to parse standard graphql error // try to parse standard graphql error
errors := &client.GqlErrorList{} errors := &client.GqlErrorList{}
if e := json.Unmarshal(responseBytes, errors); e != nil { if e := json.Unmarshal(responseBytes, errors); e != nil {

View file

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { BooleanSetting } from "../Inputs"; import { BooleanSetting } from "../Inputs";
import { PatchComponent } from "src/patch";
interface IItem { interface IItem {
id: string; id: string;
@ -13,12 +14,9 @@ interface ICheckboxGroupProps {
onChange?: (ids: string[]) => void; onChange?: (ids: string[]) => void;
} }
export const CheckboxGroup: React.FC<ICheckboxGroupProps> = ({ export const CheckboxGroup: React.FC<ICheckboxGroupProps> = PatchComponent(
groupId, "CheckboxGroup",
items, ({ groupId, items, checkedIds = [], onChange }) => {
checkedIds = [],
onChange,
}) => {
function generateId(itemId: string) { function generateId(itemId: string) {
return `${groupId}-${itemId}`; return `${groupId}-${itemId}`;
} }
@ -58,4 +56,5 @@ export const CheckboxGroup: React.FC<ICheckboxGroupProps> = ({
))} ))}
</> </>
); );
}; }
);

View file

@ -43,6 +43,7 @@ import {
defaultImageWallMargin, defaultImageWallMargin,
} from "src/utils/imageWall"; } from "src/utils/imageWall";
import { defaultMaxOptionsShown } from "src/core/config"; import { defaultMaxOptionsShown } from "src/core/config";
import { PatchComponent } from "src/patch";
const allMenuItems = [ const allMenuItems = [
{ id: "scenes", headingID: "scenes" }, { id: "scenes", headingID: "scenes" },
@ -55,7 +56,9 @@ const allMenuItems = [
{ id: "tags", headingID: "tags" }, { id: "tags", headingID: "tags" },
]; ];
export const SettingsInterfacePanel: React.FC = () => { export const SettingsInterfacePanel: React.FC = PatchComponent(
"SettingsInterfacePanel",
function SettingsInterfacePanel() {
const intl = useIntl(); const intl = useIntl();
const { const {
@ -66,7 +69,6 @@ export const SettingsInterfacePanel: React.FC = () => {
loading, loading,
error, error,
} = useSettings(); } = useSettings();
// convert old movies menu item to groups // convert old movies menu item to groups
const massageMenuItems = useCallback((menuItems: string[]) => { const massageMenuItems = useCallback((menuItems: string[]) => {
return menuItems.map((item) => { return menuItems.map((item) => {
@ -97,15 +99,13 @@ export const SettingsInterfacePanel: React.FC = () => {
function saveLightboxSettings(v: Partial<GQL.ConfigImageLightboxInput>) { function saveLightboxSettings(v: Partial<GQL.ConfigImageLightboxInput>) {
// save in local forage as well for consistency // save in local forage as well for consistency
setInterfaceLocalForage((prev) => { setInterfaceLocalForage((prev) => ({
return {
...prev, ...prev,
imageLightbox: { imageLightbox: {
...prev.imageLightbox, ...prev.imageLightbox,
...v, ...v,
}, },
}; }));
});
saveInterface({ saveInterface({
imageLightbox: { imageLightbox: {
@ -189,6 +189,7 @@ export const SettingsInterfacePanel: React.FC = () => {
if (loading) return <LoadingIndicator />; if (loading) return <LoadingIndicator />;
// https://en.wikipedia.org/wiki/List_of_language_names // https://en.wikipedia.org/wiki/List_of_language_names
return ( return (
<> <>
<SettingSection headingID="config.ui.basic_settings"> <SettingSection headingID="config.ui.basic_settings">
@ -239,7 +240,9 @@ export const SettingsInterfacePanel: React.FC = () => {
})} })}
</h3> </h3>
<div className="sub-heading"> <div className="sub-heading">
{intl.formatMessage({ id: "config.ui.menu_items.description" })} {intl.formatMessage({
id: "config.ui.menu_items.description",
})}
</div> </div>
</div> </div>
<div /> <div />
@ -248,7 +251,9 @@ export const SettingsInterfacePanel: React.FC = () => {
groupId="menu-items" groupId="menu-items"
items={allMenuItems} items={allMenuItems}
checkedIds={massagedMenuItems ?? undefined} checkedIds={massagedMenuItems ?? undefined}
onChange={(v) => saveInterface({ menuItems: massageMenuItems(v) })} onChange={(v) =>
saveInterface({ menuItems: massageMenuItems(v) })
}
/> />
</div> </div>
@ -301,7 +306,9 @@ export const SettingsInterfacePanel: React.FC = () => {
onChange={(v) => saveInterface({ wallPlayback: v })} onChange={(v) => saveInterface({ wallPlayback: v })}
> >
<option value="video"> <option value="video">
{intl.formatMessage({ id: "config.ui.preview_type.options.video" })} {intl.formatMessage({
id: "config.ui.preview_type.options.video",
})}
</option> </option>
<option value="animation"> <option value="animation">
{intl.formatMessage({ {intl.formatMessage({
@ -481,8 +488,15 @@ export const SettingsInterfacePanel: React.FC = () => {
</option> </option>
))} ))}
</SelectSetting> </SelectSetting>
)}
<BooleanSetting
id="auto_convert_metric_measurements"
headingID="config.ui.editing.auto_convert_metric_measurements.heading"
subHeadingID="config.ui.editing.auto_convert_metric_measurements.description"
checked={ui.autoConvertMetricMeasurements ?? undefined}
onChange={(v) => saveUI({ autoConvertMetricMeasurements: v })}
/>
</SettingSection> </SettingSection>
<SettingSection headingID="config.ui.image_lightbox.heading"> <SettingSection headingID="config.ui.image_lightbox.heading">
<NumberSetting <NumberSetting
headingID="config.ui.slideshow_delay.heading" headingID="config.ui.slideshow_delay.heading"
@ -533,7 +547,8 @@ export const SettingsInterfacePanel: React.FC = () => {
headingID="dialogs.lightbox.scroll_mode.label" headingID="dialogs.lightbox.scroll_mode.label"
subHeadingID="dialogs.lightbox.scroll_mode.description" subHeadingID="dialogs.lightbox.scroll_mode.description"
value={ value={
iface.imageLightbox?.scrollMode ?? GQL.ImageLightboxScrollMode.Zoom iface.imageLightbox?.scrollMode ??
GQL.ImageLightboxScrollMode.Zoom
} }
onChange={(v) => onChange={(v) =>
saveLightboxSettings({ saveLightboxSettings({
@ -730,13 +745,6 @@ export const SettingsInterfacePanel: React.FC = () => {
))} ))}
</SelectSetting> </SelectSetting>
)} )}
<BooleanSetting
id="auto_convert_metric_measurements"
headingID="config.ui.editing.auto_convert_metric_measurements.heading"
subHeadingID="config.ui.editing.auto_convert_metric_measurements.description"
checked={ui.autoConvertMetricMeasurements ?? undefined}
onChange={(v) => saveUI({ autoConvertMetricMeasurements: v })}
/>
</SettingSection> </SettingSection>
<SettingSection headingID="config.ui.custom_css.heading"> <SettingSection headingID="config.ui.custom_css.heading">
@ -932,4 +940,5 @@ export const SettingsInterfacePanel: React.FC = () => {
</SettingSection> </SettingSection>
</> </>
); );
}; }
);

View file

@ -54,6 +54,15 @@ export const ScraperMenu: React.FC<{
<Dropdown.Toggle variant={variant}>{toggle}</Dropdown.Toggle> <Dropdown.Toggle variant={variant}>{toggle}</Dropdown.Toggle>
<Dropdown.Menu> <Dropdown.Menu>
<Dropdown.Item onClick={() => onReloadScrapers()}>
<span className="fa-icon">
<Icon icon={faSyncAlt} />
</span>
<span>
<FormattedMessage id="actions.reload_scrapers" />
</span>
</Dropdown.Item>
{(stashBoxes?.length ?? 0) + scrapers.length > minFilteredScrapers && ( {(stashBoxes?.length ?? 0) + scrapers.length > minFilteredScrapers && (
<ClearableInput <ClearableInput
placeholder={`${intl.formatMessage({ id: "filter" })}...`} placeholder={`${intl.formatMessage({ id: "filter" })}...`}
@ -61,6 +70,7 @@ export const ScraperMenu: React.FC<{
setValue={setFilter} setValue={setFilter}
/> />
)} )}
{filteredStashboxes.map((s, index) => ( {filteredStashboxes.map((s, index) => (
<Dropdown.Item <Dropdown.Item
key={s.endpoint} key={s.endpoint}
@ -86,14 +96,6 @@ export const ScraperMenu: React.FC<{
{s.name} {s.name}
</Dropdown.Item> </Dropdown.Item>
))} ))}
<Dropdown.Item onClick={() => onReloadScrapers()}>
<span className="fa-icon">
<Icon icon={faSyncAlt} />
</span>
<span>
<FormattedMessage id="actions.reload_scrapers" />
</span>
</Dropdown.Item>
</Dropdown.Menu> </Dropdown.Menu>
</Dropdown> </Dropdown>
); );