Skip to content

Commit

Permalink
Improve handling of reconnects with modal barrier overlay. Special ro…
Browse files Browse the repository at this point in the history
…utes and screen for connecting removed.
  • Loading branch information
Kern, Thomas committed Jan 13, 2024
1 parent 92c0018 commit 322fadd
Show file tree
Hide file tree
Showing 17 changed files with 594 additions and 604 deletions.
88 changes: 71 additions & 17 deletions lib/components/busy_wrapper.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:mopicon/pages/settings/preferences_controller.dart';
import 'package:mopicon/services/mopidy_service.dart';
import 'package:mopicon/common/globals.dart';
import 'package:mopicon/generated/l10n.dart';

/// Shows a modal busy indicator.
///
Expand All @@ -19,24 +22,45 @@ class BusyWrapper extends StatefulWidget {

class _BusyWrapperState extends State<BusyWrapper> with TickerProviderStateMixin {
final preferences = GetIt.instance<PreferencesController>();
final mopidyService = GetIt.instance<MopidyService>();

late final AnimationController _controller = AnimationController(
late final AnimationController _primaryController = AnimationController(
duration: const Duration(seconds: 4),
vsync: this,
);

late final Animation<double> _animation = CurvedAnimation(
parent: _controller,
late final AnimationController _secondaryController = AnimationController(
duration: const Duration(seconds: 10),
vsync: this,
);

late final Animation<double> _connectionAnimation = CurvedAnimation(
parent: _secondaryController,
curve: Curves.easeIn,
);

late final Animation<double> _busyAnimation = CurvedAnimation(
parent: _primaryController,
curve: Curves.easeIn,
);

void _startAnimation() {
_primaryController.forward(from: 0);
_secondaryController.forward(from: 0);
}

void _stopAnimation() {
_primaryController.reset();
_secondaryController.reset();
}

bool _busy = false;

bool get busy => _busy;

set busy(bool b) {
setState(() {
b ? _controller.forward(from: 0) : _controller.reset();
b ? _startAnimation() : _stopAnimation();
_busy = b;
});
}
Expand All @@ -45,42 +69,72 @@ class _BusyWrapperState extends State<BusyWrapper> with TickerProviderStateMixin
initState() {
super.initState();
_busy = widget.busy;
_controller.forward(from: 0);
_startAnimation();
}

@override
dispose() {
_controller.dispose();
_primaryController.dispose();
_secondaryController.dispose();
super.dispose();
}

@override
void didUpdateWidget(covariant BusyWrapper oldWidget) {
_controller.reset();
_controller.forward(from: 0);
_startAnimation();
super.didUpdateWidget(oldWidget);
}

void stop() async {
_stopAnimation();
mopidyService.stop();
Globals.applicationRoutes.gotoSettings();
}

@override
Widget build(BuildContext context) {
if (!widget.busy) {
if (!widget.busy && mopidyService.connected) {
return widget.child;
}

return Stack(
return Material(
child: Stack(
children: [
widget.child,
Opacity(
opacity: 0.4,
opacity: 0.5,
child: ModalBarrier(dismissible: false, color: preferences.theme.data.dialogBackgroundColor),
),
Center(
child: FadeTransition(
opacity: _animation,
child: const CircularProgressIndicator(),
),
FadeTransition(
opacity: _busyAnimation,
child: Center(child: Container(padding: const EdgeInsets.all(40), child: const CircularProgressIndicator())),
),
mopidyService.connected == false
? Center(
child: FadeTransition(
opacity: _connectionAnimation,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
S.of(context).connectingPageConnecting,
style: const TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 100),
ElevatedButton(
onPressed: stop,
child: Text(S.of(context).connectingPageStopBtn,
style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold)))
],
),
),
)
: const SizedBox(),
],
);
));
}
}
16 changes: 6 additions & 10 deletions lib/components/titled_divider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ class TitledDivider extends StatelessWidget {
child: Row(children: <Widget>[
Text(title),
Expanded(
child: Container(
margin: const EdgeInsets.only(left: 10.0),
child: const Divider()),
child: Container(margin: const EdgeInsets.only(left: 10.0), child: const Divider()),
),
]));
}
Expand All @@ -54,24 +52,22 @@ class SpacedDivider extends StatelessWidget {

@override
build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: _defaultTop, bottom: _defaultBottom),
child: const Divider());
return Container(margin: EdgeInsets.only(top: _defaultTop, bottom: _defaultBottom), child: const Divider());
}
}

