Nikolas Rimikis
1 year ago
4 changed files with 214 additions and 149 deletions
@ -0,0 +1,210 @@
|
||||
import 'dart:async'; |
||||
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:meta/meta.dart'; |
||||
import 'package:neon/l10n/localizations.dart'; |
||||
import 'package:neon/neon.dart'; |
||||
import 'package:neon/src/router.dart'; |
||||
import 'package:neon/src/widgets/drawer_destination.dart'; |
||||
import 'package:provider/provider.dart'; |
||||
|
||||
@internal |
||||
class NeonDrawer extends StatelessWidget { |
||||
const NeonDrawer({ |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) { |
||||
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false); |
||||
final appsBloc = accountsBloc.activeAppsBloc; |
||||
|
||||
return StreamBuilder( |
||||
stream: appsBloc.appImplementations, |
||||
builder: (final context, final snapshot) { |
||||
if (snapshot.data?.data == null) { |
||||
return Container(); |
||||
} |
||||
|
||||
return _NeonDrawer( |
||||
apps: snapshot.data!.data!, |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
||||
|
||||
class _NeonDrawer extends StatefulWidget { |
||||
const _NeonDrawer({ |
||||
required this.apps, |
||||
}); |
||||
|
||||
final Iterable<AppImplementation> apps; |
||||
|
||||
@override |
||||
State<_NeonDrawer> createState() => __NeonDrawerState(); |
||||
} |
||||
|
||||
class __NeonDrawerState extends State<_NeonDrawer> with SingleTickerProviderStateMixin { |
||||
late TabController _tabController; |
||||
late AccountsBloc _accountsBloc; |
||||
late AppsBloc _appsBloc; |
||||
late List<AppImplementation> _apps; |
||||
|
||||
int _activeApp = 0; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
|
||||
_accountsBloc = Provider.of<AccountsBloc>(context, listen: false); |
||||
_appsBloc = _accountsBloc.activeAppsBloc; |
||||
|
||||
_apps = widget.apps.toList(); |
||||
_activeApp = _apps.indexWhere((final app) => app.id == _appsBloc.activeAppID.valueOrNull); |
||||
|
||||
_tabController = TabController( |
||||
vsync: this, |
||||
length: widget.apps.length, |
||||
); |
||||
} |
||||
|
||||
@override |
||||
void dispose() { |
||||
_tabController.dispose(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
void onAppChange(final int index) { |
||||
Scaffold.maybeOf(context)?.closeDrawer(); |
||||
|
||||
// selected item is not a registered app like the SettingsPage |
||||
if (index >= _apps.length) { |
||||
const SettingsRoute().go(context); |
||||
return; |
||||
} |
||||
|
||||
setState(() { |
||||
_activeApp = index; |
||||
}); |
||||
|
||||
unawaited(_appsBloc.setActiveApp(_apps[index].id)); |
||||
//context.goNamed(apps[index].routeName); |
||||
} |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) { |
||||
final appDestinations = _apps.map( |
||||
(final app) => NavigationDrawerDestinationExtension.fromNeonDestination( |
||||
app.destination(context), |
||||
), |
||||
); |
||||
|
||||
final drawer = NavigationDrawer( |
||||
selectedIndex: _activeApp, |
||||
onDestinationSelected: onAppChange, |
||||
children: [ |
||||
const NeonDrawerHeader(), |
||||
...appDestinations, |
||||
NavigationDrawerDestination( |
||||
icon: const Icon(Icons.settings), |
||||
label: Text(AppLocalizations.of(context).settings), |
||||
), |
||||
], |
||||
); |
||||
|
||||
return drawer; |
||||
} |
||||
} |
||||
|
||||
@internal |
||||
class NeonDrawerHeader extends StatelessWidget { |
||||
const NeonDrawerHeader({super.key}); |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) { |
||||
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false); |
||||
final capabilitiesBloc = accountsBloc.activeCapabilitiesBloc; |
||||
|
||||
final accountSelecor = StreamBuilder<List<Account>>( |
||||
stream: accountsBloc.accounts, |
||||
builder: (final context, final accountsSnapshot) { |
||||
final accounts = accountsSnapshot.data; |
||||
if (accounts == null || accounts.length <= 1) { |
||||
return const SizedBox.shrink(); |
||||
} |
||||
|
||||
final items = accounts.map((final account) { |
||||
final child = NeonAccountTile( |
||||
account: account, |
||||
dense: true, |
||||
textColor: Theme.of(context).appBarTheme.foregroundColor, |
||||
); |
||||
|
||||
return DropdownMenuItem( |
||||
value: account, |
||||
child: child, |
||||
); |
||||
}).toList(); |
||||
|
||||
return DropdownButtonHideUnderline( |
||||
child: DropdownButton( |
||||
isExpanded: true, |
||||
dropdownColor: Theme.of(context).colorScheme.primary, |
||||
iconEnabledColor: Theme.of(context).colorScheme.onBackground, |
||||
value: accountsBloc.activeAccount.value, |
||||
items: items, |
||||
onChanged: (final account) { |
||||
if (account == null) { |
||||
return; |
||||
} |
||||
|
||||
accountsBloc.setActiveAccount(account); |
||||
}, |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
|
||||
return ResultBuilder<Capabilities>( |
||||
stream: capabilitiesBloc.capabilities, |
||||
builder: (final context, final capabilities) => DrawerHeader( |
||||
decoration: BoxDecoration( |
||||
color: Theme.of(context).colorScheme.primary, |
||||
), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
children: [ |
||||
if (capabilities.data != null) ...[ |
||||
if (capabilities.data!.capabilities.theming?.name != null) ...[ |
||||
Text( |
||||
capabilities.data!.capabilities.theming!.name!, |
||||
style: DefaultTextStyle.of(context).style.copyWith( |
||||
color: Theme.of(context).appBarTheme.foregroundColor, |
||||
), |
||||
), |
||||
], |
||||
if (capabilities.data!.capabilities.theming?.logo != null) ...[ |
||||
Flexible( |
||||
child: NeonCachedUrlImage( |
||||
url: capabilities.data!.capabilities.theming!.logo!, |
||||
), |
||||
), |
||||
], |
||||
] else ...[ |
||||
NeonException( |
||||
capabilities.error, |
||||
onRetry: capabilitiesBloc.refresh, |
||||
), |
||||
NeonLinearProgressIndicator( |
||||
visible: capabilities.loading, |
||||
), |
||||
], |
||||
accountSelecor, |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
Loading…
Reference in new issue