mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
Add shortcuts for decimal rating (#3226)
* Add shortcuts for decimal rating * Add shortcut to reset decimal rating * Generalise rating keybind code Use r x x for decimal ratings. * Update manual page --------- Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
@@ -36,6 +36,8 @@ import { RatingSystem } from "src/components/Shared/Rating/RatingSystem";
|
|||||||
import { GalleryScrapeDialog } from "./GalleryScrapeDialog";
|
import { GalleryScrapeDialog } from "./GalleryScrapeDialog";
|
||||||
import { faSyncAlt } from "@fortawesome/free-solid-svg-icons";
|
import { faSyncAlt } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { galleryTitle } from "src/core/galleries";
|
import { galleryTitle } from "src/core/galleries";
|
||||||
|
import { useRatingKeybinds } from "src/hooks/keybinds";
|
||||||
|
import { ConfigurationContext } from "src/hooks/Config";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
@@ -65,6 +67,8 @@ export const GalleryEditPanel: React.FC<
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { configuration: stashConfig } = React.useContext(ConfigurationContext);
|
||||||
|
|
||||||
const Scrapers = useListGalleryScrapers();
|
const Scrapers = useListGalleryScrapers();
|
||||||
const [queryableScrapers, setQueryableScrapers] = useState<GQL.Scraper[]>([]);
|
const [queryableScrapers, setQueryableScrapers] = useState<GQL.Scraper[]>([]);
|
||||||
|
|
||||||
@@ -133,6 +137,12 @@ export const GalleryEditPanel: React.FC<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useRatingKeybinds(
|
||||||
|
isVisible,
|
||||||
|
stashConfig?.ui.ratingSystemOptions.type,
|
||||||
|
setRating
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
Mousetrap.bind("s s", () => {
|
Mousetrap.bind("s s", () => {
|
||||||
@@ -142,35 +152,9 @@ export const GalleryEditPanel: React.FC<
|
|||||||
onDelete();
|
onDelete();
|
||||||
});
|
});
|
||||||
|
|
||||||
// numeric keypresses get caught by jwplayer, so blur the element
|
|
||||||
// if the rating sequence is started
|
|
||||||
Mousetrap.bind("r", () => {
|
|
||||||
if (document.activeElement instanceof HTMLElement) {
|
|
||||||
document.activeElement.blur();
|
|
||||||
}
|
|
||||||
|
|
||||||
Mousetrap.bind("0", () => setRating(NaN));
|
|
||||||
Mousetrap.bind("1", () => setRating(20));
|
|
||||||
Mousetrap.bind("2", () => setRating(40));
|
|
||||||
Mousetrap.bind("3", () => setRating(60));
|
|
||||||
Mousetrap.bind("4", () => setRating(80));
|
|
||||||
Mousetrap.bind("5", () => setRating(100));
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
Mousetrap.unbind("0");
|
|
||||||
Mousetrap.unbind("1");
|
|
||||||
Mousetrap.unbind("2");
|
|
||||||
Mousetrap.unbind("3");
|
|
||||||
Mousetrap.unbind("4");
|
|
||||||
Mousetrap.unbind("5");
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
Mousetrap.unbind("s s");
|
Mousetrap.unbind("s s");
|
||||||
Mousetrap.unbind("d d");
|
Mousetrap.unbind("d d");
|
||||||
|
|
||||||
Mousetrap.unbind("r");
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import { FormUtils } from "src/utils";
|
|||||||
import { useFormik } from "formik";
|
import { useFormik } from "formik";
|
||||||
import { Prompt } from "react-router-dom";
|
import { Prompt } from "react-router-dom";
|
||||||
import { RatingSystem } from "src/components/Shared/Rating/RatingSystem";
|
import { RatingSystem } from "src/components/Shared/Rating/RatingSystem";
|
||||||
|
import { useRatingKeybinds } from "src/hooks/keybinds";
|
||||||
|
import { ConfigurationContext } from "src/hooks/Config";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
image: GQL.ImageDataFragment;
|
image: GQL.ImageDataFragment;
|
||||||
@@ -35,6 +37,8 @@ export const ImageEditPanel: React.FC<IProps> = ({
|
|||||||
// Network state
|
// Network state
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
const { configuration } = React.useContext(ConfigurationContext);
|
||||||
|
|
||||||
const [updateImage] = useImageUpdate();
|
const [updateImage] = useImageUpdate();
|
||||||
|
|
||||||
const schema = yup.object({
|
const schema = yup.object({
|
||||||
@@ -69,6 +73,12 @@ export const ImageEditPanel: React.FC<IProps> = ({
|
|||||||
formik.setFieldValue("rating100", v);
|
formik.setFieldValue("rating100", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useRatingKeybinds(
|
||||||
|
true,
|
||||||
|
configuration?.ui.ratingSystemOptions.type,
|
||||||
|
setRating
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
Mousetrap.bind("s s", () => {
|
Mousetrap.bind("s s", () => {
|
||||||
@@ -78,35 +88,9 @@ export const ImageEditPanel: React.FC<IProps> = ({
|
|||||||
onDelete();
|
onDelete();
|
||||||
});
|
});
|
||||||
|
|
||||||
// numeric keypresses get caught by jwplayer, so blur the element
|
|
||||||
// if the rating sequence is started
|
|
||||||
Mousetrap.bind("r", () => {
|
|
||||||
if (document.activeElement instanceof HTMLElement) {
|
|
||||||
document.activeElement.blur();
|
|
||||||
}
|
|
||||||
|
|
||||||
Mousetrap.bind("0", () => setRating(NaN));
|
|
||||||
Mousetrap.bind("1", () => setRating(20));
|
|
||||||
Mousetrap.bind("2", () => setRating(40));
|
|
||||||
Mousetrap.bind("3", () => setRating(60));
|
|
||||||
Mousetrap.bind("4", () => setRating(80));
|
|
||||||
Mousetrap.bind("5", () => setRating(100));
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
Mousetrap.unbind("0");
|
|
||||||
Mousetrap.unbind("1");
|
|
||||||
Mousetrap.unbind("2");
|
|
||||||
Mousetrap.unbind("3");
|
|
||||||
Mousetrap.unbind("4");
|
|
||||||
Mousetrap.unbind("5");
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
Mousetrap.unbind("s s");
|
Mousetrap.unbind("s s");
|
||||||
Mousetrap.unbind("d d");
|
Mousetrap.unbind("d d");
|
||||||
|
|
||||||
Mousetrap.unbind("r");
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import { RatingSystem } from "src/components/Shared/Rating/RatingSystem";
|
|||||||
import { useFormik } from "formik";
|
import { useFormik } from "formik";
|
||||||
import { Prompt } from "react-router-dom";
|
import { Prompt } from "react-router-dom";
|
||||||
import { MovieScrapeDialog } from "./MovieScrapeDialog";
|
import { MovieScrapeDialog } from "./MovieScrapeDialog";
|
||||||
|
import { useRatingKeybinds } from "src/hooks/keybinds";
|
||||||
|
import { ConfigurationContext } from "src/hooks/Config";
|
||||||
|
|
||||||
interface IMovieEditPanel {
|
interface IMovieEditPanel {
|
||||||
movie?: Partial<GQL.MovieDataFragment>;
|
movie?: Partial<GQL.MovieDataFragment>;
|
||||||
@@ -45,6 +47,7 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const Toast = useToast();
|
const Toast = useToast();
|
||||||
|
const { configuration: stashConfig } = React.useContext(ConfigurationContext);
|
||||||
|
|
||||||
const isNew = movie === undefined;
|
const isNew = movie === undefined;
|
||||||
|
|
||||||
@@ -119,14 +122,10 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
|
|||||||
formik.setFieldValue("rating100", v);
|
formik.setFieldValue("rating100", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useRatingKeybinds(true, stashConfig?.ui.ratingSystemOptions.type, setRating);
|
||||||
|
|
||||||
// set up hotkeys
|
// set up hotkeys
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Mousetrap.bind("r 0", () => setRating(NaN));
|
|
||||||
Mousetrap.bind("r 1", () => setRating(20));
|
|
||||||
Mousetrap.bind("r 2", () => setRating(40));
|
|
||||||
Mousetrap.bind("r 3", () => setRating(60));
|
|
||||||
Mousetrap.bind("r 4", () => setRating(80));
|
|
||||||
Mousetrap.bind("r 5", () => setRating(100));
|
|
||||||
// Mousetrap.bind("u", (e) => {
|
// Mousetrap.bind("u", (e) => {
|
||||||
// setStudioFocus()
|
// setStudioFocus()
|
||||||
// e.preventDefault();
|
// e.preventDefault();
|
||||||
@@ -134,12 +133,6 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
|
|||||||
Mousetrap.bind("s s", () => formik.handleSubmit());
|
Mousetrap.bind("s s", () => formik.handleSubmit());
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
Mousetrap.unbind("r 0");
|
|
||||||
Mousetrap.unbind("r 1");
|
|
||||||
Mousetrap.unbind("r 2");
|
|
||||||
Mousetrap.unbind("r 3");
|
|
||||||
Mousetrap.unbind("r 4");
|
|
||||||
Mousetrap.unbind("r 5");
|
|
||||||
// Mousetrap.unbind("u");
|
// Mousetrap.unbind("u");
|
||||||
Mousetrap.unbind("s s");
|
Mousetrap.unbind("s s");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import {
|
|||||||
faLink,
|
faLink,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { IUIConfig } from "src/core/config";
|
import { IUIConfig } from "src/core/config";
|
||||||
|
import { useRatingKeybinds } from "src/hooks/keybinds";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
performer: GQL.PerformerDataFragment;
|
performer: GQL.PerformerDataFragment;
|
||||||
@@ -110,6 +111,12 @@ const PerformerPage: React.FC<IProps> = ({ performer }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useRatingKeybinds(
|
||||||
|
true,
|
||||||
|
configuration?.ui.ratingSystemOptions.type,
|
||||||
|
setRating
|
||||||
|
);
|
||||||
|
|
||||||
// set up hotkeys
|
// set up hotkeys
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Mousetrap.bind("a", () => setActiveTabKey("details"));
|
Mousetrap.bind("a", () => setActiveTabKey("details"));
|
||||||
@@ -119,30 +126,6 @@ const PerformerPage: React.FC<IProps> = ({ performer }) => {
|
|||||||
Mousetrap.bind("m", () => setActiveTabKey("movies"));
|
Mousetrap.bind("m", () => setActiveTabKey("movies"));
|
||||||
Mousetrap.bind("f", () => setFavorite(!performer.favorite));
|
Mousetrap.bind("f", () => setFavorite(!performer.favorite));
|
||||||
|
|
||||||
// numeric keypresses get caught by jwplayer, so blur the element
|
|
||||||
// if the rating sequence is started
|
|
||||||
Mousetrap.bind("r", () => {
|
|
||||||
if (document.activeElement instanceof HTMLElement) {
|
|
||||||
document.activeElement.blur();
|
|
||||||
}
|
|
||||||
|
|
||||||
Mousetrap.bind("0", () => setRating(NaN));
|
|
||||||
Mousetrap.bind("1", () => setRating(20));
|
|
||||||
Mousetrap.bind("2", () => setRating(40));
|
|
||||||
Mousetrap.bind("3", () => setRating(60));
|
|
||||||
Mousetrap.bind("4", () => setRating(80));
|
|
||||||
Mousetrap.bind("5", () => setRating(100));
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
Mousetrap.unbind("0");
|
|
||||||
Mousetrap.unbind("1");
|
|
||||||
Mousetrap.unbind("2");
|
|
||||||
Mousetrap.unbind("3");
|
|
||||||
Mousetrap.unbind("4");
|
|
||||||
Mousetrap.unbind("5");
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
Mousetrap.unbind("a");
|
Mousetrap.unbind("a");
|
||||||
Mousetrap.unbind("e");
|
Mousetrap.unbind("e");
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import {
|
|||||||
faTrashAlt,
|
faTrashAlt,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { objectTitle } from "src/core/files";
|
import { objectTitle } from "src/core/files";
|
||||||
|
import { useRatingKeybinds } from "src/hooks/keybinds";
|
||||||
|
|
||||||
const SceneScrapeDialog = lazy(() => import("./SceneScrapeDialog"));
|
const SceneScrapeDialog = lazy(() => import("./SceneScrapeDialog"));
|
||||||
const SceneQueryModal = lazy(() => import("./SceneQueryModal"));
|
const SceneQueryModal = lazy(() => import("./SceneQueryModal"));
|
||||||
@@ -187,6 +188,12 @@ export const SceneEditPanel: React.FC<IProps> = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useRatingKeybinds(
|
||||||
|
isVisible,
|
||||||
|
stashConfig?.ui.ratingSystemOptions.type,
|
||||||
|
setRating
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
Mousetrap.bind("s s", () => {
|
Mousetrap.bind("s s", () => {
|
||||||
@@ -198,35 +205,9 @@ export const SceneEditPanel: React.FC<IProps> = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// numeric keypresses get caught by jwplayer, so blur the element
|
|
||||||
// if the rating sequence is started
|
|
||||||
Mousetrap.bind("r", () => {
|
|
||||||
if (document.activeElement instanceof HTMLElement) {
|
|
||||||
document.activeElement.blur();
|
|
||||||
}
|
|
||||||
|
|
||||||
Mousetrap.bind("0", () => setRating(NaN));
|
|
||||||
Mousetrap.bind("1", () => setRating(20));
|
|
||||||
Mousetrap.bind("2", () => setRating(40));
|
|
||||||
Mousetrap.bind("3", () => setRating(60));
|
|
||||||
Mousetrap.bind("4", () => setRating(80));
|
|
||||||
Mousetrap.bind("5", () => setRating(100));
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
Mousetrap.unbind("0");
|
|
||||||
Mousetrap.unbind("1");
|
|
||||||
Mousetrap.unbind("2");
|
|
||||||
Mousetrap.unbind("3");
|
|
||||||
Mousetrap.unbind("4");
|
|
||||||
Mousetrap.unbind("5");
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
Mousetrap.unbind("s s");
|
Mousetrap.unbind("s s");
|
||||||
Mousetrap.unbind("d d");
|
Mousetrap.unbind("d d");
|
||||||
|
|
||||||
Mousetrap.unbind("r");
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { useFormik } from "formik";
|
|||||||
import { Prompt } from "react-router-dom";
|
import { Prompt } from "react-router-dom";
|
||||||
import { StringListInput } from "../../Shared/StringListInput";
|
import { StringListInput } from "../../Shared/StringListInput";
|
||||||
import { faTrashAlt } from "@fortawesome/free-solid-svg-icons";
|
import { faTrashAlt } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { useRatingKeybinds } from "src/hooks/keybinds";
|
||||||
|
import { ConfigurationContext } from "src/hooks/Config";
|
||||||
|
|
||||||
interface IStudioEditPanel {
|
interface IStudioEditPanel {
|
||||||
studio: Partial<GQL.StudioDataFragment>;
|
studio: Partial<GQL.StudioDataFragment>;
|
||||||
@@ -33,6 +35,8 @@ export const StudioEditPanel: React.FC<IStudioEditPanel> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const { configuration } = React.useContext(ConfigurationContext);
|
||||||
|
|
||||||
const isNew = !studio || !studio.id;
|
const isNew = !studio || !studio.id;
|
||||||
|
|
||||||
const imageEncoding = ImageUtils.usePasteImage(onImageLoad, true);
|
const imageEncoding = ImageUtils.usePasteImage(onImageLoad, true);
|
||||||
@@ -99,38 +103,18 @@ export const StudioEditPanel: React.FC<IStudioEditPanel> = ({
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useRatingKeybinds(
|
||||||
|
true,
|
||||||
|
configuration?.ui.ratingSystemOptions.type,
|
||||||
|
setRating
|
||||||
|
);
|
||||||
|
|
||||||
// set up hotkeys
|
// set up hotkeys
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Mousetrap.bind("s s", () => formik.handleSubmit());
|
Mousetrap.bind("s s", () => formik.handleSubmit());
|
||||||
|
|
||||||
// numeric keypresses get caught by jwplayer, so blur the element
|
|
||||||
// if the rating sequence is started
|
|
||||||
Mousetrap.bind("r", () => {
|
|
||||||
if (document.activeElement instanceof HTMLElement) {
|
|
||||||
document.activeElement.blur();
|
|
||||||
}
|
|
||||||
|
|
||||||
Mousetrap.bind("0", () => setRating(NaN));
|
|
||||||
Mousetrap.bind("1", () => setRating(20));
|
|
||||||
Mousetrap.bind("2", () => setRating(40));
|
|
||||||
Mousetrap.bind("3", () => setRating(60));
|
|
||||||
Mousetrap.bind("4", () => setRating(80));
|
|
||||||
Mousetrap.bind("5", () => setRating(100));
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
Mousetrap.unbind("0");
|
|
||||||
Mousetrap.unbind("1");
|
|
||||||
Mousetrap.unbind("2");
|
|
||||||
Mousetrap.unbind("3");
|
|
||||||
Mousetrap.unbind("4");
|
|
||||||
Mousetrap.unbind("5");
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
Mousetrap.unbind("s s");
|
Mousetrap.unbind("s s");
|
||||||
|
|
||||||
Mousetrap.unbind("e");
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
* Added Anonymise task to generate an anonymised version of the database. ([#3186](https://github.com/stashapp/stash/pull/3186))
|
* Added Anonymise task to generate an anonymised version of the database. ([#3186](https://github.com/stashapp/stash/pull/3186))
|
||||||
|
|
||||||
### 🎨 Improvements
|
### 🎨 Improvements
|
||||||
|
* Added `r x x` keyboard shortcuts to set decimal ratings. ([#3226](https://github.com/stashapp/stash/pull/3226))
|
||||||
* Changed performer aliases to be a list, rather than a string field. ([#3113](https://github.com/stashapp/stash/pull/3113))
|
* Changed performer aliases to be a list, rather than a string field. ([#3113](https://github.com/stashapp/stash/pull/3113))
|
||||||
|
|
||||||
### 🐛 Bug fixes
|
### 🐛 Bug fixes
|
||||||
|
|||||||
@@ -84,8 +84,10 @@
|
|||||||
|
|
||||||
| Keyboard sequence | Action |
|
| Keyboard sequence | Action |
|
||||||
|-------------------|--------|
|
|-------------------|--------|
|
||||||
| `r {1-5}` | Set rating |
|
| `r {1-5}` | Set rating (stars) |
|
||||||
| `r 0` | Unset rating |
|
| `r 0` | Unset rating (stars) |
|
||||||
|
| `r {0-9} {0-9}` | Set rating (decimal - `00` for `10.0`) |
|
||||||
|
| ``r ` `` | Unset rating (decimal) |
|
||||||
| `s s` | Save Scene |
|
| `s s` | Save Scene |
|
||||||
| `d d` | Delete Scene |
|
| `d d` | Delete Scene |
|
||||||
| `Ctrl + v` | Paste Scene cover |
|
| `Ctrl + v` | Paste Scene cover |
|
||||||
@@ -110,8 +112,10 @@
|
|||||||
| `e` | Edit Movie |
|
| `e` | Edit Movie |
|
||||||
| `s s` | Save Movie |
|
| `s s` | Save Movie |
|
||||||
| `d d` | Delete Movie |
|
| `d d` | Delete Movie |
|
||||||
| `r {1-5}` | Set rating (in edit mode) |
|
| `r {1-5}` | [Edit mode] Set rating (stars) |
|
||||||
| `r 0` | Unset rating (in edit mode) |
|
| `r 0` | [Edit mode] Unset rating (stars) |
|
||||||
|
| `r {0-9} {0-9}` | [Edit mode] Set rating (decimal - `r 0 0` for `10.0`) |
|
||||||
|
| ``r ` `` | [Edit mode] Unset rating (decimal) |
|
||||||
| `Ctrl + v` | Paste Movie image |
|
| `Ctrl + v` | Paste Movie image |
|
||||||
|
|
||||||
[//]: # "Commented until implementation is dealt with"
|
[//]: # "Commented until implementation is dealt with"
|
||||||
|
|||||||
85
ui/v2.5/src/hooks/keybinds.ts
Normal file
85
ui/v2.5/src/hooks/keybinds.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import Mousetrap from "mousetrap";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
import { RatingSystemType } from "src/utils/rating";
|
||||||
|
|
||||||
|
export function useRatingKeybinds(
|
||||||
|
isVisible: boolean,
|
||||||
|
ratingSystem: RatingSystemType,
|
||||||
|
setRating: (v: number) => void
|
||||||
|
) {
|
||||||
|
const firstChar = useRef<string | undefined>(undefined);
|
||||||
|
|
||||||
|
const starRatingShortcuts: { [char: string]: number } = {
|
||||||
|
"0": NaN,
|
||||||
|
"1": 20,
|
||||||
|
"2": 40,
|
||||||
|
"3": 60,
|
||||||
|
"4": 80,
|
||||||
|
"5": 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleStarRatingKeybinds() {
|
||||||
|
for (const key in starRatingShortcuts) {
|
||||||
|
Mousetrap.bind(key, () => setRating(starRatingShortcuts[key]));
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
for (const key in starRatingShortcuts) {
|
||||||
|
Mousetrap.unbind(key);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDecimalKeybinds() {
|
||||||
|
Mousetrap.bind("`", () => {
|
||||||
|
setRating(NaN);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i = 0; i <= 9; ++i) {
|
||||||
|
Mousetrap.bind(i.toString(), () => {
|
||||||
|
if (firstChar.current !== undefined) {
|
||||||
|
let combined = parseInt(firstChar.current + i.toString());
|
||||||
|
if (combined === 0) {
|
||||||
|
combined = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRating(combined);
|
||||||
|
firstChar.current = undefined;
|
||||||
|
} else {
|
||||||
|
firstChar.current = i.toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
firstChar.current = undefined;
|
||||||
|
|
||||||
|
Mousetrap.unbind("`");
|
||||||
|
for (let i = 0; i <= 9; ++i) {
|
||||||
|
Mousetrap.unbind(i.toString());
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isVisible) return;
|
||||||
|
|
||||||
|
Mousetrap.bind("r", () => {
|
||||||
|
// numeric keypresses get caught by jwplayer, so blur the element
|
||||||
|
// if the rating sequence is started
|
||||||
|
if (document.activeElement instanceof HTMLElement) {
|
||||||
|
document.activeElement.blur();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ratingSystem === RatingSystemType.Stars) {
|
||||||
|
return handleStarRatingKeybinds();
|
||||||
|
} else {
|
||||||
|
return handleDecimalKeybinds();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
Mousetrap.unbind("r");
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user