diff --git a/packages/neon/integration_test/screenshot_test.dart b/packages/neon/integration_test/screenshot_test.dart index 6adab889..f07ce56f 100644 --- a/packages/neon/integration_test/screenshot_test.dart +++ b/packages/neon/integration_test/screenshot_test.dart @@ -128,6 +128,10 @@ Future pumpAppPage( globalOptions, platform, ); + final firstLaunchBloc = FirstLaunchBloc( + sharedPreferences, + disabled: true, + ); // ignore: close_sinks final userThemeStream = BehaviorSubject(); @@ -156,6 +160,9 @@ Future pumpAppPage( Provider( create: (final _) => pushNotificationsBloc, ), + Provider( + create: (final _) => firstLaunchBloc, + ), Provider>( create: (final _) => allAppImplementations, ), diff --git a/packages/neon/lib/l10n/en.arb b/packages/neon/lib/l10n/en.arb index 75809a42..e0fcb88f 100644 --- a/packages/neon/lib/l10n/en.arb +++ b/packages/neon/lib/l10n/en.arb @@ -65,6 +65,7 @@ } } }, + "settingsGoToSettingsToEnablePushNotifications": "Go to the settings to enable push notifications", "optionsCategoryGeneral": "General", "optionsCategoryTheme": "Theme", "optionsCategoryPushNotifications": "Push notifications", diff --git a/packages/neon/lib/l10n/localizations.dart b/packages/neon/lib/l10n/localizations.dart index 1fea3412..f7febc86 100644 --- a/packages/neon/lib/l10n/localizations.dart +++ b/packages/neon/lib/l10n/localizations.dart @@ -311,6 +311,12 @@ abstract class AppLocalizations { /// **'Do you want to reset all settings for {name}?'** String settingsResetForConfirmation(String name); + /// No description provided for @settingsGoToSettingsToEnablePushNotifications. + /// + /// In en, this message translates to: + /// **'Go to the settings to enable push notifications'** + String get settingsGoToSettingsToEnablePushNotifications; + /// No description provided for @optionsCategoryGeneral. /// /// In en, this message translates to: diff --git a/packages/neon/lib/l10n/localizations_en.dart b/packages/neon/lib/l10n/localizations_en.dart index 45f2f92b..4f0bb430 100644 --- a/packages/neon/lib/l10n/localizations_en.dart +++ b/packages/neon/lib/l10n/localizations_en.dart @@ -126,6 +126,9 @@ class AppLocalizationsEn extends AppLocalizations { return 'Do you want to reset all settings for $name?'; } + @override + String get settingsGoToSettingsToEnablePushNotifications => 'Go to the settings to enable push notifications'; + @override String get optionsCategoryGeneral => 'General'; diff --git a/packages/neon/lib/main.dart b/packages/neon/lib/main.dart index 154d39ea..a01d0d7a 100644 --- a/packages/neon/lib/main.dart +++ b/packages/neon/lib/main.dart @@ -54,6 +54,7 @@ Future main() async { globalOptions, platform, ); + final firstLaunchBloc = FirstLaunchBloc(sharedPreferences); runApp( MultiProvider( @@ -79,6 +80,9 @@ Future main() async { Provider( create: (final _) => pushNotificationsBloc, ), + Provider( + create: (final _) => firstLaunchBloc, + ), Provider>( create: (final _) => allAppImplementations, ), diff --git a/packages/neon/lib/src/app.dart b/packages/neon/lib/src/app.dart index a49df05c..cf5b2dbd 100644 --- a/packages/neon/lib/src/app.dart +++ b/packages/neon/lib/src/app.dart @@ -70,13 +70,15 @@ class _NeonAppState extends State with WidgetsBindingObserver, tray.Tra const settings = RouteSettings( name: 'home', ); - Widget builder(final context) => HomePage( - account: activeAccount, - onThemeChanged: (final nextcloudTheme) { - setState(() { - _nextcloudTheme = nextcloudTheme; - }); - }, + Widget builder(final context) => Scaffold( + body: HomePage( + account: activeAccount, + onThemeChanged: (final nextcloudTheme) { + setState(() { + _nextcloudTheme = nextcloudTheme; + }); + }, + ), ); await _navigatorKey.currentState!.pushAndRemoveUntil( widget.globalOptions.navigationMode.value == NavigationMode.drawer diff --git a/packages/neon/lib/src/blocs/first_launch.dart b/packages/neon/lib/src/blocs/first_launch.dart new file mode 100644 index 00000000..e2755d2a --- /dev/null +++ b/packages/neon/lib/src/blocs/first_launch.dart @@ -0,0 +1,30 @@ +part of '../neon.dart'; + +abstract class FirstLaunchBlocEvents {} + +abstract class FirstLaunchBlocStates { + BehaviorSubject get onFirstLaunch; +} + +class FirstLaunchBloc extends Bloc implements FirstLaunchBlocEvents, FirstLaunchBlocStates { + FirstLaunchBloc( + this._sharedPreferences, { + final bool disabled = false, + }) { + if (!disabled && !_sharedPreferences.containsKey(_keyFirstLaunch)) { + onFirstLaunch.add(null); + unawaited(_sharedPreferences.setBool(_keyFirstLaunch, false)); + } + } + + final SharedPreferences _sharedPreferences; + final _keyFirstLaunch = 'first-launch'; + + @override + void dispose() { + unawaited(onFirstLaunch.close()); + } + + @override + BehaviorSubject onFirstLaunch = BehaviorSubject(); +} diff --git a/packages/neon/lib/src/neon.dart b/packages/neon/lib/src/neon.dart index adba8144..84b72364 100644 --- a/packages/neon/lib/src/neon.dart +++ b/packages/neon/lib/src/neon.dart @@ -50,6 +50,7 @@ part 'app.dart'; part 'blocs/accounts.dart'; part 'blocs/apps.dart'; part 'blocs/capabilities.dart'; +part 'blocs/first_launch.dart'; part 'blocs/login.dart'; part 'blocs/push_notifications.dart'; part 'blocs/user_details.dart'; diff --git a/packages/neon/lib/src/pages/home.dart b/packages/neon/lib/src/pages/home.dart index 35374ef3..580a3b62 100644 --- a/packages/neon/lib/src/pages/home.dart +++ b/packages/neon/lib/src/pages/home.dart @@ -23,6 +23,7 @@ class _HomePageState extends State { late GlobalOptions _globalOptions; late CapabilitiesBloc _capabilitiesBloc; late AppsBloc _appsBloc; + late FirstLaunchBloc _firstLaunchBloc; @override void initState() { @@ -31,6 +32,7 @@ class _HomePageState extends State { _globalOptions = Provider.of(context, listen: false); _appsBloc = Provider.of(context, listen: false).getAppsBloc(widget.account); _capabilitiesBloc = Provider.of(context, listen: false).getCapabilitiesBloc(widget.account); + _firstLaunchBloc = Provider.of(context, listen: false); _capabilitiesBloc.capabilities.listen((final result) async { if (result.data != null) { @@ -83,6 +85,24 @@ class _HomePageState extends State { } }); + _firstLaunchBloc.onFirstLaunch.listen((final _) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppLocalizations.of(context).settingsGoToSettingsToEnablePushNotifications), + action: SnackBarAction( + label: AppLocalizations.of(context).settings, + onPressed: () async { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (final context) => const SettingsPage(), + ), + ); + }, + ), + ), + ); + }); + unawaited(_checkMaintenanceMode()); }