Skip to content

Commit 86bf059

Browse files
authored
Development (#110)
2 parents 157f4c2 + 1a917b8 commit 86bf059

12 files changed

Lines changed: 148 additions & 27 deletions

File tree

.fvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"flutter": "3.35.2",
2+
"flutter": "3.38.6",
33
"flavors": {}
44
}

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,34 @@
11
# Changelog
22

3+
## 7.5.7
4+
- Added `focusNode` prop to `ThemedNumberInput` to allow external focus node management.
5+
6+
## 7.5.6
7+
- Add `onLongPress` with `customLongPressDuration` in `ThemedButton`
8+
9+
## 7.5.5
10+
- Added `itemsLength` parameter to `deleteConfirmationDialog` utility to show the number of items being deleted in the confirmation dialog.
11+
12+
## 7.5.4
13+
- Critical fix on `ThemedTable2` Select All checkbox, fixed an issue where selecting all items selected everything avaiable even when filtering with the search bar.
14+
15+
## 7.5.3
16+
17+
- Changed `customSort` signature on `ThemedColumn2` to include the `ascending` parameter to allow more complex sorting algorithms.
18+
19+
## 7.5.2
20+
- Fixed `ThemedMapToolbar` zoom in and zoom out buttons doing the opposite action.
21+
22+
## 7.5.1+1
23+
- Minor state validation on `ThemedTable2` setState call on search.
24+
25+
## 7.5.1
26+
- Fixed `ThemedTable2` search debounce not working as expected.
27+
28+
## 7.5.0+1
29+
30+
- Hotfix regarding of a bug on `ThemedTable2` where the loading indicator was not being removed after filtering and sorting when the items list is empty.
31+
332
## 7.5.0
433

534
- Updated constraint of Dart SDK to `>=3.10.0 <4.0.0`

