Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions lib/app/theme/custom_system_bars_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
class CustomSystemBarsTheme {
static Future<void> setupSystemBarsTheme({required ProviderContainer providerContainer}) async {
final brightness = providerContainer.read(themeModeNotifierProvider.notifier).brightness;
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
await _setupSystemBarsUpdateCallback(providerContainer: providerContainer);
await setSystemBarsTheme(brightness: brightness);
}

static Future<void> setSystemBarsTheme({required Brightness brightness}) async {
final brightness = PlatformDispatcher.instance.platformBrightness;
SystemChrome.setSystemUIOverlayStyle((getSystemBarsTheme(brightness: brightness)));
await _setupSystemBarsUpdateCallback(providerContainer: providerContainer);
_setSystemBarsTheme(brightness: brightness);
}

static SystemUiOverlayStyle getSystemBarsTheme({required Brightness brightness}) {
Expand All @@ -46,6 +41,10 @@ class CustomSystemBarsTheme {
}
}

static void _setSystemBarsTheme({required Brightness brightness}) {
SystemChrome.setSystemUIOverlayStyle(getSystemBarsTheme(brightness: brightness));
}

static SystemUiOverlayStyle _getAndroidSystemBarsTheme({required Brightness brightness}) {
final AndroidDeviceInfo androidInfo = Configuration.instance.androidDeviceInfo!;
final bool canUseTransparentNavigation = androidInfo.version.sdkInt >= 29; // Enabled by default for iOS
Expand All @@ -54,7 +53,7 @@ class CustomSystemBarsTheme {
// StatusBar
systemStatusBarContrastEnforced: false,
statusBarColor: Colors.transparent,
statusBarIconBrightness: brightness.inverse, // For Android
statusBarIconBrightness: brightness.inverse,

// NavigationBar
systemNavigationBarContrastEnforced: false,
Expand All @@ -72,14 +71,10 @@ class CustomSystemBarsTheme {
return SystemUiOverlayStyle(
// StatusBar
systemStatusBarContrastEnforced: false,
statusBarColor: Colors.transparent,
statusBarBrightness: brightness, // For iOS

// NavigationBar
systemNavigationBarContrastEnforced: false,
systemNavigationBarColor: Colors.transparent,
systemNavigationBarDividerColor: Colors.transparent,
systemNavigationBarIconBrightness: brightness,
);
}

Expand All @@ -89,19 +84,19 @@ class CustomSystemBarsTheme {
originalCallback?.call();
final themeMode = await providerContainer.read(themeModeNotifierProvider.future);
if (themeMode == ThemeMode.system) {
setSystemBarsTheme(brightness: PlatformDispatcher.instance.platformBrightness);
_setSystemBarsTheme(brightness: PlatformDispatcher.instance.platformBrightness);
}
};

// HotFix for API 28, that need SystemBarsTheme applied on each app resume!
if (AppPlatform.isAndroid) {
final AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo;
final AndroidDeviceInfo androidInfo = Configuration.instance.androidDeviceInfo!;
if (androidInfo.version.sdkInt == 28) {
SystemChannels.lifecycle.setMessageHandler((msg) async {
if (msg == AppLifecycleState.resumed.toString()) {
final themeMode = await providerContainer.read(themeModeNotifierProvider.future);
if (themeMode == ThemeMode.system) {
setSystemBarsTheme(brightness: PlatformDispatcher.instance.platformBrightness);
_setSystemBarsTheme(brightness: PlatformDispatcher.instance.platformBrightness);
}
}
return Future.value(msg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,15 @@ class TextValidatorControllerGeneral extends TextValidatorController {
this.condition,
this.conditionText,
}) {
if (tooShortText != null && minLength == null) throw Exception('minLength must be also set when tooShortText is set.');
if (minLength != null && tooShortText == null) throw Exception('tooShortText must be also set when minLength is set.');

if (tooLongText != null && maxLength == null) throw Exception('maxLength must be also set when tooLongText is set.');
if (maxLength != null && tooLongText == null) throw Exception('tooLongText must be also set when maxLength is set.');

if (regexText != null && regex == null) throw Exception('regex must be also set when regexText is set.');
if (regex != null && regexText == null) throw Exception('regexText must be also set when regex is set.');

if (conditionText != null && condition == null) throw Exception('condition must be also set when conditionText is set.');
if (condition != null && conditionText == null) throw Exception('conditionText must be also set when condition is set.');
if ((tooShortText != null && minLength == null) || (minLength != null && tooShortText == null)) {
throw Exception('minLength and tooShortText must be set together.');
} else if ((tooLongText != null && maxLength == null) || (maxLength != null && tooLongText == null)) {
throw Exception('maxLength and tooLongText must be set together.');
} else if ((regexText != null && regex == null) || (regex != null && regexText == null)) {
throw Exception('regex and regexText must be set together.');
} else if ((conditionText != null && condition == null) || (condition != null && conditionText == null)) {
throw Exception('condition and conditionText must be set together.');
}
}

final String Function(BuildContext context)? emptyText;
Expand All @@ -35,7 +33,7 @@ class TextValidatorControllerGeneral extends TextValidatorController {
final String Function(BuildContext context)? tooLongText;
final RegExp? regex;
final String Function(BuildContext context)? regexText;
final bool Function(String text)? condition;
final Future<bool> Function(String text)? condition;
final String Function(BuildContext context)? conditionText;

TextFieldValidatorState _state = const TextFieldValidatorState.initial();
Expand All @@ -44,7 +42,7 @@ class TextValidatorControllerGeneral extends TextValidatorController {
TextFieldValidatorState get state => _state;

@override
void validate() {
Future<void> validate() async {
if (!canValidate) return;

final text = controller.text;
Expand All @@ -57,12 +55,16 @@ class TextValidatorControllerGeneral extends TextValidatorController {
_state = TextFieldValidatorState.invalid(exception: ValidatorException.generalIsTooLong(tooLongText!));
} else if (regex != null && !regex!.hasMatch(text)) {
_state = TextFieldValidatorState.invalid(exception: ValidatorException.generalIsInvalid(regexText!));
} else if (condition?.call(text) ?? false) {
} else if (condition != null && await condition!(text)) {
_state = TextFieldValidatorState.invalid(exception: ValidatorException.generalIsInvalid(conditionText!));
} else {
_state = const TextFieldValidatorState.valid();
}

notifyListeners();
}

bool get isValid => _state is TextFieldValidatorStateValid;

bool get isInvalid => _state is TextFieldValidatorStateInvalid;
}
21 changes: 12 additions & 9 deletions lib/common/validator/text_validator_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,19 @@ abstract class TextValidatorController extends ChangeNotifier {
});
}

/// Indicates, if form is validated immediatelly. It's due to postponing validation until some action button is selected.
bool canValidate;
/// Text field controller.
final controller = TextEditingController();

/// Indicates, if form is validated immediately. It's due to postponing validation until some action button is selected.
bool canValidate;

/// State of the validator.
TextFieldValidatorState get state;
Timer? _debounceTimer;

String get text {
return controller.text;
}
/// Debounce timer to postpone validation.
Timer? _debounceTimer;

String get text => controller.text;
set text(String text) {
controller.text = text;
}
Expand All @@ -49,10 +52,10 @@ abstract class TextValidatorController extends ChangeNotifier {
}

/// Sets `canValidate` to `true` and calls `validate()` function.
void forceValidate() {
Future<void> forceValidate() async {
canValidate = true;
validate();
await validate();
}

void validate();
Future<void> validate();
}
Loading