Browse Source

Merge pull request #1031 from nextcloud/doc/neon_utils

docs(neon): document neon utils
pull/1055/head
Nikolas Rimikis 1 year ago committed by GitHub
parent
commit
3b949f2cf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      packages/neon/neon/lib/src/utils/account_options.dart
  2. 1
      packages/neon/neon/lib/src/utils/global.dart
  3. 91
      packages/neon/neon/lib/src/utils/global_options.dart
  4. 14
      packages/neon/neon/lib/src/utils/global_popups.dart
  5. 2
      packages/neon/neon/lib/src/utils/hex_color.dart
  6. 5
      packages/neon/neon/lib/src/utils/save_file.dart
  7. 7
      packages/neon/neon/lib/src/utils/validators.dart

7
packages/neon/neon/lib/src/utils/account_options.dart

@ -5,9 +5,11 @@ import 'package:neon/src/settings/models/option.dart';
import 'package:neon/src/settings/models/options_collection.dart';
import 'package:neon/src/settings/models/storage.dart';
/// Account related options.
@internal
@immutable
class AccountSpecificOptions extends OptionsCollection {
/// Creates a new account options collection.
AccountSpecificOptions(
super.storage,
this._appsBloc,
@ -30,6 +32,9 @@ class AccountSpecificOptions extends OptionsCollection {
initialApp,
];
/// The initial app to show on app start.
///
/// Defaults to `null` letting the framework choose one.
late final initialApp = SelectOption<String?>(
storage: storage,
key: AccountOptionKeys.initialApp,
@ -39,8 +44,10 @@ class AccountSpecificOptions extends OptionsCollection {
);
}
/// Storage keys for the [AccountSpecificOptions].
@internal
enum AccountOptionKeys implements Storable {
/// The storage key for [AccountSpecificOptions.initialApp]
initialApp._('initial-app');
const AccountOptionKeys._(this.value);

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

@ -1,6 +1,7 @@
import 'package:meta/meta.dart';
import 'package:neon/src/models/push_notification.dart';
/// Global states handling notification callbacks.
@internal
class Global {
const Global._();

91
packages/neon/neon/lib/src/utils/global_options.dart

@ -10,11 +10,14 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:universal_io/io.dart';
/// The package id of the NextPush UnifiedPush distributor.
const unifiedPushNextPushID = 'org.unifiedpush.distributor.nextpush';
/// Global options for the Neon framework.
@internal
@immutable
class GlobalOptions extends OptionsCollection {
/// Creates a new global options collection.
GlobalOptions(
this._packageInfo,
) : super(const AppStorage(StorageKeys.global)) {
@ -89,6 +92,9 @@ class GlobalOptions extends OptionsCollection {
rememberLastUsedAccount.removeListener(_rememberLastUsedAccountListener);
}
/// Updates the available values of [initialAccount].
///
/// If the current `initialAccount` is not supported anymore the option will be reset.
void updateAccounts(final List<Account> accounts) {
initialAccount.values = Map.fromEntries(
accounts.map(
@ -101,6 +107,10 @@ class GlobalOptions extends OptionsCollection {
}
}
/// Updates the values of [pushNotificationsDistributor].
///
/// If the new `distributors` does not contain the currently active one
/// both [pushNotificationsDistributor] and [pushNotificationsEnabled] will be reset.
void updateDistributors(final List<String> distributors) {
pushNotificationsDistributor.values = Map.fromEntries(
distributors.map(
@ -116,6 +126,7 @@ class GlobalOptions extends OptionsCollection {
}
}
/// The theme mode of the app implementing the Neon framework.
late final themeMode = SelectOption(
storage: storage,
key: GlobalOptionKeys.themeMode,
@ -128,6 +139,10 @@ class GlobalOptions extends OptionsCollection {
},
);
/// Whether the [ThemeMode.dark] should use a plain black background.
///
/// This is commonly used for OLED screens.
/// Defaults to `false`.
late final themeOLEDAsDark = ToggleOption(
storage: storage,
key: GlobalOptionKeys.themeOLEDAsDark,
@ -135,6 +150,9 @@ class GlobalOptions extends OptionsCollection {
defaultValue: false,
);
/// Whether the `ColorScheme` should keep the accent color provided by the Nextcloud server.
///
/// Defaults to `false` generating a Material 3 style color.
late final themeKeepOriginalAccentColor = ToggleOption(
storage: storage,
key: GlobalOptionKeys.themeKeepOriginalAccentColor,
@ -142,6 +160,12 @@ class GlobalOptions extends OptionsCollection {
defaultValue: false,
);
/// Whether to enable the push notifications plugin.
///
/// Setting this option to true will request the permission to show notifications.
/// Disabling this option will reset [pushNotificationsDistributor].
///
/// Defaults to `false`.
late final pushNotificationsEnabled = ToggleOption(
storage: storage,
key: GlobalOptionKeys.pushNotificationsEnabled,
@ -149,6 +173,7 @@ class GlobalOptions extends OptionsCollection {
defaultValue: false,
);
/// The registered distributor for push notifications.
late final pushNotificationsDistributor = SelectOption<String?>.depend(
storage: storage,
key: GlobalOptionKeys.pushNotificationsDistributor,
@ -158,6 +183,13 @@ class GlobalOptions extends OptionsCollection {
enabled: pushNotificationsEnabled,
);
/// Whether to start the app minimized.
///
/// Defaults to `false`.
///
/// See:
/// * [minimizeInsteadOfExit]: for an option to minimize instead of closing the app.
/// * [systemTrayHideToTrayWhenMinimized]: to minimize the app to system tray.
late final startupMinimized = ToggleOption(
storage: storage,
key: GlobalOptionKeys.startupMinimized,
@ -165,6 +197,13 @@ class GlobalOptions extends OptionsCollection {
defaultValue: false,
);
/// Whether to minimize app instead of closing it.
///
/// Defaults to `false`.
///
/// See:
/// * [startupMinimized]: for an option to startup in the minimized state.
/// * [systemTrayHideToTrayWhenMinimized]: to minimize the app to system tray.
late final startupMinimizeInsteadOfExit = ToggleOption(
storage: storage,
key: GlobalOptionKeys.startupMinimizeInsteadOfExit,
@ -174,6 +213,12 @@ class GlobalOptions extends OptionsCollection {
// TODO: Autostart option
/// Whether to enable the system tray.
///
/// Defaults to `false`.
///
/// See:
/// * [systemTrayHideToTrayWhenMinimized]: to minimize the app to system tray.
late final systemTrayEnabled = ToggleOption(
storage: storage,
key: GlobalOptionKeys.systemTrayEnabled,
@ -181,6 +226,15 @@ class GlobalOptions extends OptionsCollection {
defaultValue: false,
);
/// Whether to minimize to the system tray or not.
///
/// Requires [systemTrayEnabled] to be true.
/// Defaults to `true`.
///
/// See:
/// * [systemTrayEnabled]: to enable the system tray.
/// * [startupMinimized]: for an option to startup in the minimized state.
/// * [minimizeInsteadOfExit]: for an option to minimize instead of closing the app.
late final systemTrayHideToTrayWhenMinimized = ToggleOption.depend(
storage: storage,
key: GlobalOptionKeys.systemTrayHideToTrayWhenMinimized,
@ -189,6 +243,10 @@ class GlobalOptions extends OptionsCollection {
enabled: systemTrayEnabled,
);
/// Whether to remember the last active account.
///
/// Enabling this option will reset the [initialAccount].
/// Defaults to `true`.
late final rememberLastUsedAccount = ToggleOption(
storage: storage,
key: GlobalOptionKeys.rememberLastUsedAccount,
@ -196,6 +254,7 @@ class GlobalOptions extends OptionsCollection {
defaultValue: true,
);
/// The initial account to use when opening the app.
late final initialAccount = SelectOption<String?>(
storage: storage,
key: GlobalOptionKeys.initialAccount,
@ -218,19 +277,43 @@ class GlobalOptions extends OptionsCollection {
);
}
/// The storage keys for the [GlobalOptions].
@internal
enum GlobalOptionKeys implements Storable {
/// The storage key for [GlobalOptions.themeMode]
themeMode._('theme-mode'),
/// The storage key for [GlobalOptions.themeOLEDAsDark]
themeOLEDAsDark._('theme-oled-as-dark'),
/// The storage key for [GlobalOptions.themeKeepOriginalAccentColor]
themeKeepOriginalAccentColor._('theme-keep-original-accent-color'),
/// The storage key for [GlobalOptions.pushNotificationsEnabled]
pushNotificationsEnabled._('push-notifications-enabled'),
/// The storage key for [GlobalOptions.pushNotificationsDistributor]
pushNotificationsDistributor._('push-notifications-distributor'),
/// The storage key for [GlobalOptions.startupMinimized]
startupMinimized._('startup-minimized'),
/// The storage key for [GlobalOptions.startupMinimizeInsteadOfExit]
startupMinimizeInsteadOfExit._('startup-minimize-instead-of-exit'),
/// The storage key for [GlobalOptions.systemTrayEnabled]
systemTrayEnabled._('system-tray-enabled'),
/// The storage key for [GlobalOptions.systemTrayHideToTrayWhenMinimized]
systemTrayHideToTrayWhenMinimized._('system-tray-hide-to-tray-when-minimized'),
/// The storage key for [GlobalOptions.rememberLastUsedAccount]
rememberLastUsedAccount._('remember-last-used-account'),
/// The storage key for [GlobalOptions.initialAccount]
initialAccount._('initial-account'),
/// The storage key for [GlobalOptions.navigationMode]
navigationMode._('navigation-mode');
const GlobalOptionKeys._(this.value);
@ -239,8 +322,16 @@ enum GlobalOptionKeys implements Storable {
final String value;
}
/// App navigation modes.
@internal
enum NavigationMode {
/// Drawer behind a hamburger menu.
///
/// The default for small screen sizes.
drawer,
/// Persistent drawer on the leading edge.
///
/// The default on large screen sizes.
drawerAlwaysVisible,
}

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

@ -12,15 +12,23 @@ import 'package:neon/src/utils/global_options.dart';
import 'package:neon/src/utils/provider.dart';
import 'package:url_launcher/url_launcher_string.dart';
/// Singleton class managing global popups.
@internal
class GlobalPopups {
/// Returns the current instance.
///
/// Instantiates a new one if not yet present.
factory GlobalPopups() => instance ??= GlobalPopups._();
/// Returns the current instance.
///
/// Instantiates a new one with a [mock]ed value if not yet present.
@visibleForTesting
factory GlobalPopups.mocked(final GlobalPopups mock) => instance ??= mock;
GlobalPopups._();
/// The instance of this singleton.
@visibleForTesting
static GlobalPopups? instance;
@ -28,6 +36,9 @@ class GlobalPopups {
late BuildContext _context;
final _subscriptions = <StreamSubscription<dynamic>>[];
/// Disposes this instance and cancels all active subscriptions.
///
/// The instance will be reset. Subsequent calls will instantiate a new one.
void dispose() {
for (final subscription in _subscriptions) {
unawaited(subscription.cancel());
@ -37,6 +48,9 @@ class GlobalPopups {
instance = null;
}
/// Registers the global backups to the given [context].
///
/// Subsequent calls will update the cached `context` but will not run the registration again.
void register(final BuildContext context) {
_context = context;
if (_registered) {

2
packages/neon/neon/lib/src/utils/hex_color.dart

@ -1,6 +1,8 @@
import 'dart:ui';
/// A [Color] from a hex string.
class HexColor extends Color {
/// Creates a new [Color] from the given [hexColor] string.
HexColor(final String hexColor) : super(_parse(hexColor));
static int _parse(final String hexColor) {

5
packages/neon/neon/lib/src/utils/save_file.dart

@ -5,6 +5,11 @@ import 'package:flutter_file_dialog/flutter_file_dialog.dart';
import 'package:neon/src/platform/platform.dart';
import 'package:universal_io/io.dart';
/// Displays a dialog for selecting a location where to save a file with the [data] content.
///
/// Set the the suggested [fileName] to use when saving the file.
///
/// Returns the path of the saved file or `null` if the operation was cancelled.
Future<String?> saveFileWithPickDialog(final String fileName, final Uint8List data) async {
if (NeonPlatform.instance.shouldUseFileDialog) {
// TODO: https://github.com/nextcloud/neon/issues/8

7
packages/neon/neon/lib/src/utils/validators.dart

@ -1,6 +1,10 @@
import 'package:flutter/widgets.dart';
import 'package:neon/l10n/localizations.dart';
/// Validates whether the given [input] is a valid HTTP(S) URL.
///
/// Set [httpsOnly] if you want to only allow HTTPS URLs.
/// Returns `null` if the URL is valid or a localized error message if not.
String? validateHttpUrl(
final BuildContext context,
final String? input, {
@ -24,6 +28,9 @@ String? validateHttpUrl(
return NeonLocalizations.of(context).errorInvalidURL;
}
/// Validates that the given [input] is neither null nor empty.
///
/// Returns `null` if not empty or a localized error message if empty.
String? validateNotEmpty(final BuildContext context, final String? input) {
if (input == null || input.isEmpty) {
return NeonLocalizations.of(context).errorEmptyField;

Loading…
Cancel
Save