Browse Source

Merge pull request #371 from Leptopoda/fix/notifications_navigaator

neon: fix blocProvider of notifications app
pull/378/head
Nikolas Rimikis 1 year ago committed by GitHub
parent
commit
3c34cb6298
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      packages/neon/neon/lib/neon.dart
  2. 19
      packages/neon/neon/lib/src/app.dart
  3. 22
      packages/neon/neon/lib/src/blocs/apps.dart
  4. 8
      packages/neon/neon/lib/src/interfaces/notifications.dart
  5. 62
      packages/neon/neon/lib/src/pages/home.dart
  6. 13
      packages/neon/neon/lib/src/utils/app_implementation.dart
  7. 11
      packages/neon/neon_notifications/lib/blocs/notifications.dart
  8. 3
      packages/neon/neon_notifications/lib/neon_notifications.dart
  9. 2
      packages/neon/neon_notifications/lib/options.dart
  10. 2
      packages/neon/neon_notifications/lib/pages/main.dart

7
packages/neon/neon/lib/neon.dart

@ -194,12 +194,7 @@ Future runNeon({
create: (final _) => branding, create: (final _) => branding,
), ),
], ],
child: NeonApp( child: const NeonApp(),
accountsBloc: accountsBloc,
sharedPreferences: sharedPreferences,
platform: platform,
globalOptions: globalOptions,
),
), ),
); );
} }

19
packages/neon/neon/lib/src/app.dart

