diff --git a/packages/neon/neon/lib/neon.dart b/packages/neon/neon/lib/neon.dart index 6542e5b0..b84514e6 100644 --- a/packages/neon/neon/lib/neon.dart +++ b/packages/neon/neon/lib/neon.dart @@ -194,12 +194,7 @@ Future runNeon({ create: (final _) => branding, ), ], - child: NeonApp( - accountsBloc: accountsBloc, - sharedPreferences: sharedPreferences, - platform: platform, - globalOptions: globalOptions, - ), + child: const NeonApp(), ), ); } diff --git a/packages/neon/neon/lib/src/app.dart b/packages/neon/neon/lib/src/app.dart index 48c7bded..7a32d29f 100644 --- a/packages/neon/neon/lib/src/app.dart +++ b/packages/neon/neon/lib/src/app.dart @@ -2,18 +2,9 @@ part of '../../neon.dart'; class NeonApp extends StatefulWidget { const NeonApp({ - required this.accountsBloc, - required this.sharedPreferences, - required this.platform, - required this.globalOptions, super.key, }); - final AccountsBloc accountsBloc; - final SharedPreferences sharedPreferences; - final NeonPlatform platform; - final GlobalOptions globalOptions; - @override State createState() => _NeonAppState(); } @@ -253,13 +244,13 @@ class _NeonAppState extends State with WidgetsBindingObserver, tray.Tra @override Widget build(final BuildContext context) => OptionBuilder( - option: widget.globalOptions.themeMode, + option: _globalOptions.themeMode, builder: (final context, final themeMode) => OptionBuilder( - option: widget.globalOptions.themeOLEDAsDark, + option: _globalOptions.themeOLEDAsDark, builder: (final context, final themeOLEDAsDark) => OptionBuilder( - option: widget.globalOptions.themeKeepOriginalAccentColor, + option: _globalOptions.themeKeepOriginalAccentColor, builder: (final context, final themeKeepOriginalAccentColor) => StreamBuilder( - stream: widget.accountsBloc.activeAccount, + stream: _accountsBloc.activeAccount, builder: (final context, final activeAccountSnapshot) { if (themeMode == null || themeOLEDAsDark == null) { return Container(); @@ -268,7 +259,7 @@ class _NeonAppState extends State with WidgetsBindingObserver, tray.Tra FlutterNativeSplash.remove(); return ResultBuilder( stream: activeAccountSnapshot.hasData - ? widget.accountsBloc.getCapabilitiesBlocFor(activeAccountSnapshot.data!).capabilities + ? _accountsBloc.getCapabilitiesBlocFor(activeAccountSnapshot.data!).capabilities : null, builder: (final context, final capabilitiesSnapshot) { final nextcloudTheme = capabilitiesSnapshot.data?.capabilities.theming; diff --git a/packages/neon/neon/lib/src/blocs/apps.dart b/packages/neon/neon/lib/src/blocs/apps.dart index 85f2cd28..223b8c3b 100644 --- a/packages/neon/neon/lib/src/blocs/apps.dart +++ b/packages/neon/neon/lib/src/blocs/apps.dart @@ -82,8 +82,6 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates final Account _account; final Iterable _allAppImplementations; - final Map _blocs = {}; - @override void dispose() { unawaited(apps.close()); @@ -91,8 +89,11 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates unawaited(notificationsAppImplementation.close()); unawaited(activeAppID.close()); unawaited(openNotifications.close()); - for (final key in _blocs.keys) { - _blocs[key]!.dispose(); + + for (final app in _allAppImplementations) { + for (final bloc in app.blocs.values) { + bloc.dispose(); + } } } @@ -137,15 +138,8 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates } } - T getAppBloc(final AppImplementation appImplementation) { - if (_blocs[appImplementation.id] != null) { - return _blocs[appImplementation.id]! as T; - } - - return _blocs[appImplementation.id] = appImplementation.buildBloc(_account.client) as T; - } + T getAppBloc(final AppImplementation appImplementation) => appImplementation.getBloc(_account) as T; - List? getAppProviders() => appImplementations.valueOrNull?.data - ?.map((final appImplementation) => appImplementation.blocProvider(_account.client)) - .toList(); + List get appBlocProviders => + _allAppImplementations.map((final appImplementation) => appImplementation.blocProvider).toList(); } diff --git a/packages/neon/neon/lib/src/interfaces/notifications.dart b/packages/neon/neon/lib/src/interfaces/notifications.dart index 0f9a5de5..a23c30fa 100644 --- a/packages/neon/neon/lib/src/interfaces/notifications.dart +++ b/packages/neon/neon/lib/src/interfaces/notifications.dart @@ -1,7 +1,7 @@ part of '../../neon.dart'; -abstract class NotificationsAppInterface - extends AppImplementation { +abstract interface class NotificationsAppInterface extends AppImplementation { NotificationsAppInterface( super.sharedPreferences, super.requestManager, @@ -9,13 +9,13 @@ abstract class NotificationsAppInterface ); } -abstract class NotificationsBlocInterface extends InteractiveBloc { +abstract interface class NotificationsBlocInterface extends InteractiveBloc { NotificationsBlocInterface(this.options); final NotificationsOptionsInterface options; void deleteNotification(final int id); } -abstract class NotificationsOptionsInterface extends NextcloudAppSpecificOptions { +abstract interface class NotificationsOptionsInterface extends NextcloudAppSpecificOptions { NotificationsOptionsInterface(super.storage); } diff --git a/packages/neon/neon/lib/src/pages/home.dart b/packages/neon/neon/lib/src/pages/home.dart index 5a802ccb..b923a9f1 100644 --- a/packages/neon/neon/lib/src/pages/home.dart +++ b/packages/neon/neon/lib/src/pages/home.dart @@ -132,25 +132,30 @@ class _HomePageState extends State { final List accounts, final Account account, ) async { + final page = Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(app.name(context)), + if (accounts.length > 1) ...[ + Text( + account.client.humanReadableID, + style: Theme.of(context).textTheme.bodySmall, + ), + ], + ], + ), + ), + body: app.page, + ); + await Navigator.of(context).push( MaterialPageRoute( - builder: (final context) => Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - title: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(app.name(context)), - if (accounts.length > 1) ...[ - Text( - account.client.humanReadableID, - style: Theme.of(context).textTheme.bodySmall, - ), - ], - ], - ), - ), - body: app.page, + builder: (final context) => Provider( + create: (final context) => app.getBloc(account), + child: page, ), ), ); @@ -171,17 +176,9 @@ class _HomePageState extends State { stream: _appsBloc.notificationsAppImplementation, builder: (final context, final notificationsAppImplementation) => StreamBuilder( stream: _appsBloc.activeAppID, - builder: ( - final context, - final activeAppIDSnapshot, - ) => - StreamBuilder>( + builder: (final context, final activeAppIDSnapshot) => StreamBuilder>( stream: _accountsBloc.accounts, - builder: ( - final context, - final accountsSnapshot, - ) => - OptionBuilder( + builder: (final context, final accountsSnapshot) => OptionBuilder( option: _globalOptions.navigationMode, builder: (final context, final navigationMode) { final accounts = accountsSnapshot.data; @@ -536,13 +533,10 @@ class _HomePageState extends State { ), ); - final appProviders = _appsBloc.getAppProviders(); - if (appProviders != null) { - body = MultiProvider( - providers: appProviders, - child: body, - ); - } + body = MultiProvider( + providers: _appsBloc.appBlocProviders, + child: body, + ); return WillPopScope( onWillPop: () async { diff --git a/packages/neon/neon/lib/src/utils/app_implementation.dart b/packages/neon/neon/lib/src/utils/app_implementation.dart index c1e207ab..63b789a5 100644 --- a/packages/neon/neon/lib/src/utils/app_implementation.dart +++ b/packages/neon/neon/lib/src/utils/app_implementation.dart @@ -22,10 +22,19 @@ abstract class AppImplementation blocs = {}; + + T getBloc(final Account account) => blocs[account.id] ??= buildBloc(account.client); + T buildBloc(final NextcloudClient client); - Provider blocProvider(final NextcloudClient client) => Provider( - create: (final _) => buildBloc(client), + Provider get blocProvider => Provider( + create: (final context) { + final accountsBloc = Provider.of(context, listen: false); + final account = accountsBloc.activeAccount.value!; + + return getBloc(account); + }, ); BehaviorSubject? getUnreadCounter(final AppsBloc appsBloc); diff --git a/packages/neon/neon_notifications/lib/blocs/notifications.dart b/packages/neon/neon_notifications/lib/blocs/notifications.dart index 460c5556..b52cf9ca 100644 --- a/packages/neon/neon_notifications/lib/blocs/notifications.dart +++ b/packages/neon/neon_notifications/lib/blocs/notifications.dart @@ -1,20 +1,21 @@ part of '../neon_notifications.dart'; -abstract class NotificationsBlocEvents { +abstract interface class NotificationsBlocEvents { void deleteNotification(final int id); void deleteAllNotifications(); } -abstract class NotificationsBlocStates { +abstract interface class NotificationsBlocStates { BehaviorSubject>> get notifications; BehaviorSubject get unreadCounter; } -class NotificationsBloc extends NotificationsBlocInterface implements NotificationsBlocEvents, NotificationsBlocStates { +class NotificationsBloc extends InteractiveBloc + implements NotificationsBlocInterface, NotificationsBlocEvents, NotificationsBlocStates { NotificationsBloc( - super.options, + this.options, this._requestManager, this._client, ) { @@ -27,6 +28,8 @@ class NotificationsBloc extends NotificationsBlocInterface implements Notificati unawaited(refresh()); } + @override + final NotificationsAppSpecificOptions options; final RequestManager _requestManager; final NextcloudClient _client; diff --git a/packages/neon/neon_notifications/lib/neon_notifications.dart b/packages/neon/neon_notifications/lib/neon_notifications.dart index f5a9b61f..83db56d7 100644 --- a/packages/neon/neon_notifications/lib/neon_notifications.dart +++ b/packages/neon/neon_notifications/lib/neon_notifications.dart @@ -14,7 +14,8 @@ part 'blocs/notifications.dart'; part 'options.dart'; part 'pages/main.dart'; -class NotificationsApp extends NotificationsAppInterface { +class NotificationsApp extends AppImplementation + implements NotificationsAppInterface { NotificationsApp(super.sharedPreferences, super.requestManager, super.platform); @override diff --git a/packages/neon/neon_notifications/lib/options.dart b/packages/neon/neon_notifications/lib/options.dart index 5bdd44e9..a897b3ff 100644 --- a/packages/neon/neon_notifications/lib/options.dart +++ b/packages/neon/neon_notifications/lib/options.dart @@ -1,6 +1,6 @@ part of 'neon_notifications.dart'; -class NotificationsAppSpecificOptions extends NotificationsOptionsInterface { +class NotificationsAppSpecificOptions extends NextcloudAppSpecificOptions implements NotificationsOptionsInterface { NotificationsAppSpecificOptions(super.storage) { super.categories = []; super.options = []; diff --git a/packages/neon/neon_notifications/lib/pages/main.dart b/packages/neon/neon_notifications/lib/pages/main.dart index 1d984746..af72315f 100644 --- a/packages/neon/neon_notifications/lib/pages/main.dart +++ b/packages/neon/neon_notifications/lib/pages/main.dart @@ -16,7 +16,7 @@ class _NotificationsMainPageState extends State { void initState() { super.initState(); - bloc = Provider.of(context, listen: false); + bloc = Provider.of(context, listen: false) as NotificationsBloc; bloc.errors.listen((final error) { NeonException.showSnackbar(context, error);