Skip to content

Commit

Permalink
Merge pull request #47 from enrique-lozano/hot-fixes
Browse files Browse the repository at this point in the history
Layout improvements on desktop
  • Loading branch information
enrique-lozano authored Oct 7, 2023
2 parents 97fb44a + 08afabc commit a9f672b
Show file tree
Hide file tree
Showing 9 changed files with 633 additions and 329 deletions.
574 changes: 296 additions & 278 deletions lib/app/home/home.page.dart

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -64,50 +64,57 @@ class HomeDrawer extends StatelessWidget {
),
];

return Drawer(
child: ListView(padding: EdgeInsets.zero, children: [
StreamBuilder(
stream: UserSettingService.instance.getSettings(
(p0) =>
p0.settingKey.equalsValue(SettingKey.userName) |
p0.settingKey.equalsValue(SettingKey.avatar),
),
builder: (context, snapshot) {
final userName = snapshot.data
?.firstWhere(
(element) => element.settingKey == SettingKey.userName,
)
.settingValue;
final userAvatar = snapshot.data
?.firstWhere(
(element) => element.settingKey == SettingKey.avatar,
)
.settingValue;
return ListView(padding: EdgeInsets.zero, children: [
StreamBuilder(
stream: UserSettingService.instance.getSettings(
(p0) =>
p0.settingKey.equalsValue(SettingKey.userName) |
p0.settingKey.equalsValue(SettingKey.avatar),
),
builder: (context, snapshot) {
final userName = snapshot.data
?.firstWhere(
(element) => element.settingKey == SettingKey.userName,
)
.settingValue;
final userAvatar = snapshot.data
?.firstWhere(
(element) => element.settingKey == SettingKey.avatar,
)
.settingValue;

return UserAccountsDrawerHeader(
accountName: userName != null
? Text(userName)
: const Skeleton(width: 25, height: 12),
currentAccountPicture: UserAvatar(avatar: userAvatar),
currentAccountPictureSize: const Size.fromRadius(24),
accountEmail: Text(
t.home.hello_day,
style: const TextStyle(
fontWeight: FontWeight.w300,
fontSize: 12,
),
return UserAccountsDrawerHeader(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
),
accountName: userName != null
? Text(
userName,
style: TextStyle(
color: Theme.of(context).colorScheme.onBackground,
),
)
: const Skeleton(width: 25, height: 12),
currentAccountPicture: UserAvatar(avatar: userAvatar),
currentAccountPictureSize: const Size.fromRadius(24),
accountEmail: Text(
t.home.hello_day,
style: TextStyle(
fontWeight: FontWeight.w300,
fontSize: 12,
color: Theme.of(context).colorScheme.onBackground,
),
);
}),
...List.generate(drawerActions.length, (index) {
final item = drawerActions[index];
return ListTile(
title: Text(item.label),
leading: Icon(item.icon),
onTap: item.onClick,
);
}),
]),
);
),
);
}),
...List.generate(drawerActions.length, (index) {
final item = drawerActions[index];
return ListTile(
title: Text(item.label),
leading: Icon(item.icon),
onTap: item.onClick,
);
}),
]);
}
}
3 changes: 2 additions & 1 deletion lib/app/stats/widgets/balance_bar_chart_small.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:async/async.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:monekin/core/database/services/account/account_service.dart';
import 'package:monekin/core/presentation/responsive/breakpoints.dart';
import 'package:monekin/core/services/filters/date_range_service.dart';
import 'package:monekin/i18n/translations.g.dart';

