mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-29 16:07:40 +01:00
Merge 7dba435a22
into e93887a62a
This commit is contained in:
commit
1e18d3f08e
2 changed files with 100 additions and 26 deletions
|
@ -7,7 +7,7 @@ import { Icon, Icons } from "@/components/Icon";
|
||||||
import { Menu } from "@/components/player/internals/ContextMenu";
|
import { Menu } from "@/components/player/internals/ContextMenu";
|
||||||
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
||||||
import { useProgressBar } from "@/hooks/useProgressBar";
|
import { useProgressBar } from "@/hooks/useProgressBar";
|
||||||
import { useSubtitleStore } from "@/stores/subtitles";
|
import { SubtitleStyling, useSubtitleStore } from "@/stores/subtitles";
|
||||||
|
|
||||||
export function ColorOption(props: {
|
export function ColorOption(props: {
|
||||||
color: string;
|
color: string;
|
||||||
|
@ -214,7 +214,7 @@ export function CaptionSetting(props: {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const colors = ["#ffffff", "#b0b0b0", "#80b1fa", "#e2e535"];
|
export const colors = ["#ffffff", "#80b1fa", "#e2e535", "#10B239FF"];
|
||||||
|
|
||||||
export function CaptionSettingsView({
|
export function CaptionSettingsView({
|
||||||
id,
|
id,
|
||||||
|
@ -225,12 +225,21 @@ export function CaptionSettingsView({
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const router = useOverlayRouter(id);
|
const router = useOverlayRouter(id);
|
||||||
const styling = useSubtitleStore((s) => s.styling);
|
const subtitleStore = useSubtitleStore();
|
||||||
const overrideCasing = useSubtitleStore((s) => s.overrideCasing);
|
const styling = subtitleStore.styling;
|
||||||
const delay = useSubtitleStore((s) => s.delay);
|
const overrideCasing = subtitleStore.overrideCasing;
|
||||||
const setOverrideCasing = useSubtitleStore((s) => s.setOverrideCasing);
|
const delay = subtitleStore.delay;
|
||||||
const setDelay = useSubtitleStore((s) => s.setDelay);
|
const setOverrideCasing = subtitleStore.setOverrideCasing;
|
||||||
const updateStyling = useSubtitleStore((s) => s.updateStyling);
|
const setDelay = subtitleStore.setDelay;
|
||||||
|
const updateStyling = subtitleStore.updateStyling;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
subtitleStore.updateStyling(styling);
|
||||||
|
}, [styling, subtitleStore]);
|
||||||
|
|
||||||
|
const handleStylingChange = (newStyling: SubtitleStyling) => {
|
||||||
|
updateStyling(newStyling);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -270,7 +279,9 @@ export function CaptionSettingsView({
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex justify-center items-center">
|
||||||
<Toggle
|
<Toggle
|
||||||
enabled={styling.bold}
|
enabled={styling.bold}
|
||||||
onClick={() => updateStyling({ bold: !styling.bold })}
|
onClick={() =>
|
||||||
|
handleStylingChange({ ...styling, bold: !styling.bold })
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -279,7 +290,9 @@ export function CaptionSettingsView({
|
||||||
label={t("settings.subtitles.backgroundLabel")}
|
label={t("settings.subtitles.backgroundLabel")}
|
||||||
max={100}
|
max={100}
|
||||||
min={0}
|
min={0}
|
||||||
onChange={(v) => updateStyling({ backgroundOpacity: v / 100 })}
|
onChange={(v) =>
|
||||||
|
handleStylingChange({ ...styling, backgroundOpacity: v / 100 })
|
||||||
|
}
|
||||||
value={styling.backgroundOpacity * 100}
|
value={styling.backgroundOpacity * 100}
|
||||||
textTransformer={(s) => `${s}%`}
|
textTransformer={(s) => `${s}%`}
|
||||||
/>
|
/>
|
||||||
|
@ -287,7 +300,9 @@ export function CaptionSettingsView({
|
||||||
label={t("settings.subtitles.backgroundBlurLabel")}
|
label={t("settings.subtitles.backgroundBlurLabel")}
|
||||||
max={100}
|
max={100}
|
||||||
min={0}
|
min={0}
|
||||||
onChange={(v) => updateStyling({ backgroundBlur: v / 100 })}
|
onChange={(v) =>
|
||||||
|
handleStylingChange({ ...styling, backgroundBlur: v / 100 })
|
||||||
|
}
|
||||||
value={styling.backgroundBlur * 100}
|
value={styling.backgroundBlur * 100}
|
||||||
textTransformer={(s) => `${s}%`}
|
textTransformer={(s) => `${s}%`}
|
||||||
/>
|
/>
|
||||||
|
@ -296,22 +311,38 @@ export function CaptionSettingsView({
|
||||||
max={200}
|
max={200}
|
||||||
min={1}
|
min={1}
|
||||||
textTransformer={(s) => `${s}%`}
|
textTransformer={(s) => `${s}%`}
|
||||||
onChange={(v) => updateStyling({ size: v / 100 })}
|
onChange={(v) => handleStylingChange({ ...styling, size: v / 100 })}
|
||||||
value={styling.size * 100}
|
value={styling.size * 100}
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<Menu.FieldTitle>
|
<Menu.FieldTitle>
|
||||||
{t("settings.subtitles.colorLabel")}
|
{t("settings.subtitles.colorLabel")}
|
||||||
</Menu.FieldTitle>
|
</Menu.FieldTitle>
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex justify-center items-center space-x-2">
|
||||||
{colors.map((v) => (
|
{colors.map((color) => (
|
||||||
<ColorOption
|
<ColorOption
|
||||||
onClick={() => updateStyling({ color: v })}
|
key={color}
|
||||||
color={v}
|
color={color}
|
||||||
active={styling.color === v}
|
active={styling.color === color}
|
||||||
key={v}
|
onClick={() => handleStylingChange({ ...styling, color })}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
{/* Add Color Picker */}
|
||||||
|
<div className="relative inline-block">
|
||||||
|
<input
|
||||||
|
type="color"
|
||||||
|
value={styling.color}
|
||||||
|
onChange={(e) => {
|
||||||
|
const color = e.target.value;
|
||||||
|
handleStylingChange({ ...styling, color });
|
||||||
|
}}
|
||||||
|
className="absolute opacity-0 cursor-pointer w-10 h-10"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className="w-10 h-10 border-2 border-gray-300 rounded-full"
|
||||||
|
style={{ backgroundColor: styling.color }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Menu.Section>
|
</Menu.Section>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Helmet } from "react-helmet-async";
|
import { Helmet } from "react-helmet-async";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import { Menu } from "@/components/player/internals/ContextMenu";
|
||||||
import { CaptionCue } from "@/components/player/Player";
|
import { CaptionCue } from "@/components/player/Player";
|
||||||
import { Heading1 } from "@/components/utils/Text";
|
import { Heading1 } from "@/components/utils/Text";
|
||||||
import { Transition } from "@/components/utils/Transition";
|
import { Transition } from "@/components/utils/Transition";
|
||||||
import { SubtitleStyling } from "@/stores/subtitles";
|
import { SubtitleStyling, useSubtitleStore } from "@/stores/subtitles";
|
||||||
|
|
||||||
export function CaptionPreview(props: {
|
export function CaptionPreview(props: {
|
||||||
fullscreen?: boolean;
|
fullscreen?: boolean;
|
||||||
|
@ -78,6 +78,17 @@ export function CaptionsPart(props: {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [fullscreenPreview, setFullscreenPreview] = useState(false);
|
const [fullscreenPreview, setFullscreenPreview] = useState(false);
|
||||||
|
|
||||||
|
const subtitleStore = useSubtitleStore();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
subtitleStore.updateStyling(props.styling);
|
||||||
|
}, [props.styling, subtitleStore, subtitleStore.updateStyling]);
|
||||||
|
|
||||||
|
const handleStylingChange = (newStyling: SubtitleStyling) => {
|
||||||
|
props.setStyling(newStyling);
|
||||||
|
subtitleStore.updateStyling(newStyling);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Heading1 border>{t("settings.subtitles.title")}</Heading1>
|
<Heading1 border>{t("settings.subtitles.title")}</Heading1>
|
||||||
|
@ -88,7 +99,10 @@ export function CaptionsPart(props: {
|
||||||
max={100}
|
max={100}
|
||||||
min={0}
|
min={0}
|
||||||
onChange={(v) =>
|
onChange={(v) =>
|
||||||
props.setStyling({ ...props.styling, backgroundOpacity: v / 100 })
|
handleStylingChange({
|
||||||
|
...props.styling,
|
||||||
|
backgroundOpacity: v / 100,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
value={props.styling.backgroundOpacity * 100}
|
value={props.styling.backgroundOpacity * 100}
|
||||||
textTransformer={(s) => `${s}%`}
|
textTransformer={(s) => `${s}%`}
|
||||||
|
@ -98,7 +112,10 @@ export function CaptionsPart(props: {
|
||||||
max={100}
|
max={100}
|
||||||
min={0}
|
min={0}
|
||||||
onChange={(v) =>
|
onChange={(v) =>
|
||||||
props.setStyling({ ...props.styling, backgroundBlur: v / 100 })
|
handleStylingChange({
|
||||||
|
...props.styling,
|
||||||
|
backgroundBlur: v / 100,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
value={props.styling.backgroundBlur * 1}
|
value={props.styling.backgroundBlur * 1}
|
||||||
textTransformer={(s) => `${s}%`}
|
textTransformer={(s) => `${s}%`}
|
||||||
|
@ -109,7 +126,10 @@ export function CaptionsPart(props: {
|
||||||
min={1}
|
min={1}
|
||||||
textTransformer={(s) => `${s}%`}
|
textTransformer={(s) => `${s}%`}
|
||||||
onChange={(v) =>
|
onChange={(v) =>
|
||||||
props.setStyling({ ...props.styling, size: v / 100 })
|
handleStylingChange({
|
||||||
|
...props.styling,
|
||||||
|
size: v / 100,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
value={props.styling.size * 100}
|
value={props.styling.size * 100}
|
||||||
/>
|
/>
|
||||||
|
@ -121,7 +141,7 @@ export function CaptionsPart(props: {
|
||||||
<Toggle
|
<Toggle
|
||||||
enabled={props.styling.bold}
|
enabled={props.styling.bold}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
props.setStyling({
|
handleStylingChange({
|
||||||
...props.styling,
|
...props.styling,
|
||||||
bold: !props.styling.bold,
|
bold: !props.styling.bold,
|
||||||
})
|
})
|
||||||
|
@ -133,17 +153,40 @@ export function CaptionsPart(props: {
|
||||||
<Menu.FieldTitle>
|
<Menu.FieldTitle>
|
||||||
{t("settings.subtitles.colorLabel")}
|
{t("settings.subtitles.colorLabel")}
|
||||||
</Menu.FieldTitle>
|
</Menu.FieldTitle>
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex justify-center items-center space-x-2">
|
||||||
{colors.map((v) => (
|
{colors.map((v) => (
|
||||||
<ColorOption
|
<ColorOption
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
props.setStyling({ ...props.styling, color: v })
|
handleStylingChange({
|
||||||
|
...props.styling,
|
||||||
|
color: v,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
color={v}
|
color={v}
|
||||||
active={props.styling.color === v}
|
active={props.styling.color === v}
|
||||||
key={v}
|
key={v}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
{/* Add Color Picker */}
|
||||||
|
<div className="relative">
|
||||||
|
<input
|
||||||
|
type="color"
|
||||||
|
value={props.styling.color}
|
||||||
|
onChange={(e) => {
|
||||||
|
const color = e.target.value;
|
||||||
|
handleStylingChange({ ...props.styling, color });
|
||||||
|
subtitleStore.updateStyling({
|
||||||
|
...props.styling,
|
||||||
|
color,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className="absolute opacity-0 cursor-pointer w-8 h-8"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className="w-8 h-8 border-2 border-gray-300 rounded-full"
|
||||||
|
style={{ backgroundColor: props.styling.color }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue