Browse Source

feat(neon,neon_files,neon_news,neon_notifications): add a `NeonProvider` that handles disposing of `Disposable`s and does not listen by default.

Signed-off-by: Nikolas Rimikis <leptopoda@users.noreply.github.com>
pull/778/head
Nikolas Rimikis 1 year ago
parent
commit
08efadd54d
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 37
      packages/neon/neon/lib/neon.dart
  2. 12
      packages/neon/neon/lib/src/app.dart
  3. 5
      packages/neon/neon/lib/src/models/app_implementation.dart
  4. 5
      packages/neon/neon/lib/src/pages/home.dart
  5. 4
      packages/neon/neon/lib/src/pages/login_check_account.dart
  6. 4
      packages/neon/neon/lib/src/pages/route_not_found.dart
  7. 16
      packages/neon/neon/lib/src/pages/settings.dart
  8. 18
      packages/neon/neon/lib/src/router.dart
  9. 8
      packages/neon/neon/lib/src/utils/global_popups.dart
  10. 103
      packages/neon/neon/lib/src/utils/provider.dart
  11. 4
      packages/neon/neon/lib/src/widgets/account_selection_dialog.dart
  12. 6
      packages/neon/neon/lib/src/widgets/account_switcher_button.dart
  13. 4
      packages/neon/neon/lib/src/widgets/account_tile.dart
  14. 7
      packages/neon/neon/lib/src/widgets/app_bar.dart
  15. 4
      packages/neon/neon/lib/src/widgets/cached_image.dart
  16. 8
      packages/neon/neon/lib/src/widgets/drawer.dart
  17. 4
      packages/neon/neon/lib/src/widgets/exception.dart
  18. 4
      packages/neon/neon/lib/src/widgets/unified_search_results.dart
  19. 4
      packages/neon/neon/lib/src/widgets/user_avatar.dart
  20. 1
      packages/neon/neon/lib/utils.dart
  21. 1
      packages/neon/neon_files/lib/neon_files.dart
  22. 2
      packages/neon/neon_files/lib/pages/main.dart
  23. 3
      packages/neon/neon_files/lib/widgets/actions.dart
  24. 1
      packages/neon/neon_news/lib/neon_news.dart
  25. 2
      packages/neon/neon_news/lib/pages/main.dart
  26. 1
      packages/neon/neon_notes/lib/neon_notes.dart
  27. 2
      packages/neon/neon_notes/lib/pages/main.dart
  28. 1
      packages/neon/neon_notifications/lib/neon_notifications.dart
  29. 6
      packages/neon/neon_notifications/lib/pages/main.dart

37
packages/neon/neon/lib/neon.dart

