Compare commits

...

3 Commits

Author SHA1 Message Date
Uruk
d89449b1bf fix(types): resolve TypeScript errors in orientation handling
- Import OrientationLock and Orientation types from .tv.ts module
- Add explicit type annotations to orientation event handlers
- Change ScreenOrientationEnum to use Record<number, string>
- Use OrientationLock enum type instead of runtime value

This fixes ReactCodegen build failures caused by TypeScript errors.
2025-11-16 00:56:23 +01:00
Uruk
d6ccd6f756 fix(ios): remove root icon field to resolve build failure
Removing the root-level icon field allows the iOS-specific
liquid glass icon to be used without conflicts during the Xcode build.

This fixes the build error:
- None of the input catalogs contained a matching stickers icon set
  or app icon set named 'icon-ios-liquid-glass'
2025-11-16 00:37:36 +01:00
Uruk
05d4154cd6 chore(deps): upgrade react-i18next and react-native-worklets
Updates react-i18next from ^15.4.0 to 16.3.3 to leverage latest internationalization features and improvements. Bumps react-native-worklets from 0.5.1 to 0.6.1 for enhanced performance optimizations.

Changes TypeScript dependency constraint from ^5.9.3 to ~5.9.3 to restrict updates to patch versions only, ensuring better stability.
2025-11-16 00:07:03 +01:00
6 changed files with 127 additions and 22 deletions

104
PR_DESCRIPTION.md Normal file
View File

@@ -0,0 +1,104 @@
# 📦 chore(deps): upgrade deps and fix iOS build
## 🔖 Summary
Upgrade runtime dependencies (react-i18next, react-native-worklets), improve TypeScript type safety for screen orientation handling, and fix iOS build error from develop branch.
## 🏷️ Ticket / Issue
None
## 🛠️ What's Changed
- **Type**: chore
- **Scope**: deps, refactor
- **Summary**: Upgraded react-i18next and react-native-worklets to latest versions, improved type safety for screen orientation APIs, and fixed iOS build error
## 📋 Details
This PR upgrades key runtime dependencies, improves type safety across orientation-related code, and fixes an iOS build error present in the develop branch.
### Changes Made
**iOS Build Fix:**
- Removed root-level `icon` field from `app.json` to resolve Xcode build failure
- The iOS-specific liquid glass icon format was causing asset catalog compilation errors
- Build error: "None of the input catalogs contained a matching stickers icon set or app icon set named 'icon-ios-liquid-glass'"
- Removing the root icon allows the iOS-specific icon to be processed correctly
**Runtime Dependencies Updated:**
- `react-i18next`: 15.4.0 → 16.3.3 (latest internationalization features and improvements)
- `react-native-worklets`: 0.5.1 → 0.6.1 (performance optimizations)
- `typescript`: ^5.9.3 → ~5.9.3 (stricter version constraint for stability)
**TypeScript Type Safety Improvements:**
- Added explicit type annotations to orientation event handlers in `useOrientation` hook
- Fixed `OrientationLock` type references to use proper enum types from `.tv.ts` module
- Improved type consistency by using `Record<number, string>` for orientation enum mappings
- Reorganized imports to follow consistent pattern (third-party → internal)
### ⚠️ Breaking Changes
None
### 🔐 Security & Privacy Impact
None
### ⚡ Performance Impact
- react-native-worklets 0.6.1 includes performance optimizations for worklet execution
- No runtime behavior changes - orientation handling works exactly as before
## ✅ Checklist
- [x] I've read the [contribution guidelines](CONTRIBUTING.md)
- [x] Code follows project style and passes lint/format (bun scripts)
- [x] Type checks pass (tsc/biome/etc.)
- [x] Docs updated (README/ADR/usage/API) - N/A for dependency updates
- [x] No secrets/credentials included; env vars documented
- [x] Release notes/CHANGELOG entry added (if applicable) - N/A for internal tooling
- [x] Verified locally that changes behave as expected
## 🔍 Testing Instructions
1. Checkout branch: `git fetch origin && git checkout chore/update-dev-dependencies`
2. Install dependencies: `bun install`
3. Run type checks: `bun run typecheck`
- [x] Verify no TypeScript errors
4. Run linter: `bun run lint`
5. Test orientation features:
- [x] Screen rotation works correctly on mobile
- [x] Orientation lock/unlock functions work
- [x] TV platform continues to use landscape orientation
6. Test iOS build:
- [x] iOS build completes successfully without icon-related errors
- [x] App icons display correctly on iOS devices
7. Test i18n functionality:
- [x] Language switching works
- [x] Translations load correctly
8. Verification steps:
- [x] All commands complete successfully
- [x] No runtime errors
- [x] Orientation behavior unchanged
## ⚙️ Deployment Notes
- No deployment impact - standard dependency updates
- Team members will need to run `bun install` to update dependencies
- No configuration changes required
## 📝 Additional Notes
**Why these updates?**
- **react-i18next 16.3.3**: Latest stable version with improved TypeScript support and performance
- **react-native-worklets 0.6.1**: Bug fixes and performance improvements for animation worklets
- **TypeScript constraint change**: Using `~5.9.3` instead of `^5.9.3` to avoid unexpected minor version updates
**Type safety improvements:**
The TypeScript changes fix incorrect usage of `OrientationLock` as a type when it was actually a runtime value. Now we properly import the enum type from the `.tv.ts` module for type checking while keeping runtime behavior identical.

