;
}> = ({
filter,
setFilter,
filterHook,
view,
showEditFilter,
sidebarOpen,
onClose,
count,
focus,
}) => {
const showResultsId =
count !== undefined ? "actions.show_count_results" : "actions.show_results";
const hideStudios = view === View.StudioScenes;
return (
<>
{!hideStudios && (
}
data-type={StudiosCriterionOption.type}
option={StudiosCriterionOption}
filter={filter}
setFilter={setFilter}
filterHook={filterHook}
sectionID="studios"
/>
)}
}
data-type={PerformersCriterionOption.type}
option={PerformersCriterionOption}
filter={filter}
setFilter={setFilter}
filterHook={filterHook}
sectionID="performers"
/>
}
data-type={TagsCriterionOption.type}
option={TagsCriterionOption}
filter={filter}
setFilter={setFilter}
filterHook={filterHook}
sectionID="tags"
/>
}
data-type={RatingCriterionOption.type}
option={RatingCriterionOption}
filter={filter}
setFilter={setFilter}
sectionID="rating"
/>
}
option={DurationCriterionOption}
filter={filter}
setFilter={setFilter}
sectionID="duration"
/>
}
data-type={HasMarkersCriterionOption.type}
option={HasMarkersCriterionOption}
filter={filter}
setFilter={setFilter}
sectionID="hasMarkers"
/>
}
data-type={OrganizedCriterionOption.type}
option={OrganizedCriterionOption}
filter={filter}
setFilter={setFilter}
sectionID="organized"
/>
}
option={PerformerAgeCriterionOption}
filter={filter}
setFilter={setFilter}
sectionID="performer_age"
/>
>
);
};
interface IOperations {
text: string;
onClick: () => void;
isDisplayed?: () => boolean;
className?: string;
}
const SceneListOperations: React.FC<{
items: number;
hasSelection: boolean;
operations: IOperations[];
onEdit: () => void;
onDelete: () => void;
onPlay: () => void;
onCreateNew: () => void;
}> = ({
items,
hasSelection,
operations,
onEdit,
onDelete,
onPlay,
onCreateNew,
}) => {
const intl = useIntl();
return (
{!!items && (
)}
{!hasSelection && (
)}
{hasSelection && (
<>
>
)}
{operations.map((o) => {
if (o.isDisplayed && !o.isDisplayed()) {
return null;
}
return (
);
})}
);
};
interface IFilteredScenes {
filterHook?: (filter: ListFilterModel) => ListFilterModel;
defaultSort?: string;
view?: View;
alterQuery?: boolean;
fromGroupId?: string;
}
export const FilteredSceneList = (props: IFilteredScenes) => {
const intl = useIntl();
const history = useHistory();
const searchFocus = useFocus();
const [, setSearchFocus] = searchFocus;
const { filterHook, defaultSort, view, alterQuery, fromGroupId } = props;
// States
const {
showSidebar,
setShowSidebar,
loading: sidebarStateLoading,
sectionOpen,
setSectionOpen,
} = useSidebarState(view);
const { filterState, queryResult, modalState, listSelect, showEditFilter } =
useFilteredItemList({
filterStateProps: {
filterMode: GQL.FilterMode.Scenes,
defaultSort,
view,
useURL: alterQuery,
},
queryResultProps: {
useResult: useFindScenes,
getCount: (r) => r.data?.findScenes.count ?? 0,
getItems: (r) => r.data?.findScenes.scenes ?? [],
filterHook,
},
});
const { filter, setFilter } = filterState;
const { effectiveFilter, result, cachedResult, items, totalCount } =
queryResult;
const {
selectedIds,
selectedItems,
onSelectChange,
onSelectAll,
onSelectNone,
hasSelection,
} = listSelect;
const { modal, showModal, closeModal } = modalState;
// Utility hooks
const { setPage, removeCriterion, clearAllCriteria } = useFilterOperations({
filter,
setFilter,
});
useAddKeybinds(filter, totalCount);
useFilteredSidebarKeybinds({
showSidebar,
setShowSidebar,
});
useEffect(() => {
Mousetrap.bind("e", () => {
if (hasSelection) {
onEdit?.();
}
});
Mousetrap.bind("d d", () => {
if (hasSelection) {
onDelete?.();
}
});
return () => {
Mousetrap.unbind("e");
Mousetrap.unbind("d d");
};
});
useZoomKeybinds({
zoomIndex: filter.zoomIndex,
onChangeZoom: (zoom) => setFilter(filter.setZoom(zoom)),
});
const onCloseEditDelete = useCloseEditDelete({
closeModal,
onSelectNone,
result,
});
const metadataByline = useMemo(() => {
if (cachedResult.loading) return null;
return renderMetadataByline(cachedResult) ?? null;
}, [cachedResult]);
const queue = useMemo(() => SceneQueue.fromListFilterModel(filter), [filter]);
const playRandom = usePlayRandom(effectiveFilter, totalCount);
const playSelected = usePlaySelected(selectedIds);
const playFirst = usePlayFirst();
function onCreateNew() {
history.push("/scenes/new");
}
function onPlay() {
if (items.length === 0) {
return;
}
// if there are selected items, play those
if (hasSelection) {
playSelected();
return;
}
// otherwise, play the first item in the list
const sceneID = items[0].id;
playFirst(queue, sceneID, 0);
}
function onExport(all: boolean) {
showModal(
closeModal()}
/>
);
}
function onMerge() {
const selected =
selectedItems.map((s) => {
return {
id: s.id,
title: objectTitle(s),
};
}) ?? [];
showModal(
{
closeModal();
if (mergedID) {
history.push(`/scenes/${mergedID}`);
}
}}
show
/>
);
}
function onEdit() {
showModal(
);
}
function onDelete() {
showModal(
);
}
const otherOperations = [
{
text: intl.formatMessage({ id: "actions.play" }),
onClick: () => onPlay(),
isDisplayed: () => items.length > 0,
className: "play-item",
},
{
text: intl.formatMessage(
{ id: "actions.create_entity" },
{ entityType: intl.formatMessage({ id: "scene" }) }
),
onClick: () => onCreateNew(),
isDisplayed: () => !hasSelection,
className: "create-new-item",
},
{
text: intl.formatMessage({ id: "actions.select_all" }),
onClick: () => onSelectAll(),
isDisplayed: () => totalCount > 0,
},
{
text: intl.formatMessage({ id: "actions.select_none" }),
onClick: () => onSelectNone(),
isDisplayed: () => hasSelection,
},
{
text: intl.formatMessage({ id: "actions.play_random" }),
onClick: playRandom,
isDisplayed: () => totalCount > 1,
},
{
text: `${intl.formatMessage({ id: "actions.generate" })}…`,
onClick: () =>
showModal(
closeModal()}
/>
),
isDisplayed: () => hasSelection,
},
{
text: `${intl.formatMessage({ id: "actions.identify" })}…`,
onClick: () =>
showModal(
closeModal()}
/>
),
isDisplayed: () => hasSelection,
},
{
text: `${intl.formatMessage({ id: "actions.merge" })}…`,
onClick: () => onMerge(),
isDisplayed: () => hasSelection,
},
{
text: intl.formatMessage({ id: "actions.export" }),
onClick: () => onExport(false),
isDisplayed: () => hasSelection,
},
{
text: intl.formatMessage({ id: "actions.export_all" }),
onClick: () => onExport(true),
},
];
// render
if (sidebarStateLoading) return null;
const operations = (
);
return (
{modal}
setShowSidebar(false)}>
setShowSidebar(false)}
count={cachedResult.loading ? undefined : totalCount}
focus={searchFocus}
/>
setShowSidebar(!showSidebar)}
onEditCriterion={(c) =>
showEditFilter(c?.criterionOption.type)
}
onRemoveCriterion={removeCriterion}
onRemoveAllCriterion={() => clearAllCriteria(true)}
onEditSearchTerm={() => {
setShowSidebar(true);
setSearchFocus(true);
}}
onRemoveSearchTerm={() =>
setFilter(filter.clearSearchTerm())
}
view={view}
/>
}
selectionSection={
setShowSidebar(!showSidebar)}
onSelectAll={() => onSelectAll()}
onSelectNone={() => onSelectNone()}
operations={operations}
/>
}
operationSection={operations}
/>
setFilter(newFilter)}
/>
{totalCount > filter.itemsPerPage && (
)}
);
};
export default FilteredSceneList;