Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Country selector redesign #5483

Merged
merged 5 commits into from
Jul 20, 2024
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
7 changes: 7 additions & 0 deletions packages/smooth_app/lib/generic_lib/design_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const Widget EMPTY_WIDGET = SizedBox.shrink();

const double VERY_SMALL_SPACE = 4.0;
const double SMALL_SPACE = 8.0;
const double BALANCED_SPACE = 10.0;
const double MEDIUM_SPACE = 12.0;
const double LARGE_SPACE = 16.0;
const double VERY_LARGE_SPACE = 20.0;
Expand All @@ -21,6 +22,12 @@ const Radius ROUNDED_RADIUS = Radius.circular(20.0);
//ignore: non_constant_identifier_names
const BorderRadius ROUNDED_BORDER_RADIUS = BorderRadius.all(ROUNDED_RADIUS);

/// Topbar…
const Radius HEADER_ROUNDED_RADIUS = Radius.circular(30.0);
//ignore: non_constant_identifier_names
const BorderRadius HEADER_BORDER_RADIUS =
BorderRadius.all(HEADER_ROUNDED_RADIUS);

/// Full screen button, e.g. KnowledgePanel
const Radius ANGULAR_RADIUS = Radius.circular(8.0);
//ignore: non_constant_identifier_names
Expand Down
117 changes: 117 additions & 0 deletions packages/smooth_app/lib/helpers/provider_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,65 @@ class _ListenerState<T> extends SingleChildState<Listener<T>> {
}
}

/// Same as [Listener] but for [ValueNotifier] : notifies when the value changes
class ValueNotifierListener<T extends ValueNotifier<S>, S>
extends SingleChildStatefulWidget {
const ValueNotifierListener({
this.listener,
this.listenerWithValueNotifier,
super.key,
super.child,
}) : assert(
listener != null || listenerWithValueNotifier != null,
'At least one listener must be provided',
);

final void Function(
BuildContext context,
S? previousValue,
S currentValue,
)? listener;

final void Function(
BuildContext context,
T valueNotifier,
S? previousValue,
S currentValue,
)? listenerWithValueNotifier;

@override
State<ValueNotifierListener<T, S>> createState() =>
_ValueNotifierListenerState<T, S>();
}

class _ValueNotifierListenerState<T extends ValueNotifier<S>, S>
extends SingleChildState<ValueNotifierListener<T, S>> {
S? _oldValue;

@override
Widget buildWithChild(BuildContext context, Widget? child) {
final S? oldValue = _oldValue;
final T valueNotifier = context.watch<T>();
final S newValue = valueNotifier.value;
_oldValue = newValue;

widget.listener?.call(
context,
oldValue,
newValue,
);

widget.listenerWithValueNotifier?.call(
context,
valueNotifier,
oldValue,
newValue,
);

return child ?? const SizedBox.shrink();
}
}

/// Same as [Consumer] but only rebuilds if [buildWhen] returns true
/// (And on the first build)
class ConsumerFilter<T> extends StatefulWidget {
Expand Down Expand Up @@ -91,6 +150,64 @@ class _ConsumerFilterState<T> extends State<ConsumerFilter<T>> {
}
}

/// Same as [Consumer] for [ValueNotifier] but only rebuilds if [buildWhen]
/// returns true (and on the first build).
class ConsumerValueNotifierFilter<T extends ValueNotifier<S>, S>
extends StatefulWidget {
const ConsumerValueNotifierFilter({
required this.builder,
this.buildWhen,
this.child,
super.key,
});

final Widget Function(
BuildContext context,
S value,
Widget? child,
) builder;
final bool Function(S? previousValue, S currentValue)? buildWhen;

final Widget? child;

@override
State<ConsumerValueNotifierFilter<T, S>> createState() =>
_ConsumerValueNotifierFilterState<T, S>();
}

class _ConsumerValueNotifierFilterState<T extends ValueNotifier<S>, S>
extends State<ConsumerValueNotifierFilter<T, S>> {
S? oldValue;
Widget? oldWidget;

@override
Widget build(BuildContext context) {
return Consumer<T>(
builder: (BuildContext context, T provider, Widget? child) {
if ((widget.buildWhen != null &&
widget.buildWhen!.call(oldValue, provider.value)) ||
widget.buildWhen == null && oldValue != provider.value ||
oldWidget == null) {
oldWidget = widget.builder(
context,
provider.value,
child,
);
}

oldValue = provider.value;

return widget.builder(
context,
provider.value,
oldWidget,
);
},
child: widget.child,
);
}
}

