diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index ff7a3619..ad11cce2 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -74,7 +74,7 @@ body: - type: input id: reproduction-repo attributes: - label: Reproduction + label: Reproduction Link description: Provide a link to a repository with a reproduction of the bug, this is optional but it will make us to fix the bug faster placeholder: Reproduction Repository value: "repository link" diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index 371d1a9b..7d5cbb8e 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -7,7 +7,7 @@ body: - type: markdown attributes: value: Thanks for taking the time to fill out this feature report! - + - type: textarea id: description attributes: @@ -17,7 +17,7 @@ body: value: "Very cool idea!" validations: required: true - + - type: textarea id: why-it-is-needed attributes: @@ -49,4 +49,11 @@ body: validations: required: false - \ No newline at end of file + - type: markdown + attributes: + value: | + ## Support + + If this functionality is important to you and you need it, contact [TheWidlarzGroup](https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=feature-request#Contact) - [`hi@thewidlarzgroup.com`](mailto:hi@thewidlarzgroup.com) + + diff --git a/.github/scripts/validate.js b/.github/scripts/validate.js new file mode 100644 index 00000000..36de83d7 --- /dev/null +++ b/.github/scripts/validate.js @@ -0,0 +1,293 @@ +const FIELD_MAPPINGS = { + Platform: 'What platforms are you having the problem on?', + Version: 'Version', + SystemVersion: 'System Version', + DeviceType: 'On what device are you experiencing the issue?', + Architecture: 'Architecture', + Description: 'What happened?', + ReproductionLink: 'Reproduction Link', + Reproduction: 'Reproduction', +}; + +const PLATFORM_LABELS = { + iOS: 'Platform: iOS', + visionOS: 'Platform: iOS', + 'Apple tvOS': 'Platform: iOS', + Android: 'Platform: Android', + 'Android TV': 'Platform: Android', + Windows: 'Platform: Windows', + web: 'Platform: Web', +}; + +const BOT_LABELS = [ + 'Missing Info', + 'Repro Provided', + 'Missing Repro', + 'Waiting for Review', + 'Newer Version Available', + ...Object.values(PLATFORM_LABELS), +]; + +const SKIP_LABEL = 'No Validation'; + +const MESSAGE = { + FEATURE_REQUEST: `Thank you for your feature request. We will review it and get back to you if we need more information.`, + BUG_REPORT: `Thank you for your bug report. We will review it and get back to you if we need more information.`, + MISSING_INFO: (missingFields) => { + return `Thank you for your issue report. Please note that the following information is missing or incomplete:\n\n${missingFields + .map((field) => `- ${field.replace('missing-', '')}`) + .join( + '\n', + )}\n\nPlease update your issue with this information to help us address it more effectively. + \n > Note: issues without complete information have a lower priority`; + }, + OUTDATED_VERSION: (issueVersion, latestVersion) => { + return ( + `There is a newer version of the library available. ` + + `You are using version ${issueVersion}, while the latest stable version is ${latestVersion}. ` + + `Please update to the latest version and check if the issue still exists.` + + `\n > Note: If the issue still exists, please update the issue report with the latest information.` + ); + }, +}; + +const checkLatestVersion = async () => { + try { + const response = await fetch( + 'https://registry.npmjs.org/react-native-video/latest', + ); + const data = await response.json(); + return data.version; + } catch (error) { + console.error('Error checking latest version:', error); + return null; + } +}; + +const getFieldValue = (body, field) => { + if (!FIELD_MAPPINGS[field]) { + console.warn('Field not supported:', field); + return ''; + } + + const fieldValue = FIELD_MAPPINGS[field]; + + const sections = body.split('###'); + const section = sections.find((section) => { + // Find the section that contains the field + // For Reproduction, we need to make sure that we don't match Reproduction Link + if (field === 'Reproduction') { + return ( + section.includes(fieldValue) && !section.includes('Reproduction Link') + ); + } + + return section.includes(fieldValue); + }); + + return section ? section.replace(fieldValue, '').trim() : ''; +}; + +const validateBugReport = async (body, labels) => { + const selectedPlatforms = getFieldValue(body, 'Platform') + .split(',') + .map((p) => p.trim()); + + if (selectedPlatforms.length === 0) { + labels.add('missing-platform'); + } else { + selectedPlatforms.forEach((platform) => { + const label = PLATFORM_LABELS[platform]; + if (label) { + labels.add(label); + } else { + console.warn('Platform not supported', platform); + } + }); + } + + const version = getFieldValue(body, 'Version'); + if (version) { + const words = version.split(' '); + const versionPattern = /\d+\.\d+\.\d+/; + const isVersionValid = words.some((word) => versionPattern.test(word)); + + if (!isVersionValid) { + labels.add('missing-version'); + } + + const latestVersion = await checkLatestVersion(); + if (latestVersion && latestVersion !== version) { + labels.add(`outdated-version-${version}-${latestVersion}`); + } + } + + const fields = [ + { + name: 'SystemVersion', + invalidValue: + 'What version of the system is using device that you are experiencing the issue?', + }, + {name: 'DeviceType'}, + {name: 'Architecture'}, + {name: 'Description', invalidValue: 'A bug happened!'}, + {name: 'Reproduction', invalidValue: 'Step to reproduce this bug are:'}, + {name: 'ReproductionLink', invalidValue: 'repository link'}, + ]; + + fields.forEach(({name, invalidValue}) => { + const value = getFieldValue(body, name); + if (!value || value === invalidValue) { + const fieldName = FIELD_MAPPINGS[name]; + labels.add(`missing-${fieldName.toLowerCase()}`); + } + }); +}; + +const validateFeatureRequest = (body, labels) => { + // Implement feature request validation logic here +}; + +const handleIssue = async ({github, context}) => { + const {issue} = context.payload; + const {body} = issue; + const labels = new Set(issue.labels.map((label) => label.name)); + + if (labels.has(SKIP_LABEL)) { + console.log('Skiping Issue Validation'); + return; + } + + // Clear out labels that are added by the bot + BOT_LABELS.forEach((label) => labels.delete(label)); + + const isBug = labels.has('bug'); + const isFeature = labels.has('feature'); + + if (isFeature) { + await handleFeatureRequest({github, context, body, labels}); + } else if (isBug) { + await handleBugReport({github, context, body, labels}); + } else { + console.warn('Issue is not a bug or feature request'); + } + + await updateIssueLabels({github, context, labels}); +}; + +const handleFeatureRequest = async ({github, context, body, labels}) => { + validateFeatureRequest(body, labels); + + const comment = MESSAGE.FEATURE_REQUEST; + await createComment({github, context, body: comment}); +}; + +const handleBugReport = async ({github, context, body, labels}) => { + await validateBugReport(body, labels); + + if (Array.from(labels).some((label) => label.startsWith('missing-'))) { + await handleMissingInformation({github, context, labels}); + } else { + await handleValidReport({github, context, labels}); + } +}; + +const handleMissingInformation = async ({github, context, labels}) => { + const missingFields = Array.from(labels).filter((label) => + label.startsWith('missing-'), + ); + + const outdatedVersionLabel = Array.from(labels).find((label) => + label.startsWith('outdated-version'), + ); + + if (missingFields.length > 0) { + let comment = MESSAGE.MISSING_INFO(missingFields); + + if (outdatedVersionLabel) { + const [, , issueVersion, latestVersion] = outdatedVersionLabel.split('-'); + comment += `\n\n ${MESSAGE.OUTDATED_VERSION( + issueVersion, + latestVersion, + )}`; + } + + await hidePreviousComments({github, context}); + await createComment({github, context, body: comment}); + } + + updateLabelsForMissingInfo(labels); +}; + +const handleValidReport = async ({github, context, labels}) => { + let comment = MESSAGE.BUG_REPORT; + + const outdatedVersionLabel = Array.from(labels).find((label) => + label.startsWith('outdated-version'), + ); + + if (outdatedVersionLabel) { + const [, , issueVersion, latestVersion] = outdatedVersionLabel.split('-'); + comment += `\n\n ${MESSAGE.OUTDATED_VERSION(issueVersion, latestVersion)}`; + labels.add('Newer Version Available'); + } + + await hidePreviousComments({github, context}); + await createComment({github, context, body: comment}); + labels.add('Repro Provided'); + labels.add('Waiting for Review'); +}; + +const createComment = async ({github, context, body}) => { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + body, + }); +}; + +const updateIssueLabels = async ({github, context, labels}) => { + const labelsToAdd = Array.from(labels).filter( + (label) => !label.startsWith('missing-') && !label.startsWith('outdated-'), + ); + + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + labels: labelsToAdd, + }); +}; + +const hidePreviousComments = async ({github, context}) => { + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + }); + + const botComments = comments.data.filter( + (comment) => comment.user.type === 'Bot', + ); + + for (const comment of botComments) { + // Don't format string - it will broke the markdown + const hiddenBody = ` +
+Previous bot comment (click to expand) + +${comment.body} + +
`; + + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id, + body: hiddenBody, + }); + } +}; + +module.exports = handleIssue; diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 3179b082..00000000 --- a/.github/stale.yml +++ /dev/null @@ -1,60 +0,0 @@ -# Configuration for probot-stale - https://github.com/probot/stale - -# Number of days of inactivity before an Issue or Pull Request becomes stale -daysUntilStale: 60 - -# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. -# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -daysUntilClose: 3 - -# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) -onlyLabels: [] - -# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable -exemptLabels: - - pinned - - security - -# Set to true to ignore issues in a project (defaults to false) -exemptProjects: true - -# Set to true to ignore issues in a milestone (defaults to false) -exemptMilestones: true - -# Set to true to ignore issues with an assignee (defaults to false) -exemptAssignees: true - -# Label to use when marking as stale -staleLabel: stale - -# Comment to post when marking as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. If you are having a similar problem, please open a - new issue and reference this one instead of commenting on a stale or closed - issue. - -# Comment to post when removing the stale label. -unmarkComment: false - -# Comment to post when closing a stale Issue or Pull Request. -closeComment: false - -# Limit the number of actions per hour, from 1-30. Default is 30 -limitPerRun: 50 - -# Limit to only `issues` or `pulls` -only: issues - -# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': -# pulls: -# daysUntilStale: 30 -# markComment: > -# This pull request has been automatically marked as stale because it has not had -# recent activity. It will be closed if no further activity occurs. Thank you -# for your contributions. - -# issues: -# exemptLabels: -# - confirmed diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..d084767f --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,24 @@ +name: Close inactive issues +on: + schedule: + - cron: "30 1 * * *" + workflow_dispatch: + +jobs: + close-issues: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v5 + with: + days-before-issue-stale: 30 + days-before-issue-close: 14 + stale-issue-label: "stale" + stale-issue-message: "This issue is stale because it has been open for 30 days with no activity. If there won't be any activity in the next 14 days, this issue will be closed automatically." + close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." + days-before-pr-stale: -1 + days-before-pr-close: -1 + exempt-issue-labels: "feature,Accepted,good first issue" + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/validate-issue.yml b/.github/workflows/validate-issue.yml new file mode 100644 index 00000000..8e6c12ab --- /dev/null +++ b/.github/workflows/validate-issue.yml @@ -0,0 +1,19 @@ +name: Issue Validator and Labeler + +on: + issues: + types: [opened, edited] + +jobs: + validate-and-label: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Validate Issue Template and Add Labels + uses: actions/github-script@v7 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const script = require('./.github/scripts/validate.js') + await script({github, context}) \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 23c99389..0e2180b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,125 @@ +## [6.6.4](https://github.com/TheWidlarzGroup/react-native-video/compare/v6.6.3...v6.6.4) (2024-10-03) + + +### Features + +* **android:** add live video label configuration ([#4190](https://github.com/TheWidlarzGroup/react-native-video/issues/4190)) ([149924f](https://github.com/TheWidlarzGroup/react-native-video/commit/149924ffcb0cbdeaa8c671ebb4b3b6115920131a)) + +## [6.6.3](https://github.com/TheWidlarzGroup/react-native-video/compare/v6.6.2...v6.6.3) (2024-09-29) + + +### Bug Fixes + +* **android:** bad rotation handling ([#4205](https://github.com/TheWidlarzGroup/react-native-video/issues/4205)) ([3ecf324](https://github.com/TheWidlarzGroup/react-native-video/commit/3ecf324bb30208ab8efbf00958ebd4590ddf8d39)) +* **docs:** invalid URLs in updating section ([#4201](https://github.com/TheWidlarzGroup/react-native-video/issues/4201)) ([c81eea5](https://github.com/TheWidlarzGroup/react-native-video/commit/c81eea54d8291c5131fd59a93f198e0fd5f3673c)) +* **ios:** Add safety checks and remove some of the ! in types declaration ([#4182](https://github.com/TheWidlarzGroup/react-native-video/issues/4182)) ([ae82c83](https://github.com/TheWidlarzGroup/react-native-video/commit/ae82c83eef2fc7c383fd844c7471613e4ac1c7ee)) +* **tvos:** typo ([#4204](https://github.com/TheWidlarzGroup/react-native-video/issues/4204)) ([b11f05f](https://github.com/TheWidlarzGroup/react-native-video/commit/b11f05f1753a4cb963b94d1e1d8d1f6c37af2a9d)) + + +### Features + +* **android:** allow to hide specific controls ([#4183](https://github.com/TheWidlarzGroup/react-native-video/issues/4183)) ([279cc0e](https://github.com/TheWidlarzGroup/react-native-video/commit/279cc0e5ed712488fc3c153c62b14f13048103f2)) + +## [6.6.2](https://github.com/TheWidlarzGroup/react-native-video/compare/v6.6.1...v6.6.2) (2024-09-20) + + +### Features + +* **iOS:** rewrite DRM Module ([#4136](https://github.com/TheWidlarzGroup/react-native-video/issues/4136)) ([0e4c95d](https://github.com/TheWidlarzGroup/react-native-video/commit/0e4c95def968a4091fdd18d07215ba592eec99cb)) + +## [6.6.1](https://github.com/TheWidlarzGroup/react-native-video/compare/v6.6.0...v6.6.1) (2024-09-18) + + +### Bug Fixes + +* **ios:** fix side loaded text track management ([#4180](https://github.com/TheWidlarzGroup/react-native-video/issues/4180)) ([7d43d5d](https://github.com/TheWidlarzGroup/react-native-video/commit/7d43d5d3da72495e94468756be21442f96cc7a89)) + +# [6.6.0](https://github.com/TheWidlarzGroup/react-native-video/compare/v6.5.0...v6.6.0) (2024-09-18) + + +### Bug Fixes + +* **android:** ensure maxbitrate & selectedVideoTrack interact correctly ([#4155](https://github.com/TheWidlarzGroup/react-native-video/issues/4155)) ([7f6b500](https://github.com/TheWidlarzGroup/react-native-video/commit/7f6b500c82122325c326b6dcacaf7af8039b2b33)) +* **android:** ensure pause is well tken in account after onEnd ([#4147](https://github.com/TheWidlarzGroup/react-native-video/issues/4147)) ([b2fd8d6](https://github.com/TheWidlarzGroup/react-native-video/commit/b2fd8d62a10ee64e6208b43120ca9231008309c2)) +* **expo-plugin:** add check for existing service in AndroidManifest for notification controls ([#4172](https://github.com/TheWidlarzGroup/react-native-video/issues/4172)) ([0538b3b](https://github.com/TheWidlarzGroup/react-native-video/commit/0538b3b46801a535c76cf52db28cee76f2aeb0c5)) +* **ios:** ensure onBandwidthUpdate is reported only when value change ([#4149](https://github.com/TheWidlarzGroup/react-native-video/issues/4149)) ([809a730](https://github.com/TheWidlarzGroup/react-native-video/commit/809a73019836f95385891c2bba5c72b0610ffcb1)) +* **ios:** losing subtitle selection on foreground ([#3707](https://github.com/TheWidlarzGroup/react-native-video/issues/3707)) ([bee4123](https://github.com/TheWidlarzGroup/react-native-video/commit/bee4123402f4bc08dd2eb19ab0011ffdc795d0e3)) +* **JS:** improve loader api to allow function call instead of component ([#4171](https://github.com/TheWidlarzGroup/react-native-video/issues/4171)) ([835186a](https://github.com/TheWidlarzGroup/react-native-video/commit/835186a321e1940932a045a59e26e43a040fa334)) +* refactor side loaded text tracks management ([#4158](https://github.com/TheWidlarzGroup/react-native-video/issues/4158)) ([84a27f3](https://github.com/TheWidlarzGroup/react-native-video/commit/84a27f3d9f90624af3c5c3cbff50d754bab9baa4)) +* **sample:** remove warning on ios with NavigationBar ([#4148](https://github.com/TheWidlarzGroup/react-native-video/issues/4148)) ([e18769a](https://github.com/TheWidlarzGroup/react-native-video/commit/e18769ab3a6a7f4ebc459ab550f105f4d18f8201)) +* **visionOS:** remove unsupported apis ([#4154](https://github.com/TheWidlarzGroup/react-native-video/issues/4154)) ([2c1fc96](https://github.com/TheWidlarzGroup/react-native-video/commit/2c1fc964bf2cb97624c8cc37ff8138465619fc61)) + + +### Features + +* **android:** upgrade dependencies / media3 1.4.1 / androidxCore to 1.13.1 / androidxActivity 1.8.2 ([#4173](https://github.com/TheWidlarzGroup/react-native-video/issues/4173)) ([e57c7bd](https://github.com/TheWidlarzGroup/react-native-video/commit/e57c7bda5df7d624d90b20620859b8a4eb3f76b7)) + +# [6.5.0](https://github.com/TheWidlarzGroup/react-native-video/compare/v6.4.5...v6.5.0) (2024-09-04) + + +### Bug Fixes + +* **android:** show the status bar and navigation bar after exiting full-screen mode ([#4112](https://github.com/TheWidlarzGroup/react-native-video/issues/4112)) ([8b8ebe9](https://github.com/TheWidlarzGroup/react-native-video/commit/8b8ebe9410e95085e5602393c2ce3de814df4a96)) +* **android:** add subtitleStyle.subtitlesFollowVideo prop to control subtitles positionning ([#4133](https://github.com/TheWidlarzGroup/react-native-video/issues/4133)) ([2fa6c43](https://github.com/TheWidlarzGroup/react-native-video/commit/2fa6c43615c1bc0a3bbcb5f472ffaeb8ae16a1af)) +* **android:** hide surfaceView for loading time when shutter is hidden ([#4060](https://github.com/TheWidlarzGroup/react-native-video/issues/4060)) ([65faba3](https://github.com/TheWidlarzGroup/react-native-video/commit/65faba312d23de981972d2b6ffecefbc87ecac61)) +* **expo-plugin:** adding bg mode if none exist yet ([#4126](https://github.com/TheWidlarzGroup/react-native-video/issues/4126)) ([451806c](https://github.com/TheWidlarzGroup/react-native-video/commit/451806c547591fbe5714b133e704ffac9efb05d8)) +* **ios:** Add handler for Earpods play/pause command ([#4116](https://github.com/TheWidlarzGroup/react-native-video/issues/4116)) ([9c38d9f](https://github.com/TheWidlarzGroup/react-native-video/commit/9c38d9f4ef42c3e275ee39a08aa227e6b976fdb2)) +* **ios:** build fail due to an unwrapped value ([#4101](https://github.com/TheWidlarzGroup/react-native-video/issues/4101)) ([0a1085c](https://github.com/TheWidlarzGroup/react-native-video/commit/0a1085ce03152d58d98da408dbe79e76fa5ebc1a)) +* **ios:** ensure behavior is correct with empty text track list ([#4123](https://github.com/TheWidlarzGroup/react-native-video/issues/4123)) ([3a32d67](https://github.com/TheWidlarzGroup/react-native-video/commit/3a32d67087c39bcf7904043d15a2fdba65307f4e)) +* **ios:** ensure we don't disable tracks when not necessary (causes black screen) ([#4130](https://github.com/TheWidlarzGroup/react-native-video/issues/4130)) ([89df9d6](https://github.com/TheWidlarzGroup/react-native-video/commit/89df9d69ff96f7d6ff3d493bf1a3eb9c3da51c3c)) +* **ios:** fix onBandwidth update event (old ios api is deprecated and doens't work) ([#4140](https://github.com/TheWidlarzGroup/react-native-video/issues/4140)) ([d6bae3c](https://github.com/TheWidlarzGroup/react-native-video/commit/d6bae3cd076018f07556ab27af2779479bc7ff7d)) +* **sample:** update dependencies to fix local asset playback ([#4121](https://github.com/TheWidlarzGroup/react-native-video/issues/4121)) ([7a2b401](https://github.com/TheWidlarzGroup/react-native-video/commit/7a2b4014f40758a025fcd6b388448d3559ec6a4a)) +* set does not have `find` method ([#4110](https://github.com/TheWidlarzGroup/react-native-video/issues/4110)) ([7db7024](https://github.com/TheWidlarzGroup/react-native-video/commit/7db7024cb36ea34289fddf5c7f66e7b4d7827146)) +* **tvos:** fix build (and update sample) ([#4134](https://github.com/TheWidlarzGroup/react-native-video/issues/4134)) ([688d98d](https://github.com/TheWidlarzGroup/react-native-video/commit/688d98d68f888a59bde1ee33aa844ac63c9026a5)) +* **VisionOS:** do not access to isExternalPlaybackActive on VisionOS ([#4109](https://github.com/TheWidlarzGroup/react-native-video/issues/4109)) ([0576eac](https://github.com/TheWidlarzGroup/react-native-video/commit/0576eacfddb32c4dcc072b6fd3cbf74cf25946a4)) + + +### Features + +* add ads localize ([#4113](https://github.com/TheWidlarzGroup/react-native-video/issues/4113)) ([703ed43](https://github.com/TheWidlarzGroup/react-native-video/commit/703ed4399667e0142704d19686563dd62fb4883d)) +* **android:** Support Common Media Client Data (CMCD) ([#4034](https://github.com/TheWidlarzGroup/react-native-video/issues/4034)) ([ca795f2](https://github.com/TheWidlarzGroup/react-native-video/commit/ca795f298a99a183b81561ef7e09d8d1e8addaf5)) +* **android:** support hiding Exoplayer video duration on android ([#4090](https://github.com/TheWidlarzGroup/react-native-video/issues/4090)) ([41e2bed](https://github.com/TheWidlarzGroup/react-native-video/commit/41e2bed6b36f74a28d7dd640414c6d5ccbec0399)) +* Correct isBehindLiveWindow Error Handling ([#4143](https://github.com/TheWidlarzGroup/react-native-video/issues/4143)) ([22c21ad](https://github.com/TheWidlarzGroup/react-native-video/commit/22c21ad249879fe4ff8fb119384ebc82766106c3)) + +## [6.4.5](https://github.com/TheWidlarzGroup/react-native-video/compare/v6.4.4...v6.4.5) (2024-08-17) + + +### Bug Fixes + +* **android:** resolve a release issue with DefaultDashChunkSource ([#4097](https://github.com/TheWidlarzGroup/react-native-video/issues/4097)) ([7e222e8](https://github.com/TheWidlarzGroup/react-native-video/commit/7e222e8fc4f3c47a1c9cd2fbf5ff012bcbe98a7f)) + +* refactor(android): migrate DefaultDashChunkSource to Kotlin (#4078) (b7d1cabf) +* fix(ios): remove resume logic in notification seek closure (#4068) (c6ae17e4) +* chore(doc): update document (props & method) (#4072) (cd41a1b2) +* fix(android): build warnings (#4058) (899bb822) +* infra: update feature request form (#4065) (6c03d0a7) +* fix(ios): override source metadata with custom metadata (#4050) (38aa2b05) +* fix(android): return the value as a float for the getCurrentPosition function (#4054) (af0302b1) +* refactor(android): migrate ReactExoplayerViewManager to Kotlin (#4011) (74c6dd62) +* fix(android): viewType is ignored when its value is ViewType.TEXTURE (#4031) (22cfd6ce) +* fix(ios): metadata update race (#4033) (08a57a3b) +* fix(ios): updated getLicense call to work with new syntax, and fixed spelling error (#4014) (#4042) (2348c5e4) + +## [6.4.3](https://github.com/TheWidlarzGroup/react-native-video/compare/v6.4.2...v6.4.3) (2024-07-24) + + +### Bug Fixes + +* **android:** app crash at boot with old arch ([#4022](https://github.com/TheWidlarzGroup/react-native-video/issues/4022)) ([1ee5811](https://github.com/TheWidlarzGroup/react-native-video/commit/1ee5811c8e0ecfc2486f5120b575b57c6396e0f8)), closes [#3875](https://github.com/TheWidlarzGroup/react-native-video/issues/3875) +* **android:** fix backward compatibility ([#4020](https://github.com/TheWidlarzGroup/react-native-video/issues/4020)) ([ab7e02e](https://github.com/TheWidlarzGroup/react-native-video/commit/ab7e02e4538c97340f13fb052b1cad94408b48fa)) +* **android:** resize mode cover calculation ([#4010](https://github.com/TheWidlarzGroup/react-native-video/issues/4010)) ([9f38216](https://github.com/TheWidlarzGroup/react-native-video/commit/9f382163d83c3331518e2784b335da28179ac91d)) +* index of the selected track ([#4012](https://github.com/TheWidlarzGroup/react-native-video/issues/4012)) ([fb1d6bd](https://github.com/TheWidlarzGroup/react-native-video/commit/fb1d6bdef7210d43f9e34f673691a9a17b95424e)) +* **sample:** boot failure on emulator ([#4016](https://github.com/TheWidlarzGroup/react-native-video/issues/4016)) ([ffbc977](https://github.com/TheWidlarzGroup/react-native-video/commit/ffbc977ff90248aeb270626620f5c3553f955617)) + + +### Features + +* add ability to define `poster` props as Image type and render poster as custom component ([#3972](https://github.com/TheWidlarzGroup/react-native-video/issues/3972)) ([adbd06e](https://github.com/TheWidlarzGroup/react-native-video/commit/adbd06e2df557b22b8a3a19073a2de1cbb964833)) +* **android:** add error handling for Kotlin version ([#4018](https://github.com/TheWidlarzGroup/react-native-video/issues/4018)) ([6189080](https://github.com/TheWidlarzGroup/react-native-video/commit/6189080c9aac89aa3d2a4e60049999d8880bc971)) +* **android:** set originalFitsSystemWindows on fullscreen open ([#4013](https://github.com/TheWidlarzGroup/react-native-video/issues/4013)) ([2f70c02](https://github.com/TheWidlarzGroup/react-native-video/commit/2f70c02cdcf6488338df197feb61eeb10ed3281f)) + ## [6.4.2](https://github.com/TheWidlarzGroup/react-native-video/compare/v6.4.1...v6.4.2) (2024-07-15) diff --git a/README.md b/README.md index 3d6605ff..bd216d42 100644 --- a/README.md +++ b/README.md @@ -51,9 +51,9 @@ We have an discord server where you can ask questions and get help. [Join the di ## Enterprise Support

- 📱 react-native-video is provided as it is. For enterprise support or other business inquiries, please contact us 🤝. We can help you with the integration, customization and maintenance. We are providing both free and commercial support for this project. let's build something awesome together! 🚀 + 📱 react-native-video is provided as it is. For enterprise support or other business inquiries, please contact us 🤝. We can help you with the integration, customization and maintenance. We are providing both free and commercial support for this project. let's build something awesome together! 🚀

- + diff --git a/android/build.gradle b/android/build.gradle index 7920bf65..d153c936 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -5,6 +5,21 @@ apply plugin: 'kotlin-android' buildscript { def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['RNVideo_kotlinVersion'] + def requiredKotlinVersion = project.properties['RNVideo_kotlinVersion'] + + def isVersionAtLeast = { version, requiredVersion -> + def (v1, v2) = [version, requiredVersion].collect { it.tokenize('.')*.toInteger() } + for (int i = 0; i < Math.max(v1.size(), v2.size()); i++) { + int val1 = i < v1.size() ? v1[i] : 0 + int val2 = i < v2.size() ? v2[i] : 0 + if (val1 < val2) { + return false + } else if (val1 > val2) { + return true + } + } + return true + } repositories { mavenCentral() @@ -13,9 +28,17 @@ buildscript { dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") } + + ext { + if (!isVersionAtLeast(kotlin_version, requiredKotlinVersion)) { + throw new GradleException("Kotlin version mismatch: Project is using Kotlin version $kotlin_version, but it must be at least $requiredKotlinVersion. Please update the Kotlin version.") + } else { + println("Kotlin version is correct: $kotlin_version") + } + } } -// This looks funny but it's necessary to keep backwards compatibility (: +// This looks funny but it's necessary to keep backwards compatibility (: def safeExtGet(prop) { return rootProject.ext.has(prop) ? rootProject.ext.get(prop) : rootProject.ext.has("RNVideo_" + prop) ? @@ -184,7 +207,6 @@ repositories { } def media3_version = safeExtGet('media3Version') -def kotlin_version = safeExtGet('kotlinVersion') def androidxCore_version = safeExtGet('androidxCoreVersion') def androidxActivity_version = safeExtGet('androidxActivityVersion') @@ -194,7 +216,7 @@ dependencies { //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" - implementation "androidx.core:core:$androidxCore_version" + implementation "androidx.core:core-ktx:$androidxCore_version" implementation "androidx.activity:activity-ktx:$androidxActivity_version" // For media playback using ExoPlayer @@ -239,7 +261,7 @@ dependencies { implementation "androidx.media3:media3-exoplayer-rtsp:$media3_version" } } - + // For ad insertion using the Interactive Media Ads SDK with ExoPlayer if (ExoplayerDependencies["useExoplayerIMA"]) { if (media3_buildFromSource) { @@ -280,5 +302,4 @@ dependencies { // Common functionality used across multiple media libraries implementation "androidx.media3:media3-common:$media3_version" } - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" -} +} \ No newline at end of file diff --git a/android/gradle.properties b/android/gradle.properties index d4b23166..b474349b 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,15 +1,15 @@ -RNVideo_kotlinVersion=1.7.0 +RNVideo_kotlinVersion=1.8.0 RNVideo_minSdkVersion=23 RNVideo_targetSdkVersion=34 RNVideo_compileSdkVersion=34 RNVideo_ndkversion=26.1.10909125 RNVideo_buildToolsVersion=34.0.0 -RNVideo_media3Version=1.3.1 +RNVideo_media3Version=1.4.1 RNVideo_useExoplayerIMA=false RNVideo_useExoplayerRtsp=false RNVideo_useExoplayerSmoothStreaming=true RNVideo_useExoplayerDash=true RNVideo_useExoplayerHls=true -RNVideo_androidxCoreVersion=1.9.0 -RNVideo_androidxActivityVersion=1.7.0 +RNVideo_androidxCoreVersion=1.13.1 +RNVideo_androidxActivityVersion=1.8.2 RNVideo_buildFromMedia3Source=false diff --git a/android/src/main/java/androidx/media3/exoplayer/dash/DefaultDashChunkSource.java b/android/src/main/java/androidx/media3/exoplayer/dash/DefaultDashChunkSource.java index 95026f07..b5e2d349 100644 --- a/android/src/main/java/androidx/media3/exoplayer/dash/DefaultDashChunkSource.java +++ b/android/src/main/java/androidx/media3/exoplayer/dash/DefaultDashChunkSource.java @@ -7,4 +7,4 @@ public class DefaultDashChunkSource { public Factory(DataSource.Factory mediaDataSourceFactory) { } } -} +} \ No newline at end of file diff --git a/android/src/main/java/androidx/media3/exoplayer/ima/ImaAdsLoader.java b/android/src/main/java/androidx/media3/exoplayer/ima/ImaAdsLoader.java index 8d30b2b1..8fadc334 100644 --- a/android/src/main/java/androidx/media3/exoplayer/ima/ImaAdsLoader.java +++ b/android/src/main/java/androidx/media3/exoplayer/ima/ImaAdsLoader.java @@ -11,9 +11,17 @@ import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.source.ads.AdsLoader; import androidx.media3.exoplayer.source.ads.AdsMediaSource; +import com.google.ads.interactivemedia.v3.api.ImaSdkSettings; + import java.io.IOException; public class ImaAdsLoader implements AdsLoader { + private final ImaSdkSettings imaSdkSettings; + + public ImaAdsLoader(ImaSdkSettings imaSdkSettings) { + this.imaSdkSettings = imaSdkSettings; + } + public void setPlayer(ExoPlayer ignoredPlayer) { } @@ -45,6 +53,7 @@ public class ImaAdsLoader implements AdsLoader { } public static class Builder { + private ImaSdkSettings imaSdkSettings; public Builder(Context ignoredThemedReactContext) { } @@ -56,6 +65,11 @@ public class ImaAdsLoader implements AdsLoader { return this; } + public Builder setImaSdkSettings(ImaSdkSettings imaSdkSettings) { + this.imaSdkSettings = imaSdkSettings; + return this; + } + public ImaAdsLoader build() { return null; } diff --git a/android/src/main/java/com/brentvatne/common/api/AdsProps.kt b/android/src/main/java/com/brentvatne/common/api/AdsProps.kt new file mode 100644 index 00000000..9443d537 --- /dev/null +++ b/android/src/main/java/com/brentvatne/common/api/AdsProps.kt @@ -0,0 +1,46 @@ +package com.brentvatne.common.api + +import android.net.Uri +import android.text.TextUtils +import com.brentvatne.common.toolbox.DebugLog +import com.brentvatne.common.toolbox.ReactBridgeUtils +import com.facebook.react.bridge.ReadableMap + +class AdsProps { + var adTagUrl: Uri? = null + var adLanguage: String? = null + + /** return true if this and src are equals */ + override fun equals(other: Any?): Boolean { + if (other == null || other !is AdsProps) return false + return ( + adTagUrl == other.adTagUrl && + adLanguage == other.adLanguage + ) + } + + companion object { + private const val PROP_AD_TAG_URL = "adTagUrl" + private const val PROP_AD_LANGUAGE = "adLanguage" + + @JvmStatic + fun parse(src: ReadableMap?): AdsProps { + val adsProps = AdsProps() + DebugLog.w("olivier", "uri: parse AdsProps") + + if (src != null) { + val uriString = ReactBridgeUtils.safeGetString(src, PROP_AD_TAG_URL) + if (TextUtils.isEmpty(uriString)) { + adsProps.adTagUrl = null + } else { + adsProps.adTagUrl = Uri.parse(uriString) + } + val languageString = ReactBridgeUtils.safeGetString(src, PROP_AD_LANGUAGE) + if (!TextUtils.isEmpty(languageString)) { + adsProps.adLanguage = languageString + } + } + return adsProps + } + } +} diff --git a/android/src/main/java/com/brentvatne/common/api/CMCDProps.kt b/android/src/main/java/com/brentvatne/common/api/CMCDProps.kt new file mode 100644 index 00000000..76bcefa1 --- /dev/null +++ b/android/src/main/java/com/brentvatne/common/api/CMCDProps.kt @@ -0,0 +1,51 @@ +package com.brentvatne.common.api + +import com.brentvatne.common.toolbox.ReactBridgeUtils.safeGetInt +import com.facebook.react.bridge.ReadableArray +import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.ReadableType + +data class CMCDProps( + val cmcdObject: List> = emptyList(), + val cmcdRequest: List> = emptyList(), + val cmcdSession: List> = emptyList(), + val cmcdStatus: List> = emptyList(), + val mode: Int = 1 +) { + companion object { + private const val PROP_CMCD_OBJECT = "object" + private const val PROP_CMCD_REQUEST = "request" + private const val PROP_CMCD_SESSION = "session" + private const val PROP_CMCD_STATUS = "status" + private const val PROP_CMCD_MODE = "mode" + + @JvmStatic + fun parse(src: ReadableMap?): CMCDProps? { + if (src == null) return null + + return CMCDProps( + cmcdObject = parseKeyValuePairs(src.getArray(PROP_CMCD_OBJECT)), + cmcdRequest = parseKeyValuePairs(src.getArray(PROP_CMCD_REQUEST)), + cmcdSession = parseKeyValuePairs(src.getArray(PROP_CMCD_SESSION)), + cmcdStatus = parseKeyValuePairs(src.getArray(PROP_CMCD_STATUS)), + mode = safeGetInt(src, PROP_CMCD_MODE, 1) + ) + } + + private fun parseKeyValuePairs(array: ReadableArray?): List> { + if (array == null) return emptyList() + + return (0 until array.size()).mapNotNull { i -> + val item = array.getMap(i) + val key = item?.getString("key") + val value = when (item?.getType("value")) { + ReadableType.Number -> item.getDouble("value") + ReadableType.String -> item.getString("value") + else -> null + } + + if (key != null && value != null) Pair(key, value) else null + } + } + } +} diff --git a/android/src/main/java/com/brentvatne/common/api/ControlsConfig.kt b/android/src/main/java/com/brentvatne/common/api/ControlsConfig.kt index e03e5d41..8ea70014 100644 --- a/android/src/main/java/com/brentvatne/common/api/ControlsConfig.kt +++ b/android/src/main/java/com/brentvatne/common/api/ControlsConfig.kt @@ -5,18 +5,42 @@ import com.facebook.react.bridge.ReadableMap class ControlsConfig { var hideSeekBar: Boolean = false + var hideDuration: Boolean = false + var hidePosition: Boolean = false + var hidePlayPause: Boolean = false + var hideForward: Boolean = false + var hideRewind: Boolean = false + var hideNext: Boolean = false + var hidePrevious: Boolean = false + var hideFullscreen: Boolean = false + var hideNavigationBarOnFullScreenMode: Boolean = true + var hideNotificationBarOnFullScreenMode: Boolean = true + var liveLabel: String? = null + var hideSettingButton: Boolean = true + var seekIncrementMS: Int = 10000 companion object { @JvmStatic - fun parse(src: ReadableMap?): ControlsConfig { + fun parse(controlsConfig: ReadableMap?): ControlsConfig { val config = ControlsConfig() - if (src != null) { - config.hideSeekBar = ReactBridgeUtils.safeGetBool(src, "hideSeekBar", false) - config.seekIncrementMS = ReactBridgeUtils.safeGetInt(src, "seekIncrementMS", 10000) + if (controlsConfig != null) { + config.hideSeekBar = ReactBridgeUtils.safeGetBool(controlsConfig, "hideSeekBar", false) + config.hideDuration = ReactBridgeUtils.safeGetBool(controlsConfig, "hideDuration", false) + config.hidePosition = ReactBridgeUtils.safeGetBool(controlsConfig, "hidePosition", false) + config.hidePlayPause = ReactBridgeUtils.safeGetBool(controlsConfig, "hidePlayPause", false) + config.hideForward = ReactBridgeUtils.safeGetBool(controlsConfig, "hideForward", false) + config.hideRewind = ReactBridgeUtils.safeGetBool(controlsConfig, "hideRewind", false) + config.hideNext = ReactBridgeUtils.safeGetBool(controlsConfig, "hideNext", false) + config.hidePrevious = ReactBridgeUtils.safeGetBool(controlsConfig, "hidePrevious", false) + config.hideFullscreen = ReactBridgeUtils.safeGetBool(controlsConfig, "hideFullscreen", false) + config.seekIncrementMS = ReactBridgeUtils.safeGetInt(controlsConfig, "seekIncrementMS", 10000) + config.hideNavigationBarOnFullScreenMode = ReactBridgeUtils.safeGetBool(controlsConfig, "hideNavigationBarOnFullScreenMode", true) + config.hideNotificationBarOnFullScreenMode = ReactBridgeUtils.safeGetBool(controlsConfig, "hideNotificationBarOnFullScreenMode", true) + config.liveLabel = ReactBridgeUtils.safeGetString(controlsConfig, "liveLabel", null) + config.hideSettingButton = ReactBridgeUtils.safeGetBool(controlsConfig, "hideSettingButton", true) } - return config } } diff --git a/android/src/main/java/com/brentvatne/common/api/ResizeMode.kt b/android/src/main/java/com/brentvatne/common/api/ResizeMode.kt index c873a04e..18f35d94 100644 --- a/android/src/main/java/com/brentvatne/common/api/ResizeMode.kt +++ b/android/src/main/java/com/brentvatne/common/api/ResizeMode.kt @@ -1,8 +1,7 @@ package com.brentvatne.common.api import androidx.annotation.IntDef -import java.lang.annotation.Retention -import java.lang.annotation.RetentionPolicy +import kotlin.annotation.Retention internal object ResizeMode { /** @@ -42,7 +41,7 @@ internal object ResizeMode { else -> RESIZE_MODE_FIT } - @Retention(RetentionPolicy.SOURCE) + @Retention(AnnotationRetention.SOURCE) @IntDef( RESIZE_MODE_FIT, RESIZE_MODE_FIXED_WIDTH, diff --git a/android/src/main/java/com/brentvatne/common/api/SideLoadedTextTrackList.kt b/android/src/main/java/com/brentvatne/common/api/SideLoadedTextTrackList.kt index e3d519c4..494facdc 100644 --- a/android/src/main/java/com/brentvatne/common/api/SideLoadedTextTrackList.kt +++ b/android/src/main/java/com/brentvatne/common/api/SideLoadedTextTrackList.kt @@ -11,12 +11,18 @@ import com.facebook.react.bridge.ReadableMap class SideLoadedTextTrackList { var tracks = ArrayList() + /** return true if this and src are equals */ + override fun equals(other: Any?): Boolean { + if (other == null || other !is SideLoadedTextTrackList) return false + return tracks == other.tracks + } + companion object { fun parse(src: ReadableArray?): SideLoadedTextTrackList? { if (src == null) { return null } - var sideLoadedTextTrackList = SideLoadedTextTrackList() + val sideLoadedTextTrackList = SideLoadedTextTrackList() for (i in 0 until src.size()) { val textTrack: ReadableMap = src.getMap(i) sideLoadedTextTrackList.tracks.add(SideLoadedTextTrack.parse(textTrack)) diff --git a/android/src/main/java/com/brentvatne/common/api/Source.kt b/android/src/main/java/com/brentvatne/common/api/Source.kt index ba4f8496..4437f668 100644 --- a/android/src/main/java/com/brentvatne/common/api/Source.kt +++ b/android/src/main/java/com/brentvatne/common/api/Source.kt @@ -14,6 +14,7 @@ import com.brentvatne.common.toolbox.ReactBridgeUtils.safeGetBool import com.brentvatne.common.toolbox.ReactBridgeUtils.safeGetInt import com.brentvatne.common.toolbox.ReactBridgeUtils.safeGetMap import com.brentvatne.common.toolbox.ReactBridgeUtils.safeGetString +import com.brentvatne.react.BuildConfig import com.facebook.react.bridge.ReadableMap import java.util.Locale import java.util.Objects @@ -38,6 +39,9 @@ class Source { /** Will crop content end at specified position */ var cropEndMs: Int = -1 + /** Will virtually consider that content before contentStartTime is a preroll ad */ + var contentStartTime: Int = -1 + /** Allow to force stream content, necessary when uri doesn't contain content type (.mlp4, .m3u, ...) */ var extension: String? = null @@ -57,6 +61,21 @@ class Source { */ var textTracksAllowChunklessPreparation: Boolean = false + /** + * CMCD properties linked to the source + */ + var cmcdProps: CMCDProps? = null + + /** + * Ads playback properties + */ + var adsProps: AdsProps? = null + + /** + * The list of sideLoaded text tracks + */ + var sideLoadedTextTracks: SideLoadedTextTrackList? = null + override fun hashCode(): Int = Objects.hash(uriString, uri, startPositionMs, cropStartMs, cropEndMs, extension, metadata, headers) /** return true if this and src are equals */ @@ -68,7 +87,11 @@ class Source { cropEndMs == other.cropEndMs && startPositionMs == other.startPositionMs && extension == other.extension && - drmProps == other.drmProps + drmProps == other.drmProps && + contentStartTime == other.contentStartTime && + cmcdProps == other.cmcdProps && + sideLoadedTextTracks == other.sideLoadedTextTracks && + adsProps == other.adsProps ) } @@ -127,11 +150,15 @@ class Source { private const val PROP_SRC_START_POSITION = "startPosition" private const val PROP_SRC_CROP_START = "cropStart" private const val PROP_SRC_CROP_END = "cropEnd" + private const val PROP_SRC_CONTENT_START_TIME = "contentStartTime" private const val PROP_SRC_TYPE = "type" private const val PROP_SRC_METADATA = "metadata" private const val PROP_SRC_HEADERS = "requestHeaders" private const val PROP_SRC_DRM = "drm" + private const val PROP_SRC_CMCD = "cmcd" + private const val PROP_SRC_ADS = "ad" private const val PROP_SRC_TEXT_TRACKS_ALLOW_CHUNKLESS_PREPARATION = "textTracksAllowChunklessPreparation" + private const val PROP_SRC_TEXT_TRACKS = "textTracks" @SuppressLint("DiscouragedApi") private fun getUriFromAssetId(context: Context, uriString: String): Uri? { @@ -187,9 +214,15 @@ class Source { source.startPositionMs = safeGetInt(src, PROP_SRC_START_POSITION, -1) source.cropStartMs = safeGetInt(src, PROP_SRC_CROP_START, -1) source.cropEndMs = safeGetInt(src, PROP_SRC_CROP_END, -1) + source.contentStartTime = safeGetInt(src, PROP_SRC_CONTENT_START_TIME, -1) source.extension = safeGetString(src, PROP_SRC_TYPE, null) source.drmProps = parse(safeGetMap(src, PROP_SRC_DRM)) + source.cmcdProps = CMCDProps.parse(safeGetMap(src, PROP_SRC_CMCD)) + if (BuildConfig.USE_EXOPLAYER_IMA) { + source.adsProps = AdsProps.parse(safeGetMap(src, PROP_SRC_ADS)) + } source.textTracksAllowChunklessPreparation = safeGetBool(src, PROP_SRC_TEXT_TRACKS_ALLOW_CHUNKLESS_PREPARATION, true) + source.sideLoadedTextTracks = SideLoadedTextTrackList.parse(safeGetArray(src, PROP_SRC_TEXT_TRACKS)) val propSrcHeadersArray = safeGetArray(src, PROP_SRC_HEADERS) if (propSrcHeadersArray != null) { diff --git a/android/src/main/java/com/brentvatne/common/api/SubtitleStyle.kt b/android/src/main/java/com/brentvatne/common/api/SubtitleStyle.kt index efb4da0a..1ac0fd03 100644 --- a/android/src/main/java/com/brentvatne/common/api/SubtitleStyle.kt +++ b/android/src/main/java/com/brentvatne/common/api/SubtitleStyle.kt @@ -6,7 +6,7 @@ import com.facebook.react.bridge.ReadableMap /** * Helper file to parse SubtitleStyle prop and build a dedicated class */ -class SubtitleStyle private constructor() { +class SubtitleStyle public constructor() { var fontSize = -1 private set var paddingLeft = 0 @@ -19,6 +19,8 @@ class SubtitleStyle private constructor() { private set var opacity = 1f private set + var subtitlesFollowVideo = true + private set companion object { private const val PROP_FONT_SIZE_TRACK = "fontSize" @@ -27,6 +29,7 @@ class SubtitleStyle private constructor() { private const val PROP_PADDING_LEFT = "paddingLeft" private const val PROP_PADDING_RIGHT = "paddingRight" private const val PROP_OPACITY = "opacity" + private const val PROP_SUBTITLES_FOLLOW_VIDEO = "subtitlesFollowVideo" @JvmStatic fun parse(src: ReadableMap?): SubtitleStyle { @@ -37,6 +40,7 @@ class SubtitleStyle private constructor() { subtitleStyle.paddingLeft = ReactBridgeUtils.safeGetInt(src, PROP_PADDING_LEFT, 0) subtitleStyle.paddingRight = ReactBridgeUtils.safeGetInt(src, PROP_PADDING_RIGHT, 0) subtitleStyle.opacity = ReactBridgeUtils.safeGetFloat(src, PROP_OPACITY, 1f) + subtitleStyle.subtitlesFollowVideo = ReactBridgeUtils.safeGetBool(src, PROP_SUBTITLES_FOLLOW_VIDEO, true) return subtitleStyle } } diff --git a/android/src/main/java/com/brentvatne/common/react/VideoEventEmitter.kt b/android/src/main/java/com/brentvatne/common/react/VideoEventEmitter.kt index 8f29779a..a7be7058 100644 --- a/android/src/main/java/com/brentvatne/common/react/VideoEventEmitter.kt +++ b/android/src/main/java/com/brentvatne/common/react/VideoEventEmitter.kt @@ -48,7 +48,7 @@ enum class EventTypes(val eventName: String) { fun toMap() = mutableMapOf().apply { EventTypes.values().toList().forEach { eventType -> - put("top${eventType.eventName.removePrefix("on")}", mapOf("registrationName" to eventType.eventName)) + put("top${eventType.eventName.removePrefix("on")}", hashMapOf("registrationName" to eventType.eventName)) } } } @@ -64,11 +64,11 @@ class VideoEventEmitter { audioTracks: ArrayList, textTracks: ArrayList, videoTracks: ArrayList, - trackId: String + trackId: String? ) -> Unit lateinit var onVideoError: (errorString: String, exception: Exception, errorCode: String) -> Unit lateinit var onVideoProgress: (currentPosition: Long, bufferedDuration: Long, seekableDuration: Long, currentPlaybackTime: Double) -> Unit - lateinit var onVideoBandwidthUpdate: (bitRateEstimate: Long, height: Int, width: Int, trackId: String) -> Unit + lateinit var onVideoBandwidthUpdate: (bitRateEstimate: Long, height: Int, width: Int, trackId: String?) -> Unit lateinit var onVideoPlaybackStateChanged: (isPlaying: Boolean, isSeeking: Boolean) -> Unit lateinit var onVideoSeek: (currentPosition: Long, seekTime: Long) -> Unit lateinit var onVideoEnd: () -> Unit @@ -108,7 +108,7 @@ class VideoEventEmitter { val naturalSize: WritableMap = aspectRatioToNaturalSize(videoWidth, videoHeight) putMap("naturalSize", naturalSize) - putString("trackId", trackId) + trackId?.let { putString("trackId", it) } putArray("videoTracks", videoTracksToArray(videoTracks)) putArray("audioTracks", audioTracksToArray(audioTracks)) putArray("textTracks", textTracksToArray(textTracks)) @@ -153,9 +153,13 @@ class VideoEventEmitter { onVideoBandwidthUpdate = { bitRateEstimate, height, width, trackId -> event.dispatch(EventTypes.EVENT_BANDWIDTH) { putDouble("bitrate", bitRateEstimate.toDouble()) - putInt("width", width) - putInt("height", height) - putString("trackId", trackId) + if (width > 0) { + putInt("width", width) + } + if (height > 0) { + putInt("height", height) + } + trackId?.let { putString("trackId", it) } } } onVideoPlaybackStateChanged = { isPlaying, isSeeking -> @@ -209,7 +213,7 @@ class VideoEventEmitter { putArray( "metadata", Arguments.createArray().apply { - metadataArrayList.forEachIndexed { i, metadata -> + metadataArrayList.forEachIndexed { _, metadata -> pushMap( Arguments.createMap().apply { putString("identifier", metadata.identifier) @@ -303,7 +307,7 @@ class VideoEventEmitter { private fun videoTracksToArray(videoTracks: java.util.ArrayList?): WritableArray = Arguments.createArray().apply { - videoTracks?.forEachIndexed { i, vTrack -> + videoTracks?.forEachIndexed { _, vTrack -> pushMap( Arguments.createMap().apply { putInt("width", vTrack.width) @@ -336,15 +340,19 @@ class VideoEventEmitter { private fun aspectRatioToNaturalSize(videoWidth: Int, videoHeight: Int): WritableMap = Arguments.createMap().apply { - putInt("width", videoWidth) - putInt("height", videoHeight) - val orientation = if (videoWidth > videoHeight) { - "landscape" - } else if (videoWidth < videoHeight) { - "portrait" - } else { - "square" + if (videoWidth > 0) { + putInt("width", videoWidth) } + if (videoHeight > 0) { + putInt("height", videoHeight) + } + + val orientation = when { + videoWidth > videoHeight -> "landscape" + videoWidth < videoHeight -> "portrait" + else -> "square" + } + putString("orientation", orientation) } } diff --git a/android/src/main/java/com/brentvatne/common/toolbox/ReactBridgeUtils.kt b/android/src/main/java/com/brentvatne/common/toolbox/ReactBridgeUtils.kt index 10f4752a..b4cce426 100644 --- a/android/src/main/java/com/brentvatne/common/toolbox/ReactBridgeUtils.kt +++ b/android/src/main/java/com/brentvatne/common/toolbox/ReactBridgeUtils.kt @@ -3,7 +3,6 @@ package com.brentvatne.common.toolbox import com.facebook.react.bridge.Dynamic import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap -import java.util.HashMap /* * Toolbox to safe parsing of
+ We are TheWidlarzGroup + + Premium support → + +
+ + ), + }, + useNextSeoProps() { return { titleTemplate: '%s – Video', diff --git a/examples/basic/android/app/build.gradle b/examples/basic/android/app/build.gradle index fa4d074b..8234f548 100644 --- a/examples/basic/android/app/build.gradle +++ b/examples/basic/android/app/build.gradle @@ -83,8 +83,6 @@ android { namespace "com.videoplayer" compileOptions { - // These options are necessary to be able to build fro source - coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } @@ -155,8 +153,6 @@ dependencies { because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib") } } - // coreLibraryDesugaring is mandatory to be able to build exoplayer from source - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' } apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) diff --git a/examples/basic/ios/Podfile.lock b/examples/basic/ios/Podfile.lock index b3681ae4..124bb1a6 100644 --- a/examples/basic/ios/Podfile.lock +++ b/examples/basic/ios/Podfile.lock @@ -3,15 +3,15 @@ PODS: - DoubleConversion (1.1.6) - EXConstants (16.0.2): - ExpoModulesCore - - Expo (51.0.17): + - Expo (51.0.32): - ExpoModulesCore - ExpoAsset (10.0.10): - ExpoModulesCore - ExpoFileSystem (17.0.1): - ExpoModulesCore - - ExpoFont (12.0.7): + - ExpoFont (12.0.10): - ExpoModulesCore - - ExpoImage (1.12.12): + - ExpoImage (1.12.15): - ExpoModulesCore - libavif/libdav1d - SDWebImage (~> 5.19.1) @@ -20,7 +20,7 @@ PODS: - SDWebImageWebPCoder (~> 0.14.6) - ExpoKeepAwake (13.0.2): - ExpoModulesCore - - ExpoModulesCore (1.12.18): + - ExpoModulesCore (1.12.24): - DoubleConversion - glog - hermes-engine @@ -43,12 +43,12 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - FBLazyVector (0.74.3) + - FBLazyVector (0.74.5) - fmt (9.1.0) - glog (0.3.5) - - hermes-engine (0.74.3): - - hermes-engine/Pre-built (= 0.74.3) - - hermes-engine/Pre-built (0.74.3) + - hermes-engine (0.74.5): + - hermes-engine/Pre-built (= 0.74.5) + - hermes-engine/Pre-built (0.74.5) - libavif/core (0.11.1) - libavif/libdav1d (0.11.1): - libavif/core @@ -82,27 +82,27 @@ PODS: - DoubleConversion - fmt (= 9.1.0) - glog - - RCTDeprecation (0.74.3) - - RCTRequired (0.74.3) - - RCTTypeSafety (0.74.3): - - FBLazyVector (= 0.74.3) - - RCTRequired (= 0.74.3) - - React-Core (= 0.74.3) - - React (0.74.3): - - React-Core (= 0.74.3) - - React-Core/DevSupport (= 0.74.3) - - React-Core/RCTWebSocket (= 0.74.3) - - React-RCTActionSheet (= 0.74.3) - - React-RCTAnimation (= 0.74.3) - - React-RCTBlob (= 0.74.3) - - React-RCTImage (= 0.74.3) - - React-RCTLinking (= 0.74.3) - - React-RCTNetwork (= 0.74.3) - - React-RCTSettings (= 0.74.3) - - React-RCTText (= 0.74.3) - - React-RCTVibration (= 0.74.3) - - React-callinvoker (0.74.3) - - React-Codegen (0.74.3): + - RCTDeprecation (0.74.5) + - RCTRequired (0.74.5) + - RCTTypeSafety (0.74.5): + - FBLazyVector (= 0.74.5) + - RCTRequired (= 0.74.5) + - React-Core (= 0.74.5) + - React (0.74.5): + - React-Core (= 0.74.5) + - React-Core/DevSupport (= 0.74.5) + - React-Core/RCTWebSocket (= 0.74.5) + - React-RCTActionSheet (= 0.74.5) + - React-RCTAnimation (= 0.74.5) + - React-RCTBlob (= 0.74.5) + - React-RCTImage (= 0.74.5) + - React-RCTLinking (= 0.74.5) + - React-RCTNetwork (= 0.74.5) + - React-RCTSettings (= 0.74.5) + - React-RCTText (= 0.74.5) + - React-RCTVibration (= 0.74.5) + - React-callinvoker (0.74.5) + - React-Codegen (0.74.5): - DoubleConversion - glog - hermes-engine @@ -122,12 +122,12 @@ PODS: - React-utils - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - React-Core (0.74.3): + - React-Core (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - RCTDeprecation - - React-Core/Default (= 0.74.3) + - React-Core/Default (= 0.74.5) - React-cxxreact - React-featureflags - React-hermes @@ -139,7 +139,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/CoreModulesHeaders (0.74.3): + - React-Core/CoreModulesHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -156,7 +156,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/Default (0.74.3): + - React-Core/Default (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -172,13 +172,13 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/DevSupport (0.74.3): + - React-Core/DevSupport (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - RCTDeprecation - - React-Core/Default (= 0.74.3) - - React-Core/RCTWebSocket (= 0.74.3) + - React-Core/Default (= 0.74.5) + - React-Core/RCTWebSocket (= 0.74.5) - React-cxxreact - React-featureflags - React-hermes @@ -190,7 +190,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTActionSheetHeaders (0.74.3): + - React-Core/RCTActionSheetHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -207,7 +207,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTAnimationHeaders (0.74.3): + - React-Core/RCTAnimationHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -224,7 +224,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTBlobHeaders (0.74.3): + - React-Core/RCTBlobHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -241,7 +241,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTImageHeaders (0.74.3): + - React-Core/RCTImageHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -258,7 +258,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTLinkingHeaders (0.74.3): + - React-Core/RCTLinkingHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -275,7 +275,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTNetworkHeaders (0.74.3): + - React-Core/RCTNetworkHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -292,7 +292,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTSettingsHeaders (0.74.3): + - React-Core/RCTSettingsHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -309,7 +309,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTTextHeaders (0.74.3): + - React-Core/RCTTextHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -326,7 +326,7 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTVibrationHeaders (0.74.3): + - React-Core/RCTVibrationHeaders (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -343,12 +343,12 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-Core/RCTWebSocket (0.74.3): + - React-Core/RCTWebSocket (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - RCTDeprecation - - React-Core/Default (= 0.74.3) + - React-Core/Default (= 0.74.5) - React-cxxreact - React-featureflags - React-hermes @@ -360,36 +360,36 @@ PODS: - React-utils - SocketRocket (= 0.7.0) - Yoga - - React-CoreModules (0.74.3): + - React-CoreModules (0.74.5): - DoubleConversion - fmt (= 9.1.0) - RCT-Folly (= 2024.01.01.00) - - RCTTypeSafety (= 0.74.3) + - RCTTypeSafety (= 0.74.5) - React-Codegen - - React-Core/CoreModulesHeaders (= 0.74.3) - - React-jsi (= 0.74.3) + - React-Core/CoreModulesHeaders (= 0.74.5) + - React-jsi (= 0.74.5) - React-jsinspector - React-NativeModulesApple - React-RCTBlob - - React-RCTImage (= 0.74.3) + - React-RCTImage (= 0.74.5) - ReactCommon - SocketRocket (= 0.7.0) - - React-cxxreact (0.74.3): + - React-cxxreact (0.74.5): - boost (= 1.83.0) - DoubleConversion - fmt (= 9.1.0) - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - - React-callinvoker (= 0.74.3) - - React-debug (= 0.74.3) - - React-jsi (= 0.74.3) + - React-callinvoker (= 0.74.5) + - React-debug (= 0.74.5) + - React-jsi (= 0.74.5) - React-jsinspector - - React-logger (= 0.74.3) - - React-perflogger (= 0.74.3) - - React-runtimeexecutor (= 0.74.3) - - React-debug (0.74.3) - - React-Fabric (0.74.3): + - React-logger (= 0.74.5) + - React-perflogger (= 0.74.5) + - React-runtimeexecutor (= 0.74.5) + - React-debug (0.74.5) + - React-Fabric (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -400,20 +400,20 @@ PODS: - React-Core - React-cxxreact - React-debug - - React-Fabric/animations (= 0.74.3) - - React-Fabric/attributedstring (= 0.74.3) - - React-Fabric/componentregistry (= 0.74.3) - - React-Fabric/componentregistrynative (= 0.74.3) - - React-Fabric/components (= 0.74.3) - - React-Fabric/core (= 0.74.3) - - React-Fabric/imagemanager (= 0.74.3) - - React-Fabric/leakchecker (= 0.74.3) - - React-Fabric/mounting (= 0.74.3) - - React-Fabric/scheduler (= 0.74.3) - - React-Fabric/telemetry (= 0.74.3) - - React-Fabric/templateprocessor (= 0.74.3) - - React-Fabric/textlayoutmanager (= 0.74.3) - - React-Fabric/uimanager (= 0.74.3) + - React-Fabric/animations (= 0.74.5) + - React-Fabric/attributedstring (= 0.74.5) + - React-Fabric/componentregistry (= 0.74.5) + - React-Fabric/componentregistrynative (= 0.74.5) + - React-Fabric/components (= 0.74.5) + - React-Fabric/core (= 0.74.5) + - React-Fabric/imagemanager (= 0.74.5) + - React-Fabric/leakchecker (= 0.74.5) + - React-Fabric/mounting (= 0.74.5) + - React-Fabric/scheduler (= 0.74.5) + - React-Fabric/telemetry (= 0.74.5) + - React-Fabric/templateprocessor (= 0.74.5) + - React-Fabric/textlayoutmanager (= 0.74.5) + - React-Fabric/uimanager (= 0.74.5) - React-graphics - React-jsi - React-jsiexecutor @@ -422,7 +422,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/animations (0.74.3): + - React-Fabric/animations (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -441,7 +441,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/attributedstring (0.74.3): + - React-Fabric/attributedstring (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -460,7 +460,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/componentregistry (0.74.3): + - React-Fabric/componentregistry (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -479,7 +479,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/componentregistrynative (0.74.3): + - React-Fabric/componentregistrynative (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -498,7 +498,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components (0.74.3): + - React-Fabric/components (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -509,17 +509,17 @@ PODS: - React-Core - React-cxxreact - React-debug - - React-Fabric/components/inputaccessory (= 0.74.3) - - React-Fabric/components/legacyviewmanagerinterop (= 0.74.3) - - React-Fabric/components/modal (= 0.74.3) - - React-Fabric/components/rncore (= 0.74.3) - - React-Fabric/components/root (= 0.74.3) - - React-Fabric/components/safeareaview (= 0.74.3) - - React-Fabric/components/scrollview (= 0.74.3) - - React-Fabric/components/text (= 0.74.3) - - React-Fabric/components/textinput (= 0.74.3) - - React-Fabric/components/unimplementedview (= 0.74.3) - - React-Fabric/components/view (= 0.74.3) + - React-Fabric/components/inputaccessory (= 0.74.5) + - React-Fabric/components/legacyviewmanagerinterop (= 0.74.5) + - React-Fabric/components/modal (= 0.74.5) + - React-Fabric/components/rncore (= 0.74.5) + - React-Fabric/components/root (= 0.74.5) + - React-Fabric/components/safeareaview (= 0.74.5) + - React-Fabric/components/scrollview (= 0.74.5) + - React-Fabric/components/text (= 0.74.5) + - React-Fabric/components/textinput (= 0.74.5) + - React-Fabric/components/unimplementedview (= 0.74.5) + - React-Fabric/components/view (= 0.74.5) - React-graphics - React-jsi - React-jsiexecutor @@ -528,7 +528,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/inputaccessory (0.74.3): + - React-Fabric/components/inputaccessory (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -547,7 +547,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/legacyviewmanagerinterop (0.74.3): + - React-Fabric/components/legacyviewmanagerinterop (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -566,7 +566,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/modal (0.74.3): + - React-Fabric/components/modal (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -585,7 +585,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/rncore (0.74.3): + - React-Fabric/components/rncore (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -604,7 +604,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/root (0.74.3): + - React-Fabric/components/root (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -623,7 +623,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/safeareaview (0.74.3): + - React-Fabric/components/safeareaview (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -642,7 +642,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/scrollview (0.74.3): + - React-Fabric/components/scrollview (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -661,7 +661,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/text (0.74.3): + - React-Fabric/components/text (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -680,7 +680,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/textinput (0.74.3): + - React-Fabric/components/textinput (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -699,7 +699,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/unimplementedview (0.74.3): + - React-Fabric/components/unimplementedview (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -718,7 +718,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/view (0.74.3): + - React-Fabric/components/view (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -738,7 +738,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-Fabric/core (0.74.3): + - React-Fabric/core (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -757,7 +757,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/imagemanager (0.74.3): + - React-Fabric/imagemanager (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -776,7 +776,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/leakchecker (0.74.3): + - React-Fabric/leakchecker (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -795,7 +795,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/mounting (0.74.3): + - React-Fabric/mounting (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -814,7 +814,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/scheduler (0.74.3): + - React-Fabric/scheduler (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -833,7 +833,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/telemetry (0.74.3): + - React-Fabric/telemetry (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -852,7 +852,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/templateprocessor (0.74.3): + - React-Fabric/templateprocessor (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -871,7 +871,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/textlayoutmanager (0.74.3): + - React-Fabric/textlayoutmanager (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -891,7 +891,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/uimanager (0.74.3): + - React-Fabric/uimanager (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog @@ -910,45 +910,45 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-FabricImage (0.74.3): + - React-FabricImage (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.01.01.00) - - RCTRequired (= 0.74.3) - - RCTTypeSafety (= 0.74.3) + - RCTRequired (= 0.74.5) + - RCTTypeSafety (= 0.74.5) - React-Fabric - React-graphics - React-ImageManager - React-jsi - - React-jsiexecutor (= 0.74.3) + - React-jsiexecutor (= 0.74.5) - React-logger - React-rendererdebug - React-utils - ReactCommon - Yoga - - React-featureflags (0.74.3) - - React-graphics (0.74.3): + - React-featureflags (0.74.5) + - React-graphics (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog - RCT-Folly/Fabric (= 2024.01.01.00) - - React-Core/Default (= 0.74.3) + - React-Core/Default (= 0.74.5) - React-utils - - React-hermes (0.74.3): + - React-hermes (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - - React-cxxreact (= 0.74.3) + - React-cxxreact (= 0.74.5) - React-jsi - - React-jsiexecutor (= 0.74.3) + - React-jsiexecutor (= 0.74.5) - React-jsinspector - - React-perflogger (= 0.74.3) + - React-perflogger (= 0.74.5) - React-runtimeexecutor - - React-ImageManager (0.74.3): + - React-ImageManager (0.74.5): - glog - RCT-Folly/Fabric - React-Core/Default @@ -957,44 +957,44 @@ PODS: - React-graphics - React-rendererdebug - React-utils - - React-jserrorhandler (0.74.3): + - React-jserrorhandler (0.74.5): - RCT-Folly/Fabric (= 2024.01.01.00) - React-debug - React-jsi - React-Mapbuffer - - React-jsi (0.74.3): + - React-jsi (0.74.5): - boost (= 1.83.0) - DoubleConversion - fmt (= 9.1.0) - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - - React-jsiexecutor (0.74.3): + - React-jsiexecutor (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - - React-cxxreact (= 0.74.3) - - React-jsi (= 0.74.3) + - React-cxxreact (= 0.74.5) + - React-jsi (= 0.74.5) - React-jsinspector - - React-perflogger (= 0.74.3) - - React-jsinspector (0.74.3): + - React-perflogger (= 0.74.5) + - React-jsinspector (0.74.5): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - React-featureflags - React-jsi - - React-runtimeexecutor (= 0.74.3) - - React-jsitracing (0.74.3): + - React-runtimeexecutor (= 0.74.5) + - React-jsitracing (0.74.5): - React-jsi - - React-logger (0.74.3): + - React-logger (0.74.5): - glog - - React-Mapbuffer (0.74.3): + - React-Mapbuffer (0.74.5): - glog - React-debug - - react-native-video (6.3.0): + - react-native-video (6.6.2): - DoubleConversion - glog - hermes-engine @@ -1008,7 +1008,7 @@ PODS: - React-featureflags - React-graphics - React-ImageManager - - react-native-video/Video (= 6.3.0) + - react-native-video/Video (= 6.6.2) - React-NativeModulesApple - React-RCTFabric - React-rendererdebug @@ -1038,7 +1038,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-video/Video (6.3.0): + - react-native-video/Video (6.6.2): - DoubleConversion - glog - hermes-engine @@ -1059,8 +1059,8 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - React-nativeconfig (0.74.3) - - React-NativeModulesApple (0.74.3): + - React-nativeconfig (0.74.5) + - React-NativeModulesApple (0.74.5): - glog - hermes-engine - React-callinvoker @@ -1071,10 +1071,10 @@ PODS: - React-runtimeexecutor - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - React-perflogger (0.74.3) - - React-RCTActionSheet (0.74.3): - - React-Core/RCTActionSheetHeaders (= 0.74.3) - - React-RCTAnimation (0.74.3): + - React-perflogger (0.74.5) + - React-RCTActionSheet (0.74.5): + - React-Core/RCTActionSheetHeaders (= 0.74.5) + - React-RCTAnimation (0.74.5): - RCT-Folly (= 2024.01.01.00) - RCTTypeSafety - React-Codegen @@ -1082,7 +1082,7 @@ PODS: - React-jsi - React-NativeModulesApple - ReactCommon - - React-RCTAppDelegate (0.74.3): + - React-RCTAppDelegate (0.74.5): - RCT-Folly (= 2024.01.01.00) - RCTRequired - RCTTypeSafety @@ -1106,7 +1106,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon - - React-RCTBlob (0.74.3): + - React-RCTBlob (0.74.5): - DoubleConversion - fmt (= 9.1.0) - hermes-engine @@ -1119,7 +1119,7 @@ PODS: - React-NativeModulesApple - React-RCTNetwork - ReactCommon - - React-RCTFabric (0.74.3): + - React-RCTFabric (0.74.5): - glog - hermes-engine - RCT-Folly/Fabric (= 2024.01.01.00) @@ -1139,7 +1139,7 @@ PODS: - React-runtimescheduler - React-utils - Yoga - - React-RCTImage (0.74.3): + - React-RCTImage (0.74.5): - RCT-Folly (= 2024.01.01.00) - RCTTypeSafety - React-Codegen @@ -1148,14 +1148,14 @@ PODS: - React-NativeModulesApple - React-RCTNetwork - ReactCommon - - React-RCTLinking (0.74.3): + - React-RCTLinking (0.74.5): - React-Codegen - - React-Core/RCTLinkingHeaders (= 0.74.3) - - React-jsi (= 0.74.3) + - React-Core/RCTLinkingHeaders (= 0.74.5) + - React-jsi (= 0.74.5) - React-NativeModulesApple - ReactCommon - - ReactCommon/turbomodule/core (= 0.74.3) - - React-RCTNetwork (0.74.3): + - ReactCommon/turbomodule/core (= 0.74.5) + - React-RCTNetwork (0.74.5): - RCT-Folly (= 2024.01.01.00) - RCTTypeSafety - React-Codegen @@ -1163,7 +1163,7 @@ PODS: - React-jsi - React-NativeModulesApple - ReactCommon - - React-RCTSettings (0.74.3): + - React-RCTSettings (0.74.5): - RCT-Folly (= 2024.01.01.00) - RCTTypeSafety - React-Codegen @@ -1171,23 +1171,23 @@ PODS: - React-jsi - React-NativeModulesApple - ReactCommon - - React-RCTText (0.74.3): - - React-Core/RCTTextHeaders (= 0.74.3) + - React-RCTText (0.74.5): + - React-Core/RCTTextHeaders (= 0.74.5) - Yoga - - React-RCTVibration (0.74.3): + - React-RCTVibration (0.74.5): - RCT-Folly (= 2024.01.01.00) - React-Codegen - React-Core/RCTVibrationHeaders - React-jsi - React-NativeModulesApple - ReactCommon - - React-rendererdebug (0.74.3): + - React-rendererdebug (0.74.5): - DoubleConversion - fmt (= 9.1.0) - RCT-Folly (= 2024.01.01.00) - React-debug - - React-rncore (0.74.3) - - React-RuntimeApple (0.74.3): + - React-rncore (0.74.5) + - React-RuntimeApple (0.74.5): - hermes-engine - RCT-Folly/Fabric (= 2024.01.01.00) - React-callinvoker @@ -1205,7 +1205,7 @@ PODS: - React-runtimeexecutor - React-RuntimeHermes - React-utils - - React-RuntimeCore (0.74.3): + - React-RuntimeCore (0.74.5): - glog - hermes-engine - RCT-Folly/Fabric (= 2024.01.01.00) @@ -1218,9 +1218,9 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - React-runtimeexecutor (0.74.3): - - React-jsi (= 0.74.3) - - React-RuntimeHermes (0.74.3): + - React-runtimeexecutor (0.74.5): + - React-jsi (= 0.74.5) + - React-RuntimeHermes (0.74.5): - hermes-engine - RCT-Folly/Fabric (= 2024.01.01.00) - React-featureflags @@ -1231,7 +1231,7 @@ PODS: - React-nativeconfig - React-RuntimeCore - React-utils - - React-runtimescheduler (0.74.3): + - React-runtimescheduler (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -1243,56 +1243,56 @@ PODS: - React-rendererdebug - React-runtimeexecutor - React-utils - - React-utils (0.74.3): + - React-utils (0.74.5): - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - React-debug - - React-jsi (= 0.74.3) - - ReactCommon (0.74.3): - - ReactCommon/turbomodule (= 0.74.3) - - ReactCommon/turbomodule (0.74.3): + - React-jsi (= 0.74.5) + - ReactCommon (0.74.5): + - ReactCommon/turbomodule (= 0.74.5) + - ReactCommon/turbomodule (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - - React-callinvoker (= 0.74.3) - - React-cxxreact (= 0.74.3) - - React-jsi (= 0.74.3) - - React-logger (= 0.74.3) - - React-perflogger (= 0.74.3) - - ReactCommon/turbomodule/bridging (= 0.74.3) - - ReactCommon/turbomodule/core (= 0.74.3) - - ReactCommon/turbomodule/bridging (0.74.3): + - React-callinvoker (= 0.74.5) + - React-cxxreact (= 0.74.5) + - React-jsi (= 0.74.5) + - React-logger (= 0.74.5) + - React-perflogger (= 0.74.5) + - ReactCommon/turbomodule/bridging (= 0.74.5) + - ReactCommon/turbomodule/core (= 0.74.5) + - ReactCommon/turbomodule/bridging (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - - React-callinvoker (= 0.74.3) - - React-cxxreact (= 0.74.3) - - React-jsi (= 0.74.3) - - React-logger (= 0.74.3) - - React-perflogger (= 0.74.3) - - ReactCommon/turbomodule/core (0.74.3): + - React-callinvoker (= 0.74.5) + - React-cxxreact (= 0.74.5) + - React-jsi (= 0.74.5) + - React-logger (= 0.74.5) + - React-perflogger (= 0.74.5) + - ReactCommon/turbomodule/core (0.74.5): - DoubleConversion - fmt (= 9.1.0) - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) - - React-callinvoker (= 0.74.3) - - React-cxxreact (= 0.74.3) - - React-debug (= 0.74.3) - - React-jsi (= 0.74.3) - - React-logger (= 0.74.3) - - React-perflogger (= 0.74.3) - - React-utils (= 0.74.3) + - React-callinvoker (= 0.74.5) + - React-cxxreact (= 0.74.5) + - React-debug (= 0.74.5) + - React-jsi (= 0.74.5) + - React-logger (= 0.74.5) + - React-perflogger (= 0.74.5) + - React-utils (= 0.74.5) - RNCPicker (2.7.5): - React-Core - - SDWebImage (5.19.2): - - SDWebImage/Core (= 5.19.2) - - SDWebImage/Core (5.19.2) + - SDWebImage (5.19.7): + - SDWebImage/Core (= 5.19.7) + - SDWebImage/Core (5.19.7) - SDWebImageAVIFCoder (0.11.0): - libavif/core (>= 0.11.0) - SDWebImage (~> 5.10) @@ -1521,76 +1521,76 @@ SPEC CHECKSUMS: boost: d3f49c53809116a5d38da093a8aa78bf551aed09 DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 EXConstants: 409690fbfd5afea964e5e9d6c4eb2c2b59222c59 - Expo: 675a5642b5860771507237259da50b921c03a9f3 + Expo: 33132a667698a3259a4e6c0af1b4936388e5fa33 ExpoAsset: 323700f291684f110fb55f0d4022a3362ea9f875 ExpoFileSystem: 80bfe850b1f9922c16905822ecbf97acd711dc51 - ExpoFont: 43b69559cef3d773db57c7ae7edd3cb0aa0dc610 - ExpoImage: 2ccccff1219ebc765e344f3338f2430af2df4824 + ExpoFont: 00756e6c796d8f7ee8d211e29c8b619e75cbf238 + ExpoImage: f77df382153d716f332f974438a803c4527f60b0 ExpoKeepAwake: 3b8815d9dd1d419ee474df004021c69fdd316d08 - ExpoModulesCore: b2fa8cc3c12f0ba45a9ae125c0e3bcad04f3fb7b - FBLazyVector: 7e977dd099937dc5458851233141583abba49ff2 + ExpoModulesCore: db3e31e694684f08223d713e89f7648c6d3e04d0 + FBLazyVector: ac12dc084d1c8ec4cc4d7b3cf1b0ebda6dab85af fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 glog: fdfdfe5479092de0c4bdbebedd9056951f092c4f - hermes-engine: 1f547997900dd0752dc0cc0ae6dd16173c49e09b + hermes-engine: 8c1577f3fdb849cbe7729c2e7b5abc4b845e88f8 libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7 libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 RCT-Folly: 02617c592a293bd6d418e0a88ff4ee1f88329b47 - RCTDeprecation: 4c7eeb42be0b2e95195563c49be08d0b839d22b4 - RCTRequired: d530a0f489699c8500e944fde963102c42dcd0c2 - RCTTypeSafety: b20878506b094fa3d9007d7b9e4be0faa3562499 - React: 2f9da0177233f60fa3462d83fcccde245759f81a - React-callinvoker: d0205f0dcebf72ec27263ab41e3a5ad827ed503f - React-Codegen: 27212e14727ad7d6d9fd1b1967fbf21929e4ce29 - React-Core: 690ebbbf8f8dcfba6686ce8927731d3f025c3114 - React-CoreModules: 185da31f5eb2e6043c3d19b10c64c4661322ed6a - React-cxxreact: c53d2ac9246235351086b8c588feaf775b4ec7f7 - React-debug: 40caf8ab4c0fd3afe831912e3d4d0e7303eecc5d - React-Fabric: 51ccb4f7e45df5837e796f339d602737063c463e - React-FabricImage: 376b7a81bfe64102e7da5fc85cd1775638584c92 - React-featureflags: 0d0576ae8306801a8a660b36afcdbda04dd7cc12 - React-graphics: e0e6b8fbb1c5968c70d3584dccec42544b769b60 - React-hermes: 917b7ab4c3cb9204c2ad020d74f313830097148b - React-ImageManager: 5cebcc0136f3b309c7f5189b96e6c0ebd0ec8192 - React-jserrorhandler: 5dc7e036cba3b7d167380c02afabf818ad0b2f98 - React-jsi: 024b933267079f80c30a5cae97bf5ce521217505 - React-jsiexecutor: 45cb079c87db3f514da3acfc686387a0e01de5c5 - React-jsinspector: c9551971f1298163c93e2bfb082c2b4245618fc6 - React-jsitracing: 1aa5681c353b41573b03e0e480a5adf5fa1c56d8 - React-logger: fa92ba4d3a5d39ac450f59be2a3cec7b099f0304 - React-Mapbuffer: 70da5955150a58732e9336a0c7e71cd49e909f25 - react-native-video: c44719c9a5261ad54fdad49e6dd0e98439e0e1b3 + RCTDeprecation: 3afceddffa65aee666dafd6f0116f1d975db1584 + RCTRequired: ec1239bc9d8bf63e10fb92bd8b26171a9258e0c1 + RCTTypeSafety: f5ecbc86c5c5fa163c05acb7a1c5012e15b5f994 + React: fc9fa7258eff606f44d58c5b233a82dc9cf09018 + React-callinvoker: e3fab14d69607fb7e8e3a57e5a415aed863d3599 + React-Codegen: bd1a15f54af401efee5f439aa6fd420b10550125 + React-Core: 3a5fd9e781cecf87803e5b091496a606a3df774a + React-CoreModules: cbf4707dafab8f9f826ac0c63a07d0bf5d01e256 + React-cxxreact: 7b188556271e3c7fdf22a04819f6a6225045b9dd + React-debug: 2d6f912c0c4c91a9fde617d8425088af7315c10b + React-Fabric: 47ff62e0c7f017606585327f6016190625295c5e + React-FabricImage: 823627aa521b4ecc896334f0dbf2bc8376edbf1e + React-featureflags: 2a4555681de0d4b683d98d7e9fd7bdf9e9ce1aa2 + React-graphics: edbd2a6c018b2e2d541ab8cb886cc31babf14646 + React-hermes: a7054fbcbda3957e3c5eaad06ef9bf79998d535a + React-ImageManager: 314824c4bb6f152699724dc9eb3ce544b87048bd + React-jserrorhandler: fffe10523886a352161ef492af2063651721c8ee + React-jsi: f3ce1dd2e950b6ad12b65ea3ef89168f1b94c584 + React-jsiexecutor: b4df3a27973d82f9abf3c4bd0f88e042cda25f16 + React-jsinspector: 2ea90b8e53970a1fea1449fb8e6419e21ca79867 + React-jsitracing: c83efb63c8e9e1dff72a3c56e88ae1c530a87795 + React-logger: 257858bd55f3a4e1bc0cf07ddc8fb9faba6f8c7c + React-Mapbuffer: dce508662b995ffefd29e278a16b78217039d43d + react-native-video: b52a7473fd467d8c18032535ec5f332b81f9bdf0 react-native-video-plugin-sample: d3a93b7ad777cad7fa2c30473de75a2635ce5feb - React-nativeconfig: 84806b820491db30175afbf027e99e8415dc63f0 - React-NativeModulesApple: 7b79212f8cf496ab554e0b7b09acbd4aa4690260 - React-perflogger: 7bb9ba49435ff66b666e7966ee10082508a203e8 - React-RCTActionSheet: a2816ae2b5c8523c2bc18a8f874a724a096e6d97 - React-RCTAnimation: e78f52d7422bac13e1213e25e9bcbf99be872e1a - React-RCTAppDelegate: 24f46de486cfa3a9f46e4b0786eaf17d92e1e0c6 - React-RCTBlob: 9f9d6599d1b00690704dadc4a4bc33a7e76938be - React-RCTFabric: 416d20a24b117a7ec7d32088fc8f359b5e558fa7 - React-RCTImage: 39dd5aee6b92213845e1e7a7c41865801dc33493 - React-RCTLinking: 35d742a982f901f9ea416d772763e2da65c2dc7d - React-RCTNetwork: b078576c0c896c71905f841716b9f9f5922111dc - React-RCTSettings: 900aab52b5b1212f247c2944d88f4defbf6146f2 - React-RCTText: a3895ab4e5df4a5fd41b6f059eed484a0c7016d1 - React-RCTVibration: ab4912e1427d8de00ef89e9e6582094c4c25dc05 - React-rendererdebug: 8ea55aebb8cba804db2a8449a2f0c80ccfe0ce5a - React-rncore: 1f725aee4e00c317e51cb4d37aca7f6a47da9a11 - React-RuntimeApple: c1833d8e82f7c5314c001d61d289849c75217944 - React-RuntimeCore: 0a5b37b50737af3505b5801376ae5788532c013e - React-runtimeexecutor: 69cab8ddf409de6d6a855a71c8af9e7290c4e55b - React-RuntimeHermes: 44847ba3e8a9394b9829d9a9abde7590624f32d0 - React-runtimescheduler: e4ad653e1d2f5ff40ba047446cacde009694f0ed - React-utils: 6f7ac39d9a0de447d4334bb25d144a28c0c5d8c9 - ReactCommon: 4a09c7d8a06e93c1e2e988a3b9f3db3d2449f2fc + React-nativeconfig: f326487bc61eba3f0e328da6efb2711533dcac46 + React-NativeModulesApple: d89733f5baed8b9249ca5a8e497d63c550097312 + React-perflogger: ed4e0c65781521e0424f2e5e40b40cc7879d737e + React-RCTActionSheet: 49d53ff03bb5688ca4606c55859053a0cd129ea5 + React-RCTAnimation: 07b4923885c52c397c4ec103924bf6e53b42c73e + React-RCTAppDelegate: 316e295076734baf9bdf1bfac7d92ab647aed930 + React-RCTBlob: 85c57b0d5e667ff8a472163ba3af0628171a64bb + React-RCTFabric: 62695e345da7c451b05a131f0c6ba80367dbd5c3 + React-RCTImage: b965c85bec820e2a9c154b1fb00a2ecdd59a9c92 + React-RCTLinking: 75f04a5f27c26c4e73a39c50df470820d219df79 + React-RCTNetwork: c1a9143f4d5778efc92da40d83969d03912ccc24 + React-RCTSettings: c6800f91c0ecd48868cd5db754b0b0a7f5ffe039 + React-RCTText: b923e24f9b7250bc4f7ab154c4168ad9f8d8fc9d + React-RCTVibration: 08c4f0c917c435b3619386c25a94ee5d64c250f0 + React-rendererdebug: fac75dc155e1202cfc187485a6e4f6e842fcc5c7 + React-rncore: 12dc32f08f195e573e9d969a348b976a3d057bbc + React-RuntimeApple: 5c7591dd19de1c7fefe8e61cf934d8f8f9fc0409 + React-RuntimeCore: ec3c8be706ca2e4607eb8c675d32512352501f9e + React-runtimeexecutor: 0e688aefc14c6bc8601f4968d8d01c3fb6446844 + React-RuntimeHermes: df243bd7c8d4ba3bd237ce6ded22031e02d37908 + React-runtimescheduler: db7189185a2e5912b0d17194302e501f801a381e + React-utils: 3f1fcffc14893afb9a7e5b7c736353873cc5fc95 + ReactCommon: f79ae672224dc1e6c2d932062176883c98eebd57 RNCPicker: 3e2c37a8328f368ce14da050cdc8231deb5fc9f9 - SDWebImage: dfe95b2466a9823cf9f0c6d01217c06550d7b29a + SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3 SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90 SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d - Yoga: eed50599a85bd9f6882a9938d118aed6a397db9c + Yoga: 1ab23c1835475da69cf14e211a560e73aab24cb0 PODFILE CHECKSUM: a73d485df51877001f2b04a5a4379cfa5a3ba8fa diff --git a/examples/basic/package.json b/examples/basic/package.json index 2843b526..d3e5cf21 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -16,14 +16,15 @@ "dependencies": { "@expo/metro-runtime": "~3.2.1", "@react-native-picker/picker": "2.7.5", - "expo": "^51.0.17", - "expo-asset": "^10.0.9", - "expo-image": "^1.12.12", + "expo": "^51.0.32", + "expo-asset": "~10.0.10", + "expo-image": "^1.12.15", + "expo-navigation-bar": "~3.0.7", "react": "18.2.0", - "react-native": "0.74.3", + "react-native": "0.74.5", "react-dom": "18.2.0", "react-native-web": "~0.19.10", - "react-native-windows": "0.74.1" + "react-native-windows": "0.74.19" }, "devDependencies": { "@babel/core": "^7.24.0", diff --git a/examples/basic/src/VideoPlayer.tsx b/examples/basic/src/VideoPlayer.tsx index 76d7c65c..dfe2552f 100644 --- a/examples/basic/src/VideoPlayer.tsx +++ b/examples/basic/src/VideoPlayer.tsx @@ -1,8 +1,8 @@ 'use strict'; -import React, {type FC, useCallback, useRef, useState} from 'react'; +import React, {type FC, useCallback, useRef, useState, useEffect} from 'react'; -import {Platform, TouchableOpacity, View} from 'react-native'; +import {Platform, TouchableOpacity, View, StatusBar} from 'react-native'; import Video, { VideoRef, @@ -26,23 +26,24 @@ import Video, { type OnPlaybackRateChangeData, type OnVideoTracksData, type ReactVideoSource, - type TextTracks, type VideoTrack, type SelectedTrack, type SelectedVideoTrack, type EnumValues, + OnBandwidthUpdateData, + ControlsStyles, } from 'react-native-video'; import styles from './styles'; import {type AdditionalSourceInfo} from './types'; -import {bufferConfig, srcList, textTracksSelectionBy} from './constants'; -import {Overlay, toast} from './components'; - -type AdditionnalSourceInfo = { - textTracks: TextTracks; - adTagUrl: string; - description: string; - noView: boolean; -}; +import { + bufferConfig, + isAndroid, + srcList, + textTracksSelectionBy, + audioTracksSelectionBy, +} from './constants'; +import {Overlay, toast, VideoLoader} from './components'; +import * as NavigationBar from 'expo-navigation-bar'; type Props = NonNullable; @@ -76,7 +77,7 @@ const VideoPlayer: FC = ({}) => { const [repeat, setRepeat] = useState(false); const [controls, setControls] = useState(false); const [useCache, setUseCache] = useState(false); - const [poster, setPoster] = useState(undefined); + const [showPoster, setShowPoster] = useState(false); const [showNotificationControls, setShowNotificationControls] = useState(false); const [isSeeking, setIsSeeking] = useState(false); @@ -111,19 +112,30 @@ const VideoPlayer: FC = ({}) => { goToChannel((srcListId + srcList.length - 1) % srcList.length); }, [goToChannel, srcListId]); + useEffect(() => { + if (isAndroid) { + NavigationBar.setVisibilityAsync('visible'); + } + }, []); + const onAudioTracks = (data: OnAudioTracksData) => { + console.log('onAudioTracks', data); const selectedTrack = data.audioTracks?.find((x: AudioTrack) => { return x.selected; }); - if (selectedTrack?.index) { - setAudioTracks(data.audioTracks); - setSelectedAudioTrack({ - type: SelectedTrackType.INDEX, - value: selectedTrack.index, - }); - } else { - setAudioTracks(data.audioTracks); + let value; + if (audioTracksSelectionBy === SelectedTrackType.INDEX) { + value = selectedTrack?.index; + } else if (audioTracksSelectionBy === SelectedTrackType.LANGUAGE) { + value = selectedTrack?.language; + } else if (audioTracksSelectionBy === SelectedTrackType.TITLE) { + value = selectedTrack?.title; } + setAudioTracks(data.audioTracks); + setSelectedAudioTrack({ + type: audioTracksSelectionBy, + value: value, + }); }; const onVideoTracks = (data: OnVideoTracksData) => { @@ -136,22 +148,19 @@ const VideoPlayer: FC = ({}) => { return x?.selected; }); - if (selectedTrack?.language) { - setTextTracks(data.textTracks); - if (textTracksSelectionBy === 'index') { - setSelectedTextTrack({ - type: SelectedTrackType.INDEX, - value: selectedTrack?.index, - }); - } else { - setSelectedTextTrack({ - type: SelectedTrackType.LANGUAGE, - value: selectedTrack?.language, - }); - } - } else { - setTextTracks(data.textTracks); + setTextTracks(data.textTracks); + let value; + if (textTracksSelectionBy === SelectedTrackType.INDEX) { + value = selectedTrack?.index; + } else if (textTracksSelectionBy === SelectedTrackType.LANGUAGE) { + value = selectedTrack?.language; + } else if (textTracksSelectionBy === SelectedTrackType.TITLE) { + value = selectedTrack?.title; } + setSelectedTextTrack({ + type: textTracksSelectionBy, + value: value, + }); }; const onLoad = (data: OnLoadData) => { @@ -221,28 +230,48 @@ const VideoPlayer: FC = ({}) => { console.log('onPlaybackStateChanged', data); }; + const onVideoBandwidthUpdate = (data: OnBandwidthUpdateData) => { + console.log('onVideoBandwidthUpdate', data); + }; + const onFullScreenExit = () => { // iOS pauses video on exit from full screen Platform.OS === 'ios' && setPaused(true); }; + const _renderLoader = showPoster ? () => : undefined; + + const _subtitleStyle = {subtitlesFollowVideo: true}; + const _controlsStyles : ControlsStyles = { + hideNavigationBarOnFullScreenMode: true, + hideNotificationBarOnFullScreenMode: true, + liveLabel: "LIVE" + }; + const _bufferConfig = { + ...bufferConfig, + cacheSizeMB: useCache ? 200 : 0, + }; + + useEffect(() => { + videoRef.current?.setSource(currentSrc) + }, [currentSrc]) + return ( +