diff --git a/lib/api/api.dart b/lib/api/api.dart index df0ce992..542bea8a 100644 --- a/lib/api/api.dart +++ b/lib/api/api.dart @@ -56,6 +56,7 @@ class API { ); } } catch (exception, stacktrace) { + debugPrint('Failed to checkServerCredentials on server $server'); debugPrint(exception.toString()); debugPrint(stacktrace.toString()); } @@ -104,6 +105,7 @@ class API { ..addAll(devices); return devices; } catch (exception, stacktrace) { + debugPrint('Failed to getDevices on server $server'); debugPrint(exception.toString()); debugPrint(stacktrace.toString()); } @@ -162,6 +164,7 @@ class API { ); }).cast(); } catch (exception, stacktrace) { + debugPrint('Failed to getEvents on server $server'); debugPrint(exception.toString()); debugPrint(stacktrace.toString()); } @@ -187,6 +190,7 @@ class API { final body = jsonDecode(response.body); return body['notification_api_endpoint']; } catch (exception, stacktrace) { + debugPrint('Failed to getNotificationAPIEndpoint on server $server'); debugPrint(exception.toString()); debugPrint(stacktrace.toString()); } @@ -228,6 +232,7 @@ class API { debugPrint(response.body); return true; } catch (exception, stacktrace) { + debugPrint('Failed to registerNotificationToToken on server $server'); debugPrint(exception.toString()); debugPrint(stacktrace.toString()); return false; @@ -261,6 +266,7 @@ class API { debugPrint(response.body); return true; } catch (exception, stacktrace) { + debugPrint('Failed to unregisterNotificationToken on server $server'); debugPrint(exception.toString()); debugPrint(stacktrace.toString()); return false; diff --git a/lib/widgets/device_grid/desktop_device_grid.dart b/lib/widgets/device_grid/desktop_device_grid.dart index 304ac1ed..de2186b1 100644 --- a/lib/widgets/device_grid/desktop_device_grid.dart +++ b/lib/widgets/device_grid/desktop_device_grid.dart @@ -19,9 +19,6 @@ part of 'device_grid.dart'; -const kGridInnerPadding = 8.0; -const kGridPadding = EdgeInsets.all(10.0); - typedef FoldedDevices = List>; class DesktopDeviceGrid extends StatefulWidget { @@ -172,27 +169,17 @@ class _DesktopDeviceGridState extends State { final crossAxisCount = calculateCrossAxisCount(dl); - return ReorderableGridView.builder( + return StaticGrid( key: ValueKey(view.currentLayout.hashCode), - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: crossAxisCount.clamp(1, 50), - mainAxisSpacing: kGridInnerPadding, - crossAxisSpacing: kGridInnerPadding, - childAspectRatio: 16 / 9, - ), - padding: kGridPadding, + crossAxisCount: crossAxisCount.clamp(1, 50), + childAspectRatio: 16 / 9, onReorder: view.reorder, - itemCount: devices.length, - itemBuilder: (context, index) { - final device = devices[index]; - + children: devices.map((device) { return DesktopDeviceTile( key: ValueKey('$device.${device.server.serverUUID}'), device: device, ); - }, + }).toList(), ); }(), ), diff --git a/lib/widgets/device_grid/device_grid.dart b/lib/widgets/device_grid/device_grid.dart index a639c91f..8aa22cbb 100644 --- a/lib/widgets/device_grid/device_grid.dart +++ b/lib/widgets/device_grid/device_grid.dart @@ -36,11 +36,11 @@ import 'package:bluecherry_client/widgets/device_tile_selector.dart'; import 'package:bluecherry_client/widgets/error_warning.dart'; import 'package:bluecherry_client/widgets/hover_button.dart'; import 'package:bluecherry_client/widgets/misc.dart'; +import 'package:bluecherry_client/widgets/reorderable_static_grid.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; -import 'package:reorderable_grid_view/reorderable_grid_view.dart'; import 'package:unity_video_player/unity_video_player.dart'; part 'desktop_device_grid.dart'; diff --git a/lib/widgets/device_grid/mobile_device_grid.dart b/lib/widgets/device_grid/mobile_device_grid.dart index a6327229..1c5e61d7 100644 --- a/lib/widgets/device_grid/mobile_device_grid.dart +++ b/lib/widgets/device_grid/mobile_device_grid.dart @@ -175,9 +175,7 @@ class _MobileDeviceGridChild extends StatelessWidget { color: Colors.black, height: double.infinity, width: double.infinity, - child: ReorderableGridView.count( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, + child: StaticGrid( crossAxisCount: { 4: 2, 2: 2, diff --git a/lib/widgets/events_playback/events_playback.dart b/lib/widgets/events_playback/events_playback.dart index 3ac8843a..0de9cf7e 100644 --- a/lib/widgets/events_playback/events_playback.dart +++ b/lib/widgets/events_playback/events_playback.dart @@ -295,8 +295,10 @@ abstract class EventsPlaybackState extends State { @override void initState() { super.initState(); - timelineController.addListener(() { - if (mounted) setState(() {}); + WidgetsBinding.instance.addPostFrameCallback((timestamp) { + timelineController.addListener(() { + if (mounted) setState(() {}); + }); }); } diff --git a/lib/widgets/events_playback/events_playback_desktop.dart b/lib/widgets/events_playback/events_playback_desktop.dart index 0fa725cd..0a19c708 100644 --- a/lib/widgets/events_playback/events_playback_desktop.dart +++ b/lib/widgets/events_playback/events_playback_desktop.dart @@ -32,12 +32,12 @@ import 'package:bluecherry_client/widgets/events/event_player_desktop.dart'; import 'package:bluecherry_client/widgets/events_playback/events_playback.dart'; import 'package:bluecherry_client/widgets/events_playback/timeline_controller.dart'; import 'package:bluecherry_client/widgets/misc.dart'; +import 'package:bluecherry_client/widgets/reorderable_static_grid.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; -import 'package:reorderables/reorderables.dart'; import 'package:unity_video_player/unity_video_player.dart'; typedef FutureValueChanged = Future Function(T data); @@ -101,8 +101,6 @@ class _EventsPlaybackDesktopState extends EventsPlaybackState { timelineController.tiles.length, ), childAspectRatio: 16 / 9, - mainAxisSpacing: kGridInnerPadding, - crossAxisSpacing: kGridInnerPadding, onReorder: eventsProvider.onReorder, children: timelineController.tiles.map((tile) { final has = timelineController.currentItem @@ -114,6 +112,7 @@ class _EventsPlaybackDesktopState extends EventsPlaybackState { .canvasColor; return IndexedStack( + key: ValueKey(tile), index: !has ? 0 : 1, children: [ Container( @@ -654,110 +653,3 @@ class FilterTile extends StatelessWidget { ]); } } - -/// A non-scrollable grid view -class StaticGrid extends StatefulWidget { - final int crossAxisCount; - final List children; - - final double childAspectRatio; - - final double mainAxisSpacing; - final double crossAxisSpacing; - - final ReorderCallback onReorder; - final bool reorderable; - - const StaticGrid({ - Key? key, - required this.crossAxisCount, - required this.children, - this.childAspectRatio = 1.0, - this.mainAxisSpacing = 0.0, - this.crossAxisSpacing = 0.0, - required this.onReorder, - this.reorderable = true, - }) : super(key: key); - - @override - State createState() => StaticGridState(); -} - -class StaticGridState extends State { - List realChildren = []; - int get gridFactor => (realChildren.length / widget.crossAxisCount).round(); - void generateRealChildren() { - realChildren = [...widget.children]; - - bool check() { - if (realChildren.isEmpty) return false; - - // if the children length is multiple of the crossAxisCount, return. This - // avoids adding multiple emtpy areas in the view - if (realChildren.length % widget.crossAxisCount == 0) return false; - if (gridFactor == 1) return false; - - return true; - } - - while (check()) { - realChildren.add(const SizedBox.shrink()); - } - } - - @override - void initState() { - super.initState(); - generateRealChildren(); - } - - @override - void didUpdateWidget(covariant StaticGrid oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.children != widget.children) { - generateRealChildren(); - } - } - - @override - Widget build(BuildContext context) { - return Padding( - padding: kGridPadding.add(EdgeInsetsDirectional.only( - start: widget.crossAxisSpacing, - top: widget.mainAxisSpacing, - )), - child: LayoutBuilder(builder: (context, constraints) { - final width = (constraints.biggest.width / widget.crossAxisCount) - - widget.mainAxisSpacing; - return ScrollConfiguration( - behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false), - child: ReorderableWrap( - enableReorder: widget.reorderable, - spacing: widget.mainAxisSpacing, - runSpacing: widget.crossAxisSpacing, - maxMainAxisCount: widget.crossAxisCount, - onReorder: widget.onReorder, - needsLongPressDraggable: isMobile, - alignment: WrapAlignment.center, - runAlignment: WrapAlignment.center, - crossAxisAlignment: WrapCrossAlignment.center, - scrollPhysics: const NeverScrollableScrollPhysics(), - children: List.generate(realChildren.length, (index) { - return SizedBox( - key: ValueKey(index), - // height: height, - width: width, - child: Center( - child: AspectRatio( - aspectRatio: widget.childAspectRatio, - child: realChildren[index], - ), - ), - ); - }), - ), - ); - }), - ); - } -} diff --git a/lib/widgets/events_playback/events_playback_mobile.dart b/lib/widgets/events_playback/events_playback_mobile.dart index d21ccde0..9fd2199b 100644 --- a/lib/widgets/events_playback/events_playback_mobile.dart +++ b/lib/widgets/events_playback/events_playback_mobile.dart @@ -26,8 +26,8 @@ import 'package:bluecherry_client/widgets/device_grid/device_grid.dart'; import 'package:bluecherry_client/widgets/device_selector_screen.dart'; import 'package:bluecherry_client/widgets/error_warning.dart'; import 'package:bluecherry_client/widgets/events_playback/events_playback.dart'; -import 'package:bluecherry_client/widgets/events_playback/events_playback_desktop.dart'; import 'package:bluecherry_client/widgets/events_playback/timeline_controller.dart'; +import 'package:bluecherry_client/widgets/reorderable_static_grid.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; @@ -85,8 +85,6 @@ class _EventsPlaybackMobileState extends EventsPlaybackState { timelineController.tiles.length, ), childAspectRatio: 16 / 9, - mainAxisSpacing: kGridInnerPadding, - crossAxisSpacing: kGridInnerPadding, onReorder: eventsProvider.onReorder, children: timelineController.tiles.map((tile) { final has = diff --git a/lib/widgets/events_playback/timeline_controller.dart b/lib/widgets/events_playback/timeline_controller.dart index 86cfad32..44ec89c8 100644 --- a/lib/widgets/events_playback/timeline_controller.dart +++ b/lib/widgets/events_playback/timeline_controller.dart @@ -726,6 +726,9 @@ class TimelineController extends ChangeNotifier { } void setVideoPosition(Duration precision) { + // to avoid issues on the client + if (currentItem == null) return; + assert(currentItem != null); assert(currentItem is TimelineValue); diff --git a/lib/widgets/reorderable_static_grid.dart b/lib/widgets/reorderable_static_grid.dart new file mode 100644 index 00000000..01300789 --- /dev/null +++ b/lib/widgets/reorderable_static_grid.dart @@ -0,0 +1,135 @@ +/* + * This file is a part of Bluecherry Client (https://github.com/bluecherrydvr/unity). + * + * Copyright 2022 Bluecherry, LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import 'package:bluecherry_client/widgets/misc.dart'; +import 'package:flutter/material.dart'; +import 'package:reorderables/reorderables.dart'; + +const kGridInnerPadding = 8.0; +const kGridPadding = EdgeInsets.all(10.0); + +/// A non-scrollable reorderable grid view +class StaticGrid extends StatefulWidget { + final int crossAxisCount; + final List children; + + final double childAspectRatio; + + final double mainAxisSpacing; + final double crossAxisSpacing; + + final ReorderCallback onReorder; + final bool reorderable; + + final EdgeInsetsGeometry padding; + + const StaticGrid({ + Key? key, + required this.crossAxisCount, + required this.children, + this.childAspectRatio = 1.0, + this.mainAxisSpacing = kGridInnerPadding, + this.crossAxisSpacing = kGridInnerPadding, + required this.onReorder, + this.reorderable = true, + this.padding = kGridPadding, + }) : super(key: key); + + @override + State createState() => StaticGridState(); +} + +class StaticGridState extends State { + List realChildren = []; + int get gridFactor => (realChildren.length / widget.crossAxisCount).round(); + void generateRealChildren() { + realChildren = [...widget.children]; + + bool check() { + if (realChildren.isEmpty) return false; + + // if the children length is multiple of the crossAxisCount, return. This + // avoids adding multiple emtpy areas in the view + if (realChildren.length % widget.crossAxisCount == 0) return false; + if (gridFactor == 1) return false; + + return true; + } + + while (check()) { + realChildren.add(const SizedBox.shrink()); + } + } + + @override + void initState() { + super.initState(); + generateRealChildren(); + } + + @override + void didUpdateWidget(covariant StaticGrid oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.children != widget.children) { + generateRealChildren(); + } + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: widget.padding.add(EdgeInsetsDirectional.only( + start: widget.crossAxisSpacing, + top: widget.mainAxisSpacing, + )), + child: LayoutBuilder(builder: (context, constraints) { + final width = (constraints.biggest.width / widget.crossAxisCount) - + widget.mainAxisSpacing; + return ScrollConfiguration( + behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false), + child: ReorderableWrap( + enableReorder: widget.reorderable, + spacing: widget.mainAxisSpacing, + runSpacing: widget.crossAxisSpacing, + maxMainAxisCount: widget.crossAxisCount, + onReorder: widget.onReorder, + needsLongPressDraggable: isMobile, + alignment: WrapAlignment.center, + runAlignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + scrollPhysics: const NeverScrollableScrollPhysics(), + children: List.generate(realChildren.length, (index) { + return SizedBox( + key: ValueKey(index), + // height: height, + width: width, + child: Center( + child: AspectRatio( + aspectRatio: widget.childAspectRatio, + child: realChildren[index], + ), + ), + ); + }), + ), + ); + }), + ); + } +} diff --git a/packages/unity_video_player/unity_video_player_media_kit/pubspec.yaml b/packages/unity_video_player/unity_video_player_media_kit/pubspec.yaml index 2a62397b..86271607 100644 --- a/packages/unity_video_player/unity_video_player_media_kit/pubspec.yaml +++ b/packages/unity_video_player/unity_video_player_media_kit/pubspec.yaml @@ -12,30 +12,32 @@ environment: dependencies: flutter: sdk: flutter + # We lock the version to a commit because of the inconsistency of the pub cache + # If an upgrade is necessary, change the [ref] of all packages below to the desired commit media_kit: git: url: https://github.com/alexmercerind/media_kit.git - ref: 6cc242355decc163d377dcfc611fd0300556c222 + ref: 618d78e495b5809191e23966c4932fb02a425ef3 path: media_kit/ media_kit_native_event_loop: git: url: https://github.com/alexmercerind/media_kit.git - ref: 6cc242355decc163d377dcfc611fd0300556c222 + ref: 618d78e495b5809191e23966c4932fb02a425ef3 path: media_kit_native_event_loop/ media_kit_video: git: url: https://github.com/alexmercerind/media_kit.git - ref: 6cc242355decc163d377dcfc611fd0300556c222 + ref: 618d78e495b5809191e23966c4932fb02a425ef3 path: media_kit_video/ media_kit_libs_windows_video: git: url: https://github.com/alexmercerind/media_kit.git - ref: 6cc242355decc163d377dcfc611fd0300556c222 + ref: 618d78e495b5809191e23966c4932fb02a425ef3 path: media_kit_libs_windows_video/ media_kit_libs_linux: git: url: https://github.com/alexmercerind/media_kit.git - ref: 6cc242355decc163d377dcfc611fd0300556c222 + ref: 618d78e495b5809191e23966c4932fb02a425ef3 path: media_kit_libs_linux/ unity_video_player_platform_interface: path: ../unity_video_player_platform_interface/ diff --git a/pubspec.lock b/pubspec.lock index 29a94632..b0a7ba5f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -395,8 +395,8 @@ packages: dependency: transitive description: path: media_kit - ref: "6cc242355decc163d377dcfc611fd0300556c222" - resolved-ref: "6cc242355decc163d377dcfc611fd0300556c222" + ref: "618d78e495b5809191e23966c4932fb02a425ef3" + resolved-ref: "618d78e495b5809191e23966c4932fb02a425ef3" url: "https://github.com/alexmercerind/media_kit.git" source: git version: "0.0.1" @@ -404,8 +404,8 @@ packages: dependency: transitive description: path: media_kit_libs_linux - ref: "6cc242355decc163d377dcfc611fd0300556c222" - resolved-ref: "6cc242355decc163d377dcfc611fd0300556c222" + ref: "618d78e495b5809191e23966c4932fb02a425ef3" + resolved-ref: "618d78e495b5809191e23966c4932fb02a425ef3" url: "https://github.com/alexmercerind/media_kit.git" source: git version: "1.0.0" @@ -413,8 +413,8 @@ packages: dependency: transitive description: path: media_kit_libs_windows_video - ref: "6cc242355decc163d377dcfc611fd0300556c222" - resolved-ref: "6cc242355decc163d377dcfc611fd0300556c222" + ref: "618d78e495b5809191e23966c4932fb02a425ef3" + resolved-ref: "618d78e495b5809191e23966c4932fb02a425ef3" url: "https://github.com/alexmercerind/media_kit.git" source: git version: "1.0.0" @@ -422,8 +422,8 @@ packages: dependency: transitive description: path: media_kit_native_event_loop - ref: "6cc242355decc163d377dcfc611fd0300556c222" - resolved-ref: "6cc242355decc163d377dcfc611fd0300556c222" + ref: "618d78e495b5809191e23966c4932fb02a425ef3" + resolved-ref: "618d78e495b5809191e23966c4932fb02a425ef3" url: "https://github.com/alexmercerind/media_kit.git" source: git version: "1.0.0" @@ -431,8 +431,8 @@ packages: dependency: transitive description: path: media_kit_video - ref: "6cc242355decc163d377dcfc611fd0300556c222" - resolved-ref: "6cc242355decc163d377dcfc611fd0300556c222" + ref: "618d78e495b5809191e23966c4932fb02a425ef3" + resolved-ref: "618d78e495b5809191e23966c4932fb02a425ef3" url: "https://github.com/alexmercerind/media_kit.git" source: git version: "0.0.1" @@ -620,14 +620,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" - reorderable_grid_view: - dependency: "direct main" - description: - name: reorderable_grid_view - sha256: "56d84da3b0ea459b3da2c21e844c0f125a9db5100bc909c7eb807c4c41aa27b1" - url: "https://pub.dev" - source: hosted - version: "2.2.6-alpha.14" reorderables: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 16b2f259..cdad9e89 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: Bluecherry client written in Flutter. publish_to: "none" -version: 3.0.0-beta2 +version: 3.0.0-beta5 environment: sdk: ">=2.18.5 <3.0.0" @@ -26,7 +26,6 @@ dependencies: auto_size_text: ^3.0.0 animations: ^2.0.7 provider: ^6.0.5 - reorderable_grid_view: ^2.2.6-alpha.14 reorderables: ^0.6.0 flutter_simple_treeview: ^3.0.2 diff --git a/version.txt b/version.txt index 7047ccd3..490fb8ec 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -#define MyAppVersion "3.0.0-beta4" +#define MyAppVersion "3.0.0-beta5"