@ -2,18 +2,9 @@ part of '../../neon.dart';
class NeonApp extends StatefulWidget { class NeonApp extends StatefulWidget {
const NeonApp({ const NeonApp({
required this.accountsBloc,
required this.sharedPreferences,
required this.platform,
required this.globalOptions,
super.key, super.key,
}); });
final AccountsBloc accountsBloc;
final SharedPreferences sharedPreferences;
final NeonPlatform platform;
final GlobalOptions globalOptions;
@override @override
State<NeonApp> createState() => _NeonAppState(); State<NeonApp> createState() => _NeonAppState();
} }
@ -253,13 +244,13 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
@override @override
Widget build(final BuildContext context) => OptionBuilder( Widget build(final BuildContext context) => OptionBuilder(
option: widget.globalOptions.themeMode, option: _globalOptions.themeMode,
builder: (final context, final themeMode) => OptionBuilder( builder: (final context, final themeMode) => OptionBuilder(
option: widget.globalOptions.themeOLEDAsDark, option: _globalOptions.themeOLEDAsDark,
builder: (final context, final themeOLEDAsDark) => OptionBuilder( builder: (final context, final themeOLEDAsDark) => OptionBuilder(
option: widget.globalOptions.themeKeepOriginalAccentColor, option: _globalOptions.themeKeepOriginalAccentColor,
builder: (final context, final themeKeepOriginalAccentColor) => StreamBuilder<Account?>( builder: (final context, final themeKeepOriginalAccentColor) => StreamBuilder<Account?>(
stream: widget.accountsBloc.activeAccount, stream: _accountsBloc.activeAccount,
builder: (final context, final activeAccountSnapshot) { builder: (final context, final activeAccountSnapshot) {
if (themeMode == null || themeOLEDAsDark == null) { if (themeMode == null || themeOLEDAsDark == null) {
return Container(); return Container();
@ -268,7 +259,7 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
FlutterNativeSplash.remove(); FlutterNativeSplash.remove();
return ResultBuilder<Capabilities?>( return ResultBuilder<Capabilities?>(
stream: activeAccountSnapshot.hasData stream: activeAccountSnapshot.hasData
? widget.accountsBloc.getCapabilitiesBlocFor(activeAccountSnapshot.data!).capabilities ? _accountsBloc.getCapabilitiesBlocFor(activeAccountSnapshot.data!).capabilities
: null, : null,
builder: (final context, final capabilitiesSnapshot) { builder: (final context, final capabilitiesSnapshot) {
final nextcloudTheme = capabilitiesSnapshot.data?.capabilities.theming; final nextcloudTheme = capabilitiesSnapshot.data?.capabilities.theming;

22
packages/neon/neon/lib/src/blocs/apps.dart

@ -82,8 +82,6 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates
final Account _account; final Account _account;
final Iterable<AppImplementation> _allAppImplementations; final Iterable<AppImplementation> _allAppImplementations;
final Map<String, Bloc> _blocs = {};
@override @override
void dispose() { void dispose() {
unawaited(apps.close()); unawaited(apps.close());
@ -91,8 +89,11 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates
unawaited(notificationsAppImplementation.close()); unawaited(notificationsAppImplementation.close());
unawaited(activeAppID.close()); unawaited(activeAppID.close());
unawaited(openNotifications.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<T extends Bloc>(final AppImplementation appImplementation) { T getAppBloc<T extends Bloc>(final AppImplementation appImplementation) => appImplementation.getBloc(_account) as T;
if (_blocs[appImplementation.id] != null) {
return _blocs[appImplementation.id]! as T;
}
return _blocs[appImplementation.id] = appImplementation.buildBloc(_account.client) as T;
}
List<Provider>? getAppProviders() => appImplementations.valueOrNull?.data List<Provider> get appBlocProviders =>
?.map((final appImplementation) => appImplementation.blocProvider(_account.client)) _allAppImplementations.map((final appImplementation) => appImplementation.blocProvider).toList();
.toList();
} }

8
packages/neon/neon/lib/src/interfaces/notifications.dart

@ -1,7 +1,7 @@
part of '../../neon.dart'; part of '../../neon.dart';
abstract class NotificationsAppInterface abstract interface class NotificationsAppInterface<T extends NotificationsBlocInterface,
extends AppImplementation<NotificationsBlocInterface, NotificationsOptionsInterface> { R extends NotificationsOptionsInterface> extends AppImplementation<T, R> {
NotificationsAppInterface( NotificationsAppInterface(
super.sharedPreferences, super.sharedPreferences,
super.requestManager, super.requestManager,
@ -9,13 +9,13 @@ abstract class NotificationsAppInterface
); );
} }
abstract class NotificationsBlocInterface extends InteractiveBloc { abstract interface class NotificationsBlocInterface extends InteractiveBloc {
NotificationsBlocInterface(this.options); NotificationsBlocInterface(this.options);
final NotificationsOptionsInterface options; final NotificationsOptionsInterface options;
void deleteNotification(final int id); void deleteNotification(final int id);
} }
abstract class NotificationsOptionsInterface extends NextcloudAppSpecificOptions { abstract interface class NotificationsOptionsInterface extends NextcloudAppSpecificOptions {
NotificationsOptionsInterface(super.storage); NotificationsOptionsInterface(super.storage);
} }

62
packages/neon/neon/lib/src/pages/home.dart

@ -132,25 +132,30 @@ class _HomePageState extends State<HomePage> {
final List<Account> accounts, final List<Account> accounts,
final Account account, final Account account,
) async { ) 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( await Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (final context) => Scaffold( builder: (final context) => Provider<NotificationsBlocInterface>(
resizeToAvoidBottomInset: false, create: (final context) => app.getBloc(account),
appBar: AppBar( child: page,
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,
), ),
), ),
); );
@ -171,17 +176,9 @@ class _HomePageState extends State<HomePage> {
stream: _appsBloc.notificationsAppImplementation, stream: _appsBloc.notificationsAppImplementation,
builder: (final context, final notificationsAppImplementation) => StreamBuilder<String?>( builder: (final context, final notificationsAppImplementation) => StreamBuilder<String?>(
stream: _appsBloc.activeAppID, stream: _appsBloc.activeAppID,
builder: ( builder: (final context, final activeAppIDSnapshot) => StreamBuilder<List<Account>>(
final context,
final activeAppIDSnapshot,
) =>
StreamBuilder<List<Account>>(
stream: _accountsBloc.accounts, stream: _accountsBloc.accounts,
builder: ( builder: (final context, final accountsSnapshot) => OptionBuilder<NavigationMode>(
final context,
final accountsSnapshot,
) =>
OptionBuilder<NavigationMode>(
option: _globalOptions.navigationMode, option: _globalOptions.navigationMode,
builder: (final context, final navigationMode) { builder: (final context, final navigationMode) {
final accounts = accountsSnapshot.data; final accounts = accountsSnapshot.data;
@ -536,13 +533,10 @@ class _HomePageState extends State<HomePage> {
), ),
); );
final appProviders = _appsBloc.getAppProviders(); body = MultiProvider(
if (appProviders != null) { providers: _appsBloc.appBlocProviders,
body = MultiProvider( child: body,
providers: appProviders, );
child: body,
);
}
return WillPopScope( return WillPopScope(
onWillPop: () async { onWillPop: () async {

13
packages/neon/neon/lib/src/utils/app_implementation.dart

@ -22,10 +22,19 @@ abstract class AppImplementation<T extends Bloc, R extends NextcloudAppSpecificO
late final R options; late final R options;
R buildOptions(final AppStorage storage); R buildOptions(final AppStorage storage);
final Map<String, T> blocs = {};
T getBloc(final Account account) => blocs[account.id] ??= buildBloc(account.client);
T buildBloc(final NextcloudClient client); T buildBloc(final NextcloudClient client);
Provider<T> blocProvider(final NextcloudClient client) => Provider<T>( Provider<T> get blocProvider => Provider<T>(
create: (final _) => buildBloc(client), create: (final context) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final account = accountsBloc.activeAccount.value!;
return getBloc(account);
},
); );
BehaviorSubject<int>? getUnreadCounter(final AppsBloc appsBloc); BehaviorSubject<int>? getUnreadCounter(final AppsBloc appsBloc);

11
packages/neon/neon_notifications/lib/blocs/notifications.dart

@ -1,20 +1,21 @@
part of '../neon_notifications.dart'; part of '../neon_notifications.dart';
abstract class NotificationsBlocEvents { abstract interface class NotificationsBlocEvents {
void deleteNotification(final int id); void deleteNotification(final int id);
void deleteAllNotifications(); void deleteAllNotifications();
} }
abstract class NotificationsBlocStates { abstract interface class NotificationsBlocStates {
BehaviorSubject<Result<List<NextcloudNotificationsNotification>>> get notifications; BehaviorSubject<Result<List<NextcloudNotificationsNotification>>> get notifications;
BehaviorSubject<int> get unreadCounter; BehaviorSubject<int> get unreadCounter;
} }
class NotificationsBloc extends NotificationsBlocInterface implements NotificationsBlocEvents, NotificationsBlocStates { class NotificationsBloc extends InteractiveBloc
implements NotificationsBlocInterface, NotificationsBlocEvents, NotificationsBlocStates {
NotificationsBloc( NotificationsBloc(
super.options, this.options,
this._requestManager, this._requestManager,
this._client, this._client,
) { ) {
@ -27,6 +28,8 @@ class NotificationsBloc extends NotificationsBlocInterface implements Notificati
unawaited(refresh()); unawaited(refresh());
} }
@override
final NotificationsAppSpecificOptions options;
final RequestManager _requestManager; final RequestManager _requestManager;
final NextcloudClient _client; final NextcloudClient _client;

3
packages/neon/neon_notifications/lib/neon_notifications.dart

@ -14,7 +14,8 @@ part 'blocs/notifications.dart';
part 'options.dart'; part 'options.dart';
part 'pages/main.dart'; part 'pages/main.dart';
class NotificationsApp extends NotificationsAppInterface { class NotificationsApp extends AppImplementation<NotificationsBloc, NotificationsAppSpecificOptions>
implements NotificationsAppInterface<NotificationsBloc, NotificationsAppSpecificOptions> {
NotificationsApp(super.sharedPreferences, super.requestManager, super.platform); NotificationsApp(super.sharedPreferences, super.requestManager, super.platform);
@override @override

2
packages/neon/neon_notifications/lib/options.dart

@ -1,6 +1,6 @@
part of 'neon_notifications.dart'; part of 'neon_notifications.dart';
class NotificationsAppSpecificOptions extends NotificationsOptionsInterface { class NotificationsAppSpecificOptions extends NextcloudAppSpecificOptions implements NotificationsOptionsInterface {
NotificationsAppSpecificOptions(super.storage) { NotificationsAppSpecificOptions(super.storage) {
super.categories = []; super.categories = [];
super.options = []; super.options = [];

2
packages/neon/neon_notifications/lib/pages/main.dart

@ -16,7 +16,7 @@ class _NotificationsMainPageState extends State<NotificationsMainPage> {
void initState() { void initState() {
super.initState(); super.initState();
bloc = Provider.of<NotificationsBloc>(context, listen: false); bloc = Provider.of<NotificationsBlocInterface>(context, listen: false) as NotificationsBloc;
bloc.errors.listen((final error) { bloc.errors.listen((final error) {
NeonException.showSnackbar(context, error); NeonException.showSnackbar(context, error);

Loading…
Cancel
Save