mirror of
https://github.com/movie-web/movie-web.git
synced 2024-11-14 08:25:07 +01:00
suggested changes
This commit is contained in:
parent
c472e7f7b8
commit
b9b0380dfe
29
src/components/CaptionColorSelector.tsx
Normal file
29
src/components/CaptionColorSelector.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import { useSettings } from "@/state/settings";
|
||||
import { Icon, Icons } from "./Icon";
|
||||
|
||||
export const colors = ["#ffffff", "#00ffff", "#ffff00"];
|
||||
export default function CaptionColorSelector({ color }: { color: string }) {
|
||||
const { captionSettings, setCaptionColor } = useSettings();
|
||||
return (
|
||||
<div
|
||||
className={`flex h-8 w-8 items-center justify-center rounded transition-[background-color,transform] duration-100 hover:bg-[#1c161b79] active:scale-110 ${
|
||||
color === captionSettings.style.color ? "bg-[#1C161B]" : ""
|
||||
}`}
|
||||
onClick={() => setCaptionColor(color)}
|
||||
>
|
||||
<div
|
||||
className="h-4 w-4 cursor-pointer appearance-none rounded-full"
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
}}
|
||||
/>
|
||||
<Icon
|
||||
className={[
|
||||
"absolute text-xs text-[#1C161B]",
|
||||
color === captionSettings.style.color ? "" : "hidden",
|
||||
].join(" ")}
|
||||
icon={Icons.CHECKMARK}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -40,7 +40,7 @@ export function ModalCard(props: { className?: string; children?: ReactNode }) {
|
||||
<div
|
||||
className={[
|
||||
"relative mx-2 w-[500px] overflow-hidden rounded-lg bg-denim-200 px-10 py-10 sm:w-[500px] md:w-[500px] lg:w-[1000px]",
|
||||
props.className,
|
||||
props.className ?? "",
|
||||
].join(" ")}
|
||||
>
|
||||
{props.children}
|
||||
|
@ -184,7 +184,7 @@ export type LangCode =
|
||||
| "za"
|
||||
| "zh"
|
||||
| "zu";
|
||||
type CaptionLanguageOptions = {
|
||||
export type CaptionLanguageOption = {
|
||||
id: LangCode;
|
||||
name: string;
|
||||
englishName: string;
|
||||
@ -212,7 +212,7 @@ type CaptionLanguageOptions = {
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
export const captionLanguages: CaptionLanguageOptions[] = [
|
||||
export const captionLanguages: CaptionLanguageOption[] = [
|
||||
{
|
||||
id: "none",
|
||||
englishName: "None",
|
||||
|
@ -22,14 +22,10 @@ export function CaptionCue({ text, scale }: { text?: string; scale?: number }) {
|
||||
|
||||
return (
|
||||
<p
|
||||
className={[
|
||||
"pointer-events-none mb-1 select-none rounded px-4 py-1 text-center [text-shadow:0_2px_4px_rgba(0,0,0,0.5)]",
|
||||
].join(" ")}
|
||||
className="pointer-events-none mb-1 select-none rounded px-4 py-1 text-center [text-shadow:0_2px_4px_rgba(0,0,0,0.5)]"
|
||||
style={{
|
||||
...captionSettings.style,
|
||||
fontSize: !scale
|
||||
? captionSettings.style.fontSize
|
||||
: captionSettings.style.fontSize * scale,
|
||||
fontSize: captionSettings.style.fontSize * (scale ?? 1),
|
||||
}}
|
||||
>
|
||||
<span
|
||||
|
@ -4,8 +4,10 @@ import { useFloatingRouter } from "@/hooks/useFloatingRouter";
|
||||
import { useSettings } from "@/state/settings";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { Slider } from "@/components/Slider";
|
||||
import CaptionColorSelector, {
|
||||
colors,
|
||||
} from "@/components/CaptionColorSelector";
|
||||
|
||||
export function CaptionSettingsPopout(props: {
|
||||
router: ReturnType<typeof useFloatingRouter>;
|
||||
@ -16,11 +18,9 @@ export function CaptionSettingsPopout(props: {
|
||||
const {
|
||||
captionSettings,
|
||||
setCaptionBackgroundColor,
|
||||
setCaptionColor,
|
||||
setCaptionDelay,
|
||||
setCaptionFontSize,
|
||||
} = useSettings();
|
||||
const colors = ["#ffffff", "#00ffff", "#ffff00"];
|
||||
return (
|
||||
<FloatingView {...props.router.pageProps(props.prefix)} width={375}>
|
||||
<FloatingCardView.Header
|
||||
@ -39,7 +39,7 @@ export function CaptionSettingsPopout(props: {
|
||||
onChange={(e) => setCaptionDelay(e.target.valueAsNumber)}
|
||||
/>
|
||||
<Slider
|
||||
label="Size"
|
||||
label={t("videoPlayer.popouts.captionPreferences.fontSize") as string}
|
||||
min={14}
|
||||
step={1}
|
||||
max={60}
|
||||
@ -71,26 +71,7 @@ export function CaptionSettingsPopout(props: {
|
||||
</label>
|
||||
<div className="flex flex-row gap-2">
|
||||
{colors.map((color) => (
|
||||
<div
|
||||
className={`flex h-8 w-8 items-center justify-center rounded transition-[background-color,transform] duration-100 hover:bg-[#1c161b79] active:scale-110 ${
|
||||
color === captionSettings.style.color ? "bg-[#1C161B]" : ""
|
||||
}`}
|
||||
onClick={() => setCaptionColor(color)}
|
||||
>
|
||||
<div
|
||||
className="h-4 w-4 cursor-pointer appearance-none rounded-full"
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
}}
|
||||
/>
|
||||
<Icon
|
||||
className={[
|
||||
"absolute text-xs text-[#1C161B]",
|
||||
color === captionSettings.style.color ? "" : "hidden",
|
||||
].join(" ")}
|
||||
icon={Icons.CHECKMARK}
|
||||
/>
|
||||
</div>
|
||||
<CaptionColorSelector color={color} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,10 +4,18 @@ import { Modal, ModalCard } from "@/components/layout/Modal";
|
||||
import { useSettings } from "@/state/settings";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { CaptionCue } from "@/video/components/actions/CaptionRendererAction";
|
||||
import { Slider } from "@/video/components/popouts/CaptionSettingsPopout";
|
||||
import { LangCode, captionLanguages } from "@/setup/iso6391";
|
||||
import {
|
||||
CaptionLanguageOption,
|
||||
LangCode,
|
||||
captionLanguages,
|
||||
} from "@/setup/iso6391";
|
||||
import { useMemo } from "react";
|
||||
import { appLanguageOptions } from "@/setup/i18n";
|
||||
import CaptionColorSelector, {
|
||||
colors,
|
||||
} from "@/components/CaptionColorSelector";
|
||||
import { Slider } from "@/components/Slider";
|
||||
import { conf } from "@/setup/config";
|
||||
|
||||
export default function SettingsModal(props: {
|
||||
onClose: () => void;
|
||||
@ -19,16 +27,18 @@ export default function SettingsModal(props: {
|
||||
setLanguage,
|
||||
setCaptionLanguage,
|
||||
setCaptionBackgroundColor,
|
||||
setCaptionColor,
|
||||
setCaptionFontSize,
|
||||
} = useSettings();
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
const colors = ["#ffffff", "#00ffff", "#ffff00"];
|
||||
const selectedCaptionLanguage = useMemo(
|
||||
() => captionLanguages.find((l) => l.id === captionSettings.language)!,
|
||||
() => captionLanguages.find((l) => l.id === captionSettings.language),
|
||||
[captionSettings.language]
|
||||
);
|
||||
) as CaptionLanguageOption;
|
||||
const appLanguage = useMemo(
|
||||
() => appLanguageOptions.find((l) => l.id === language),
|
||||
[language]
|
||||
) as CaptionLanguageOption;
|
||||
const captionBackgroundOpacity = (
|
||||
(parseInt(captionSettings.style.backgroundColor.substring(7, 9), 16) /
|
||||
255) *
|
||||
@ -54,9 +64,7 @@ export default function SettingsModal(props: {
|
||||
{t("settings.language")}
|
||||
</label>
|
||||
<Dropdown
|
||||
selectedItem={
|
||||
appLanguageOptions.find((l) => l.id === language)!
|
||||
}
|
||||
selectedItem={appLanguage}
|
||||
setSelectedItem={(val) => {
|
||||
i18n.changeLanguage(val.id);
|
||||
setLanguage(val.id as LangCode);
|
||||
@ -78,7 +86,11 @@ export default function SettingsModal(props: {
|
||||
</div>
|
||||
<div className="flex flex-col justify-between">
|
||||
<Slider
|
||||
label="Size"
|
||||
label={
|
||||
t(
|
||||
"videoPlayer.popouts.captionPreferences.fontSize"
|
||||
) as string
|
||||
}
|
||||
min={14}
|
||||
step={1}
|
||||
max={60}
|
||||
@ -86,7 +98,11 @@ export default function SettingsModal(props: {
|
||||
onChange={(e) => setCaptionFontSize(e.target.valueAsNumber)}
|
||||
/>
|
||||
<Slider
|
||||
label={t("videoPlayer.popouts.captionPreferences.opacity")}
|
||||
label={
|
||||
t(
|
||||
"videoPlayer.popouts.captionPreferences.opacity"
|
||||
) as string
|
||||
}
|
||||
step={1}
|
||||
min={0}
|
||||
max={255}
|
||||
@ -105,30 +121,7 @@ export default function SettingsModal(props: {
|
||||
</label>
|
||||
<div className="flex flex-row gap-2">
|
||||
{colors.map((color) => (
|
||||
<div
|
||||
className={`flex h-8 w-8 items-center justify-center rounded transition-[background-color,transform] duration-100 hover:bg-[#1c161b79] active:scale-110 ${
|
||||
color === captionSettings.style.color
|
||||
? "bg-[#1C161B]"
|
||||
: ""
|
||||
}`}
|
||||
onClick={() => setCaptionColor(color)}
|
||||
>
|
||||
<div
|
||||
className="h-4 w-4 cursor-pointer appearance-none rounded-full"
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
}}
|
||||
/>
|
||||
<Icon
|
||||
className={[
|
||||
"absolute text-xs text-[#1C161B]",
|
||||
color === captionSettings.style.color
|
||||
? ""
|
||||
: "hidden",
|
||||
].join(" ")}
|
||||
icon={Icons.CHECKMARK}
|
||||
/>
|
||||
</div>
|
||||
<CaptionColorSelector color={color} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@ -149,6 +142,7 @@ export default function SettingsModal(props: {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-right mt-1 text-sm">v{conf().APP_VERSION}</div>
|
||||
</ModalCard>
|
||||
</Modal>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user