extension ValueNotifierExtensions<T> on ValueNotifier<T> {
void emit(T value) => this.value = value;
}
4 changes: 4 additions & 0 deletions packages/smooth_app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
"@reason": {},
"okay": "Okay",
"@okay": {},
"validate": "Validate",
"@validate": {
"description": "Button label: Validate the input"
},
"create": "Create",
"@create": {
"description": "An action to create"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class _GuidesParagraphTitle extends StatelessWidget {
child: Padding(
padding: const EdgeInsetsDirectional.symmetric(
horizontal: GuidesParagraph._HORIZONTAL_PADDING,
vertical: 10.0,
vertical: BALANCED_SPACE,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
Expand All @@ -189,7 +189,7 @@ class _GuidesParagraphTitle extends StatelessWidget {
padding: EdgeInsetsDirectional.only(top: 3.3),
child: _GuidesParagraphArrow(),
),
const SizedBox(width: 10.0),
const SizedBox(width: BALANCED_SPACE),
Expanded(
child: Text(
title,
Expand Down Expand Up @@ -244,7 +244,7 @@ class GuidesText extends StatelessWidget {
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsetsDirectional.only(
top: 10.0,
top: BALANCED_SPACE,
start: GuidesParagraph._HORIZONTAL_PADDING,
end: GuidesParagraph._HORIZONTAL_PADDING,
),
Expand Down Expand Up @@ -453,7 +453,7 @@ class GuidesImage extends StatelessWidget {
excludeSemantics: true,
child: Padding(
padding: const EdgeInsetsDirectional.only(
top: 10.0,
top: BALANCED_SPACE,
start: GuidesParagraph._HORIZONTAL_PADDING,
end: GuidesParagraph._HORIZONTAL_PADDING,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class GuidesFooter extends StatelessWidget {
top: _FooterPainter.WAVE_SIZE + MEDIUM_SPACE,
start: VERY_LARGE_SPACE,
end: VERY_LARGE_SPACE,
bottom: 10.0 + MediaQuery.viewPaddingOf(context).bottom,
bottom: BALANCED_SPACE + MediaQuery.viewPaddingOf(context).bottom,
),
child: TextButton(
style: TextButton.styleFrom(
Expand Down
14 changes: 7 additions & 7 deletions packages/smooth_app/lib/pages/guides/helpers/guides_header.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class GuidesHeader extends StatelessWidget {
style: const TextStyle(color: Colors.white),
child: SliverPadding(
padding: const EdgeInsetsDirectional.only(
bottom: 10.0,
bottom: BALANCED_SPACE,
),
// Pinned = for the header to stay at the top of the screen
sliver: SliverPersistentHeader(
Expand Down Expand Up @@ -79,7 +79,7 @@ class _GuidesHeaderDelegate extends SliverPersistentHeaderDelegate {
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(30.0 * (1 - progress)),
bottom: HEADER_ROUNDED_RADIUS * (1 - progress),
),
),
color: colors.primaryDark,
Expand Down Expand Up @@ -113,7 +113,7 @@ class _GuidesHeaderDelegate extends SliverPersistentHeaderDelegate {
child: Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: const EdgeInsets.only(bottom: 10.0),
padding: const EdgeInsets.only(bottom: BALANCED_SPACE),
child: AutoSizeText(
title,
maxLines: 4,
Expand Down Expand Up @@ -193,8 +193,8 @@ class _GuidesHeaderLayout extends MultiChildLayoutDelegate {

@override
void performLayout(Size size) {
final double topMargin = topPadding + 10.0;
final double maxHeight = size.height - topPadding - (10.0 * 2);
final double topMargin = topPadding + BALANCED_SPACE;
final double maxHeight = size.height - topPadding - (BALANCED_SPACE * 2);

final Size closeButtonSize = layoutChild(
_GuidesHeaderLayoutId.closeButton,
Expand Down Expand Up @@ -250,7 +250,7 @@ class _GuidesHeaderLayout extends MultiChildLayoutDelegate {
positionChild(
_GuidesHeaderLayoutId.minimizedTitle,
Offset(
_CloseButtonLayout._CLOSE_BUTTON_SIZE + 10.0,
_CloseButtonLayout._CLOSE_BUTTON_SIZE + BALANCED_SPACE,
topMargin + 5.0,
),
);
Expand Down Expand Up @@ -295,7 +295,7 @@ class _BackButton extends StatelessWidget {
child: ExcludeSemantics(
child: Padding(
padding: const EdgeInsetsDirectional.only(
start: 10.0,
start: BALANCED_SPACE,
end: 24.0,
),
child: Opacity(
Expand Down
4 changes: 2 additions & 2 deletions packages/smooth_app/lib/pages/image_crop_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Future<UserPictureSource?> _getUserPictureSource(
closeButtonSemanticsOrder: 5.0,
body: const _ImageSourcePicker(),
bodyPadding: const EdgeInsetsDirectional.only(
start: 10.0,
start: BALANCED_SPACE,
end: MEDIUM_SPACE,
top: LARGE_SPACE,
bottom: MEDIUM_SPACE,
Expand Down Expand Up @@ -127,7 +127,7 @@ class _ImageSourcePickerState extends State<_ImageSourcePicker> {
children: <Widget>[
IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
padding: const EdgeInsets.symmetric(horizontal: BALANCED_SPACE),
child: Row(
children: <Widget>[
Expanded(
Expand Down
Loading
Loading