View File

@@ -4,7 +4,6 @@
"slug": "streamyfin", "slug": "streamyfin",
"version": "0.47.1", "version": "0.47.1",
"orientation": "default", "orientation": "default",
"icon": "./assets/images/icon.png",
"scheme": "streamyfin", "scheme": "streamyfin",
"userInterfaceStyle": "dark", "userInterfaceStyle": "dark",
"jsEngine": "hermes", "jsEngine": "hermes",

View File

@@ -50,7 +50,7 @@
"patch-package": "^8.0.0", "patch-package": "^8.0.0",
"react": "19.1.0", "react": "19.1.0",
"react-dom": "19.1.0", "react-dom": "19.1.0",
"react-i18next": "^15.4.0", "react-i18next": "16.3.3",
"react-native": "npm:react-native-tvos@0.81.5-1", "react-native": "npm:react-native-tvos@0.81.5-1",
"react-native-awesome-slider": "^2.9.0", "react-native-awesome-slider": "^2.9.0",
"react-native-bottom-tabs": "^1.0.2", "react-native-bottom-tabs": "^1.0.2",
@@ -78,7 +78,7 @@
"react-native-video": "6.16.1", "react-native-video": "6.16.1",
"react-native-volume-manager": "^2.0.8", "react-native-volume-manager": "^2.0.8",
"react-native-web": "^0.21.0", "react-native-web": "^0.21.0",
"react-native-worklets": "0.5.1", "react-native-worklets": "0.6.1",
"sonner-native": "^0.21.0", "sonner-native": "^0.21.0",
"tailwindcss": "3.3.2", "tailwindcss": "3.3.2",
"use-debounce": "^10.0.4", "use-debounce": "^10.0.4",
@@ -98,7 +98,7 @@
"husky": "^9.1.7", "husky": "^9.1.7",
"lint-staged": "^16.2.6", "lint-staged": "^16.2.6",
"react-test-renderer": "19.1.1", "react-test-renderer": "19.1.1",
"typescript": "^5.9.3", "typescript": "~5.9.3",
}, },
}, },
}, },
@@ -1609,7 +1609,7 @@
"react-freeze": ["react-freeze@1.0.4", "", { "peerDependencies": { "react": ">=17.0.0" } }, "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA=="], "react-freeze": ["react-freeze@1.0.4", "", { "peerDependencies": { "react": ">=17.0.0" } }, "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA=="],
"react-i18next": ["react-i18next@15.7.4", "", { "dependencies": { "@babel/runtime": "^7.27.6", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { "i18next": ">= 23.4.0", "react": ">= 16.8.0", "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw=="], "react-i18next": ["react-i18next@16.3.3", "", { "dependencies": { "@babel/runtime": "^7.27.6", "html-parse-stringify": "^3.0.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "i18next": ">= 25.6.2", "react": ">= 16.8.0", "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-IaY2W+ueVd/fe7H6Wj2S4bTuLNChnajFUlZFfCTrTHWzGcOrUHlVzW55oXRSl+J51U8Onn6EvIhQ+Bar9FUcjw=="],
"react-is": ["react-is@19.2.0", "", {}, "sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA=="], "react-is": ["react-is@19.2.0", "", {}, "sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA=="],
@@ -1671,7 +1671,7 @@
"react-native-web": ["react-native-web@0.21.2", "", { "dependencies": { "@babel/runtime": "^7.18.6", "@react-native/normalize-colors": "^0.74.1", "fbjs": "^3.0.4", "inline-style-prefixer": "^7.0.1", "memoize-one": "^6.0.0", "nullthrows": "^1.1.1", "postcss-value-parser": "^4.2.0", "styleq": "^0.1.3" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg=="], "react-native-web": ["react-native-web@0.21.2", "", { "dependencies": { "@babel/runtime": "^7.18.6", "@react-native/normalize-colors": "^0.74.1", "fbjs": "^3.0.4", "inline-style-prefixer": "^7.0.1", "memoize-one": "^6.0.0", "nullthrows": "^1.1.1", "postcss-value-parser": "^4.2.0", "styleq": "^0.1.3" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg=="],
"react-native-worklets": ["react-native-worklets@0.5.1", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "^7.0.0-0", "@babel/plugin-transform-class-properties": "^7.0.0-0", "@babel/plugin-transform-classes": "^7.0.0-0", "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", "@babel/plugin-transform-optional-chaining": "^7.0.0-0", "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", "@babel/plugin-transform-template-literals": "^7.0.0-0", "@babel/plugin-transform-unicode-regex": "^7.0.0-0", "@babel/preset-typescript": "^7.16.7", "convert-source-map": "^2.0.0", "semver": "7.7.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0", "react": "*", "react-native": "*" } }, "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w=="], "react-native-worklets": ["react-native-worklets@0.6.1", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "^7.0.0-0", "@babel/plugin-transform-class-properties": "^7.0.0-0", "@babel/plugin-transform-classes": "^7.0.0-0", "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", "@babel/plugin-transform-optional-chaining": "^7.0.0-0", "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", "@babel/plugin-transform-template-literals": "^7.0.0-0", "@babel/plugin-transform-unicode-regex": "^7.0.0-0", "@babel/preset-typescript": "^7.16.7", "convert-source-map": "^2.0.0", "semver": "7.7.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0", "react": "*", "react-native": "*" } }, "sha512-URca8l7c7Uog7gv4mcg9KILdJlnbvwdS5yfXQYf5TDkD2W1VY1sduEKrD+sA3lUPXH/TG1vmXAvNxCNwPMYgGg=="],
"react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="], "react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="],

View File

@@ -1,8 +1,10 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Platform } from "react-native"; import { Platform } from "react-native";
import * as ScreenOrientation from "@/packages/expo-screen-orientation"; import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { OrientationLock } from "@/packages/expo-screen-orientation"; import {
import { Orientation } from "../packages/expo-screen-orientation.tv"; Orientation,
OrientationLock,
} from "../packages/expo-screen-orientation.tv";
const orientationToOrientationLock = ( const orientationToOrientationLock = (
orientation: Orientation, orientation: Orientation,
@@ -30,13 +32,15 @@ export const useOrientation = () => {
if (Platform.isTV) return; if (Platform.isTV) return;
const orientationSubscription = const orientationSubscription =
ScreenOrientation.addOrientationChangeListener((event) => { ScreenOrientation.addOrientationChangeListener(
setOrientation( (event: { orientationInfo: { orientation: Orientation } }) => {
orientationToOrientationLock(event.orientationInfo.orientation), setOrientation(
); orientationToOrientationLock(event.orientationInfo.orientation),
}); );
},
);
ScreenOrientation.getOrientationAsync().then((orientation) => { ScreenOrientation.getOrientationAsync().then((orientation: Orientation) => {
setOrientation(orientationToOrientationLock(orientation)); setOrientation(orientationToOrientationLock(orientation));
}); });

View File

@@ -68,7 +68,7 @@
"patch-package": "^8.0.0", "patch-package": "^8.0.0",
"react": "19.1.0", "react": "19.1.0",
"react-dom": "19.1.0", "react-dom": "19.1.0",
"react-i18next": "^15.4.0", "react-i18next": "16.3.3",
"react-native": "npm:react-native-tvos@0.81.5-1", "react-native": "npm:react-native-tvos@0.81.5-1",
"react-native-awesome-slider": "^2.9.0", "react-native-awesome-slider": "^2.9.0",
"react-native-bottom-tabs": "^1.0.2", "react-native-bottom-tabs": "^1.0.2",
@@ -96,7 +96,7 @@
"react-native-video": "6.16.1", "react-native-video": "6.16.1",
"react-native-volume-manager": "^2.0.8", "react-native-volume-manager": "^2.0.8",
"react-native-web": "^0.21.0", "react-native-web": "^0.21.0",
"react-native-worklets": "0.5.1", "react-native-worklets": "0.6.1",
"sonner-native": "^0.21.0", "sonner-native": "^0.21.0",
"tailwindcss": "3.3.2", "tailwindcss": "3.3.2",
"use-debounce": "^10.0.4", "use-debounce": "^10.0.4",

View File

@@ -11,6 +11,7 @@ import { useCallback, useEffect, useMemo } from "react";
import { Platform } from "react-native"; import { Platform } from "react-native";
import { BITRATES, type Bitrate } from "@/components/BitrateSelector"; import { BITRATES, type Bitrate } from "@/components/BitrateSelector";
import * as ScreenOrientation from "@/packages/expo-screen-orientation"; import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { OrientationLock } from "@/packages/expo-screen-orientation.tv";
import { apiAtom } from "@/providers/JellyfinProvider"; import { apiAtom } from "@/providers/JellyfinProvider";
import { writeInfoLog } from "@/utils/log"; import { writeInfoLog } from "@/utils/log";
import { storage } from "../mmkv"; import { storage } from "../mmkv";
@@ -25,10 +26,7 @@ export type DownloadOption = {
value: DownloadQuality; value: DownloadQuality;
}; };
export const ScreenOrientationEnum: Record< export const ScreenOrientationEnum: Record<number, string> = {
ScreenOrientation.OrientationLock,
string
> = {
[ScreenOrientation.OrientationLock.DEFAULT]: [ScreenOrientation.OrientationLock.DEFAULT]:
"home.settings.other.orientations.DEFAULT", "home.settings.other.orientations.DEFAULT",
[ScreenOrientation.OrientationLock.ALL]: [ScreenOrientation.OrientationLock.ALL]:
@@ -154,7 +152,7 @@ export type Settings = {
subtitleMode: SubtitlePlaybackMode; subtitleMode: SubtitlePlaybackMode;
rememberSubtitleSelections: boolean; rememberSubtitleSelections: boolean;
showHomeTitles: boolean; showHomeTitles: boolean;
defaultVideoOrientation: ScreenOrientation.OrientationLock; defaultVideoOrientation: OrientationLock;
forwardSkipTime: number; forwardSkipTime: number;
rewindSkipTime: number; rewindSkipTime: number;
showCustomMenuLinks: boolean; showCustomMenuLinks: boolean;
@@ -218,7 +216,7 @@ export const defaultValues: Settings = {
subtitleMode: SubtitlePlaybackMode.Default, subtitleMode: SubtitlePlaybackMode.Default,
rememberSubtitleSelections: true, rememberSubtitleSelections: true,
showHomeTitles: true, showHomeTitles: true,
defaultVideoOrientation: ScreenOrientation.OrientationLock.DEFAULT, defaultVideoOrientation: OrientationLock.DEFAULT,
forwardSkipTime: 30, forwardSkipTime: 30,
rewindSkipTime: 10, rewindSkipTime: 10,
showCustomMenuLinks: false, showCustomMenuLinks: false,