example/lib/views/table/src/table2.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class _InfinityTableViewState extends State<InfinityTableView> {
3939
Asset _generateAsset(int index) {
4040
return Asset(
4141
id: (index + 1).toString(),
42-
name: (index == 2) ? "Asset asdasfasfasf ${index + 1}" : "Other Asset ${index + 1}",
42+
name: (index == 2) ? "Asset LOREM ${index + 1}" : "Other Asset ${index + 1}",
4343
plate: 'PLATE${index + 1} testestes',
4444
vin: 'VIN${index + 1}',
4545
mode: AssetMode.single,
@@ -54,6 +54,7 @@ class _InfinityTableViewState extends State<InfinityTableView> {
5454
body: ThemedTable2<Asset>(
5555
items: _items,
5656
actionsCount: 3,
57+
canSearch: true,
5758
multiselectActions: [
5859
ThemedActionButton(
5960
icon: LayrzIcons.faSolidLayerGroup,
@@ -87,7 +88,7 @@ class _InfinityTableViewState extends State<InfinityTableView> {
8788
ThemedColumn2(
8889
headerText: 'Plate',
8990
valueBuilder: (item) => item.plate ?? 'N/A',
90-
customSort: (a, b) {
91+
customSort: (a, b, ascending) {
9192
return (a.plate ?? '').compareTo(b.plate ?? '');
9293
},
9394
onTap: (item) async {

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ packages:
374374
path: ".."
375375
relative: true
376376
source: path
377-
version: "7.5.0"
377+
version: "7.5.5"
378378
leak_tracker:
379379
dependency: transitive
380380
description:

lib/src/buttons/buttons.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
library;
22

3+
import 'dart:async';
34
import 'dart:math';
45

56
import 'package:flutter/material.dart';

lib/src/buttons/src/button.dart

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ class ThemedButton extends StatefulWidget {
111111
/// By default uses the `Theme.of(context).inputDecorationTheme.fillColor`
112112
final Color? loadingForegroundColor;
113113

114+
/// [onLongPressDuration] is used to set the duration to trigger a long press.
115+
final Duration customLongPressDuration;
116+
117+
/// [onLongPress] is called when the button is long pressed.
118+
/// This callback is only available when the button is not disabled.
119+
final VoidCallback? onLongPress;
120+
114121
/// [ThemedButton] is a widget that displays a button with a custom label.
115122
const ThemedButton({
116123
super.key,
@@ -136,12 +143,15 @@ class ThemedButton extends StatefulWidget {
136143
this.iconSeparatorSize = 8,
137144
this.loadingBackgroundColor,
138145
this.loadingForegroundColor,
146+
this.customLongPressDuration = const Duration(milliseconds: 500),
147+
this.onLongPress,
139148
}) : assert(label != null || labelText != null, "You must provide a label or labelText, not both or none."),
140149
assert(height >= 30, "Height must be greater than 30u"),
141150
assert(iconSize >= 0, "Icon size must be greater than 0"),
142151
assert(iconSize <= height, "Icon size must be less than or equal to height"),
143152
assert(fontSize >= 0, "Font size must be greater than 0"),
144-
assert(fontSize <= height, "Font size must be less than or equal to height");
153+
assert(fontSize <= height, "Font size must be less than or equal to height"),
154+
assert(!(onTap != null && onLongPress != null), "You must provide either onTap or onLongPress, not both.");
145155

146156
factory ThemedButton.save({
147157
bool isMobile = false,
@@ -463,6 +473,15 @@ class _ThemedButtonState extends State<ThemedButton> {
463473
/// [iconSeparatorSize] is used to know the size of the icon separator.
464474
double get iconSeparatorSize => widget.iconSeparatorSize;
465475

476+
/// [_longPressTimer] is used to handle the long press event.
477+
Timer? _longPressTimer;
478+
479+
/// [longPressTriggered] is used to know if the long press event was triggered.
480+
bool longPressTriggered = false;
481+
482+
/// [customLongPressDuration] is used to set the duration to trigger a long press.
483+
Duration get customLongPressDuration => widget.customLongPressDuration;
484+
466485
WidgetSpan get iconSeparator => WidgetSpan(
467486
alignment: .middle,
468487
child: SizedBox(width: iconSeparatorSize),
@@ -601,6 +620,37 @@ class _ThemedButtonState extends State<ThemedButton> {
601620
);
602621
}
603622

623+
/// [_handleTapDown] is used to handle the tap down event.
624+
/// This method starts the long press timer.
625+
void _handleTapDown(TapDownDetails details) {
626+
if (isDisabled || widget.onLongPress == null) return;
627+
longPressTriggered = false;
628+
_longPressTimer = Timer(customLongPressDuration, () {
629+
longPressTriggered = true;
630+
widget.onLongPress?.call();
631+
});
632+
}
633+
634+
/// [_handleTapUp] is used to handle the tap up event.
635+
/// This method cancels the long press timer.
636+
void _handleTapUp(TapUpDetails details) {
637+
_longPressTimer?.cancel();
638+
_longPressTimer = null;
639+
}
640+
641+
/// [_handleTapCancel] is used to handle the tap cancel event.
642+
/// This method cancels the long press timer.
643+
void _handleTapCancel() {
644+
_longPressTimer?.cancel();
645+
_longPressTimer = null;
646+
}
647+
648+
@override
649+
void dispose() {
650+
_longPressTimer?.cancel();
651+
super.dispose();
652+
}
653+
604654
/// [_buildFilledTonal] is used to build a filled tonal button.
605655
/// This button is used when the [style] is [.filledTonal].
606656
Widget _buildFilledTonal() {
@@ -617,6 +667,9 @@ class _ThemedButtonState extends State<ThemedButton> {
617667
color: Colors.transparent,
618668
child: InkWell(
619669
onTap: isDisabled ? null : onTap,
670+
onTapDown: widget.onLongPress != null ? _handleTapDown : null,
671+
onTapUp: widget.onLongPress != null ? _handleTapUp : null,
672+
onTapCancel: widget.onLongPress != null ? _handleTapCancel : null,
620673
child: Padding(
621674
padding: padding,
622675
child: _buildLoadingOrChild(

lib/src/inputs/src/general/number_input.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ class ThemedNumberInput extends StatefulWidget {
8181
/// [hidePrefixSuffixActions] is the state of the input to hide the prefix and suffix actions. on the input
8282
final bool hidePrefixSuffixActions;
8383

84+
/// [focusNode] is the focus node of the input.
85+
final FocusNode? focusNode;
86+
8487
/// [ThemedNumberInput] is the constructor of the input.
8588
/// Simplifies (I hope so) the creation of an input using the standard format of Layrz.
8689
const ThemedNumberInput({
@@ -110,6 +113,7 @@ class ThemedNumberInput extends StatefulWidget {
110113
this.suffixText,
111114
this.prefixText,
112115
this.hidePrefixSuffixActions = false,
116+
this.focusNode,
113117
}) : assert(
114118
(label == null && labelText != null) || (label != null && labelText == null),
115119
'You must provide either a labelText or a label, but not both.',
@@ -250,6 +254,7 @@ class _ThemedNumberInputState extends State<ThemedNumberInput> {
250254
widget.onChanged?.call(castedValue);
251255
},
252256
onSubmitted: widget.onSubmitted,
257+
focusNode: widget.focusNode,
253258
);
254259
}
255260
}

lib/src/map/src/layers/toolbar.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ class _ThemedMapToolbarState extends State<ThemedMapToolbar> {
237237
icon: LayrzIcons.solarBoldAddSquare,
238238
isDisabled: value >= widget.maxZoom,
239239
onTap: () async {
240-
double newZoom = (value - 1).clamp(widget.minZoom, widget.maxZoom);
240+
// Increase zoom by 1
241+
double newZoom = (value + 1).clamp(widget.minZoom, widget.maxZoom);
241242
debugPrint('layrz_theme/ThemedMapToolbar/ZoomOut: Zoom to $newZoom');
242243
await widget.animatedMapController.animatedZoomTo(newZoom);
243244
_zoomListenable.value = newZoom;
@@ -283,7 +284,8 @@ class _ThemedMapToolbarState extends State<ThemedMapToolbar> {
283284
icon: LayrzIcons.solarBoldMinusSquare,
284285
isDisabled: value <= widget.minZoom,
285286
onTap: () async {
286-
double newZoom = (value + 1).clamp(widget.minZoom, widget.maxZoom);
287+
// reduce zoom by 1
288+
double newZoom = (value - 1).clamp(widget.minZoom, widget.maxZoom);
287289
debugPrint('layrz_theme/ThemedMapToolbar/ZoomOut: Zoom to $newZoom');
288290
await widget.animatedMapController.animatedZoomTo(newZoom);
289291
_zoomListenable.value = newZoom;

lib/src/scaffolds/src/utilities.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,23 @@ Future<bool> deleteConfirmationDialog({
1919
String? customContent,
2020
String? customConfirm,
2121
String? customDismiss,
22+
int? itemsLength,
2223
}) async {
2324
LayrzAppLocalizations? i18n = .maybeOf(context);
2425

2526
String title = '';
2627
String content = '';
28+
String? countInfo;
29+
30+
if (itemsLength != null) {
31+
countInfo =
32+
i18n?.tc(
33+
'actions.confirmation.countInfo',
34+
itemsLength,
35+
{'count': itemsLength},
36+
) ??
37+
((itemsLength > 1) ? 'Deleting $itemsLength items.' : 'Deleting $itemsLength item.');
38+
}
2739

2840
if (isMultiple) {
2941
title = i18n?.t('actions.confirmationMultiple.title') ?? 'Are you sure that you want to delete these items?';
@@ -78,6 +90,15 @@ Future<bool> deleteConfirmationDialog({
7890
textAlign: .justify,
7991
maxLines: 10,
8092
),
93+
if (countInfo != null) ...[
94+
const SizedBox(height: 5),
95+
96+
Text(
97+
countInfo,
98+
textAlign: .justify,
99+
maxLines: 10,
100+
),
101+
],
81102
const SizedBox(height: 20),
82103
Row(
83104
mainAxisAlignment: .spaceBetween,

lib/src/table2/src/column.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class ThemedColumn2<T> {
2424
final CellTap<T>? onTap;
2525

2626
/// [customSort] is a function that takes two items and returns an integer for custom sorting
27-
int Function(T a, T b)? customSort;
27+
int Function(T a, T b, bool ascending)? customSort;
2828

2929
/// [ThemedColumn2] is the new implementation of ThemedColumn with enhanced features
3030
///

0 commit comments

Comments
 (0)