144 lines
5.0 KiB
Dart
144 lines
5.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
import 'package:get_it/get_it.dart';
|
|
|
|
import '../components/ViewSelector/no_music_libraries_message.dart';
|
|
import '../services/finamp_user_helper.dart';
|
|
import 'music_screen.dart';
|
|
import '../services/jellyfin_api_helper.dart';
|
|
import '../models/jellyfin_models.dart';
|
|
import '../components/error_snackbar.dart';
|
|
|
|
class ViewSelector extends StatefulWidget {
|
|
const ViewSelector({Key? key}) : super(key: key);
|
|
|
|
static const routeName = "/settings/views";
|
|
|
|
@override
|
|
State<ViewSelector> createState() => _ViewSelectorState();
|
|
}
|
|
|
|
class _ViewSelectorState extends State<ViewSelector> {
|
|
final _jellyfinApiHelper = GetIt.instance<JellyfinApiHelper>();
|
|
final _finampUserHelper = GetIt.instance<FinampUserHelper>();
|
|
late Future<List<BaseItemDto>> viewListFuture;
|
|
final Map<BaseItemDto, bool> _views = {};
|
|
bool isSubmitButtonEnabled = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
viewListFuture = _jellyfinApiHelper.getViews();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureBuilder<List<BaseItemDto>>(
|
|
future: viewListFuture,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasData) {
|
|
// Finamp only supports music libraries. We used to allow people to
|
|
// select unsupported libraries, but some people selected "general"
|
|
// libraries and thought Finamp was broken.
|
|
if (snapshot.data!.isEmpty ||
|
|
!snapshot.data!
|
|
.any((element) => element.collectionType == "music")) {
|
|
return NoMusicLibrariesMessage(
|
|
onRefresh: () {
|
|
setState(() {
|
|
_views.clear();
|
|
viewListFuture = _jellyfinApiHelper.getViews();
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
if (_views.isEmpty) {
|
|
_views.addEntries(snapshot.data!
|
|
.where((element) => element.collectionType != "playlists")
|
|
.map((e) => MapEntry(e, e.collectionType == "music")));
|
|
|
|
// If only one music library is available and user doesn't have a
|
|
// view saved (assuming setup is in progress), skip the selector.
|
|
if (_views.values.where((element) => element == true).length == 1 &&
|
|
_finampUserHelper.currentUser!.currentView == null) {
|
|
_submitChoice();
|
|
} else {
|
|
if (mounted) {
|
|
isSubmitButtonEnabled = _views.values.contains(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(AppLocalizations.of(context)!.selectMusicLibraries),
|
|
),
|
|
floatingActionButton: isSubmitButtonEnabled
|
|
? FloatingActionButton(
|
|
onPressed: _submitChoice,
|
|
child: const Icon(Icons.check),
|
|
)
|
|
: null,
|
|
body: Scrollbar(
|
|
child: ListView.builder(
|
|
itemCount: _views.length,
|
|
itemBuilder: (context, index) {
|
|
final isSelected = _views.values.elementAt(index);
|
|
final view = _views.keys.elementAt(index);
|
|
|
|
return CheckboxListTile(
|
|
value: isSelected,
|
|
enabled: view.collectionType == "music",
|
|
title: Text(_views.keys.elementAt(index).name ??
|
|
AppLocalizations.of(context)!.unknownName),
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_views[_views.keys.elementAt(index)] = value!;
|
|
isSubmitButtonEnabled = _views.values.contains(true);
|
|
});
|
|
},
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
} else if (snapshot.hasError) {
|
|
errorSnackbar(snapshot.error, context);
|
|
// TODO: Let the user refresh the page
|
|
return Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(Icons.error),
|
|
Text(snapshot.error.toString()),
|
|
],
|
|
));
|
|
} else {
|
|
return const Center(child: CircularProgressIndicator.adaptive());
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
void _submitChoice() {
|
|
if (_views.values.where((element) => element == true).isEmpty) {
|
|
// This should no longer be possible since the submit button only shows
|
|
// when views are selected, but we return just in case
|
|
return;
|
|
} else {
|
|
try {
|
|
_finampUserHelper.setCurrentUserViews(_views.entries
|
|
.where((element) => element.value == true)
|
|
.map((e) => e.key)
|
|
.toList());
|
|
// allow navigation to music screen while selector is being built
|
|
Future.microtask(() => Navigator.of(context)
|
|
.pushNamedAndRemoveUntil(MusicScreen.routeName, (route) => false));
|
|
} catch (e) {
|
|
errorSnackbar(e, context);
|
|
}
|
|
}
|
|
}
|
|
}
|