From 3d42542e0ac6f4b81383e1f371b5efc27ad5ab78 Mon Sep 17 00:00:00 2001 From: Bruno D'Luka Date: Tue, 1 Oct 2024 01:21:09 -0300 Subject: [PATCH 1/5] chore(refactor): Use HttpHeaders interface --- lib/api/api.dart | 13 ++++++++----- lib/api/events.dart | 8 ++++++-- lib/api/ptz.dart | 8 +++++--- lib/models/device.dart | 5 ++++- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/api/api.dart b/lib/api/api.dart index 0c369033..71ab9719 100644 --- a/lib/api/api.dart +++ b/lib/api/api.dart @@ -18,6 +18,7 @@ */ import 'dart:convert'; +import 'dart:io'; import 'package:bluecherry_client/api/api_helpers.dart'; import 'package:bluecherry_client/models/device.dart'; @@ -52,6 +53,8 @@ class API { } } + static String get cookieHeader => HttpHeaders.cookieHeader; + /// Checks details of a [server] entered by the user. /// If the attributes present in [Server] are correct, then the /// returned object will have [Server.serverUUID] & [Server.cookie] @@ -139,7 +142,7 @@ class API { }, ), headers: { - if (server.cookie != null) 'Cookie': server.cookie!, + if (server.cookie != null) API.cookieHeader: server.cookie!, }, ); // debugPrint(response.body); @@ -207,7 +210,7 @@ class API { '/mobile-app-config.json', ), headers: { - 'Cookie': server.cookie!, + if (server.cookie != null) API.cookieHeader: server.cookie!, }, ); final body = jsonDecode(response.body); @@ -235,8 +238,8 @@ class API { final response = await client.post( Uri.parse('${uri!}store-token'), headers: { - 'Cookie': server.cookie!, - 'Content-Type': 'application/json', + API.cookieHeader: server.cookie!, + HttpHeaders.contentTypeHeader: 'application/json', }, body: jsonEncode( { @@ -279,7 +282,7 @@ class API { final response = await client.post( Uri.parse('${uri!}remove-token'), headers: { - 'Cookie': server.cookie!, + API.cookieHeader: server.cookie!, 'Content-Type': 'application/json', }, body: jsonEncode( diff --git a/lib/api/events.dart b/lib/api/events.dart index 2c6b4c61..8212706c 100644 --- a/lib/api/events.dart +++ b/lib/api/events.dart @@ -85,8 +85,12 @@ extension EventsExtension on API { if (deviceId != null) 'device_id': '$deviceId', }, ); - final response = - await API.client.get(uri, headers: {'Cookie': server.cookie!}); + final response = await API.client.get( + uri, + headers: { + if (server.cookie != null) API.cookieHeader: server.cookie!, + }, + ); var events = const Iterable.empty(); diff --git a/lib/api/ptz.dart b/lib/api/ptz.dart index 51ebe38b..77e48ad7 100644 --- a/lib/api/ptz.dart +++ b/lib/api/ptz.dart @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +import 'dart:io'; + import 'package:bluecherry_client/api/api.dart'; import 'package:bluecherry_client/models/device.dart'; import 'package:flutter/widgets.dart'; @@ -116,7 +118,7 @@ extension PtzApiExtension on API { url, headers: { 'Content-Type': 'application/x-www-form-urlencoded', - 'Cookie': server.cookie!, + if (server.cookie != null) API.cookieHeader: server.cookie!, }, ); @@ -158,8 +160,8 @@ extension PtzApiExtension on API { final response = await API.client.get( url, headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Cookie': server.cookie!, + HttpHeaders.contentTypeHeader: 'application/x-www-form-urlencoded', + if (server.cookie != null) API.cookieHeader: server.cookie!, }, ); diff --git a/lib/models/device.dart b/lib/models/device.dart index e97e1264..f19ef5b4 100644 --- a/lib/models/device.dart +++ b/lib/models/device.dart @@ -277,7 +277,10 @@ class Device { ); try { - var response = await API.client.get(uri); + var response = await API.client.get(uri, headers: { + if (device.server.cookie != null) + API.cookieHeader: device.server.cookie!, + }); if (response.statusCode == 200) { var ret = json.decode(response.body) as Map; From a960c9b9b7853c665ab09d7fea822e0cf4eede8c Mon Sep 17 00:00:00 2001 From: Bruno D'Luka Date: Tue, 1 Oct 2024 01:28:14 -0300 Subject: [PATCH 2/5] feat: Pass on headers to video players --- lib/utils/video_player.dart | 18 +++++++++++++++--- .../lib/unity_video_player_flutter.dart | 11 +++++++++-- .../lib/unity_video_player_main.dart | 11 +++++++++-- .../unity_video_player_platform_interface.dart | 6 +++++- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/lib/utils/video_player.dart b/lib/utils/video_player.dart index 71c4a871..1ae56e69 100644 --- a/lib/utils/video_player.dart +++ b/lib/utils/video_player.dart @@ -19,6 +19,7 @@ import 'dart:async'; +import 'package:bluecherry_client/api/api.dart'; import 'package:bluecherry_client/models/device.dart'; import 'package:bluecherry_client/models/event.dart'; import 'package:bluecherry_client/providers/settings_provider.dart'; @@ -100,7 +101,10 @@ class UnityPlayers with ChangeNotifier { }; debugPrint('Initializing $source'); controller.fallbackUrl = fallback; - await controller.setDataSource(source); + await controller.setDataSource(source, headers: { + if (device.server.cookie != null) + API.cookieHeader: device.server.cookie!, + }); _reloadable.add(source); } @@ -155,12 +159,20 @@ class UnityPlayers with ChangeNotifier { softwareZoom: settings().kSoftwareZooming.value, onLog: (message) { logStreamToFile( - event.mediaURL?.toString() ?? 'Event ${event.title} (${event.id})', + event.mediaURL == null + ? 'Event ${event.title} (${event.id})' + : event.mediaPath, message, ); }, ) - ..setDataSource(event.mediaPath.toString()) + ..setDataSource( + event.mediaPath, + headers: { + if (event.server.cookie != null) + API.cookieHeader: event.server.cookie!, + }, + ) ..setVolume(1.0) ..setSpeed(1.0); diff --git a/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart b/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart index 7cf326b6..dd9725a5 100644 --- a/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart +++ b/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart @@ -164,7 +164,11 @@ class UnityVideoPlayerFlutter extends UnityVideoPlayer { _videoStream.stream.map((value) => value.isPlaying); @override - Future setDataSource(String url, {bool autoPlay = true}) async { + Future setDataSource( + String url, { + bool autoPlay = true, + Map? headers, + }) async { if (url == dataSource) return Future.value(); if (player != null) { @@ -180,7 +184,10 @@ class UnityVideoPlayerFlutter extends UnityVideoPlayer { if (uri.scheme == 'file') { player = VideoPlayerController.file(File.fromUri(uri)); } else { - player = VideoPlayerController.networkUrl(uri); + player = VideoPlayerController.networkUrl( + uri, + httpHeaders: headers ?? const {}, + ); } try { diff --git a/packages/unity_video_player/unity_video_player_main/lib/unity_video_player_main.dart b/packages/unity_video_player/unity_video_player_main/lib/unity_video_player_main.dart index 6ec5f625..a0d3dd6b 100644 --- a/packages/unity_video_player/unity_video_player_main/lib/unity_video_player_main.dart +++ b/packages/unity_video_player/unity_video_player_main/lib/unity_video_player_main.dart @@ -306,13 +306,20 @@ class UnityVideoPlayerMediaKit extends UnityVideoPlayer { } @override - Future setDataSource(String url, {bool autoPlay = true}) { + Future setDataSource( + String url, { + bool autoPlay = true, + Map? headers, + }) { if (url == dataSource) return Future.value(); debugPrint('Playing $url'); return ensureVideoControllerInitialized((controller) async { await mkPlayer.setPlaylistMode(PlaylistMode.loop); // do not use mkPlayer.add because it doesn't support auto play - await mkPlayer.open(Playlist([Media(url)]), play: autoPlay); + await mkPlayer.open( + Playlist([Media(url, httpHeaders: headers)]), + play: autoPlay, + ); }); } diff --git a/packages/unity_video_player/unity_video_player_platform_interface/lib/unity_video_player_platform_interface.dart b/packages/unity_video_player/unity_video_player_platform_interface/lib/unity_video_player_platform_interface.dart index 899f2340..b936ec28 100644 --- a/packages/unity_video_player/unity_video_player_platform_interface/lib/unity_video_player_platform_interface.dart +++ b/packages/unity_video_player/unity_video_player_platform_interface/lib/unity_video_player_platform_interface.dart @@ -395,7 +395,11 @@ abstract class UnityVideoPlayer with ChangeNotifier { /// Whether the media is seekable bool get isSeekable; - Future setDataSource(String url, {bool autoPlay = true}); + Future setDataSource( + String url, { + bool autoPlay = true, + Map? headers, + }); Future setMultipleDataSource( Iterable url, { bool autoPlay = true, From 737f5cc7ef89cf7f25d7a3d9251817eb633fa4e8 Mon Sep 17 00:00:00 2001 From: Bruno D'Luka Date: Tue, 1 Oct 2024 01:34:46 -0300 Subject: [PATCH 3/5] fix: Remove media_kit_native_event_loop dependency --- lib/providers/settings_provider.dart | 2 +- linux/flutter/generated_plugins.cmake | 1 - .../unity_video_player_main/pubspec.yaml | 24 ++++++------ pubspec.lock | 37 +++++++------------ windows/flutter/generated_plugins.cmake | 1 - 5 files changed, 27 insertions(+), 38 deletions(-) diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 5a884e1f..d8d0281e 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -435,7 +435,7 @@ class SettingsProvider extends UnityProvider { }; } - // TODO(bdlukaa): remove this in future releases + // TODO(bdlukaa): Remove this migration in future releases var _hasMigratedTimezone = false; late final kConvertTimeToLocalTimezone = _SettingsOption( def: true, diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 9d520730..1f4aaf58 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -13,7 +13,6 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - media_kit_native_event_loop ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/packages/unity_video_player/unity_video_player_main/pubspec.yaml b/packages/unity_video_player/unity_video_player_main/pubspec.yaml index 6effe1af..a1c8dd7e 100644 --- a/packages/unity_video_player/unity_video_player_main/pubspec.yaml +++ b/packages/unity_video_player/unity_video_player_main/pubspec.yaml @@ -22,10 +22,10 @@ dependencies: # git: # url: https://github.com/media-kit/media-kit/ # path: media_kit/ - media_kit_native_event_loop: - git: - url: https://github.com/media-kit/media-kit/ - path: media_kit_native_event_loop/ + # media_kit_native_event_loop: + # git: + # url: https://github.com/media-kit/media-kit/ + # path: media_kit_native_event_loop/ # media_kit_video: # git: # url: https://github.com/media-kit/media-kit/ @@ -57,18 +57,18 @@ dev_dependencies: flutter_lints: ^2.0.0 dependency_overrides: - media_kit: - git: - url: https://github.com/media-kit/media-kit/ - path: media_kit/ + # media_kit: + # git: + # url: https://github.com/media-kit/media-kit/ + # path: media_kit/ #media_kit_native_event_loop: # git: # url: https://github.com/media-kit/media-kit/ # path: media_kit_native_event_loop/ - media_kit_video: - git: - url: https://github.com/media-kit/media-kit/ - path: media_kit_video/ + # media_kit_video: + # git: + # url: https://github.com/media-kit/media-kit/ + # path: media_kit_video/ # media_kit_libs_android_video: # git: # url: https://github.com/media-kit/media-kit/ diff --git a/pubspec.lock b/pubspec.lock index 677c3793..c4f31236 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -562,7 +562,7 @@ packages: description: path: "libs/android/media_kit_libs_android_video" ref: HEAD - resolved-ref: e41e50c8cfb370e69612b205dcfd9f3ca80690f5 + resolved-ref: "88c49c6c0f6187a131a4053f0f1a3a42f2922a8a" url: "https://github.com/media-kit/media-kit/" source: git version: "1.3.6" @@ -571,7 +571,7 @@ packages: description: path: "libs/ios/media_kit_libs_ios_video" ref: HEAD - resolved-ref: e41e50c8cfb370e69612b205dcfd9f3ca80690f5 + resolved-ref: "88c49c6c0f6187a131a4053f0f1a3a42f2922a8a" url: "https://github.com/media-kit/media-kit/" source: git version: "1.1.4" @@ -580,7 +580,7 @@ packages: description: path: "libs/macos/media_kit_libs_macos_video" ref: HEAD - resolved-ref: e41e50c8cfb370e69612b205dcfd9f3ca80690f5 + resolved-ref: "88c49c6c0f6187a131a4053f0f1a3a42f2922a8a" url: "https://github.com/media-kit/media-kit/" source: git version: "1.1.4" @@ -589,19 +589,10 @@ packages: description: path: "libs/windows/media_kit_libs_windows_video" ref: HEAD - resolved-ref: e41e50c8cfb370e69612b205dcfd9f3ca80690f5 + resolved-ref: "88c49c6c0f6187a131a4053f0f1a3a42f2922a8a" url: "https://github.com/media-kit/media-kit/" source: git version: "1.0.10" - media_kit_native_event_loop: - dependency: transitive - description: - path: media_kit_native_event_loop - ref: HEAD - resolved-ref: e41e50c8cfb370e69612b205dcfd9f3ca80690f5 - url: "https://github.com/media-kit/media-kit/" - source: git - version: "1.0.9" media_kit_video: dependency: transitive description: @@ -955,10 +946,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "51b08572b9f091f8c3eb4d9d4be253f196ff0075d5ec9b10a884026d5b55d7bc" + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" url: "https://pub.dev" source: hosted - version: "3.3.0+2" + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -1078,10 +1069,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" url_launcher_platform_interface: dependency: transitive description: @@ -1110,10 +1101,10 @@ packages: dependency: "direct main" description: name: uuid - sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77 + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.5.1" vector_math: dependency: transitive description: @@ -1142,10 +1133,10 @@ packages: dependency: transitive description: name: video_player_android - sha256: "38d8fe136c427abdce68b5e8c3c08ea29d7a794b453c7a51b12ecfad4aad9437" + sha256: "45d21bbba3d10b7182aa08ade5d4c68ed3367016d40f29732bb04a799b26842d" url: "https://pub.dev" source: hosted - version: "2.7.3" + version: "2.7.5" video_player_avfoundation: dependency: transitive description: @@ -1206,10 +1197,10 @@ packages: dependency: transitive description: name: web - sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.1.0" win32: dependency: transitive description: diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index ed265f3e..7f90e002 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -17,7 +17,6 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - media_kit_native_event_loop ) set(PLUGIN_BUNDLED_LIBRARIES) From 836831a3d7fbac50a4b1a4569f1878c17d2da9ef Mon Sep 17 00:00:00 2001 From: Bruno D'Luka Date: Tue, 1 Oct 2024 01:36:38 -0300 Subject: [PATCH 4/5] fix: Do not try to create a random log file --- lib/utils/logging.dart | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/utils/logging.dart b/lib/utils/logging.dart index 09da42d7..e093084d 100644 --- a/lib/utils/logging.dart +++ b/lib/utils/logging.dart @@ -45,12 +45,12 @@ void handleError( writeErrorToFile(error, stackTrace, context); } -Future getLogFile() async { +Future getLogFile() async { try { return File(path.join(supportDir.path, 'logs.txt')); } catch (e) { - debugPrint('Error getting log file: $e'); - return File('./logs.txt'); + // debugPrint('Error getting log file: $e'); + return null; } } @@ -67,9 +67,8 @@ Future writeErrorToFile( '[$time]Stack trace: $stackTrace'; final file = await getLogFile(); - - await file.writeAsString(errorLog, mode: FileMode.append); - Logger.root.log(Level.INFO, 'Wrote log file to "${file.path}"'); + await file?.writeAsString(errorLog, mode: FileMode.append); + Logger.root.log(Level.INFO, 'Wrote log file to "${file?.path}"'); Logger.root.log(Level.SEVERE, errorLog); } @@ -78,8 +77,8 @@ Future writeLogToFile(String text, {bool print = false}) async { final time = DateTime.now().toIso8601String(); final file = await getLogFile(); - await file.writeAsString('\n[$time] $text', mode: FileMode.append); - if (print) Logger.root.log(Level.INFO, 'Wrote log file to "${file.path}"'); + await file?.writeAsString('\n[$time] $text', mode: FileMode.append); + if (print) Logger.root.log(Level.INFO, 'Wrote log file to "${file?.path}"'); } if (print) debugPrint(text); } From b68cd6bcd45de7d3a8b19bbe663a36bb01edc1ef Mon Sep 17 00:00:00 2001 From: Bruno D'Luka Date: Tue, 1 Oct 2024 01:46:45 -0300 Subject: [PATCH 5/5] fix: Remove selected devices that don't exist anymore In case of device deletion --- lib/main.dart | 2 +- lib/providers/events_provider.dart | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 80b9d323..00248124 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -153,11 +153,11 @@ Future main(List args) async { // wait time at the splash screen // settings provider needs to be initalized alone await SettingsProvider.ensureInitialized(); + await ServersProvider.ensureInitialized(); await Future.wait([ DownloadsManager.ensureInitialized(), MobileViewProvider.ensureInitialized(), DesktopViewProvider.ensureInitialized(), - ServersProvider.ensureInitialized(), UpdateManager.ensureInitialized(), EventsProvider.ensureInitialized(), ]); diff --git a/lib/providers/events_provider.dart b/lib/providers/events_provider.dart index 403e3195..1badaa22 100644 --- a/lib/providers/events_provider.dart +++ b/lib/providers/events_provider.dart @@ -24,6 +24,7 @@ import 'package:bluecherry_client/providers/app_provider_interface.dart'; import 'package:bluecherry_client/providers/server_provider.dart'; import 'package:bluecherry_client/screens/events_browser/filter.dart'; import 'package:bluecherry_client/utils/constants.dart'; +import 'package:bluecherry_client/utils/extensions.dart'; import 'package:bluecherry_client/utils/logging.dart'; import 'package:bluecherry_client/utils/storage.dart'; import 'package:flutter/foundation.dart'; @@ -133,6 +134,19 @@ class EventsProvider extends UnityProvider { selectedDevices = List.from(data['selectedDevices'] as List).toSet(); + selectedDevices.removeWhere((device) { + final server = ServersProvider.instance.servers.firstWhereOrNull( + (server) => server.devices.any((d) => d.streamURL == device), + ); + return server == null || + !server.devices.any((d) { + if (d.streamURL == device) { + return d.status; + } else { + return false; + } + }); + }); super.restore(notifyListeners: notifyListeners); }