Files
Redesnigned-Finamp/lib/screens/view_selector.dart
T
Zakaria d0ca84d8d2
Build / Build for Android (push) Has been cancelled
Build / Build for iOS (push) Has been cancelled
redesign app phase 1
2026-05-18 14:34:41 -04:00

144 lines
5.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:finamp/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);
}
}
}
}