From 887f30e739710eb113274578ad66e36f42518d5e Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Fri, 7 Mar 2025 07:54:13 +0100 Subject: [PATCH] fix: rename auto rotate to follow device orientation --- app/_layout.tsx | 4 +- components/settings/OtherSettings.tsx | 33 +++++--- hooks/useOrientationSettings.ts | 12 +-- translations/de.json | 10 +-- translations/en.json | 8 +- translations/es.json | 10 +-- translations/fr.json | 9 +-- translations/it.json | 4 +- translations/ja.json | 4 +- translations/nl.json | 4 +- translations/tr.json | 4 +- translations/zh-CN.json | 4 +- translations/zh-TW.json | 4 +- utils/atoms/settings.ts | 104 ++++++++++---------------- 14 files changed, 98 insertions(+), 116 deletions(-) diff --git a/app/_layout.tsx b/app/_layout.tsx index e3bc69d2..8d7aed55 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -105,7 +105,7 @@ if (!Platform.isTV) { const result = response.data.filter((s) => s.NowPlayingItem); Notifications.setBadgeCountAsync(result.length); - + return BackgroundFetch.BackgroundFetchResult.NewData; }); @@ -279,7 +279,7 @@ function Layout() { useEffect(() => { // If the user has auto rotate enabled, unlock the orientation if (Platform.isTV) return; - if (settings.autoRotate === true) { + if (settings.followDeviceOrientation === true) { ScreenOrientation.unlockAsync(); } else { // If the user has auto rotate disabled, lock the orientation to portrait diff --git a/components/settings/OtherSettings.tsx b/components/settings/OtherSettings.tsx index 932ad967..896f2399 100644 --- a/components/settings/OtherSettings.tsx +++ b/components/settings/OtherSettings.tsx @@ -60,7 +60,7 @@ export const OtherSettings: React.FC = () => { const disabled = useMemo( () => - pluginSettings?.autoRotate?.locked === true && + pluginSettings?.followDeviceOrientation?.locked === true && pluginSettings?.defaultVideoOrientation?.locked === true && pluginSettings?.safeAreaInControlsEnabled?.locked === true && pluginSettings?.showCustomMenuLinks?.locked === true && @@ -76,32 +76,47 @@ export const OtherSettings: React.FC = () => { ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT, ]; + const orientationTranslations = useMemo( + () => ({ + [ScreenOrientation.OrientationLock.DEFAULT]: "home.settings.other.orientations.DEFAULT", + [ScreenOrientation.OrientationLock.PORTRAIT_UP]: "home.settings.other.orientations.PORTRAIT_UP", + [ScreenOrientation.OrientationLock.LANDSCAPE_LEFT]: "home.settings.other.orientations.LANDSCAPE_LEFT", + [ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT]: "home.settings.other.orientations.LANDSCAPE_RIGHT", + }), + [] + ); + if (!settings) return null; return ( - + updateSettings({ autoRotate: value })} + value={settings.followDeviceOrientation} + disabled={pluginSettings?.followDeviceOrientation?.locked} + onValueChange={(value) => updateSettings({ followDeviceOrientation: value })} /> ScreenOrientationEnum[item]} + titleExtractor={(item) => t(ScreenOrientationEnum[item])} title={ - {t(ScreenOrientationEnum[settings.defaultVideoOrientation])} + {t( + orientationTranslations[settings.defaultVideoOrientation as keyof typeof orientationTranslations] + ) || "Unknown Orientation"} diff --git a/hooks/useOrientationSettings.ts b/hooks/useOrientationSettings.ts index 7b657d77..b58a06ce 100644 --- a/hooks/useOrientationSettings.ts +++ b/hooks/useOrientationSettings.ts @@ -9,21 +9,17 @@ export const useOrientationSettings = () => { const [settings] = useSettings(); useEffect(() => { - if (settings?.autoRotate) { - ScreenOrientation.lockAsync( - ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT - ); + if (settings?.followDeviceOrientation) { + ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT); } else if (settings?.defaultVideoOrientation) { ScreenOrientation.lockAsync(settings.defaultVideoOrientation); } return () => { - if (settings?.autoRotate) { + if (settings?.followDeviceOrientation) { ScreenOrientation.unlockAsync(); } else { - ScreenOrientation.lockAsync( - ScreenOrientation.OrientationLock.PORTRAIT_UP - ); + ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP); } }; }, [settings]); diff --git a/translations/de.json b/translations/de.json index 19258147..ac1b2759 100644 --- a/translations/de.json +++ b/translations/de.json @@ -113,7 +113,7 @@ }, "other": { "other_title": "Sonstiges", - "auto_rotate": "Automatische Drehung", + "follow_device_orientation": "Automatische Drehung", "video_orientation": "Videoausrichtung", "orientation": "Ausrichtung", "orientations": { @@ -128,7 +128,7 @@ "OTHER": "Andere", "UNKNOWN": "Unbekannt" }, - "safe_area_in_controls": "Sicherer Bereich in den Steuerungen", + "safe_area_in_controls": "Sicherer Bereich in den Steuerungen", "video_player": "Video player", "video_players": { "VLC_3": "VLC 3", @@ -152,7 +152,7 @@ "default": "Standard", "optimized_version_hint": "Gib die URL für den optimierten Server ein. Die URL sollte http oder https enthalten und optional den Port.", "read_more_about_optimized_server": "Mehr über den optimierten Server lesen.", - "url":"URL", + "url": "URL", "server_url_placeholder": "http(s)://domain.org:port" }, "plugins": { @@ -215,7 +215,7 @@ "app_language_description": "Wähle die Sprache für die App aus.", "system": "System" }, - "toasts":{ + "toasts": { "error_deleting_files": "Fehler beim Löschen von Dateien", "background_downloads_enabled": "Hintergrunddownloads aktiviert", "background_downloads_disabled": "Hintergrunddownloads deaktiviert", @@ -412,7 +412,7 @@ "for_kids": "Für Kinder", "news": "Nachrichten" }, - "jellyseerr":{ + "jellyseerr": { "confirm": "Bestätigen", "cancel": "Abbrechen", "yes": "Ja", diff --git a/translations/en.json b/translations/en.json index e804e5cb..4c454f9a 100644 --- a/translations/en.json +++ b/translations/en.json @@ -113,7 +113,7 @@ }, "other": { "other_title": "Other", - "auto_rotate": "Auto rotate", + "follow_device_orientation": "Follow device orientation", "video_orientation": "Video orientation", "orientation": "Orientation", "orientations": { @@ -138,7 +138,7 @@ "hide_libraries": "Hide Libraries", "select_liraries_you_want_to_hide": "Select the libraries you want to hide from the Library tab and home page sections.", "disable_haptic_feedback": "Disable Haptic Feedback", - "default_quality": "Default quality", + "default_quality": "Default quality" }, "downloads": { "downloads_title": "Downloads", @@ -222,7 +222,7 @@ "connected": "Connected", "could_not_connect": "Could not connect", "invalid_url": "Invalid URL" - }, + } }, "sessions": { "title": "Sessions", @@ -472,4 +472,4 @@ "custom_links": "Custom Links", "favorites": "Favorites" } -} \ No newline at end of file +} diff --git a/translations/es.json b/translations/es.json index 463d86f2..95e30124 100644 --- a/translations/es.json +++ b/translations/es.json @@ -20,7 +20,7 @@ "server_is_taking_too_long_to_respond_try_again_later": "El servidor está tardando mucho en responder, inténtalo de nuevo más tarde.", "server_received_too_many_requests_try_again_later": "El servidor está recibiendo muchas peticiones, inténtalo de nuevo más tarde.", "there_is_a_server_error": "Hay un error en el servidor", - "an_unexpected_error_occured_did_you_enter_the_correct_url": "Ha ocurrido un error inesperado. ¿Has introducido la URL correcta?" + "an_unexpected_error_occured_did_you_enter_the_correct_url": "Ha ocurrido un error inesperado. ¿Has introducido la URL correcta?" }, "server": { "enter_url_to_jellyfin_server": "Introduce la URL de tu servidor Jellyfin", @@ -113,7 +113,7 @@ }, "other": { "other_title": "Otros", - "auto_rotate": "Rotación automática", + "follow_device_orientation": "Rotación automática", "video_orientation": "Orientación de vídeo", "orientation": "Orientación", "orientations": { @@ -128,7 +128,7 @@ "OTHER": "Otra", "UNKNOWN": "Desconocida" }, - "safe_area_in_controls": "Área segura en controles", + "safe_area_in_controls": "Área segura en controles", "video_player": "Video player", "video_players": { "VLC_3": "VLC 3", @@ -215,7 +215,7 @@ "app_language_description": "Selecciona el idioma de la app.", "system": "Sistema" }, - "toasts":{ + "toasts": { "error_deleting_files": "Error al eliminar archivos", "background_downloads_enabled": "Descargas en segundo plano habilitadas", "background_downloads_disabled": "Descargas en segundo plano deshabilitadas", @@ -412,7 +412,7 @@ "for_kids": "Para niños", "news": "Noticias" }, - "jellyseerr":{ + "jellyseerr": { "confirm": "Confirmar", "cancel": "Cancelar", "yes": "Sí", diff --git a/translations/fr.json b/translations/fr.json index 6df653ff..dbd5b5ef 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -113,7 +113,7 @@ }, "other": { "other_title": "Autres", - "auto_rotate": "Rotation automatique", + "follow_device_orientation": "Rotation automatique", "video_orientation": "Orientation vidéo", "orientation": "Orientation", "orientations": { @@ -128,7 +128,7 @@ "OTHER": "Autre", "UNKNOWN": "Inconnu" }, - "safe_area_in_controls": "Zone de sécurité dans les contrôles", + "safe_area_in_controls": "Zone de sécurité dans les contrôles", "video_player": "Video player", "video_players": { "VLC_3": "VLC 3", @@ -139,7 +139,6 @@ "select_liraries_you_want_to_hide": "Sélectionnez les bibliothèques que vous souhaitez masquer dans l’onglet Bibliothèque et les sections de la page d’accueil.", "disable_haptic_feedback": "Désactiver le retour haptique", "default_quality": "Qualité par défaut" - }, "downloads": { "downloads_title": "Téléchargements", @@ -216,7 +215,7 @@ "app_language_description": "Sélectionnez la langue de l'application", "system": "Système" }, - "toasts":{ + "toasts": { "error_deleting_files": "Erreur lors de la suppression des fichiers", "background_downloads_enabled": "Téléchargements en arrière-plan activés", "background_downloads_disabled": "Téléchargements en arrière-plan désactivés", @@ -413,7 +412,7 @@ "for_kids": "Pour enfants", "news": "Actualités" }, - "jellyseerr":{ + "jellyseerr": { "confirm": "Confirmer", "cancel": "Annuler", "yes": "Oui", diff --git a/translations/it.json b/translations/it.json index 87882704..98b6a903 100644 --- a/translations/it.json +++ b/translations/it.json @@ -113,7 +113,7 @@ }, "other": { "other_title": "Altro", - "auto_rotate": "Rotazione automatica", + "follow_device_orientation": "Rotazione automatica", "video_orientation": "Orientamento del video", "orientation": "Orientamento", "orientations": { @@ -128,7 +128,7 @@ "OTHER": "Altro", "UNKNOWN": "Sconosciuto" }, - "safe_area_in_controls": "Area sicura per i controlli", + "safe_area_in_controls": "Area sicura per i controlli", "video_player": "Video player", "video_players": { "VLC_3": "VLC 3", diff --git a/translations/ja.json b/translations/ja.json index dfdbc59d..7cf14a65 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -113,7 +113,7 @@ }, "other": { "other_title": "その他", - "auto_rotate": "画面の自動回転", + "follow_device_orientation": "画面の自動回転", "video_orientation": "動画の向き", "orientation": "向き", "orientations": { @@ -128,7 +128,7 @@ "OTHER": "その他", "UNKNOWN": "不明" }, - "safe_area_in_controls": "コントロールの安全エリア", + "safe_area_in_controls": "コントロールの安全エリア", "video_player": "Video player", "video_players": { "VLC_3": "VLC 3", diff --git a/translations/nl.json b/translations/nl.json index 1f87dfc8..54c39e34 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -113,7 +113,7 @@ }, "other": { "other_title": "Andere", - "auto_rotate": "Automatisch draaien", + "follow_device_orientation": "Automatisch draaien", "video_orientation": "Video oriëntatie", "orientation": "Oriëntatie", "orientations": { @@ -128,7 +128,7 @@ "OTHER": "Andere", "UNKNOWN": "Onbekend" }, - "safe_area_in_controls": "Veilig gebied in bedieningen", + "safe_area_in_controls": "Veilig gebied in bedieningen", "video_player": "Video player", "video_players": { "VLC_3": "VLC 3", diff --git a/translations/tr.json b/translations/tr.json index 47f6fc02..f9e0e45f 100644 --- a/translations/tr.json +++ b/translations/tr.json @@ -113,7 +113,7 @@ }, "other": { "other_title": "Diğer", - "auto_rotate": "Otomatik Döndürme", + "follow_device_orientation": "Otomatik Döndürme", "video_orientation": "Video Yönü", "orientation": "Yön", "orientations": { @@ -128,7 +128,7 @@ "OTHER": "Diğer", "UNKNOWN": "Bilinmeyen" }, - "safe_area_in_controls": "Kontrollerde Güvenli Alan", + "safe_area_in_controls": "Kontrollerde Güvenli Alan", "video_player": "Video player", "video_players": { "VLC_3": "VLC 3", diff --git a/translations/zh-CN.json b/translations/zh-CN.json index ad2d0468..aad0efd9 100644 --- a/translations/zh-CN.json +++ b/translations/zh-CN.json @@ -113,7 +113,7 @@ }, "other": { "other_title": "其他", - "auto_rotate": "自动旋转", + "follow_device_orientation": "自动旋转", "video_orientation": "视频方向", "orientation": "方向", "orientations": { @@ -128,7 +128,7 @@ "OTHER": "其他", "UNKNOWN": "未知" }, - "safe_area_in_controls": "控制中的安全区域", + "safe_area_in_controls": "控制中的安全区域", "video_player": "Video player", "video_players": { "VLC_3": "VLC 3", diff --git a/translations/zh-TW.json b/translations/zh-TW.json index d4f42fe3..cfe2f7ce 100644 --- a/translations/zh-TW.json +++ b/translations/zh-TW.json @@ -113,7 +113,7 @@ }, "other": { "other_title": "其他", - "auto_rotate": "自動旋轉", + "follow_device_orientation": "自動旋轉", "video_orientation": "影片方向", "orientation": "方向", "orientations": { @@ -128,7 +128,7 @@ "OTHER": "其他", "UNKNOWN": "未知" }, - "safe_area_in_controls": "控制中的安全區域", + "safe_area_in_controls": "控制中的安全區域", "video_player": "Video player", "video_players": { "VLC_3": "VLC 3", diff --git a/utils/atoms/settings.ts b/utils/atoms/settings.ts index a1ba7d0b..34b2f776 100644 --- a/utils/atoms/settings.ts +++ b/utils/atoms/settings.ts @@ -14,7 +14,7 @@ import { import { Bitrate, BITRATES } from "@/components/BitrateSelector"; import { apiAtom } from "@/providers/JellyfinProvider"; import { writeInfoLog } from "@/utils/log"; -import {Video} from "@/utils/jellyseerr/server/models/Movie"; +import { Video } from "@/utils/jellyseerr/server/models/Movie"; const STREAMYFIN_PLUGIN_ID = "1e9e5d386e6746158719e98a5c34f004"; const STREAMYFIN_PLUGIN_SETTINGS = "STREAMYFIN_PLUGIN_SETTINGS"; @@ -26,30 +26,17 @@ export type DownloadOption = { value: DownloadQuality; }; -export const ScreenOrientationEnum: Record< - ScreenOrientation.OrientationLock, - string -> = { - [ScreenOrientation.OrientationLock.DEFAULT]: - "home.settings.other.orientations.DEFAULT", - [ScreenOrientation.OrientationLock.ALL]: - "home.settings.other.orientations.ALL", - [ScreenOrientation.OrientationLock.PORTRAIT]: - "home.settings.other.orientations.PORTRAIT", - [ScreenOrientation.OrientationLock.PORTRAIT_UP]: - "home.settings.other.orientations.PORTRAIT_UP", - [ScreenOrientation.OrientationLock.PORTRAIT_DOWN]: - "home.settings.other.orientations.PORTRAIT_DOWN", - [ScreenOrientation.OrientationLock.LANDSCAPE]: - "home.settings.other.orientations.LANDSCAPE", - [ScreenOrientation.OrientationLock.LANDSCAPE_LEFT]: - "home.settings.other.orientations.LANDSCAPE_LEFT", - [ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT]: - "home.settings.other.orientations.LANDSCAPE_RIGHT", - [ScreenOrientation.OrientationLock.OTHER]: - "home.settings.other.orientations.OTHER", - [ScreenOrientation.OrientationLock.UNKNOWN]: - "home.settings.other.orientations.UNKNOWN", +export const ScreenOrientationEnum: Record = { + [ScreenOrientation.OrientationLock.DEFAULT]: "home.settings.other.orientations.DEFAULT", + [ScreenOrientation.OrientationLock.ALL]: "home.settings.other.orientations.ALL", + [ScreenOrientation.OrientationLock.PORTRAIT]: "home.settings.other.orientations.PORTRAIT", + [ScreenOrientation.OrientationLock.PORTRAIT_UP]: "home.settings.other.orientations.PORTRAIT_UP", + [ScreenOrientation.OrientationLock.PORTRAIT_DOWN]: "home.settings.other.orientations.PORTRAIT_DOWN", + [ScreenOrientation.OrientationLock.LANDSCAPE]: "home.settings.other.orientations.LANDSCAPE", + [ScreenOrientation.OrientationLock.LANDSCAPE_LEFT]: "home.settings.other.orientations.LANDSCAPE_LEFT", + [ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT]: "home.settings.other.orientations.LANDSCAPE_RIGHT", + [ScreenOrientation.OrientationLock.OTHER]: "home.settings.other.orientations.OTHER", + [ScreenOrientation.OrientationLock.UNKNOWN]: "home.settings.other.orientations.UNKNOWN", }; export const DownloadOptions: DownloadOption[] = [ @@ -116,12 +103,12 @@ export type HomeSectionNextUpResolver = { export enum VideoPlayer { // NATIVE, //todo: changes will make this a lot more easier to implement if we want. delete if not wanted VLC_3, - VLC_4 + VLC_4, } export type Settings = { home?: Home | null; - autoRotate?: boolean; + followDeviceOrientation?: boolean; forceLandscapeInVideoPlayer?: boolean; deviceProfile?: "Expo" | "Native" | "Old"; mediaListCollectionIds?: string[]; @@ -170,7 +157,7 @@ export type StreamyfinPluginConfig = { const defaultValues: Settings = { home: null, - autoRotate: true, + followDeviceOrientation: true, forceLandscapeInVideoPlayer: false, deviceProfile: "Expo", mediaListCollectionIds: [], @@ -214,8 +201,7 @@ const defaultValues: Settings = { const loadSettings = (): Partial => { try { const jsonValue = storage.getString("settings"); - const loadedValues: Partial = - jsonValue != null ? JSON.parse(jsonValue) : {}; + const loadedValues: Partial = jsonValue != null ? JSON.parse(jsonValue) : {}; return loadedValues; } catch (error) { @@ -237,9 +223,7 @@ const saveSettings = (settings: Settings) => { }; export const settingsAtom = atom | null>(null); -export const pluginSettingsAtom = atom( - storage.get(STREAMYFIN_PLUGIN_SETTINGS) -); +export const pluginSettingsAtom = atom(storage.get(STREAMYFIN_PLUGIN_SETTINGS)); export const useSettings = () => { const [api] = useAtom(apiAtom); @@ -275,12 +259,13 @@ export const useSettings = () => { }, [api]); const updateSettings = (update: Partial) => { - if (settings) { - const newSettings = { ..._settings, ...update }; + if (!_settings) return; + const hasChanges = Object.entries(update).some(([key, value]) => _settings[key as keyof Settings] !== value); + if (hasChanges) { + // Merge default settings, current settings, and updates to ensure all required properties exist + const newSettings = { ...defaultValues, ..._settings, ...update } as Settings; setSettings(newSettings); - - // @ts-expect-error saveSettings(newSettings); } }; @@ -290,31 +275,24 @@ export const useSettings = () => { // use user settings first and fallback on admin setting if required. const settings: Settings = useMemo(() => { let unlockedPluginDefaults = {} as Settings; - const overrideSettings = Object.entries(pluginSettings || {}).reduce( - (acc, [key, setting]) => { - if (setting) { - const { value, locked } = setting; + const overrideSettings = Object.entries(pluginSettings || {}).reduce((acc, [key, setting]) => { + if (setting) { + const { value, locked } = setting; - // Make sure we override default settings with plugin settings when they are not locked. - // Admin decided what users defaults should be and grants them the ability to change them too. - if ( - locked === false && - value && - _settings?.[key as keyof Settings] !== value - ) { - unlockedPluginDefaults = Object.assign(unlockedPluginDefaults, { - [key as keyof Settings]: value, - }); - } - - acc = Object.assign(acc, { - [key]: locked ? value : _settings?.[key as keyof Settings] ?? value, + // Make sure we override default settings with plugin settings when they are not locked. + // Admin decided what users defaults should be and grants them the ability to change them too. + if (locked === false && value && _settings?.[key as keyof Settings] !== value) { + unlockedPluginDefaults = Object.assign(unlockedPluginDefaults, { + [key as keyof Settings]: value, }); } - return acc; - }, - {} as Settings - ); + + acc = Object.assign(acc, { + [key]: locked ? value : _settings?.[key as keyof Settings] ?? value, + }); + } + return acc; + }, {} as Settings); return { ...defaultValues, @@ -323,11 +301,5 @@ export const useSettings = () => { }; }, [_settings, pluginSettings]); - return [ - settings, - updateSettings, - pluginSettings, - setPluginSettings, - refreshStreamyfinPluginSettings, - ] as const; + return [settings, updateSettings, pluginSettings, setPluginSettings, refreshStreamyfinPluginSettings] as const; };