Skip to content

Commit

Permalink
v6.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
agordn52 committed Nov 23, 2024
1 parent e853411 commit 5ec8f70
Show file tree
Hide file tree
Showing 12 changed files with 275 additions and 52 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## [6.5.0] - 2024-11-23

* Dark mode support for Form fields: picker, date picker, checkbox and chips
* New helper `color({light, dark})` to get the color based on the theme
* New helper `whenTheme({light, dark})` to handle widgets based on the theme
* Add `NyThemeType` to BaseThemeConfig. This will allow you to set if a theme is light or dark
* Contribution from [stensonb](https://github.com/stensonb) to update the documentation for the sleep method
* Update pubspec.yaml

## [6.4.1] - 2024-11-22

* Update pubspec.yaml
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ packages:
path: ".."
relative: true
source: path
version: "6.4.0"
version: "6.5.0"
path:
dependency: transitive
description:
Expand Down
23 changes: 18 additions & 5 deletions lib/helpers/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@ import 'package:flutter/material.dart'
VerticalDivider;
import 'package:get_time_ago/get_time_ago.dart';
import 'package:intl/intl.dart' as intl;
import '/themes/base_theme_config.dart';
import '/helpers/state_action.dart';
import '/nylo.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:theme_provider/theme_provider.dart';
import '../local_storage/local_storage.dart';
import '/local_storage/local_storage.dart';
import '/helpers/backpack.dart';
import '/helpers/helper.dart';
import '/localization/app_localization.dart';
Expand Down Expand Up @@ -2186,10 +2187,8 @@ extension DarkMode on BuildContext {
/// if (context.isDeviceInDarkMode) {
/// do something here...
/// }
bool get isDeviceInDarkMode {
final brightness = MediaQuery.of(this).platformBrightness;
return brightness == Brightness.dark;
}
bool get isDeviceInDarkMode =>
MediaQuery.of(this).platformBrightness == Brightness.dark;
}

extension NyContext on BuildContext {
Expand Down Expand Up @@ -2217,6 +2216,20 @@ extension NyContext on BuildContext {
double widgetHeight() {
return mediaQuery().size.height;
}

/// Check if the device is in dark mode
bool get isThemeDark {
if (isDeviceInDarkMode) return true;
ThemeController themeController = ThemeProvider.controllerOf(this);
if ((themeController.theme.options as NyThemeOptions).meta is Map &&
(themeController.theme.options as NyThemeOptions).meta['type'] ==
NyThemeType.dark) {
return true;
}

return ThemeProvider.controllerOf(this).currentThemeId ==
getEnv('DARK_THEME_ID');
}
}

extension NyMapEntry on Iterable<MapEntry<String, dynamic>> {
Expand Down
13 changes: 11 additions & 2 deletions lib/themes/base_theme_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@ class BaseThemeConfig<T> {
final String description;
ThemeData Function(T colorStyles) theme;
final T colors;
final dynamic meta;
Map<String, dynamic>? meta;
final NyThemeType type;

/// Create a new [BaseThemeConfig].
BaseThemeConfig(
{required this.id,
required this.description,
required this.theme,
required this.colors,
this.meta = const {}});
this.type = NyThemeType.light,
this.meta}) {
if (meta == null) {
this.meta = {};
}
this.meta?.addAll({"type": type});
}

/// Convert the theme to a [AppTheme] object.
AppTheme toAppTheme({ThemeData? defaultTheme}) => AppTheme(
Expand All @@ -34,3 +41,5 @@ class NyThemeOptions<T> extends AppThemeOptions {

NyThemeOptions({required this.colors, this.meta = const {}});
}

enum NyThemeType { light, dark }
67 changes: 66 additions & 1 deletion lib/widgets/fields/field_base_state.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:nylo_support/helpers/extensions.dart';
import 'package:theme_provider/theme_provider.dart';
import '/helpers/helper.dart';
import '/themes/base_theme_config.dart';
import '/widgets/ny_form.dart';

import '/widgets/spacing.dart';
Expand All @@ -7,6 +11,9 @@ abstract class FieldBaseState<T extends StatefulWidget> extends State<T> {
FieldBaseState(this.field);
late Field field;

/// Default surface color for dark mode
Color surfaceColorDark = "222831".toHexColor();

/// Get metadata from a field
// ignore: avoid_shadowing_type_parameters
T getFieldMeta<T>(String name, T defaultValue) {
Expand Down Expand Up @@ -51,4 +58,62 @@ abstract class FieldBaseState<T extends StatefulWidget> extends State<T> {

return widget;
}

/// Get the color based on the device mode
Color color({Color? light, Color? dark}) {
bool isDarkModeEnabled = false;
ThemeController themeController = ThemeProvider.controllerOf(context);

if (themeController.currentThemeId == getEnv('DARK_THEME_ID')) {
isDarkModeEnabled = true;
}

if ((themeController.theme.options as NyThemeOptions).meta is Map &&
(themeController.theme.options as NyThemeOptions).meta['type'] ==
NyThemeType.dark) {
isDarkModeEnabled = true;
}

if (context.isDeviceInDarkMode) {
isDarkModeEnabled = true;
}

if (isDarkModeEnabled) {
return dark ?? Colors.black38;
}

return light ?? Colors.grey.shade100;
}

/// When the theme is in [light] mode, return [light] function, else return [dark] function
// ignore: avoid_shadowing_type_parameters
T whenTheme<T>({
required T Function() light,
T Function()? dark,
}) {
bool isDarkModeEnabled = false;
ThemeController themeController = ThemeProvider.controllerOf(context);

if (themeController.currentThemeId == getEnv('DARK_THEME_ID')) {
isDarkModeEnabled = true;
}

if ((themeController.theme.options as NyThemeOptions).meta is Map &&
(themeController.theme.options as NyThemeOptions).meta['type'] ==
NyThemeType.dark) {
isDarkModeEnabled = true;
}

if (context.isDeviceInDarkMode) {
isDarkModeEnabled = true;
}

if (isDarkModeEnabled) {
if (dark != null) {
return dark();
}
}

return light();
}
}
28 changes: 20 additions & 8 deletions lib/widgets/fields/form_checkbox.dart
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,24 @@ class _NyFormCheckboxState extends FieldBaseState<NyFormCheckbox> {

title ??= Text(
widget.field.name.titleCase,
style: TextStyle(
color: color(light: Colors.black, dark: Colors.white),
),
);
if (title is Text && (title.data == null || title.data!.isEmpty)) {
title = Text(
widget.field.name.titleCase,
style: TextStyle(
color: color(light: Colors.black, dark: Colors.white),
),
);
}

Color? fillColorMetaData = getMetaData('fillColor');
WidgetStateProperty<Color?>? fillColor;
if (fillColorMetaData != null) {
fillColor = WidgetStateProperty.all(fillColorMetaData);
}
Color? fillColorMetaData = color(
light: getMetaData('fillColor') ?? Colors.transparent,
dark: Colors.black);
WidgetStateProperty<Color?>? fillColor =
WidgetStateProperty.all(fillColorMetaData);

Color? overlayColorMetaData = getMetaData('overlayColor');
WidgetStateProperty<Color?>? overlayColor;
Expand All @@ -151,9 +157,12 @@ class _NyFormCheckboxState extends FieldBaseState<NyFormCheckbox> {
});
},
controlAffinity: ListTileControlAffinity.leading,
activeColor: getMetaData('activeColor'),
activeColor: color(
light: getMetaData('activeColor') ?? Colors.black,
dark: Colors.black),
fillColor: fillColor,
checkColor: getMetaData('checkColor'),
checkColor: color(
light: getMetaData('checkColor') ?? Colors.black, dark: Colors.white),
hoverColor: getMetaData('hoverColor'),
overlayColor: overlayColor,
splashRadius: getMetaData('splashRadius'),
Expand All @@ -162,7 +171,10 @@ class _NyFormCheckboxState extends FieldBaseState<NyFormCheckbox> {
focusNode: getMetaData('focusNode'),
autofocus: getMetaData('autofocus'),
shape: getMetaData('shape'),
side: getMetaData('side'),
side: whenTheme(
light: () => getMetaData('side'),
dark: () => BorderSide(
width: 2, color: color(light: Colors.black, dark: Colors.white))),
isError: getMetaData('isError'),
enabled: getMetaData('enabled'),
tileColor: getMetaData('tileColor'),
Expand Down
48 changes: 34 additions & 14 deletions lib/widgets/fields/form_chips.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,33 @@ class _NyFormChipState extends FieldBaseState<NyFormChip> {
bool isSelected = currentValues.contains(option);
return ChoiceChip(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
side: isSelected ? getSelectedSide() : getUnselectedSide(),
side: whenTheme(
light: () =>
isSelected ? getSelectedSide() : getUnselectedSide(),
dark: () => BorderSide(color: Colors.transparent)),
shape: getShape(),
label: Text(option,
style: isSelected
? getSelectedTextStyle()
: getUnselectedTextStyle()),
style: whenTheme(
light: () => isSelected
? getSelectedTextStyle()
: getUnselectedTextStyle(),
dark: () => TextStyle(
fontWeight: FontWeight.bold, color: Colors.white))),
labelStyle: getLabelStyle(),
selected: isSelected,
selectedColor: getSelectedColor(),
padding: getPadding(),
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
checkmarkColor: getCheckmarkColor(),
checkmarkColor: whenTheme(
light: () => getCheckmarkColor(), dark: () => Colors.white),
selectedShadowColor: Colors.transparent,
color: WidgetStateColor.resolveWith((color) {
return isSelected ? getSelectedColor() : getBackgroundColor();
color: WidgetStateColor.resolveWith((_) {
return color(
light:
isSelected ? getSelectedColor() : getBackgroundColor(),
dark: surfaceColorDark);
}),
onSelected: (bool selected) {
setState(() {
Expand All @@ -123,7 +133,8 @@ class _NyFormChipState extends FieldBaseState<NyFormChip> {
Color getBackgroundColor() => getFieldMeta("backgroundColor", Colors.white);

/// Get the selected color from the field
Color getSelectedColor() => getFieldMeta("selectedColor", Colors.black);
Color getSelectedColor() => getFieldMeta(
"selectedColor", color(light: Colors.black, dark: Colors.white));

/// Get the borderRadius from the field
OutlinedBorder getShape() => getFieldMeta(
Expand All @@ -138,16 +149,25 @@ class _NyFormChipState extends FieldBaseState<NyFormChip> {
"selectedSide", BorderSide(color: "#bfbbc5".toHexColor(), width: 1));

/// Get the labelStyle from the field
TextStyle getLabelStyle() => getFieldMeta("labelStyle",
const TextStyle(fontWeight: FontWeight.bold, color: Colors.black));
TextStyle getLabelStyle() => getFieldMeta(
"labelStyle",
TextStyle(
fontWeight: FontWeight.bold,
color: color(light: Colors.black, dark: Colors.white)));

/// Get the unselectedTextStyle from the field
TextStyle getUnselectedTextStyle() => getFieldMeta("unselectedTextStyle",
const TextStyle(fontWeight: FontWeight.bold, color: Colors.black));
TextStyle getUnselectedTextStyle() => getFieldMeta(
"unselectedTextStyle",
TextStyle(
fontWeight: FontWeight.bold,
color: color(light: Colors.black, dark: Colors.white)));

/// Get the selectedTextStyle from the field
TextStyle getSelectedTextStyle() => getFieldMeta("selectedTextStyle",
const TextStyle(fontWeight: FontWeight.bold, color: Colors.white));
TextStyle getSelectedTextStyle() => getFieldMeta(
"selectedTextStyle",
TextStyle(
fontWeight: FontWeight.bold,
color: color(light: Colors.black, dark: Colors.white)));

/// Get the padding from the field
EdgeInsets getPadding() => getFieldMeta("padding", const EdgeInsets.all(8.0));
Expand Down
21 changes: 15 additions & 6 deletions lib/widgets/fields/form_date_time_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,15 @@ class _NyFormDateTimePickerState extends FieldBaseState<NyFormDateTimePicker> {
return DateTimeFormField(
decoration: getMetaData('decoration') ??
InputDecoration(
fillColor: Colors.grey.shade100,
fillColor:
color(light: Colors.grey.shade100, dark: surfaceColorDark),
border: InputBorder.none,
filled: true,
suffixIconColor: color(light: Colors.black, dark: Colors.white),
labelText: widget.field.name.titleCase,
labelStyle: TextStyle(
fontSize: 16,
color: color(light: Colors.grey, dark: Colors.white)),
isDense: true,
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
Expand All @@ -124,17 +129,21 @@ class _NyFormDateTimePickerState extends FieldBaseState<NyFormDateTimePicker> {
materialTimePickerOptions: getMetaData('materialTimePickerOptions') ??
const MaterialTimePickerOptions(),
cupertinoDatePickerOptions: getMetaData('cupertinoDatePickerOptions') ??
const CupertinoDatePickerOptions(),
CupertinoDatePickerOptions(
style: CupertinoDatePickerOptionsStyle(
modalTitle: TextStyle(
color: color(light: Colors.black, dark: Colors.white))),
),
hideDefaultSuffixIcon: getMetaData('hideDefaultSuffixIcon') ?? false,
padding: getMetaData('padding') ?? EdgeInsets.zero,
style: getMetaData('style') ??
const TextStyle(fontSize: 16, color: Colors.black),
TextStyle(
fontSize: 16,
color: color(light: Colors.black, dark: Colors.white)),
onChanged: widget.onChanged,
);
}

/// Get the metadata from the field
getMetaData(String key) {
return widget.field.cast.metaData[key];
}
getMetaData(String key) => widget.field.cast.metaData[key];
}
Loading

0 comments on commit 5ec8f70

Please sign in to comment.