diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index c6c23d942..246a6e45f 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -28,6 +28,12 @@ PODS: - Flutter - isar_flutter_libs (1.0.0): - Flutter + - media_kit_libs_ios_video (1.0.4): + - Flutter + - media_kit_native_event_loop (1.0.0): + - Flutter + - media_kit_video (0.0.1): + - Flutter - package_info_plus (0.4.5): - Flutter - path_provider_foundation (0.0.1): @@ -42,6 +48,8 @@ PODS: - FlutterMacOS - ReachabilitySwift (5.0.0) - SAMKeychain (1.5.3) + - screen_brightness_ios (0.1.0): + - Flutter - share_plus (0.0.1): - Flutter - shared_preferences_foundation (0.0.1): @@ -55,6 +63,8 @@ PODS: - Flutter - video_player_avfoundation (0.0.1): - Flutter + - volume_controller (0.0.1): + - Flutter - wakelock_plus (0.0.1): - Flutter @@ -71,16 +81,21 @@ DEPENDENCIES: - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - integration_test (from `.symlinks/plugins/integration_test/ios`) - isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`) + - media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`) + - media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`) + - media_kit_video (from `.symlinks/plugins/media_kit_video/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - photo_manager (from `.symlinks/plugins/photo_manager/ios`) + - screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite (from `.symlinks/plugins/sqflite/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`) + - volume_controller (from `.symlinks/plugins/volume_controller/ios`) - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) SPEC REPOS: @@ -115,6 +130,12 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/integration_test/ios" isar_flutter_libs: :path: ".symlinks/plugins/isar_flutter_libs/ios" + media_kit_libs_ios_video: + :path: ".symlinks/plugins/media_kit_libs_ios_video/ios" + media_kit_native_event_loop: + :path: ".symlinks/plugins/media_kit_native_event_loop/ios" + media_kit_video: + :path: ".symlinks/plugins/media_kit_video/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: @@ -125,6 +146,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/permission_handler_apple/ios" photo_manager: :path: ".symlinks/plugins/photo_manager/ios" + screen_brightness_ios: + :path: ".symlinks/plugins/screen_brightness_ios/ios" share_plus: :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: @@ -135,6 +158,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/url_launcher_ios/ios" video_player_avfoundation: :path: ".symlinks/plugins/video_player_avfoundation/ios" + volume_controller: + :path: ".symlinks/plugins/volume_controller/ios" wakelock_plus: :path: ".symlinks/plugins/wakelock_plus/ios" @@ -152,6 +177,9 @@ SPEC CHECKSUMS: image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 integration_test: 13825b8a9334a850581300559b8839134b124670 isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073 + media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 + media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a + media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 @@ -159,14 +187,16 @@ SPEC CHECKSUMS: photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c + screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126 + volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9 wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 PODFILE CHECKSUM: 599d8aeb73728400c15364e734525722250a5382 -COCOAPODS: 1.12.1 +COCOAPODS: 1.11.3 diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 3ad2f4b62..6cf3ecb86 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -35,6 +35,7 @@ import 'package:immich_mobile/utils/immich_app_theme.dart'; import 'package:immich_mobile/utils/migration.dart'; import 'package:isar/isar.dart'; import 'package:logging/logging.dart'; +import 'package:media_kit/media_kit.dart'; import 'package:path_provider/path_provider.dart'; void main() async { @@ -49,6 +50,7 @@ void main() async { Future initApp() async { await EasyLocalization.ensureInitialized(); + MediaKit.ensureInitialized(); if (kReleaseMode && Platform.isAndroid) { try { diff --git a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart index d62e63649..707f0a458 100644 --- a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart +++ b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart @@ -791,11 +791,6 @@ class GalleryViewerPage extends HookConsumerWidget { localPosition = details.localPosition, onDragUpdate: (_, details, __) => handleSwipeUpDown(details), - heroAttributes: PhotoViewHeroAttributes( - tag: isFromDto - ? '${a.remoteId}-$heroOffset' - : a.id + heroOffset, - ), filterQuality: FilterQuality.high, maxScale: 1.0, minScale: 1.0, diff --git a/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart b/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart index a56d65595..dd3b9601f 100644 --- a/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart +++ b/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart @@ -9,6 +9,8 @@ import 'package:immich_mobile/modules/asset_viewer/ui/video_player_controls.dart import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; +import 'package:media_kit/media_kit.dart'; +import 'package:media_kit_video/media_kit_video.dart'; import 'package:photo_manager/photo_manager.dart'; import 'package:video_player/video_player.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; @@ -125,99 +127,128 @@ class VideoPlayer extends StatefulWidget { } class _VideoPlayerState extends State { - late VideoPlayerController videoPlayerController; - ChewieController? chewieController; + // late VideoPlayerController videoPlayerController; + // ChewieController? chewieController; + + // Create a [Player] to control playback. + late final player = Player(); + // Create a [VideoController] to handle video output from [Player]. + late final controller = VideoController(player); @override void initState() { super.initState(); - initializePlayer(); + // initializePlayer(); - videoPlayerController.addListener(() { - if (videoPlayerController.value.isInitialized) { - if (videoPlayerController.value.isPlaying) { - WakelockPlus.enable(); - widget.onPlaying?.call(); - } else if (!videoPlayerController.value.isPlaying) { - WakelockPlus.disable(); - widget.onPaused?.call(); - } + // videoPlayerController.addListener(() { + // if (videoPlayerController.value.isInitialized) { + // if (videoPlayerController.value.isPlaying) { + // WakelockPlus.enable(); + // widget.onPlaying?.call(); + // } else if (!videoPlayerController.value.isPlaying) { + // WakelockPlus.disable(); + // widget.onPaused?.call(); + // } - if (videoPlayerController.value.position == - videoPlayerController.value.duration) { - WakelockPlus.disable(); - widget.onVideoEnded(); - } - } - }); - } + // if (videoPlayerController.value.position == + // videoPlayerController.value.duration) { + // WakelockPlus.disable(); + // widget.onVideoEnded(); + // } + // } + // }); - Future initializePlayer() async { - try { - videoPlayerController = widget.file == null - ? VideoPlayerController.networkUrl( - Uri.parse(widget.url!), - httpHeaders: {"Authorization": "Bearer ${widget.jwtToken}"}, - ) - : VideoPlayerController.file(widget.file!); - - await videoPlayerController.initialize(); - _createChewieController(); - setState(() {}); - } catch (e) { - debugPrint("ERROR initialize video player $e"); + if (widget.file == null) { + player.open( + Media( + Uri.parse(widget.url!).toString(), + httpHeaders: { + "Authorization": "Bearer ${widget.jwtToken}", + }, + ), + ); + } else { + player.open( + Media( + widget.file!.path, + ), + ); } } - _createChewieController() { - chewieController = ChewieController( - controlsSafeAreaMinimum: const EdgeInsets.only( - bottom: 100, - ), - showOptions: true, - showControlsOnInitialize: false, - videoPlayerController: videoPlayerController, - autoPlay: true, - autoInitialize: true, - allowFullScreen: false, - allowedScreenSleep: false, - showControls: !widget.isMotionVideo, - customControls: const VideoPlayerControls(), - hideControlsTimer: const Duration(seconds: 5), - ); - } + // Future initializePlayer() async { + // try { + // videoPlayerController = widget.file == null + // ? VideoPlayerController.networkUrl( + // Uri.parse(widget.url!), + // httpHeaders: {"Authorization": "Bearer ${widget.jwtToken}"}, + // ) + // : VideoPlayerController.file(widget.file!); + + // await videoPlayerController.initialize(); + // _createChewieController(); + // setState(() {}); + // } catch (e) { + // debugPrint("ERROR initialize video player $e"); + // } + // } + + // _createChewieController() { + // chewieController = ChewieController( + // controlsSafeAreaMinimum: const EdgeInsets.only( + // bottom: 100, + // ), + // showOptions: true, + // showControlsOnInitialize: false, + // videoPlayerController: videoPlayerController, + // autoPlay: true, + // autoInitialize: true, + // allowFullScreen: false, + // allowedScreenSleep: false, + // showControls: !widget.isMotionVideo, + // customControls: const VideoPlayerControls(), + // hideControlsTimer: const Duration(seconds: 5), + // ); + // } @override void dispose() { super.dispose(); - videoPlayerController.pause(); - videoPlayerController.dispose(); - chewieController?.dispose(); + player.dispose(); + // videoPlayerController.pause(); + // videoPlayerController.dispose(); + // chewieController?.dispose(); } @override Widget build(BuildContext context) { - if (chewieController?.videoPlayerController.value.isInitialized == true) { - return SizedBox( - child: Chewie( - controller: chewieController!, - ), - ); - } else { - return SizedBox( - height: MediaQuery.of(context).size.height, - width: MediaQuery.of(context).size.width, - child: Center( - child: Stack( - children: [ - if (widget.placeholder != null) widget.placeholder!, - const Center( - child: ImmichLoadingIndicator(), - ), - ], - ), - ), - ); - } + return SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + child: Video(controller: controller), + ); + + // if (chewieController?.videoPlayerController.value.isInitialized == true) { + // return SizedBox( + // child: Chewie( + // controller: chewieController!, + // ), + // ); + // } else { + // return SizedBox( + // height: MediaQuery.of(context).size.height, + // width: MediaQuery.of(context).size.width, + // child: Center( + // child: Stack( + // children: [ + // if (widget.placeholder != null) widget.placeholder!, + // const Center( + // child: ImmichLoadingIndicator(), + // ), + // ], + // ), + // ), + // ); + // } } } diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 73bfd11b0..155f83d30 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: archive - sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + sha256: "7e0d52067d05f2e0324268097ba723b71cb41ac8a6a2b24d1edf9c536b987b03" url: "https://pub.dev" source: hosted - version: "3.3.7" + version: "3.4.6" args: dependency: transitive description: @@ -201,6 +201,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.7.0" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 + url: "https://pub.dev" + source: hosted + version: "0.4.0" clock: dependency: transitive description: @@ -455,10 +463,10 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: "559c600f056e7c704bd843723c21e01b5fba47e8824bd02422165bcc02a5de1d" + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" url: "https://pub.dev" source: hosted - version: "0.9.3" + version: "0.13.1" flutter_lints: dependency: "direct dev" description: @@ -516,10 +524,10 @@ packages: dependency: "direct dev" description: name: flutter_native_splash - sha256: "6777a3abb974021a39b5fdd2d46a03ca390e03903b6351f21d10e7ecc969f12d" + sha256: d93394f22f73e810bda59e11ebe83329c5511d6460b6b7509c4e1f3c92d6d625 url: "https://pub.dev" source: hosted - version: "2.2.16" + version: "2.3.5" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -691,10 +699,10 @@ packages: dependency: transitive description: name: image - sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "4.1.3" image_picker: dependency: "direct main" description: @@ -868,6 +876,78 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.0" + media_kit: + dependency: "direct main" + description: + name: media_kit + sha256: "3289062540e3b8b9746e5c50d95bd78a9289826b7227e253dff806d002b9e67a" + url: "https://pub.dev" + source: hosted + version: "1.1.10+1" + media_kit_libs_android_video: + dependency: transitive + description: + name: media_kit_libs_android_video + sha256: "9dd8012572e4aff47516e55f2597998f0a378e3d588d0fad0ca1f11a53ae090c" + url: "https://pub.dev" + source: hosted + version: "1.3.6" + media_kit_libs_ios_video: + dependency: transitive + description: + name: media_kit_libs_ios_video + sha256: b5382994eb37a4564c368386c154ad70ba0cc78dacdd3fb0cd9f30db6d837991 + url: "https://pub.dev" + source: hosted + version: "1.1.4" + media_kit_libs_linux: + dependency: transitive + description: + name: media_kit_libs_linux + sha256: e186891c31daa6bedab4d74dcdb4e8adfccc7d786bfed6ad81fe24a3b3010310 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + media_kit_libs_macos_video: + dependency: transitive + description: + name: media_kit_libs_macos_video + sha256: f26aa1452b665df288e360393758f84b911f70ffb3878032e1aabba23aa1032d + url: "https://pub.dev" + source: hosted + version: "1.1.4" + media_kit_libs_video: + dependency: "direct main" + description: + name: media_kit_libs_video + sha256: "3688e0c31482074578652bf038ce6301a5d21e1eda6b54fc3117ffeb4bdba067" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + media_kit_libs_windows_video: + dependency: transitive + description: + name: media_kit_libs_windows_video + sha256: "7bace5f35d9afcc7f9b5cdadb7541d2191a66bb3fc71bfa11c1395b3360f6122" + url: "https://pub.dev" + source: hosted + version: "1.0.9" + media_kit_native_event_loop: + dependency: transitive + description: + name: media_kit_native_event_loop + sha256: a605cf185499d14d58935b8784955a92a4bf0ff4e19a23de3d17a9106303930e + url: "https://pub.dev" + source: hosted + version: "1.0.8" + media_kit_video: + dependency: "direct main" + description: + name: media_kit_video + sha256: c048d11a19e379aebbe810647636e3fc6d18374637e2ae12def4ff8a4b99a882 + url: "https://pub.dev" + source: hosted + version: "1.2.4" meta: dependency: transitive description: @@ -1171,6 +1251,62 @@ packages: url: "https://pub.dev" source: hosted version: "0.27.7" + safe_local_storage: + dependency: transitive + description: + name: safe_local_storage + sha256: ede4eb6cb7d88a116b3d3bf1df70790b9e2038bc37cb19112e381217c74d9440 + url: "https://pub.dev" + source: hosted + version: "1.0.2" + screen_brightness: + dependency: transitive + description: + name: screen_brightness + sha256: ed8da4a4511e79422fc1aa88138e920e4008cd312b72cdaa15ccb426c0faaedd + url: "https://pub.dev" + source: hosted + version: "0.2.2+1" + screen_brightness_android: + dependency: transitive + description: + name: screen_brightness_android + sha256: "3df10961e3a9e968a5e076fe27e7f4741fa8a1d3950bdeb48cf121ed529d0caf" + url: "https://pub.dev" + source: hosted + version: "0.1.0+2" + screen_brightness_ios: + dependency: transitive + description: + name: screen_brightness_ios + sha256: "99adc3ca5490b8294284aad5fcc87f061ad685050e03cf45d3d018fe398fd9a2" + url: "https://pub.dev" + source: hosted + version: "0.1.0" + screen_brightness_macos: + dependency: transitive + description: + name: screen_brightness_macos + sha256: "64b34e7e3f4900d7687c8e8fb514246845a73ecec05ab53483ed025bd4a899fd" + url: "https://pub.dev" + source: hosted + version: "0.1.0+1" + screen_brightness_platform_interface: + dependency: transitive + description: + name: screen_brightness_platform_interface + sha256: b211d07f0c96637a15fb06f6168617e18030d5d74ad03795dd8547a52717c171 + url: "https://pub.dev" + source: hosted + version: "0.1.0" + screen_brightness_windows: + dependency: transitive + description: + name: screen_brightness_windows + sha256: "9261bf33d0fc2707d8cf16339ce25768100a65e70af0fcabaf032fc12408ba86" + url: "https://pub.dev" + source: hosted + version: "0.1.3" scrollable_positioned_list: dependency: "direct main" description: @@ -1448,6 +1584,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + universal_platform: + dependency: transitive + description: + name: universal_platform + sha256: d315be0f6641898b280ffa34e2ddb14f3d12b1a37882557869646e0cc363d0cc + url: "https://pub.dev" + source: hosted + version: "1.0.0+1" + uri_parser: + dependency: transitive + description: + name: uri_parser + sha256: "6543c9fd86d2862fac55d800a43e67c0dcd1a41677cb69c2f8edfe73bbcf1835" + url: "https://pub.dev" + source: hosted + version: "2.0.2" url_launcher: dependency: "direct main" description: @@ -1576,6 +1728,14 @@ packages: url: "https://pub.dev" source: hosted version: "11.7.1" + volume_controller: + dependency: transitive + description: + name: volume_controller + sha256: "189bdc7a554f476b412e4c8b2f474562b09d74bc458c23667356bce3ca1d48c9" + url: "https://pub.dev" + source: hosted + version: "2.0.7" wakelock_plus: dependency: "direct main" description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 63c6f312f..a2b80d4d1 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -53,6 +53,10 @@ dependencies: wakelock_plus: ^1.1.1 flutter_local_notifications: ^15.1.0+1 + media_kit: ^1.1.10 # Primary package. + media_kit_video: ^1.2.4 # For video rendering. + media_kit_libs_video: ^1.0.4 # Native video dependencies. + openapi: path: openapi @@ -75,7 +79,7 @@ dev_dependencies: flutter_lints: ^2.0.1 build_runner: ^2.2.1 auto_route_generator: ^5.0.2 - flutter_launcher_icons: "^0.9.2" + flutter_launcher_icons: "^0.13.1" flutter_native_splash: ^2.2.16 isar_generator: *isar_version mockito: ^5.3.2