@ -9,10 +9,12 @@ import 'package:neon/src/blocs/next_push.dart';
import 'package:neon/src/blocs/push_notifications.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/models/app_implementation.dart';
import 'package:neon/src/models/disposable.dart';
import 'package:neon/src/platform/platform.dart';
import 'package:neon/src/settings/models/storage.dart';
import 'package:neon/src/theme/neon.dart';
import 'package:neon/src/utils/global_options.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/utils/request_manager.dart';
import 'package:neon/src/utils/user_agent.dart';
import 'package:package_info_plus/package_info_plus.dart';
@ -65,37 +67,16 @@ Future<void> runNeon({
runApp(
MultiProvider(
providers: [
Provider<GlobalOptions>(
create: (final _) => globalOptions,
dispose: (final _, final globalOptions) => globalOptions.dispose(),
),
Provider<AccountsBloc>(
create: (final _) => accountsBloc,
dispose: (final _, final accountsBloc) => accountsBloc.dispose(),
),
Provider<PushNotificationsBloc>(
create: (final _) => pushNotificationsBloc,
dispose: (final _, final pushNotificationsBloc) => pushNotificationsBloc.dispose(),
),
Provider<FirstLaunchBloc>(
create: (final _) => firstLaunchBloc,
dispose: (final _, final firstLaunchBloc) => firstLaunchBloc.dispose(),
),
Provider<NextPushBloc>(
create: (final _) => nextPushBloc,
dispose: (final _, final nextPushBloc) => nextPushBloc.dispose(),
),
NeonProvider<GlobalOptions>.value(value: globalOptions),
NeonProvider<AccountsBloc>.value(value: accountsBloc),
NeonProvider<PushNotificationsBloc>.value(value: pushNotificationsBloc),
NeonProvider<FirstLaunchBloc>.value(value: firstLaunchBloc),
NeonProvider<NextPushBloc>.value(value: nextPushBloc),
Provider<Iterable<AppImplementation>>(
create: (final _) => appImplementations,
dispose: (final _, final appImplementations) {
for (final app in appImplementations) {
app.dispose();
}
},
),
Provider<PackageInfo>(
create: (final _) => packageInfo,
dispose: (final _, final appImplementations) => appImplementations.disposeAll(),
),
Provider<PackageInfo>.value(value: packageInfo),
],
child: NeonApp(neonTheme: theme),
),

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

@ -21,9 +21,9 @@ import 'package:neon/src/theme/theme.dart';
import 'package:neon/src/utils/global.dart';
import 'package:neon/src/utils/global_options.dart';
import 'package:neon/src/utils/localizations.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/utils/push_utils.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:provider/provider.dart';
import 'package:quick_actions/quick_actions.dart';
import 'package:tray_manager/tray_manager.dart' as tray;
import 'package:window_manager/window_manager.dart';
@ -59,9 +59,9 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
void initState() {
super.initState();
_appImplementations = Provider.of<Iterable<AppImplementation>>(context, listen: false);
_globalOptions = Provider.of<GlobalOptions>(context, listen: false);
_accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
_appImplementations = NeonProvider.of<Iterable<AppImplementation>>(context);
_globalOptions = NeonProvider.of<GlobalOptions>(context);
_accountsBloc = NeonProvider.of<AccountsBloc>(context);
WidgetsBinding.instance.addObserver(this);
if (NeonPlatform.instance.canUseSystemTray) {
@ -144,7 +144,7 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
return;
}
final allAppImplementations = Provider.of<Iterable<AppImplementation>>(context, listen: false);
final allAppImplementations = NeonProvider.of<Iterable<AppImplementation>>(context);
final app = allAppImplementations.tryFind(AppIDs.notifications) as NotificationsAppInterface?;
if (app == null) {
@ -160,7 +160,7 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
}
_accountsBloc.setActiveAccount(account);
final allAppImplementations = Provider.of<Iterable<AppImplementation>>(context, listen: false);
final allAppImplementations = NeonProvider.of<Iterable<AppImplementation>>(context);
final notificationsApp = allAppImplementations.tryFind(AppIDs.notifications) as NotificationsAppInterface?;
if (notificationsApp != null) {

5
packages/neon/neon/lib/src/models/app_implementation.dart

@ -10,6 +10,7 @@ import 'package:neon/src/models/account_cache.dart';
import 'package:neon/src/models/disposable.dart';
import 'package:neon/src/settings/models/options_collection.dart';
import 'package:neon/src/settings/models/storage.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/drawer_destination.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
@ -41,7 +42,7 @@ abstract class AppImplementation<T extends Bloc, R extends NextcloudAppOptions>
Provider<T> get blocProvider => Provider<T>(
create: (final context) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final account = accountsBloc.activeAccount.value!;
return getBloc(account);
@ -53,7 +54,7 @@ abstract class AppImplementation<T extends Bloc, R extends NextcloudAppOptions>
Widget get page;
NeonNavigationDestination destination(final BuildContext context) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final account = accountsBloc.activeAccount.value!;
final bloc = getBloc(account);

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

@ -11,6 +11,7 @@ import 'package:neon/src/models/app_implementation.dart';
import 'package:neon/src/utils/global_options.dart';
import 'package:neon/src/utils/global_options.dart' as global_options;
import 'package:neon/src/utils/global_popups.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/app_bar.dart';
import 'package:neon/src/widgets/drawer.dart';
import 'package:neon/src/widgets/exception.dart';
@ -39,8 +40,8 @@ class _HomePageState extends State<HomePage> {
@override
void initState() {
super.initState();
_globalOptions = Provider.of<GlobalOptions>(context, listen: false);
_accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
_globalOptions = NeonProvider.of<GlobalOptions>(context);
_accountsBloc = NeonProvider.of<AccountsBloc>(context);
_account = _accountsBloc.activeAccount.value!;
_appsBloc = _accountsBloc.activeAppsBloc;

4
packages/neon/neon/lib/src/pages/login_check_account.dart

@ -10,10 +10,10 @@ import 'package:neon/src/blocs/login_check_account.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/router.dart';
import 'package:neon/src/theme/dialog.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/account_tile.dart';
import 'package:neon/src/widgets/exception.dart';
import 'package:neon/src/widgets/validation_tile.dart';
import 'package:provider/provider.dart';
@internal
class LoginCheckAccountPage extends StatefulWidget {
@ -84,7 +84,7 @@ class _LoginCheckAccountPageState extends State<LoginCheckAccountPage> {
child: ElevatedButton(
onPressed: state.hasData
? () {
Provider.of<AccountsBloc>(context, listen: false)
NeonProvider.of<AccountsBloc>(context)
..updateAccount(state.requireData)
..setActiveAccount(state.requireData);

4
packages/neon/neon/lib/src/pages/route_not_found.dart

@ -5,7 +5,7 @@ import 'package:meta/meta.dart';
import 'package:neon/l10n/localizations.dart';
import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/router.dart';
import 'package:provider/provider.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:url_launcher/url_launcher.dart';
@internal
@ -30,7 +30,7 @@ class _RouteNotFoundPageState extends State<RouteNotFoundPage> {
}
Future<void> _checkLaunchable() async {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
if (!accountsBloc.hasAccounts) {
return;
}

16
packages/neon/neon/lib/src/pages/settings.dart

@ -21,10 +21,10 @@ import 'package:neon/src/theme/branding.dart';
import 'package:neon/src/theme/dialog.dart';
import 'package:neon/src/utils/confirmation_dialog.dart';
import 'package:neon/src/utils/global_options.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/utils/save_file.dart';
import 'package:neon/src/widgets/exception.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher_string.dart';
@internal
@ -55,9 +55,9 @@ class SettingsPage extends StatefulWidget {
class _SettingsPageState extends State<SettingsPage> {
@override
Widget build(final BuildContext context) {
final globalOptions = Provider.of<GlobalOptions>(context);
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final appImplementations = Provider.of<Iterable<AppImplementation>>(context);
final globalOptions = NeonProvider.of<GlobalOptions>(context);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final appImplementations = NeonProvider.of<Iterable<AppImplementation>>(context);
final branding = Branding.of(context);
final appBar = AppBar(
@ -265,7 +265,7 @@ class _SettingsPageState extends State<SettingsPage> {
applicationName: branding.name,
applicationIcon: branding.logo,
applicationLegalese: branding.legalese,
applicationVersion: Provider.of<PackageInfo>(context, listen: false).version,
applicationVersion: NeonProvider.of<PackageInfo>(context).version,
);
},
),
@ -350,9 +350,9 @@ class _SettingsPageState extends State<SettingsPage> {
}
SettingsExportHelper _buildSettingsExportHelper(final BuildContext context) {
final globalOptions = Provider.of<GlobalOptions>(context, listen: false);
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final appImplementations = Provider.of<Iterable<AppImplementation>>(context, listen: false);
final globalOptions = NeonProvider.of<GlobalOptions>(context);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final appImplementations = NeonProvider.of<Iterable<AppImplementation>>(context);
return SettingsExportHelper(
exportables: {

18
packages/neon/neon/lib/src/router.dart

@ -19,8 +19,8 @@ import 'package:neon/src/pages/login_qrcode.dart';
import 'package:neon/src/pages/nextcloud_app_settings.dart';
import 'package:neon/src/pages/route_not_found.dart';
import 'package:neon/src/pages/settings.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/utils/stream_listenable.dart';
import 'package:provider/provider.dart';
part 'router.g.dart';
@ -79,7 +79,7 @@ class AccountSettingsRoute extends GoRouteData {
@override
Widget build(final BuildContext context, final GoRouterState state) {
final bloc = Provider.of<AccountsBloc>(context, listen: false);
final bloc = NeonProvider.of<AccountsBloc>(context);
final account = bloc.accounts.value.find(accountid);
return AccountSettingsPage(
@ -133,7 +133,7 @@ class HomeRoute extends GoRouteData {
@override
Widget build(final BuildContext context, final GoRouterState state) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final account = accountsBloc.activeAccount.valueOrNull!;
return HomePage(key: Key(account.id));
@ -167,7 +167,7 @@ class LoginRoute extends GoRouteData {
@override
FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
final hasAccounts = NeonProvider.of<AccountsBloc>(context).hasAccounts;
if (state.fullPath == location && hasAccounts) {
return const _AddAccountRoute().location;
@ -190,7 +190,7 @@ class LoginFlowRoute extends GoRouteData {
@override
FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
final hasAccounts = NeonProvider.of<AccountsBloc>(context).hasAccounts;
if (state.fullPath == location && hasAccounts) {
return _AddAccountFlowRoute(serverUrl: serverUrl).location;
@ -209,7 +209,7 @@ class LoginQrcodeRoute extends GoRouteData {
@override
FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
final hasAccounts = NeonProvider.of<AccountsBloc>(context).hasAccounts;
if (state.fullPath == location && hasAccounts) {
return const _AddAccountQrcodeRoute().location;
@ -254,7 +254,7 @@ class LoginCheckServerStatusRoute extends GoRouteData {
@override
FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
final hasAccounts = NeonProvider.of<AccountsBloc>(context).hasAccounts;
if (state.fullPath == location && hasAccounts) {
if (loginName != null && password != null) {
@ -295,7 +295,7 @@ class LoginCheckAccountRoute extends GoRouteData {
@override
FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
final hasAccounts = NeonProvider.of<AccountsBloc>(context).hasAccounts;
if (state.fullPath == location && hasAccounts) {
return _AddAccountCheckAccountRoute(
@ -375,7 +375,7 @@ class NextcloudAppSettingsRoute extends GoRouteData {
@override
Widget build(final BuildContext context, final GoRouterState state) {
final appImplementations = Provider.of<Iterable<AppImplementation>>(context, listen: false);
final appImplementations = NeonProvider.of<Iterable<AppImplementation>>(context);
final appImplementation = appImplementations.tryFind(appid)!;
return NextcloudAppSettingsPage(appImplementation: appImplementation);

8
packages/neon/neon/lib/src/utils/global_popups.dart

@ -9,7 +9,7 @@ import 'package:neon/src/pages/settings.dart';
import 'package:neon/src/platform/platform.dart';
import 'package:neon/src/router.dart';
import 'package:neon/src/utils/global_options.dart';
import 'package:provider/provider.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:url_launcher/url_launcher_string.dart';
@internal
@ -42,9 +42,9 @@ class GlobalPopups {
return;
}
final globalOptions = Provider.of<GlobalOptions>(context, listen: false);
final firstLaunchBloc = Provider.of<FirstLaunchBloc>(context, listen: false);
final nextPushBloc = Provider.of<NextPushBloc>(context, listen: false);
final globalOptions = NeonProvider.of<GlobalOptions>(context);
final firstLaunchBloc = NeonProvider.of<FirstLaunchBloc>(context);
final nextPushBloc = NeonProvider.of<NextPushBloc>(context);
_subscriptions.addAll([
if (NeonPlatform.instance.canUsePushNotifications) ...[

103
packages/neon/neon/lib/src/utils/provider.dart

@ -0,0 +1,103 @@
import 'package:flutter/widgets.dart';
import 'package:neon/src/models/disposable.dart';
import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
/// A [Provider] that manages the lifecycle of a [Disposable] value it provides
/// by delegating [Create] and calling [Disposable.dispose].
class NeonProvider<T extends Disposable> extends SingleChildStatelessWidget {
/// Creates a value, stores it, and exposes it to its descendants.
const NeonProvider({
required final Create<T> create,
super.key,
this.child,
this.lazy = true,
}) : _create = create,
_value = null,
super(child: child);
/// Expose an existing value without disposing it.
///
/// {@macro provider.updateshouldnotify}
const NeonProvider.value({
required final T value,
super.key,
this.child,
}) : _value = value,
_create = null,
lazy = true,
super(child: child);
/// Optional widget below this widget in the tree having access to the value.
///
/// {@macro flutter.widgets.ProxyWidget.child}
final Widget? child;
/// Whether the value should be created lazily.
/// Defaults to `true`.
final bool lazy;
final Create<T>? _create;
final T? _value;
/// Method that allows widgets to access the value as long as their
/// `BuildContext` contains a [NeonProvider] or [Provider] instance of the
/// specified type.
///
/// Calling this method is equivalent to calling:
///
/// ```dart
/// Provider.of(context, listen: false);
/// ```
///
/// If we want to access an instance of `DisposableA` which was provided higher up
/// in the widget tree we can do so via:
///
/// ```dart
/// NeonProvider.of<DisposableA>(context);
/// ```
static T of<T>(
final BuildContext context, {
final bool listen = false,
}) {
try {
return Provider.of<T>(context, listen: listen);
} on ProviderNotFoundException catch (e) {
if (e.valueType != T) {
rethrow;
}
throw FlutterError(
'''
NeonProvider.of() called with a context that does not contain a $T.
No ancestor could be found starting from the context that was passed to NeonProvider.of<$T>().
This can happen if the context you used comes from a widget above the NeonProvider.
The context used was: $context
''',
);
}
}
@override
Widget buildWithChild(final BuildContext context, final Widget? child) {
assert(
child != null,
'$runtimeType used outside of MultiBlocProvider must specify a child',
);
final value = _value;
return value != null
? InheritedProvider<T>.value(
value: value,
lazy: lazy,
child: child,
)
: InheritedProvider<T>(
create: _create,
dispose: (final _, final value) => value.dispose(),
lazy: lazy,
child: child,
);
}
}

4
packages/neon/neon/lib/src/widgets/account_selection_dialog.dart

@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/theme/dialog.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/account_tile.dart';
import 'package:provider/provider.dart';
@internal
class NeonAccountSelectionDialog extends StatelessWidget {
@ -18,7 +18,7 @@ class NeonAccountSelectionDialog extends StatelessWidget {
@override
Widget build(final BuildContext context) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final accounts = accountsBloc.accounts.value;
final activeAccount = accountsBloc.activeAccount.value!;

6
packages/neon/neon/lib/src/widgets/account_switcher_button.dart

@ -5,9 +5,9 @@ import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/pages/settings.dart';
import 'package:neon/src/router.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/account_selection_dialog.dart';
import 'package:neon/src/widgets/user_avatar.dart';
import 'package:provider/provider.dart';
@internal
class AccountSwitcherButton extends StatelessWidget {
@ -16,7 +16,7 @@ class AccountSwitcherButton extends StatelessWidget {
});
Future<void> _onPressed(final BuildContext context) async {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final account = await showDialog<Account>(
context: context,
@ -42,7 +42,7 @@ class AccountSwitcherButton extends StatelessWidget {
@override
Widget build(final BuildContext context) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final account = accountsBloc.activeAccount.value!;
return IconButton(

4
packages/neon/neon/lib/src/widgets/account_tile.dart

@ -3,11 +3,11 @@ import 'package:meta/meta.dart';
import 'package:neon/src/bloc/result_builder.dart';
import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/exception.dart';
import 'package:neon/src/widgets/linear_progress_indicator.dart';
import 'package:neon/src/widgets/user_avatar.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:provider/provider.dart';
@internal
class NeonAccountTile extends StatelessWidget {
@ -32,7 +32,7 @@ class NeonAccountTile extends StatelessWidget {
@override
Widget build(final BuildContext context) {
final userDetailsBloc = Provider.of<AccountsBloc>(context, listen: false).getUserDetailsBlocFor(account);
final userDetailsBloc = NeonProvider.of<AccountsBloc>(context).getUserDetailsBlocFor(account);
return ListTile(
textColor: textColor,

7
packages/neon/neon/lib/src/widgets/app_bar.dart

@ -9,6 +9,7 @@ import 'package:neon/src/blocs/apps.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/models/app_implementation.dart';
import 'package:neon/src/models/notifications_interface.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/account_switcher_button.dart';
import 'package:neon/src/widgets/app_implementation_icon.dart';
import 'package:neon/src/widgets/exception.dart';
@ -28,7 +29,7 @@ class NeonAppBar extends StatefulWidget implements PreferredSizeWidget {
}
class _NeonAppBarState extends State<NeonAppBar> {
late final AccountsBloc accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
late final AccountsBloc accountsBloc = NeonProvider.of<AccountsBloc>(context);
late final accounts = accountsBloc.accounts.value;
late final account = accountsBloc.activeAccount.value!;
late final appsBloc = accountsBloc.activeAppsBloc;
@ -157,7 +158,7 @@ class SearchIconButton extends StatelessWidget {
@override
Widget build(final BuildContext context) => IconButton(
onPressed: () {
Provider.of<AccountsBloc>(context, listen: false).activeUnifiedSearchBloc.enable();
NeonProvider.of<AccountsBloc>(context).activeUnifiedSearchBloc.enable();
},
tooltip: AppLocalizations.of(context).search,
icon: const Icon(
@ -186,7 +187,7 @@ class _NotificationIconButtonState extends State<NotificationIconButton> {
@override
void initState() {
super.initState();
_accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
_accountsBloc = NeonProvider.of<AccountsBloc>(context);
_appsBloc = _accountsBloc.activeAppsBloc;
_accounts = _accountsBloc.accounts.value;
_account = _accountsBloc.activeAccount.value!;

4
packages/neon/neon/lib/src/widgets/cached_image.dart

@ -8,9 +8,9 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:neon/nextcloud.dart';
import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/exception.dart';
import 'package:neon/src/widgets/linear_progress_indicator.dart';
import 'package:provider/provider.dart';
typedef CacheReviver = FutureOr<Uint8List?> Function(CacheManager cacheManager);
typedef ImageDownloader = FutureOr<Uint8List> Function();
@ -220,7 +220,7 @@ class NeonApiImage extends StatelessWidget {
@override
Widget build(final BuildContext context) {
final account = Provider.of<AccountsBloc>(context, listen: false).activeAccount.value!;
final account = NeonProvider.of<AccountsBloc>(context).activeAccount.value!;
return NeonCachedImage.custom(
getImage: () async => getImage(account.client),

8
packages/neon/neon/lib/src/widgets/drawer.dart

@ -8,12 +8,12 @@ import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/blocs/apps.dart';
import 'package:neon/src/models/app_implementation.dart';
import 'package:neon/src/router.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/cached_image.dart';
import 'package:neon/src/widgets/drawer_destination.dart';
import 'package:neon/src/widgets/exception.dart';
import 'package:neon/src/widgets/linear_progress_indicator.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:provider/provider.dart';
@internal
class NeonDrawer extends StatelessWidget {
@ -23,7 +23,7 @@ class NeonDrawer extends StatelessWidget {
@override
Widget build(final BuildContext context) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final appsBloc = accountsBloc.activeAppsBloc;
return ResultBuilder.behaviorSubject(
@ -63,7 +63,7 @@ class __NeonDrawerState extends State<_NeonDrawer> {
void initState() {
super.initState();
_accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
_accountsBloc = NeonProvider.of<AccountsBloc>(context);
_appsBloc = _accountsBloc.activeAppsBloc;
_apps = widget.apps.toList();
@ -118,7 +118,7 @@ class NeonDrawerHeader extends StatelessWidget {
@override
Widget build(final BuildContext context) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final capabilitiesBloc = accountsBloc.activeCapabilitiesBloc;
final branding = ResultBuilder<CoreOcsGetCapabilitiesResponseApplicationJson_Ocs_Data>.behaviorSubject(

4
packages/neon/neon/lib/src/widgets/exception.dart

@ -8,8 +8,8 @@ import 'package:neon/l10n/localizations.dart';
import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/router.dart';
import 'package:neon/src/utils/exceptions.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:provider/provider.dart';
class NeonException extends StatelessWidget {
const NeonException(
@ -189,7 +189,7 @@ class NeonException extends StatelessWidget {
static void _openLoginPage(final BuildContext context) {
unawaited(
LoginCheckServerStatusRoute(
serverUrl: Provider.of<AccountsBloc>(context, listen: false).activeAccount.value!.serverURL,
serverUrl: NeonProvider.of<AccountsBloc>(context).activeAccount.value!.serverURL,
).push(context),
);
}

4
packages/neon/neon/lib/src/widgets/unified_search_results.dart

@ -8,6 +8,7 @@ import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/blocs/unified_search.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/theme/sizes.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/cached_image.dart';
import 'package:neon/src/widgets/exception.dart';
import 'package:neon/src/widgets/image_wrapper.dart';
@ -15,7 +16,6 @@ import 'package:neon/src/widgets/linear_progress_indicator.dart';
import 'package:neon/src/widgets/list_view.dart';
import 'package:neon/src/widgets/server_icon.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:provider/provider.dart';
@internal
class NeonUnifiedSearchResults extends StatelessWidget {
@ -25,7 +25,7 @@ class NeonUnifiedSearchResults extends StatelessWidget {
@override
Widget build(final BuildContext context) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final bloc = accountsBloc.activeUnifiedSearchBloc;
return ResultBuilder.behaviorSubject(
stream: bloc.results,

4
packages/neon/neon/lib/src/widgets/user_avatar.dart

@ -9,10 +9,10 @@ import 'package:neon/src/bloc/result_builder.dart';
import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/theme/sizes.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:neon/src/widgets/cached_image.dart';
import 'package:neon/src/widgets/server_icon.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
class NeonUserAvatar extends StatefulWidget {
@ -38,7 +38,7 @@ class NeonUserAvatar extends StatefulWidget {
}
class _UserAvatarState extends State<NeonUserAvatar> {
late final _userStatusBloc = Provider.of<AccountsBloc>(context, listen: false).getUserStatusesBlocFor(widget.account);
late final _userStatusBloc = NeonProvider.of<AccountsBloc>(context).getUserStatusesBlocFor(widget.account);
late double size;
@override

1
packages/neon/neon/lib/utils.dart

@ -2,6 +2,7 @@ export 'package:neon/src/utils/app_route.dart';
export 'package:neon/src/utils/confirmation_dialog.dart';
export 'package:neon/src/utils/exceptions.dart';
export 'package:neon/src/utils/hex_color.dart';
export 'package:neon/src/utils/provider.dart';
export 'package:neon/src/utils/rename_dialog.dart';
export 'package:neon/src/utils/request_manager.dart' hide Cache;
export 'package:neon/src/utils/validators.dart';

1
packages/neon/neon_files/lib/neon_files.dart

@ -27,7 +27,6 @@ import 'package:neon_files/widgets/file_list_tile.dart';
import 'package:open_file/open_file.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:queue/queue.dart';
import 'package:rxdart/rxdart.dart';

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

@ -15,7 +15,7 @@ class _FilesMainPageState extends State<FilesMainPage> {
@override
void initState() {
super.initState();
bloc = Provider.of<FilesBloc>(context, listen: false);
bloc = NeonProvider.of<FilesBloc>(context);
bloc.errors.listen((final error) {
NeonException.showSnackbar(context, error);

3
packages/neon/neon_files/lib/widgets/actions.dart

@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
import 'package:neon/utils.dart';
import 'package:neon_files/l10n/localizations.dart';
import 'package:neon_files/neon_files.dart';
import 'package:provider/provider.dart';
class FileActions extends StatelessWidget {
const FileActions({
@ -14,7 +13,7 @@ class FileActions extends StatelessWidget {
final FileDetails details;
Future<void> onSelected(final BuildContext context, final FilesFileAction action) async {
final bloc = Provider.of<FilesBloc>(context, listen: false);
final bloc = NeonProvider.of<FilesBloc>(context);
final browserBloc = bloc.browser;
switch (action) {
case FilesFileAction.toggleFavorite:

1
packages/neon/neon_news/lib/neon_news.dart

@ -21,7 +21,6 @@ import 'package:neon/utils.dart';
import 'package:neon/widgets.dart';
import 'package:neon_news/l10n/localizations.dart';
import 'package:neon_news/routes.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher_string.dart';

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

@ -16,7 +16,7 @@ class _NewsMainPageState extends State<NewsMainPage> {
@override
void initState() {
super.initState();
bloc = Provider.of<NewsBloc>(context, listen: false);
bloc = NeonProvider.of<NewsBloc>(context);
bloc.errors.listen((final error) {
NeonException.showSnackbar(context, error);

1
packages/neon/neon_notes/lib/neon_notes.dart

@ -19,7 +19,6 @@ import 'package:neon/utils.dart';
import 'package:neon/widgets.dart';
import 'package:neon_notes/l10n/localizations.dart';
import 'package:neon_notes/routes.dart';
import 'package:provider/provider.dart';
import 'package:queue/queue.dart';
import 'package:rxdart/rxdart.dart';
import 'package:url_launcher/url_launcher_string.dart';

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

@ -17,7 +17,7 @@ class _NotesMainPageState extends State<NotesMainPage> {
void initState() {
super.initState();
bloc = Provider.of<NotesBloc>(context, listen: false);
bloc = NeonProvider.of<NotesBloc>(context);
bloc.errors.listen((final error) {
handleNotesException(context, error);

1
packages/neon/neon_notifications/lib/neon_notifications.dart

@ -14,7 +14,6 @@ import 'package:neon/utils.dart';
import 'package:neon/widgets.dart';
import 'package:neon_notifications/l10n/localizations.dart';
import 'package:neon_notifications/routes.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
part 'blocs/notifications.dart';

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

@ -16,7 +16,7 @@ class _NotificationsMainPageState extends State<NotificationsMainPage> {
void initState() {
super.initState();
bloc = Provider.of<NotificationsBlocInterface>(context, listen: false) as NotificationsBloc;
bloc = NeonProvider.of<NotificationsBlocInterface>(context) as NotificationsBloc;
bloc.errors.listen((final error) {
NeonException.showSnackbar(context, error);
@ -51,7 +51,7 @@ class _NotificationsMainPageState extends State<NotificationsMainPage> {
final BuildContext context,
final NotificationsNotification notification,
) {
final app = Provider.of<Iterable<AppImplementation>>(context, listen: false).tryFind(notification.app);
final app = NeonProvider.of<Iterable<AppImplementation>>(context).tryFind(notification.app);
return ListTile(
title: Text(notification.subject),
@ -90,7 +90,7 @@ class _NotificationsMainPageState extends State<NotificationsMainPage> {
}
if (app != null) {
// TODO: use go_router once implemented
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
await accountsBloc.activeAppsBloc.setActiveApp(app.id);
} else {
final colorScheme = Theme.of(context).colorScheme;

Loading…
Cancel
Save