mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
Scene selection improvements (#642)
* Select subsequent scenes on card click
This commit is contained in:
@@ -9,6 +9,7 @@ const markup = `
|
|||||||
* Add support for parent/child studios.
|
* Add support for parent/child studios.
|
||||||
|
|
||||||
### 🎨 Improvements
|
### 🎨 Improvements
|
||||||
|
* Allow click and click-drag selection after selecting scene.
|
||||||
* Added multi-scene edit dialog.
|
* Added multi-scene edit dialog.
|
||||||
* Moved images to separate tables, increasing performance.
|
* Moved images to separate tables, increasing performance.
|
||||||
* Add gallery grid view.
|
* Add gallery grid view.
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { TextUtils } from "src/utils";
|
|||||||
|
|
||||||
interface ISceneCardProps {
|
interface ISceneCardProps {
|
||||||
scene: GQL.SlimSceneDataFragment;
|
scene: GQL.SlimSceneDataFragment;
|
||||||
|
selecting?: boolean;
|
||||||
selected: boolean | undefined;
|
selected: boolean | undefined;
|
||||||
zoomIndex: number;
|
zoomIndex: number;
|
||||||
onSelectedChanged: (selected: boolean, shiftKey: boolean) => void;
|
onSelectedChanged: (selected: boolean, shiftKey: boolean) => void;
|
||||||
@@ -221,11 +222,42 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
}
|
}
|
||||||
hoverHandler.onMouseEnter();
|
hoverHandler.onMouseEnter();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMouseLeave() {
|
function onMouseLeave() {
|
||||||
hoverHandler.onMouseLeave();
|
hoverHandler.onMouseLeave();
|
||||||
setPreviewPath("");
|
setPreviewPath("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSceneClick(
|
||||||
|
event: React.MouseEvent<HTMLAnchorElement, MouseEvent>
|
||||||
|
) {
|
||||||
|
const { shiftKey } = event;
|
||||||
|
|
||||||
|
if (props.selecting) {
|
||||||
|
props.onSelectedChanged(!props.selected, shiftKey);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDrag(event: React.DragEvent<HTMLAnchorElement>) {
|
||||||
|
if (props.selecting) {
|
||||||
|
event.dataTransfer.setData("text/plain", "");
|
||||||
|
event.dataTransfer.setDragImage(new Image(), 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDragOver(event: React.DragEvent<HTMLAnchorElement>) {
|
||||||
|
const ev = event;
|
||||||
|
const shiftKey = false;
|
||||||
|
|
||||||
|
if (props.selecting && !props.selected) {
|
||||||
|
props.onSelectedChanged(true, shiftKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
ev.dataTransfer.dropEffect = "move";
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
function isPortrait() {
|
function isPortrait() {
|
||||||
const { file } = props.scene;
|
const { file } = props.scene;
|
||||||
const width = file.width ? file.width : 0;
|
const width = file.width ? file.width : 0;
|
||||||
@@ -253,7 +285,14 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Link to={`/scenes/${props.scene.id}`} className="scene-card-link">
|
<Link
|
||||||
|
to={`/scenes/${props.scene.id}`}
|
||||||
|
className="scene-card-link"
|
||||||
|
onClick={handleSceneClick}
|
||||||
|
onDragStart={handleDrag}
|
||||||
|
onDragOver={handleDragOver}
|
||||||
|
draggable={props.selecting}
|
||||||
|
>
|
||||||
{maybeRenderRatingBanner()}
|
{maybeRenderRatingBanner()}
|
||||||
{maybeRenderSceneStudioOverlay()}
|
{maybeRenderSceneStudioOverlay()}
|
||||||
{maybeRenderSceneSpecsOverlay()}
|
{maybeRenderSceneSpecsOverlay()}
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ export const SceneList: React.FC<ISceneList> = ({
|
|||||||
key={scene.id}
|
key={scene.id}
|
||||||
scene={scene}
|
scene={scene}
|
||||||
zoomIndex={zoomIndex}
|
zoomIndex={zoomIndex}
|
||||||
|
selecting={selectedIds.size > 0}
|
||||||
selected={selectedIds.has(scene.id)}
|
selected={selectedIds.has(scene.id)}
|
||||||
onSelectedChanged={(selected: boolean, shiftKey: boolean) =>
|
onSelectedChanged={(selected: boolean, shiftKey: boolean) =>
|
||||||
listData.onSelectChange(scene.id, selected, shiftKey)
|
listData.onSelectChange(scene.id, selected, shiftKey)
|
||||||
|
|||||||
@@ -24,17 +24,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scene-card-check {
|
|
||||||
left: 0.5rem;
|
|
||||||
margin-top: -12px;
|
|
||||||
opacity: 0.5;
|
|
||||||
padding-left: 15px;
|
|
||||||
position: absolute;
|
|
||||||
top: 0.7rem;
|
|
||||||
width: 1.2rem;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.performer-tag-container,
|
.performer-tag-container,
|
||||||
.movie-tag-container {
|
.movie-tag-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -189,6 +178,21 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scene-card-check {
|
||||||
|
left: 0.5rem;
|
||||||
|
margin-top: -12px;
|
||||||
|
opacity: 0;
|
||||||
|
padding-left: 15px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0.7rem;
|
||||||
|
width: 1.2rem;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.scene-specs-overlay,
|
.scene-specs-overlay,
|
||||||
.rating-banner,
|
.rating-banner,
|
||||||
.scene-studio-overlay {
|
.scene-studio-overlay {
|
||||||
@@ -207,6 +211,11 @@
|
|||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
transition: opacity 0.5s;
|
transition: opacity 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scene-card-check {
|
||||||
|
opacity: 0.75;
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user