mirror of
https://github.com/stashapp/stash.git
synced 2025-12-16 20:07:05 +03:00
Fix react warnings (#317)
* Remove unused imports * Fix === warnings * Remove unnecessary escape character * Add alt text for images * Add missing alt text * Remove unused variable * Change scrubber buttons from anchors * Change folder select anchor to button * Replace anchors with buttons * Add missing useEffect dependencies * Refactor filter debounce * Throw error object * Update dependencies * Fix === warning
This commit is contained in:
3
go.mod
3
go.mod
@@ -12,7 +12,6 @@ require (
|
||||
github.com/golang-migrate/migrate/v4 v4.3.1
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
github.com/h2non/filetype v1.0.8
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/mattn/go-sqlite3 v1.10.0
|
||||
github.com/rs/cors v1.6.0
|
||||
@@ -28,3 +27,5 @@ require (
|
||||
)
|
||||
|
||||
replace git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999
|
||||
|
||||
go 1.11
|
||||
|
||||
1
go.sum
1
go.sum
@@ -258,6 +258,7 @@ github.com/gobuffalo/packr v1.15.0/go.mod h1:t5gXzEhIviQwVlNx/+3SfS07GS+cZ2hn76W
|
||||
github.com/gobuffalo/packr v1.15.1/go.mod h1:IeqicJ7jm8182yrVmNbM6PR4g79SjN9tZLH8KduZZwE=
|
||||
github.com/gobuffalo/packr v1.19.0/go.mod h1:MstrNkfCQhd5o+Ct4IJ0skWlxN8emOq8DsoT1G98VIU=
|
||||
github.com/gobuffalo/packr v1.20.0/go.mod h1:JDytk1t2gP+my1ig7iI4NcVaXr886+N0ecUga6884zw=
|
||||
github.com/gobuffalo/packr v1.21.0 h1:p2ujcDJQp2QTiYWcI0ByHbr/gMoCouok6M0vXs/yTYQ=
|
||||
github.com/gobuffalo/packr v1.21.0/go.mod h1:H00jGfj1qFKxscFJSw8wcL4hpQtPe1PfU2wa6sg/SR0=
|
||||
github.com/gobuffalo/packr/v2 v2.0.0-rc.8/go.mod h1:y60QCdzwuMwO2R49fdQhsjCPv7tLQFR0ayzxxla9zes=
|
||||
github.com/gobuffalo/packr/v2 v2.0.0-rc.9/go.mod h1:fQqADRfZpEsgkc7c/K7aMew3n4aF1Kji7+lIZeR98Fc=
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
Spinner,
|
||||
} from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
import { StashService } from "../../core/StashService";
|
||||
@@ -20,7 +19,7 @@ export const Gallery: FunctionComponent<IProps> = (props: IProps) => {
|
||||
setIsLoading(loading);
|
||||
if (!data || !data.findGallery || !!error) { return; }
|
||||
setGallery(data.findGallery);
|
||||
}, [data]);
|
||||
}, [data, loading, error]);
|
||||
|
||||
if (!data || !data.findGallery || isLoading) { return <Spinner size={Spinner.SIZE_LARGE} />; }
|
||||
if (!!error) { return <>{error.message}</>; }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { HTMLTable } from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { QueryHookResult } from "react-apollo-hooks";
|
||||
import { Link } from "react-router-dom";
|
||||
@@ -36,7 +35,7 @@ export const GalleryList: FunctionComponent<IProps> = (props: IProps) => {
|
||||
<tr key={gallery.id}>
|
||||
<td>
|
||||
<Link to={`/galleries/${gallery.id}`}>
|
||||
{gallery.files.length > 0 ? <img src={`${gallery.files[0].path}?thumb=true`} /> : undefined}
|
||||
{gallery.files.length > 0 ? <img alt={gallery.title} src={`${gallery.files[0].path}?thumb=true`} /> : undefined}
|
||||
</Link>
|
||||
</td>
|
||||
<td><Link to={`/galleries/${gallery.id}`}>{gallery.path}</Link></td>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent, useState } from "react";
|
||||
import Lightbox from "react-images";
|
||||
import Gallery from "react-photo-gallery";
|
||||
|
||||
@@ -23,7 +23,7 @@ export const Settings: FunctionComponent<IProps> = (props: IProps) => {
|
||||
const location = Object.assign({}, props.history.location);
|
||||
location.search = queryString.stringify({tab: tabId}, {encode: false});
|
||||
props.history.replace(location);
|
||||
}, [tabId]);
|
||||
}, [tabId, props.history]);
|
||||
|
||||
function getTabId(): TabId {
|
||||
const queryParams = queryString.parse(props.location.search);
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import {
|
||||
Button,
|
||||
H1,
|
||||
H4,
|
||||
H6,
|
||||
HTMLTable,
|
||||
Spinner,
|
||||
Tag,
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
import { TextUtils } from "../../utils/text";
|
||||
import { StashService } from "../../core/StashService";
|
||||
|
||||
interface IProps { }
|
||||
@@ -93,7 +88,7 @@ export const SettingsAboutPanel: FunctionComponent<IProps> = (props: IProps) =>
|
||||
{!!error ? <span>{error.message}</span> : undefined}
|
||||
{!!errorLatest ? <span>{errorLatest.message}</span> : undefined}
|
||||
{renderVersion()}
|
||||
{!dataLatest || loadingLatest || networkStatus == 4 ? <Spinner size={Spinner.SIZE_SMALL} /> : <>{renderLatestVersion()}</>}
|
||||
{!dataLatest || loadingLatest || networkStatus === 4 ? <Spinner size={Spinner.SIZE_SMALL} /> : <>{renderLatestVersion()}</>}
|
||||
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -3,12 +3,9 @@ import {
|
||||
Button,
|
||||
Divider,
|
||||
FormGroup,
|
||||
H1,
|
||||
H4,
|
||||
H6,
|
||||
InputGroup,
|
||||
Spinner,
|
||||
Tag,
|
||||
Checkbox,
|
||||
HTMLSelect,
|
||||
} from "@blueprintjs/core";
|
||||
@@ -71,7 +68,7 @@ export const SettingsConfigurationPanel: FunctionComponent<IProps> = (props: IPr
|
||||
setLogAccess(conf.general.logAccess);
|
||||
setExcludes(conf.general.excludes);
|
||||
}
|
||||
}, [data]);
|
||||
}, [data, error]);
|
||||
|
||||
function onStashesChanged(directories: string[]) {
|
||||
setStashes(directories);
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
TextArea,
|
||||
NumericInput
|
||||
} from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import { StashService } from "../../core/StashService";
|
||||
import { ErrorUtils } from "../../utils/errors";
|
||||
@@ -48,7 +47,7 @@ export const SettingsInterfacePanel: FunctionComponent<IProps> = () => {
|
||||
setCSS(config.data.configuration.interface.css || "");
|
||||
setCSSEnabled(config.data.configuration.interface.cssEnabled || false);
|
||||
}
|
||||
}, [config.data]);
|
||||
}, [config.data, config.error]);
|
||||
|
||||
async function onSave() {
|
||||
try {
|
||||
|
||||
@@ -155,7 +155,7 @@ export const SettingsLogsPanel: FunctionComponent<IProps> = (props: IProps) => {
|
||||
const logLevels = ["Debug", "Info", "Warning", "Error"];
|
||||
|
||||
function filterByLogLevel(logEntry : LogEntry) {
|
||||
if (logLevel == "Debug") {
|
||||
if (logLevel === "Debug") {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
Divider,
|
||||
FormGroup,
|
||||
H4,
|
||||
AnchorButton,
|
||||
ProgressBar,
|
||||
H5,
|
||||
} from "@blueprintjs/core";
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
NavbarDivider,
|
||||
Popover,
|
||||
} from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { FunctionComponent, useState, useEffect } from "react";
|
||||
import { InputGroup, ButtonGroup, Button, IInputGroupProps, HTMLInputProps, ControlGroup } from "@blueprintjs/core";
|
||||
import { InputGroup, ButtonGroup, Button, HTMLInputProps, ControlGroup } from "@blueprintjs/core";
|
||||
import { DurationUtils } from "../../utils/duration";
|
||||
import { FIXED, NUMERIC_INPUT } from "@blueprintjs/core/lib/esm/common/classes";
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
Spinner,
|
||||
FormGroup,
|
||||
} from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import { StashService } from "../../../core/StashService";
|
||||
|
||||
@@ -29,7 +28,7 @@ export const FolderSelect: FunctionComponent<IProps> = (props: IProps) => {
|
||||
useEffect(() => {
|
||||
if (!data || !data.directories || !!error) { return; }
|
||||
setSelectableDirectories(StashService.nullToUndefined(data.directories));
|
||||
}, [data]);
|
||||
}, [data, error]);
|
||||
|
||||
function onSelectDirectory() {
|
||||
selectedDirectories.push(currentDirectory);
|
||||
@@ -79,7 +78,7 @@ export const FolderSelect: FunctionComponent<IProps> = (props: IProps) => {
|
||||
{renderDialog()}
|
||||
<FormGroup>
|
||||
{selectedDirectories.map((path) => {
|
||||
return <div key={path}>{path} <a onClick={() => onRemoveDirectory(path)}>Remove</a></div>;
|
||||
return <div key={path}>{path} <button className="button-link" onClick={() => onRemoveDirectory(path)}>Remove</button></div>;
|
||||
})}
|
||||
</FormGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import {
|
||||
ITagProps,
|
||||
Tag,
|
||||
} from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { PerformerDataFragment, SceneMarkerDataFragment, TagDataFragment } from "../../core/generated-graphql";
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
MenuItem,
|
||||
Menu,
|
||||
IconName,
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { IMenuItem } from "../App";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { H1, Spinner } from "@blueprintjs/core";
|
||||
import { Spinner } from "@blueprintjs/core";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { StashService } from "../core/StashService";
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import {
|
||||
Button,
|
||||
Classes,
|
||||
Dialog,
|
||||
EditableText,
|
||||
HTMLSelect,
|
||||
HTMLTable,
|
||||
Spinner,
|
||||
} from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import * as GQL from "../../../core/generated-graphql";
|
||||
import { StashService } from "../../../core/StashService";
|
||||
@@ -52,7 +47,7 @@ export const Studio: FunctionComponent<IProps> = (props: IProps) => {
|
||||
setIsLoading(loading);
|
||||
if (!data || !data.findStudio || !!error) { return; }
|
||||
setStudio(data.findStudio);
|
||||
}, [data]);
|
||||
}, [data, loading, error]);
|
||||
|
||||
useEffect(() => {
|
||||
setImagePreview(studio.image_path);
|
||||
@@ -61,7 +56,7 @@ export const Studio: FunctionComponent<IProps> = (props: IProps) => {
|
||||
if (!isNew) {
|
||||
setIsEditing(false);
|
||||
}
|
||||
}, [studio]);
|
||||
}, [studio, isNew]);
|
||||
|
||||
function onImageLoad(this: FileReader) {
|
||||
setImagePreview(this.result as string);
|
||||
@@ -120,7 +115,7 @@ export const Studio: FunctionComponent<IProps> = (props: IProps) => {
|
||||
async function onDelete() {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const result = await deleteStudio();
|
||||
await deleteStudio();
|
||||
} catch (e) {
|
||||
ErrorUtils.handle(e);
|
||||
}
|
||||
@@ -139,7 +134,7 @@ export const Studio: FunctionComponent<IProps> = (props: IProps) => {
|
||||
<>
|
||||
<div className="columns is-multiline no-spacing">
|
||||
<div className="column is-half details-image-container">
|
||||
<img className="studio" src={imagePreview} />
|
||||
<img alt={name} className="studio" src={imagePreview} />
|
||||
</div>
|
||||
<div className="column is-half details-detail-container">
|
||||
<DetailsEditNavbar
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { QueryHookResult } from "react-apollo-hooks";
|
||||
import { FindStudiosQuery, FindStudiosVariables } from "../../core/generated-graphql";
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import { Alert, Button, Classes, Dialog, EditableText, FormGroup, HTMLTable, InputGroup, Spinner, Tag } from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import { Alert, Button, Classes, Dialog, FormGroup, InputGroup, Spinner } from "@blueprintjs/core";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import { QueryHookResult } from "react-apollo-hooks";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FindGalleriesQuery, FindGalleriesVariables } from "../../core/generated-graphql";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
import { StashService } from "../../core/StashService";
|
||||
import { ListHook } from "../../hooks/ListHook";
|
||||
import { IBaseProps } from "../../models/base-props";
|
||||
import { ListFilterModel } from "../../models/list-filter/filter";
|
||||
import { DisplayMode, FilterMode } from "../../models/list-filter/types";
|
||||
import { ErrorUtils } from "../../utils/errors";
|
||||
import { NavigationUtils } from "../../utils/navigation";
|
||||
import { ToastUtils } from "../../utils/toasts";
|
||||
@@ -36,7 +30,7 @@ export const TagList: FunctionComponent<IProps> = (props: IProps) => {
|
||||
setIsLoading(loading);
|
||||
if (!data || !data.allTags || !!error) { return; }
|
||||
setTags(data.allTags);
|
||||
}, [data]);
|
||||
}, [data, loading, error]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!!editingTag) {
|
||||
|
||||
@@ -116,7 +116,7 @@ export const WallItem: FunctionComponent<IWallItemProps> = (props: IWallItemProp
|
||||
loop={true}
|
||||
ref={videoHoverHook.videoEl}
|
||||
/>
|
||||
<img src={previewPath || screenshotPath} onError={() => previewNotFound()} />
|
||||
<img alt={title} src={previewPath || screenshotPath} onError={() => previewNotFound()} />
|
||||
{showTextContainer ?
|
||||
<div className="scene-wall-item-text-container">
|
||||
<div style={{lineHeight: 1}}>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent, useState } from "react";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
import "./Wall.scss";
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
Slider,
|
||||
} from "@blueprintjs/core";
|
||||
import { debounce } from "lodash";
|
||||
import React, { FunctionComponent, SyntheticEvent, useEffect, useState } from "react";
|
||||
import React, { FunctionComponent, SyntheticEvent, useState } from "react";
|
||||
import { Criterion } from "../../models/list-filter/criteria/criterion";
|
||||
import { ListFilterModel } from "../../models/list-filter/filter";
|
||||
import { DisplayMode } from "../../models/list-filter/types";
|
||||
@@ -41,22 +41,18 @@ interface IListFilterProps {
|
||||
const PAGE_SIZE_OPTIONS = ["20", "40", "60", "120"];
|
||||
|
||||
export const ListFilter: FunctionComponent<IListFilterProps> = (props: IListFilterProps) => {
|
||||
let searchCallback: any;
|
||||
|
||||
const [editingCriterion, setEditingCriterion] = useState<Criterion | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
searchCallback = debounce((event: any) => {
|
||||
props.onChangeQuery(event.target.value);
|
||||
}, 500);
|
||||
});
|
||||
|
||||
function onChangePageSize(event: SyntheticEvent<HTMLSelectElement>) {
|
||||
const val = event!.currentTarget!.value;
|
||||
props.onChangePageSize(parseInt(val, 10));
|
||||
}
|
||||
|
||||
function onChangeQuery(event: SyntheticEvent<HTMLInputElement>) {
|
||||
let searchCallback = debounce((event: any) => {
|
||||
props.onChangeQuery(event.target.value);
|
||||
}, 500);
|
||||
|
||||
event.persist();
|
||||
searchCallback(event);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
AnchorButton,
|
||||
IconName,
|
||||
} from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import * as GQL from "../../../core/generated-graphql";
|
||||
import { StashService } from "../../../core/StashService";
|
||||
@@ -40,7 +39,7 @@ export const Performer: FunctionComponent<IPerformerProps> = (props: IPerformerP
|
||||
setIsLoading(loading);
|
||||
if (!data || !data.findPerformer || !!error) { return; }
|
||||
setPerformer(data.findPerformer);
|
||||
}, [data]);
|
||||
}, [data, error, loading]);
|
||||
|
||||
useEffect(() => {
|
||||
setImagePreview(performer.image_path);
|
||||
@@ -191,7 +190,7 @@ export const Performer: FunctionComponent<IPerformerProps> = (props: IPerformerP
|
||||
return (
|
||||
<div className="columns is-multiline no-spacing">
|
||||
<div className="column is-half details-image-container">
|
||||
<img className="performer" src={imagePreview} />
|
||||
{!imagePreview ? undefined : <img alt="Performer" className="performer" src={imagePreview} />}
|
||||
</div>
|
||||
<div className="column is-half details-detail-container">
|
||||
{renderTabs()}
|
||||
@@ -218,7 +217,7 @@ export const Performer: FunctionComponent<IPerformerProps> = (props: IPerformerP
|
||||
<>
|
||||
<div id="performer-page">
|
||||
<div className="details-image-container">
|
||||
<img className="performer" src={imagePreview} onClick={openLightbox} />
|
||||
<img alt={performer.name} className="performer" src={imagePreview} onClick={openLightbox} />
|
||||
</div>
|
||||
<div className="performer-head">
|
||||
<h1 className="bp3-heading">
|
||||
|
||||
@@ -2,10 +2,8 @@ import {
|
||||
Button,
|
||||
Classes,
|
||||
Dialog,
|
||||
EditableText,
|
||||
HTMLTable,
|
||||
Spinner,
|
||||
FormGroup,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Popover,
|
||||
@@ -19,7 +17,6 @@ import { StashService } from "../../../core/StashService";
|
||||
import { ErrorUtils } from "../../../utils/errors";
|
||||
import { TableUtils } from "../../../utils/table";
|
||||
import { ScrapePerformerSuggest } from "../../select/ScrapePerformerSuggest";
|
||||
import { ToastUtils } from "../../../utils/toasts";
|
||||
import { EditableTextUtils } from "../../../utils/editabletext";
|
||||
import { ImageUtils } from "../../../utils/image";
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
Button,
|
||||
} from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import * as GQL from "../../../core/generated-graphql";
|
||||
import { StashService } from "../../../core/StashService";
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import * as GQL from "../../../core/generated-graphql";
|
||||
import { IBaseProps } from "../../../models";
|
||||
|
||||
@@ -7,16 +7,14 @@ import {
|
||||
Elevation,
|
||||
H4,
|
||||
Popover,
|
||||
Tag,
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent, RefObject, useEffect, useRef, useState } from "react";
|
||||
import React, { FunctionComponent, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
import { VideoHoverHook } from "../../hooks/VideoHover";
|
||||
import { ColorUtils } from "../../utils/color";
|
||||
import { TextUtils } from "../../utils/text";
|
||||
import { TagLink } from "../Shared/TagLink";
|
||||
import { SceneHelpers } from "./helpers";
|
||||
import { ZoomUtils } from "../../utils/zoom";
|
||||
import { StashService } from "../../core/StashService";
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ export const Scene: FunctionComponent<ISceneProps> = (props: ISceneProps) => {
|
||||
setIsLoading(loading);
|
||||
if (!data || !data.findScene || !!error) { return; }
|
||||
setScene(StashService.nullToUndefined(data.findScene));
|
||||
}, [data]);
|
||||
}, [data, loading, error]);
|
||||
|
||||
useEffect(() => {
|
||||
const queryParams = queryString.parse(props.location.search);
|
||||
@@ -41,7 +41,7 @@ export const Scene: FunctionComponent<ISceneProps> = (props: ISceneProps) => {
|
||||
if (queryParams.autoplay && typeof queryParams.autoplay === "string") {
|
||||
setAutoplay(queryParams.autoplay === "true");
|
||||
}
|
||||
});
|
||||
}, [props.location.search, timestamp]);
|
||||
|
||||
function onClickMarker(marker: GQL.SceneMarkerDataFragment) {
|
||||
setTimestamp(marker.seconds);
|
||||
|
||||
@@ -2,12 +2,9 @@ import {
|
||||
H1,
|
||||
H4,
|
||||
H6,
|
||||
Tag,
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import * as GQL from "../../../core/generated-graphql";
|
||||
import { NavigationUtils } from "../../../utils/navigation";
|
||||
import { TextUtils } from "../../../utils/text";
|
||||
import { TagLink } from "../../Shared/TagLink";
|
||||
import { SceneHelpers } from "../helpers";
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
Popover,
|
||||
MenuItem,
|
||||
} from "@blueprintjs/core";
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import * as GQL from "../../../core/generated-graphql";
|
||||
import { StashService } from "../../../core/StashService";
|
||||
@@ -229,7 +228,7 @@ export const SceneEditPanel: FunctionComponent<IProps> = (props: IProps) => {
|
||||
}
|
||||
|
||||
function renderScraperMenu() {
|
||||
if (!queryableScrapers || queryableScrapers.length == 0) {
|
||||
if (!queryableScrapers || queryableScrapers.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -272,7 +271,7 @@ export const SceneEditPanel: FunctionComponent<IProps> = (props: IProps) => {
|
||||
setStudioId(scene.studio.id);
|
||||
}
|
||||
|
||||
if ((!performerIds || performerIds.length == 0) && scene.performers && scene.performers.length > 0) {
|
||||
if ((!performerIds || performerIds.length === 0) && scene.performers && scene.performers.length > 0) {
|
||||
let idPerfs = scene.performers.filter((p) => {
|
||||
return p.id !== undefined && p.id !== null;
|
||||
});
|
||||
@@ -283,7 +282,7 @@ export const SceneEditPanel: FunctionComponent<IProps> = (props: IProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
if ((!tagIds || tagIds.length == 0) && scene.tags && scene.tags.length > 0) {
|
||||
if ((!tagIds || tagIds.length === 0) && scene.tags && scene.tags.length > 0) {
|
||||
let idTags = scene.tags.filter((p) => {
|
||||
return p.id !== undefined && p.id !== null;
|
||||
});
|
||||
@@ -395,7 +394,7 @@ export const SceneEditPanel: FunctionComponent<IProps> = (props: IProps) => {
|
||||
<span>Cover Image</span>
|
||||
</label>
|
||||
<Collapse isOpen={isCoverImageOpen}>
|
||||
<img className="scene-cover" src={coverImagePreview} />
|
||||
<img alt="Scene cover" className="scene-cover" src={coverImagePreview} />
|
||||
<FileInput text="Choose image..." onInputChange={onCoverImageChange} inputProps={{accept: ".jpg,.jpeg,.png"}} />
|
||||
</Collapse>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
Divider,
|
||||
FormGroup,
|
||||
H3,
|
||||
NumericInput,
|
||||
Tag,
|
||||
} from "@blueprintjs/core";
|
||||
import { Field, FieldProps, Form, Formik, FormikActions, FormikProps } from "formik";
|
||||
@@ -63,8 +62,8 @@ export const SceneMarkersPanel: FunctionComponent<ISceneMarkersPanelProps> = (pr
|
||||
<div key={marker.id}>
|
||||
<Divider />
|
||||
<div>
|
||||
<a onClick={() => onClickMarker(marker)}>{marker.title}</a>
|
||||
{!isEditorOpen ? <a style={{float: "right"}} onClick={() => onOpenEditor(marker)}>Edit</a> : undefined}
|
||||
<button className="button-link" onClick={() => onClickMarker(marker)}>{marker.title}</button>
|
||||
{!isEditorOpen ? <button className="button-link" style={{float: "right"}} onClick={() => onOpenEditor(marker)}>Edit</button> : undefined}
|
||||
</div>
|
||||
<div>
|
||||
{TextUtils.secondsToTimestamp(marker.seconds)}
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
Tree,
|
||||
ITreeNode,
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent, useEffect, useState, useRef } from "react";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import { IBaseProps } from "../../models";
|
||||
import { StashService } from "../../core/StashService";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
@@ -449,19 +449,19 @@ export const SceneFilenameParser: FunctionComponent<IProps> = (props: IProps) =>
|
||||
return !r.studioId.set;
|
||||
});
|
||||
|
||||
if (newAllTitleSet != allTitleSet) {
|
||||
if (newAllTitleSet !== allTitleSet) {
|
||||
setAllTitleSet(newAllTitleSet);
|
||||
}
|
||||
if (newAllDateSet != allDateSet) {
|
||||
if (newAllDateSet !== allDateSet) {
|
||||
setAllDateSet(newAllDateSet);
|
||||
}
|
||||
if (newAllPerformerSet != allPerformerSet) {
|
||||
if (newAllPerformerSet !== allPerformerSet) {
|
||||
setAllTagSet(newAllPerformerSet);
|
||||
}
|
||||
if (newAllTagSet != allTagSet) {
|
||||
if (newAllTagSet !== allTagSet) {
|
||||
setAllTagSet(newAllTagSet);
|
||||
}
|
||||
if (newAllStudioSet != allStudioSet) {
|
||||
if (newAllStudioSet !== allStudioSet) {
|
||||
setAllStudioSet(newAllStudioSet);
|
||||
}
|
||||
}, [parserResult]);
|
||||
@@ -1071,7 +1071,7 @@ export const SceneFilenameParser: FunctionComponent<IProps> = (props: IProps) =>
|
||||
}
|
||||
|
||||
function renderTable() {
|
||||
if (parserResult.length == 0) { return undefined; }
|
||||
if (parserResult.length === 0) { return undefined; }
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import _ from "lodash";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { IBaseProps } from "../../models/base-props";
|
||||
import { SceneList } from "./SceneList";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Hotkey, Hotkeys, HotkeysTarget } from "@blueprintjs/core";
|
||||
import React, { Component, FunctionComponent } from "react";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import ReactJWPlayer from "react-jw-player";
|
||||
import * as GQL from "../../../core/generated-graphql";
|
||||
import { SceneHelpers } from "../helpers";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import axios from "axios";
|
||||
import React, { CSSProperties, FunctionComponent, RefObject, useEffect, useRef, useState } from "react";
|
||||
import React, { CSSProperties, FunctionComponent, useEffect, useRef, useState } from "react";
|
||||
import * as GQL from "../../../core/generated-graphql";
|
||||
import { TextUtils } from "../../../utils/text";
|
||||
import "./ScenePlayerScrubber.scss";
|
||||
@@ -55,7 +55,6 @@ export const ScenePlayerScrubber: FunctionComponent<IScenePlayerScrubberProps> =
|
||||
}
|
||||
|
||||
const [spriteItems, setSpriteItems] = useState<ISceneSpriteItem[]>([]);
|
||||
const [delayedRender, setDelayedRender] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!scrubberSliderEl.current) { return; }
|
||||
@@ -63,6 +62,47 @@ export const ScenePlayerScrubber: FunctionComponent<IScenePlayerScrubberProps> =
|
||||
}, [scrubberSliderEl]);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchSpriteInfo() {
|
||||
if (!props.scene || !props.scene.paths.vtt) { return; }
|
||||
|
||||
const response = await axios.get<string>(props.scene.paths.vtt, {responseType: "text"});
|
||||
if (response.status !== 200) {
|
||||
console.log(response.statusText);
|
||||
}
|
||||
|
||||
// TODO: This is gnarly
|
||||
const lines = response.data.split("\n");
|
||||
if (lines.shift() !== "WEBVTT") { return; }
|
||||
if (lines.shift() !== "") { return; }
|
||||
let item: ISceneSpriteItem = {start: 0, end: 0, x: 0, y: 0, w: 0, h: 0};
|
||||
const newSpriteItems: ISceneSpriteItem[] = [];
|
||||
while (lines.length) {
|
||||
const line = lines.shift();
|
||||
if (line === undefined) { continue; }
|
||||
|
||||
if (line.includes("#") && line.includes("=") && line.includes(",")) {
|
||||
const size = line.split("#")[1].split("=")[1].split(",");
|
||||
item.x = Number(size[0]);
|
||||
item.y = Number(size[1]);
|
||||
item.w = Number(size[2]);
|
||||
item.h = Number(size[3]);
|
||||
|
||||
newSpriteItems.push(item);
|
||||
item = {start: 0, end: 0, x: 0, y: 0, w: 0, h: 0};
|
||||
} else if (line.includes(" --> ")) {
|
||||
const times = line.split(" --> ");
|
||||
|
||||
const start = times[0].split(":");
|
||||
item.start = (+start[0]) * 60 * 60 + (+start[1]) * 60 + (+start[2]);
|
||||
|
||||
const end = times[1].split(":");
|
||||
item.end = (+end[0]) * 60 * 60 + (+end[1]) * 60 + (+end[2]);
|
||||
}
|
||||
}
|
||||
|
||||
setSpriteItems(newSpriteItems);
|
||||
}
|
||||
|
||||
fetchSpriteInfo();
|
||||
}, [props.scene]);
|
||||
|
||||
@@ -77,30 +117,20 @@ export const ScenePlayerScrubber: FunctionComponent<IScenePlayerScrubberProps> =
|
||||
}, [props.position]);
|
||||
|
||||
useEffect(() => {
|
||||
let element = contentEl.current;
|
||||
if (!element) { return; }
|
||||
element.addEventListener("mousedown", onMouseDown, false);
|
||||
element.addEventListener("mousemove", onMouseMove, false);
|
||||
window.addEventListener("mouseup", onMouseUp, false);
|
||||
|
||||
return () => {
|
||||
if (!element) { return; }
|
||||
element.removeEventListener("mousedown", onMouseDown);
|
||||
element.removeEventListener("mousemove", onMouseMove);
|
||||
window.removeEventListener("mouseup", onMouseUp);
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!contentEl.current) { return; }
|
||||
contentEl.current.addEventListener("mousedown", onMouseDown, false);
|
||||
return () => {
|
||||
if (!contentEl.current) { return; }
|
||||
contentEl.current.removeEventListener("mousedown", onMouseDown);
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!contentEl.current) { return; }
|
||||
contentEl.current.addEventListener("mousemove", onMouseMove, false);
|
||||
return () => {
|
||||
if (!contentEl.current) { return; }
|
||||
contentEl.current.removeEventListener("mousemove", onMouseMove);
|
||||
};
|
||||
});
|
||||
|
||||
function onMouseUp(this: Window, event: MouseEvent) {
|
||||
if (!startMouseEvent.current || !scrubberSliderEl.current) { return; }
|
||||
mouseDown.current = false;
|
||||
@@ -170,51 +200,6 @@ export const ScenePlayerScrubber: FunctionComponent<IScenePlayerScrubberProps> =
|
||||
setPosition(newPosition);
|
||||
}
|
||||
|
||||
async function fetchSpriteInfo() {
|
||||
if (!props.scene || !props.scene.paths.vtt) { return; }
|
||||
|
||||
const response = await axios.get<string>(props.scene.paths.vtt, {responseType: "text"});
|
||||
if (response.status !== 200) {
|
||||
console.log(response.statusText);
|
||||
}
|
||||
|
||||
// TODO: This is gnarly
|
||||
const lines = response.data.split("\n");
|
||||
if (lines.shift() !== "WEBVTT") { return; }
|
||||
if (lines.shift() !== "") { return; }
|
||||
let item: ISceneSpriteItem = {start: 0, end: 0, x: 0, y: 0, w: 0, h: 0};
|
||||
const newSpriteItems: ISceneSpriteItem[] = [];
|
||||
while (lines.length) {
|
||||
const line = lines.shift();
|
||||
if (line === undefined) { continue; }
|
||||
|
||||
if (line.includes("#") && line.includes("=") && line.includes(",")) {
|
||||
const size = line.split("#")[1].split("=")[1].split(",");
|
||||
item.x = Number(size[0]);
|
||||
item.y = Number(size[1]);
|
||||
item.w = Number(size[2]);
|
||||
item.h = Number(size[3]);
|
||||
|
||||
newSpriteItems.push(item);
|
||||
item = {start: 0, end: 0, x: 0, y: 0, w: 0, h: 0};
|
||||
} else if (line.includes(" --> ")) {
|
||||
const times = line.split(" --> ");
|
||||
|
||||
const start = times[0].split(":");
|
||||
item.start = (+start[0]) * 60 * 60 + (+start[1]) * 60 + (+start[2]);
|
||||
|
||||
const end = times[1].split(":");
|
||||
item.end = (+end[0]) * 60 * 60 + (+end[1]) * 60 + (+end[2]);
|
||||
}
|
||||
}
|
||||
|
||||
setSpriteItems(newSpriteItems);
|
||||
// TODO: Very hacky. Need to wait for the scroll width to update from the image loading.
|
||||
setTimeout(() => {
|
||||
setDelayedRender(true);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function renderTags() {
|
||||
function getTagStyle(i: number): CSSProperties {
|
||||
if (!scrubberSliderEl.current ||
|
||||
@@ -296,7 +281,7 @@ export const ScenePlayerScrubber: FunctionComponent<IScenePlayerScrubberProps> =
|
||||
|
||||
return (
|
||||
<div className="scrubber-wrapper">
|
||||
<a className="scrubber-button" id="scrubber-back" onClick={() => goBack()}><</a>
|
||||
<button className="scrubber-button" id="scrubber-back" onClick={() => goBack()}><</button>
|
||||
<div ref={contentEl} className="scrubber-content">
|
||||
<div className="scrubber-tags-background" />
|
||||
<div ref={positionIndicatorEl} id="scrubber-position-indicator" />
|
||||
@@ -310,7 +295,7 @@ export const ScenePlayerScrubber: FunctionComponent<IScenePlayerScrubberProps> =
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a className="scrubber-button" id="scrubber-forward" onClick={() => goForward()}>></a>
|
||||
<button className="scrubber-button" id="scrubber-forward" onClick={() => goForward()}>></button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
import _ from "lodash";
|
||||
import {
|
||||
AnchorButton,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
ControlGroup,
|
||||
FormGroup,
|
||||
HTMLSelect,
|
||||
InputGroup,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Popover,
|
||||
Spinner,
|
||||
Tag,
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent, SyntheticEvent, useEffect, useRef, useState } from "react";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import { FilterSelect } from "../select/FilterSelect";
|
||||
import { FilterMultiSelect } from "../select/FilterMultiSelect";
|
||||
import { StashService } from "../../core/StashService";
|
||||
@@ -106,7 +99,7 @@ export const SceneSelectedOptions: FunctionComponent<IListOperationProps> = (pro
|
||||
async function onSave() {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const result = await updateScenes();
|
||||
await updateScenes();
|
||||
ToastUtils.success("Updated scenes");
|
||||
} catch (e) {
|
||||
ErrorUtils.handle(e);
|
||||
@@ -143,7 +136,7 @@ export const SceneSelectedOptions: FunctionComponent<IListOperationProps> = (pro
|
||||
first = false;
|
||||
} else {
|
||||
var studioId = scene.studio ? scene.studio.id : undefined;
|
||||
if (ret != studioId) {
|
||||
if (ret !== studioId) {
|
||||
ret = undefined;
|
||||
}
|
||||
}
|
||||
@@ -221,7 +214,7 @@ export const SceneSelectedOptions: FunctionComponent<IListOperationProps> = (pro
|
||||
if (rating !== thisRating) {
|
||||
rating = "";
|
||||
}
|
||||
if (studioId != thisStudio) {
|
||||
if (studioId !== thisStudio) {
|
||||
studioId = undefined;
|
||||
}
|
||||
const perfIds = !!scene.performers ? scene.performers.map(toId).sort() : [];
|
||||
|
||||
@@ -120,7 +120,7 @@ export const FilterMultiSelect: React.FunctionComponent<IProps> = (props: IProps
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw "Unhandled case in FilterMultiSelect";
|
||||
throw new Error("Unhandled case in FilterMultiSelect");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ export const FilterSelect: React.FunctionComponent<IProps> = (props: IProps) =>
|
||||
};
|
||||
|
||||
function onItemSelect(item: ValidTypes | undefined) {
|
||||
if (item && item.id == "0") {
|
||||
if (item && item.id === "0") {
|
||||
item = undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { MenuItem } from "@blueprintjs/core";
|
||||
import { ItemPredicate, ItemRenderer, Suggest } from "@blueprintjs/select";
|
||||
import { ItemRenderer, Suggest } from "@blueprintjs/select";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
import { StashService } from "../../core/StashService";
|
||||
import { HTMLInputProps } from "../../models";
|
||||
|
||||
@@ -50,7 +50,7 @@ export const ValidGalleriesSelect: React.FunctionComponent<IProps> = (props: IPr
|
||||
};
|
||||
|
||||
function onItemSelect(item: GQL.ValidGalleriesForSceneValidGalleriesForScene | undefined) {
|
||||
if (item && item.id == "0") {
|
||||
if (item && item.id === "0") {
|
||||
item = undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,6 +280,28 @@ video.preview.portrait {
|
||||
}
|
||||
}
|
||||
|
||||
.button-link {
|
||||
background-color: transparent;
|
||||
color: #48aff0;
|
||||
border-width: 0;
|
||||
cursor: pointer;
|
||||
display: inline;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.button-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.scrubber-button {
|
||||
background-color: transparent;
|
||||
color: #48aff0;
|
||||
}
|
||||
|
||||
.scrubber-button:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#jwplayer-container {
|
||||
margin: 10px auto;
|
||||
width: 75%;
|
||||
|
||||
@@ -30,7 +30,7 @@ export class DurationUtils {
|
||||
let factor = 1;
|
||||
while(splits.length > 0) {
|
||||
let thisSplit = splits.pop();
|
||||
if (thisSplit == undefined) {
|
||||
if (thisSplit === undefined) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export class ImageUtils {
|
||||
}
|
||||
|
||||
public static pasteImage(e : any, onLoadEnd: (this: FileReader) => any) {
|
||||
if (e.clipboardData.files.length == 0) {
|
||||
if (e.clipboardData.files.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EditableText, HTMLSelect, InputGroup, IOptionProps, TextArea } from "@blueprintjs/core";
|
||||
import { EditableText, IOptionProps } from "@blueprintjs/core";
|
||||
import React from "react";
|
||||
import { EditableTextUtils } from "./editabletext";
|
||||
import { FilterMultiSelect } from "../components/select/FilterMultiSelect";
|
||||
|
||||
@@ -33,7 +33,7 @@ export class TextUtils {
|
||||
|
||||
public static fileNameFromPath(path: string): string {
|
||||
if (!!path === false) { return "No File Name"; }
|
||||
return path.replace(/^.*[\\\/]/, "");
|
||||
return path.replace(/^.*[\\/]/, "");
|
||||
}
|
||||
|
||||
public static age(dateString?: string, fromDateString?: string): number {
|
||||
|
||||
Reference in New Issue
Block a user