/// A vertical spaced.
class VerticalSpacer extends StatelessWidget {
double? space;
final double? space;

/// Creates a [Divider] with additional vertical spacing.
VerticalSpacer({this.space, super.key});
const VerticalSpacer({this.space, super.key});

@override
build(BuildContext context) {
space = space ?? _defaultTop + _defaultBottom;
var vsp = space ?? _defaultTop + _defaultBottom;
return Container(
margin: EdgeInsets.only(top: space! / 2.0, bottom: space! / 2),
margin: EdgeInsets.only(top: vsp / 2.0, bottom: vsp / 2),
);
}
}
2 changes: 0 additions & 2 deletions lib/initializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import 'package:get_it/get_it.dart';
import 'package:mopicon/pages/settings/preferences_controller.dart';
import 'package:mopicon/services/mopidy_service.dart';
import 'package:mopicon/services/cover_service.dart';
import 'package:mopicon/pages/connecting_screen/connecting_screen_controller.dart';
import 'package:mopicon/pages/browse/library_browser_controller.dart';
import 'package:mopicon/pages/playlist/playlist_view_controller.dart';
import 'package:mopicon/pages/tracklist/tracklist_view_controller.dart';
Expand All @@ -48,7 +47,6 @@ class Initializer {
Globals.logger.i("starting registering services");
getIt.registerLazySingleton<PreferencesController>(() => PreferencesControllerImpl());
getIt.registerLazySingleton<MopidyService>(() => MopidyServiceImpl());
getIt.registerLazySingleton<ConnectingScreenController>(() => ConnectingScreenControllerImpl());
getIt.registerLazySingleton<CoverService>(() => CoverServiceImpl());
getIt.registerLazySingleton<LibraryBrowserController>(() => LibraryBrowserControllerImpl());
getIt.registerLazySingleton<TracklistViewController>(() => TracklistViewControllerImpl());
Expand Down
87 changes: 39 additions & 48 deletions lib/pages/browse/library_browser_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import 'package:mopicon/services/mopidy_service.dart';
import 'package:mopicon/pages/settings/preferences_controller.dart';
import 'package:mopicon/utils/parameters.dart';
import 'package:mopicon/components/action_buttons.dart';
import 'package:mopicon/components/busy_wrapper.dart';
import 'package:mopicon/common/globals.dart';
import 'package:mopicon/generated/l10n.dart';
import 'package:mopicon/extensions/mopidy_utils.dart';
Expand All @@ -54,7 +53,6 @@ class _LibraryBrowserPageState extends State<LibraryBrowserPage> {
Ref? parent;
List<Ref> items = [];
var images = <String, Widget>{};
bool showBusy = false;

// selection mode (single/multiple) of track list view
SelectionMode selectionMode = SelectionMode.off;
Expand All @@ -69,9 +67,7 @@ class _LibraryBrowserPageState extends State<LibraryBrowserPage> {

Future updateItems() async {
try {
setState(() {
showBusy = true;
});
mopidyService.setBusy(true);
if (widget.parent != null) {
parent = Ref.fromMap(Parameter.fromBase64(widget.parent!));
}
Expand All @@ -93,11 +89,8 @@ class _LibraryBrowserPageState extends State<LibraryBrowserPage> {
} catch (e, s) {
Globals.logger.e(e, stackTrace: s);
} finally {
if (mounted) {
setState(() {
showBusy = false;
});
}
mopidyService.setBusy(false);
setState(() {});
}
}

Expand Down Expand Up @@ -158,45 +151,43 @@ class _LibraryBrowserPageState extends State<LibraryBrowserPage> {
}
}).build();

return BusyWrapper(
Scaffold(
appBar: AppBar(
title: Text(widget.title ?? S.of(context).libraryBrowserPageTitle),
centerTitle: true,
leading: widget.parent != null
? ActionButton<SelectedItemPositions>(Icons.arrow_back, () {
if (libraryController.isSelectionEmpty) {
Navigator.of(context).pop();
} else {
libraryController.notifyUnselect();
}
})
: null,
actions: [
parent == null
? ActionButton<SelectedItemPositions>(
Icons.delete, () => libraryController.deleteSelectedPlaylists(context),
valueListenable: libraryController.selectionChanged)
: const SizedBox(),
ActionButton<SelectedItemPositions>(Icons.queue_music, () async {
var selectedItems = await libraryController.getSelectedItems(parent);
if (context.mounted) {
await libraryController.addItemsToTracklist<Ref>(context, selectedItems);
}
libraryController.notifyUnselect();
}, valueListenable: libraryController.selectionChanged),
ActionButton<SelectedItemPositions>(Icons.playlist_add, () async {
var selectedItems = await libraryController.getSelectedItems(parent);
if (context.mounted) {
await libraryController.addItemsToPlaylist<Ref>(context, selectedItems);
return Scaffold(
appBar: AppBar(
title: Text(widget.title ?? S.of(context).libraryBrowserPageTitle),
centerTitle: true,
leading: widget.parent != null
? ActionButton<SelectedItemPositions>(Icons.arrow_back, () {
if (libraryController.isSelectionEmpty) {
Navigator.of(context).pop();
} else {
libraryController.notifyUnselect();
}
libraryController.notifyUnselect();
}, valueListenable: libraryController.selectionChanged),
VolumeControl(),
LibraryBrowserAppBarMenu(items, libraryController)
]),
body: MaterialPageFrame(child: listView)),
showBusy);
})
: null,
actions: [
parent == null
? ActionButton<SelectedItemPositions>(
Icons.delete, () => libraryController.deleteSelectedPlaylists(context),
valueListenable: libraryController.selectionChanged)
: const SizedBox(),
ActionButton<SelectedItemPositions>(Icons.queue_music, () async {
var selectedItems = await libraryController.getSelectedItems(parent);
if (context.mounted) {
await libraryController.addItemsToTracklist<Ref>(context, selectedItems);
}
libraryController.notifyUnselect();
}, valueListenable: libraryController.selectionChanged),
ActionButton<SelectedItemPositions>(Icons.playlist_add, () async {
var selectedItems = await libraryController.getSelectedItems(parent);
if (context.mounted) {
await libraryController.addItemsToPlaylist<Ref>(context, selectedItems);
}
libraryController.notifyUnselect();
}, valueListenable: libraryController.selectionChanged),
VolumeControl(),
LibraryBrowserAppBarMenu(items, libraryController)
]),
body: MaterialPageFrame(child: listView));
}

void translateNames(BuildContext context) {
Expand Down
3 changes: 2 additions & 1 deletion lib/pages/browse/library_list_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class LibraryListView {
),
);
} else if (item.type == Ref.typeTrack) {
return images[getUri(item)]!;
Widget? w = images[getUri(item)];
return w ?? ImageUtils.getIconForType(item.uri, item.type);
} else {
return ImageUtils.getIconForType(item.uri, item.type);
}
Expand Down
Loading

0 comments on commit 322fadd

Please sign in to comment.