diff --git a/src/components/launch/popovers/MorePopover.tsx b/src/components/launch/popovers/MorePopover.tsx index 9a5a52905..a7675841c 100644 --- a/src/components/launch/popovers/MorePopover.tsx +++ b/src/components/launch/popovers/MorePopover.tsx @@ -14,25 +14,13 @@ import { useI18n } from "@/contexts/I18nContext"; import { useScopedT } from "@/contexts/I18nContext"; import { useTheme } from "@/contexts/ThemeContext"; import type { AppLocale } from "@/i18n/config"; -import { SUPPORTED_LOCALES } from "@/i18n/config"; +import { APP_LANGUAGE_LABELS, SUPPORTED_LOCALES } from "@/i18n/config"; import styles from "../LaunchWindow.module.css"; import { useLaunchPopoverCoordinator } from "./LaunchPopoverCoordinator"; import { DropdownItem, HudPopover } from "./PopoverScaffold"; const POPOVER_ID = "more"; -const LOCALE_LABELS: Record = { - en: "English", - es: "Español", - fr: "Français", - it: "Italiano", - nl: "Nederlands", - ko: "한국어", - "pt-BR": "Português", - "zh-CN": "簡體中文", - "zh-TW": "繁體中文", -}; - export function MorePopover({ trigger, supportsHudCaptureProtection, @@ -170,7 +158,7 @@ export function MorePopover({ requestClose(POPOVER_ID); }} > - {LOCALE_LABELS[code] ?? code} + {APP_LANGUAGE_LABELS[code] ?? code} ))} {appVersion && ( diff --git a/src/components/video-editor/SettingsPanel.tsx b/src/components/video-editor/SettingsPanel.tsx deleted file mode 100644 index cff898a53..000000000 --- a/src/components/video-editor/SettingsPanel.tsx +++ /dev/null @@ -1,3777 +0,0 @@ -import { - CursorClick, - Palette, - PresentationChart, - Trash as Trash2, - UploadSimple as Upload, - X, -} from "@phosphor-icons/react"; -import { AnimatePresence, LayoutGroup, motion } from "motion/react"; -import { useEffect, useMemo, useRef, useState } from "react"; -import { toast } from "sonner"; -import { Button } from "@/components/ui/button"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; -import { Switch } from "@/components/ui/switch"; -import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; -import { useTheme } from "@/contexts/ThemeContext"; -import { - getAssetPath, - getRenderableAssetUrl, - getRenderableVideoUrl, - getWallpaperThumbnailUrl, -} from "@/lib/assetPath"; -import { - TEMPORAL_MOTION_BLUR_DEFAULT_SAMPLE_COUNT, - TEMPORAL_MOTION_BLUR_DEFAULT_SHUTTER_FRACTION, -} from "@/lib/exporter/temporalMotionBlur"; -import type { ExtensionSettingField } from "@/lib/extensions"; -import { extensionHost, type FrameInstance } from "@/lib/extensions"; -import { cn } from "@/lib/utils"; -import type { BuiltInWallpaper } from "@/lib/wallpapers"; -import { - BUILT_IN_WALLPAPERS, - getAvailableWallpapers, - isVideoWallpaperSource, -} from "@/lib/wallpapers"; -import { type AspectRatio } from "@/utils/aspectRatioUtils"; -import minimalCursorUrl from "@/assets/cursors/custom/minimal-cursor.svg"; -import { useI18n, useScopedT } from "../../contexts/I18nContext"; -import type { AppLocale } from "../../i18n/config"; -import { SUPPORTED_LOCALES } from "../../i18n/config"; -import { AnnotationSettingsPanel } from "./AnnotationSettingsPanel"; -import { - CURSOR_MOTION_PRESETS, - type CursorMotionPresetId, - getMatchingCursorMotionPresetId, -} from "./cursorMotionPresets"; -import { loadEditorPreferences, saveEditorPreferences } from "./editorPreferences"; -import { SliderControl } from "./SliderControl"; -import { KeyboardShortcutsDialog } from "./TutorialHelp"; -import type { - AnnotationRegion, - AnnotationType, - AutoCaptionAnimation, - AutoCaptionSettings, - CaptionCue, - CropRegion, - CursorStyle, - EditorEffectSection, - FigureData, - Padding, - WebcamOverlaySettings, - WebcamPositionPreset, - ZoomDepth, - ZoomMode, - ZoomMotionBlurTuning, - ZoomTransitionEasing, -} from "./types"; -import { - DEFAULT_AUTO_CAPTION_SETTINGS, - DEFAULT_CROP_REGION, - DEFAULT_CURSOR_CLICK_BOUNCE, - DEFAULT_CURSOR_CLICK_BOUNCE_DURATION, - DEFAULT_CURSOR_MOTION_BLUR, - DEFAULT_CURSOR_SIZE, - DEFAULT_CURSOR_STYLE, - DEFAULT_CURSOR_SWAY, - DEFAULT_PADDING, - DEFAULT_WEBCAM_CORNER_RADIUS, - DEFAULT_WEBCAM_MARGIN, - DEFAULT_WEBCAM_POSITION_PRESET, - DEFAULT_WEBCAM_POSITION_X, - DEFAULT_WEBCAM_POSITION_Y, - DEFAULT_WEBCAM_REACT_TO_ZOOM, - DEFAULT_WEBCAM_SHADOW, - DEFAULT_WEBCAM_SIZE, - DEFAULT_ZOOM_IN_DURATION_MS, - DEFAULT_ZOOM_MOTION_BLUR_TUNING, - DEFAULT_ZOOM_OUT_DURATION_MS, -} from "./types"; -import { fromCursorSwaySliderValue, toCursorSwaySliderValue } from "./videoPlayback/cursorSway"; -import { isZeroPadding } from "./videoPlayback/layoutUtils"; -import { - cursorSetAssets, - getCursorStyleSizeMultiplier, -} from "./videoPlayback/uploadedCursorAssets"; -import { WebcamCropControl } from "./WebcamCropControl"; -import { - getWebcamPositionForPreset, - normalizeWebcamCropRegion, - resolveWebcamCorner, -} from "./webcamOverlay"; - -const tahoeCursorUrl = cursorSetAssets.tahoe.arrow.url; -const BUILTIN_CURSOR_PREVIEW_SIZE = 28; -const BUILTIN_CURSOR_PREVIEW_FRAME_SIZE = 48; - -function getStepPrecision(step: number): number { - if (!Number.isFinite(step) || step <= 0) return 0; - const [mantissa = "0", exponentPart = "0"] = step.toExponential().split("e"); - const exponent = Number.parseInt(exponentPart, 10); - const mantissaDecimals = (mantissa.split(".")[1] ?? "").replace(/0+$/, "").length; - const precision = exponent < 0 ? Math.max(0, -exponent + mantissaDecimals) : mantissaDecimals; - return Math.min(12, precision); -} - -const GRADIENTS = [ - "linear-gradient( 111.6deg, rgba(114,167,232,1) 9.4%, rgba(253,129,82,1) 43.9%, rgba(253,129,82,1) 54.8%, rgba(249,202,86,1) 86.3% )", - "linear-gradient(120deg, #d4fc79 0%, #96e6a1 100%)", - "radial-gradient( circle farthest-corner at 3.2% 49.6%, rgba(80,12,139,0.87) 0%, rgba(161,10,144,0.72) 83.6% )", - "linear-gradient( 111.6deg, rgba(0,56,68,1) 0%, rgba(163,217,185,1) 51.5%, rgba(231, 148, 6, 1) 88.6% )", - "linear-gradient( 107.7deg, rgba(235,230,44,0.55) 8.4%, rgba(252,152,15,1) 90.3% )", - "linear-gradient( 91deg, rgba(72,154,78,1) 5.2%, rgba(251,206,70,1) 95.9% )", - "radial-gradient( circle farthest-corner at 10% 20%, rgba(2,37,78,1) 0%, rgba(4,56,126,1) 19.7%, rgba(85,245,221,1) 100.2% )", - "linear-gradient( 109.6deg, rgba(15,2,2,1) 11.2%, rgba(36,163,190,1) 91.1% )", - "linear-gradient(135deg, #FBC8B4, #2447B1)", - "linear-gradient(109.6deg, #F635A6, #36D860)", - "linear-gradient(90deg, #FF0101, #4DFF01)", - "linear-gradient(315deg, #EC0101, #5044A9)", - "linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%)", - "linear-gradient(to top, #a18cd1 0%, #fbc2eb 100%)", - "linear-gradient(to right, #ff8177 0%, #ff867a 0%, #ff8c7f 21%, #f99185 52%, #cf556c 78%, #b12a5b 100%)", - "linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%)", - "linear-gradient(to right, #4facfe 0%, #00f2fe 100%)", - "linear-gradient(to top, #fcc5e4 0%, #fda34b 15%, #ff7882 35%, #c8699e 52%, #7046aa 71%, #0c1db8 87%, #020f75 100%)", - "linear-gradient(to right, #fa709a 0%, #fee140 100%)", - "linear-gradient(to top, #30cfd0 0%, #330867 100%)", - "linear-gradient(to top, #c471f5 0%, #fa71cd 100%)", - "linear-gradient(to right, #f78ca0 0%, #f9748f 19%, #fd868c 60%, #fe9a8b 100%)", - "linear-gradient(to top, #48c6ef 0%, #6f86d6 100%)", - "linear-gradient(to right, #0acffe 0%, #495aff 100%)", -]; - -const CAPTION_ANIMATION_OPTIONS: Array<{ value: AutoCaptionAnimation; label: string }> = [ - { value: "none", label: "Off" }, - { value: "fade", label: "Fade" }, - { value: "rise", label: "Rise" }, - { value: "pop", label: "Pop" }, -]; - -type BackgroundTab = "image" | "video" | "color" | "gradient"; -function isHexWallpaper(value: string): boolean { - return /^#(?:[0-9a-f]{3}){1,2}$/i.test(value); -} - -function getBackgroundTabForWallpaper(value: string): BackgroundTab { - if (GRADIENTS.includes(value)) { - return "gradient"; - } - - if (isHexWallpaper(value)) { - return "color"; - } - - if (isVideoWallpaperSource(value)) { - return "video"; - } - - return "image"; -} - -function SectionLabel({ children }: { children: React.ReactNode }) { - return ( -

- {children} -

- ); -} - -function WallpaperVideoPreview({ src }: { src: string }) { - const [resolvedSrc, setResolvedSrc] = useState(src); - - useEffect(() => { - let cancelled = false; - setResolvedSrc(src); - - void (async () => { - try { - const nextSrc = await getRenderableVideoUrl(src); - if (!cancelled) { - setResolvedSrc(nextSrc); - } - } catch { - if (!cancelled) { - setResolvedSrc(src); - } - } - })(); - - return () => { - cancelled = true; - }; - }, [src]); - - return ( -