Expand Down Expand Up @@ -104,7 +105,7 @@ class _BalanceChartSmallState extends State<BalanceChartSmall> {
final t = Translations.of(context);

return SizedBox(
height: 250,
height: BreakPoint.of(context).isLargerThan(BreakpointID.md) ? 325 : 250,
child: StreamBuilder(
stream: AccountService.instance.getAccounts(),
builder: (context, accountsSnapshot) {
Expand Down
2 changes: 1 addition & 1 deletion lib/core/presentation/responsive/app_breakpoints.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:monekin/core/presentation/responsive/breakpoints.dart';

Set<BreakPoint> appBreakPoints = {
final Set<BreakPoint> appBreakPoints = {
const BreakPoint(BreakpointID.xs, width: double.infinity),
const BreakPoint(BreakpointID.sm, width: 540),
const BreakPoint(BreakpointID.md, width: 720),
Expand Down
20 changes: 20 additions & 0 deletions lib/core/presentation/responsive/breakpoints.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ class BreakPoint extends Equatable {
return appBreakPoints.firstWhere((element) => element.id == id);
}

bool isSmallerThan(BreakpointID id) {
return this < BreakPoint.getById(id);
}

bool isSmallerOrEqualTo(BreakpointID id) {
return this <= BreakPoint.getById(id);
}

bool isLargerThan(BreakpointID id) {
return this > BreakPoint.getById(id);
}

bool isLargerOrEqualTo(BreakpointID id) {
return this >= BreakPoint.getById(id);
}

bool isBetween(BreakpointID id1, BreakpointID id2) {
return this >= BreakPoint.getById(id1) && this <= BreakPoint.getById(id2);
}

@override
List<Object?> get props => [id.index];

Expand Down
245 changes: 245 additions & 0 deletions lib/core/presentation/responsive/responsive_row_column.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';

/// A convenience wrapper for responsive [Row] and
/// [Column] switching with padding and spacing.
///
/// ResponsiveRowColumn combines responsiveness
/// behaviors for managing rows and columns into one
/// convenience widget. This widget requires all [children]
/// to be [ResponsiveRowColumnItem] widgets.
///
/// Row vs column layout is controlled by passing a [Axis] to [direction].
///
/// Add spacing between widgets with [rowSpacing] and
/// [columnSpacing]. Add padding around widgets with
/// [rowPadding] and [columnPadding].
///
/// See [ResponsiveRowColumnItem] for [Flex] and
/// [FlexFit] options.
class ResponsiveRowColumn extends StatelessWidget {
final List<ResponsiveRowColumnItem> children;

/// Horizontal to row layout and vertical to column layout
final Axis direction;

final MainAxisAlignment rowMainAxisAlignment;
final MainAxisSize rowMainAxisSize;
final CrossAxisAlignment rowCrossAxisAlignment;
final TextDirection? rowTextDirection;
final VerticalDirection rowVerticalDirection;
final TextBaseline? rowTextBaseline;
final MainAxisAlignment columnMainAxisAlignment;
final MainAxisSize columnMainAxisSize;
final CrossAxisAlignment columnCrossAxisAlignment;
final TextDirection? columnTextDirection;
final VerticalDirection columnVerticalDirection;
final TextBaseline? columnTextBaseline;

/// The space between the rows of this widget
final double? rowSpacing;

/// The space between the columns of this widget
final double? columnSpacing;

/// Outside padding of all the elements in the row
final EdgeInsets rowPadding;

/// Outside padding of all the elements in the column
final EdgeInsets columnPadding;

get isRow => direction == Axis.horizontal;
get isColumn => direction == Axis.vertical;

/// The [ResponsiveRowColumn] constructor
const ResponsiveRowColumn(
{Key? key,
this.children = const [],
required this.direction,
this.rowMainAxisAlignment = MainAxisAlignment.start,
this.rowMainAxisSize = MainAxisSize.max,
this.rowCrossAxisAlignment = CrossAxisAlignment.center,
this.rowTextDirection,
this.rowVerticalDirection = VerticalDirection.down,
this.rowTextBaseline,
this.columnMainAxisAlignment = MainAxisAlignment.start,
this.columnMainAxisSize = MainAxisSize.max,
this.columnCrossAxisAlignment = CrossAxisAlignment.center,
this.columnTextDirection,
this.columnVerticalDirection = VerticalDirection.down,
this.columnTextBaseline,
this.rowSpacing,
this.columnSpacing,
this.rowPadding = EdgeInsets.zero,
this.columnPadding = EdgeInsets.zero})
: super(key: key);

/// Create a [ResponsiveRowColumn] with the same padding and space between children for row and column mode
const ResponsiveRowColumn.withSymetricSpacing(
{Key? key,
this.children = const [],
required this.direction,
this.rowMainAxisAlignment = MainAxisAlignment.start,
this.rowMainAxisSize = MainAxisSize.max,
this.rowCrossAxisAlignment = CrossAxisAlignment.center,
this.rowTextDirection,
this.rowVerticalDirection = VerticalDirection.down,
this.rowTextBaseline,
this.columnMainAxisAlignment = MainAxisAlignment.start,
this.columnMainAxisSize = MainAxisSize.max,
this.columnCrossAxisAlignment = CrossAxisAlignment.center,
this.columnTextDirection,
this.columnVerticalDirection = VerticalDirection.down,
this.columnTextBaseline,
double? spacing,
EdgeInsets padding = EdgeInsets.zero})
: rowPadding = padding,
columnPadding = padding,
rowSpacing = spacing,
columnSpacing = spacing,
super(key: key);

@override
Widget build(BuildContext context) {
if (isRow) {
return Padding(
padding: rowPadding,
child: Row(
mainAxisAlignment: rowMainAxisAlignment,
mainAxisSize: rowMainAxisSize,
crossAxisAlignment: rowCrossAxisAlignment,
textDirection: rowTextDirection,
verticalDirection: rowVerticalDirection,
textBaseline: rowTextBaseline,
children: [
...buildChildren(children, true, rowSpacing),
],
),
);
}

return Padding(
padding: columnPadding,
child: Column(
mainAxisAlignment: columnMainAxisAlignment,
mainAxisSize: columnMainAxisSize,
crossAxisAlignment: columnCrossAxisAlignment,
textDirection: columnTextDirection,
verticalDirection: columnVerticalDirection,
textBaseline: columnTextBaseline,
children: [
...buildChildren(children, false, columnSpacing),
],
),
);
}

/// Logic to construct widget [children].
List<Widget> buildChildren(
List<ResponsiveRowColumnItem> children, bool rowColumn, double? spacing) {
// Sort ResponsiveRowColumnItems by their order.
List<ResponsiveRowColumnItem> childrenHolder = [];
childrenHolder.addAll(children);
childrenHolder.sort((a, b) {
if (rowColumn) {
return a.rowOrder.compareTo(b.rowOrder);
} else {
return a.columnOrder.compareTo(b.columnOrder);
}
});

// Add padding between widgets..
List<Widget> widgetList = [];
for (int i = 0; i < childrenHolder.length; i++) {
widgetList.add(childrenHolder[i].copyWith(rowColumn: rowColumn));
if (spacing != null && i != childrenHolder.length - 1) {
widgetList.add(Padding(
padding: rowColumn
? EdgeInsets.only(right: spacing)
: EdgeInsets.only(bottom: spacing)));
}
}
return widgetList;
}
}

/// A wrapper for [ResponsiveRowColumn] children with
/// responsiveness.
///
/// Control the order of widgets within [ResponsiveRowColumn]
/// by assigning a [rowOrder] or [columnOrder] value.
/// Widgets without an order value are ranked behind
/// those with order values.
/// Set a widget's [Flex] value through [rowFlex] and
/// [columnFlex]. Set a widget's [FlexFit] through
/// [rowFit] and [columnFit].
class ResponsiveRowColumnItem extends StatelessWidget {
final Widget child;
final int rowOrder;
final int columnOrder;
final bool rowColumn;
final int? rowFlex;
final int? columnFlex;
final FlexFit? rowFit;
final FlexFit? columnFit;

const ResponsiveRowColumnItem(
{Key? key,
required this.child,
this.rowOrder = 1073741823,
this.columnOrder = 1073741823,
this.rowColumn = true,
this.rowFlex,
this.columnFlex,
this.rowFit,
this.columnFit})
: super(key: key);

/// Build a `SizedBox` inside the responsive row/column layout. The [space] define the height of the `SizedBox` in Column mode and the width in row mode
ResponsiveRowColumnItem.spacer(double space,
{Key? key,
this.rowOrder = 1073741823,
this.columnOrder = 1073741823,
this.rowColumn = true,
this.rowFlex,
this.columnFlex,
this.rowFit,
this.columnFit})
: child = SizedBox(
height: rowColumn ? space : null, width: !rowColumn ? space : null),
super(key: key);

@override
Widget build(BuildContext context) {
if (rowColumn && (rowFlex != null || rowFit != null)) {
return Flexible(
flex: rowFlex ?? 1, fit: rowFit ?? FlexFit.loose, child: child);
} else if (!rowColumn && (columnFlex != null || columnFit != null)) {
return Flexible(
flex: columnFlex ?? 1, fit: columnFit ?? FlexFit.loose, child: child);
}

return child;
}

ResponsiveRowColumnItem copyWith({
int? rowOrder,
int? columnOrder,
bool? rowColumn,
int? rowFlex,
int? columnFlex,
FlexFit? rowFlexFit,
FlexFit? columnFlexFit,
Widget? child,
}) =>
ResponsiveRowColumnItem(
rowOrder: rowOrder ?? this.rowOrder,
columnOrder: columnOrder ?? this.columnOrder,
rowColumn: rowColumn ?? this.rowColumn,
rowFlex: rowFlex ?? this.rowFlex,
columnFlex: columnFlex ?? this.columnFlex,
rowFit: rowFlexFit ?? rowFit,
columnFit: columnFlexFit ?? columnFit,
child: child ?? this.child,
);
}
Loading

0 comments on commit a9f672b

Please sign in to comment.