diff --git a/CHANGELOG.md b/CHANGELOG.md
index 48923f5..f5e559e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,9 @@
## [7.0.0]
- **BREAKING CHANGE**:
- - Upgrade min dart sdk to 3.0.0
+ - Upgrade min dart sdk to 3.0.0
+ - Replace `swipe`, `swipeLeft`, `swipeRight`, `swipeUp`, `swipeDown` with `swipe(CardSwiperDirection direction)`
+ - It also removes `direction` from the `CardSwiper` widget
## [6.1.0]
diff --git a/README.md b/README.md
index 2a2216f..f640699 100644
--- a/README.md
+++ b/README.md
@@ -116,18 +116,15 @@ class Example extends StatelessWidget {
| padding | EdgeInsets.symmetric(horizontal: 20, vertical: 25) | The padding around the swiper | false |
| scale | 0.9 | Scale of the card that is behind the front card | false |
| threshold | 50 | Threshold from which the card is swiped away | false |
-| onSwipeDirectionChange | - | A callback containing the horizontal and vertical swipe direction | false |
+| onSwipeDirectionChange | - | A callback containing the horizontal and vertical swipe direction
+ | false |
#### Controller
The `Controller` is used to swipe the card from outside of the widget. You can create a controller called `CardSwiperController` and save the instance for further usage. Please have a closer look at our [Example](https://github.com/ricardodalarme/flutter_card_swiper/tree/main/example) for the usage.
| Method | Description |
| ----------- | :--------------------------------------------- |
-| swipe | Swipes the card in the selected direction. |
-| swipeLeft | Swipes the card to the left side. |
-| swipeRight | Swipes the card to the right side. |
-| swipeTop | Swipes the card to the top side. |
-| swipeBottom | Swipes the card to the bottom side. |
+| swipe | Swipes the card to a specific direction. |
| undo | Bring back the last card that was swiped away. |
diff --git a/example/lib/main.dart b/example/lib/main.dart
index c8d8f72..81e5dcf 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -66,19 +66,21 @@ class _ExamplePageState extends State {
child: const Icon(Icons.rotate_left),
),
FloatingActionButton(
- onPressed: controller.swipeLeft,
+ onPressed: () => controller.swipe(CardSwiperDirection.left),
child: const Icon(Icons.keyboard_arrow_left),
),
FloatingActionButton(
- onPressed: controller.swipeRight,
+ onPressed: () =>
+ controller.swipe(CardSwiperDirection.right),
child: const Icon(Icons.keyboard_arrow_right),
),
FloatingActionButton(
- onPressed: controller.swipeTop,
+ onPressed: () => controller.swipe(CardSwiperDirection.top),
child: const Icon(Icons.keyboard_arrow_up),
),
FloatingActionButton(
- onPressed: controller.swipeBottom,
+ onPressed: () =>
+ controller.swipe(CardSwiperDirection.bottom),
child: const Icon(Icons.keyboard_arrow_down),
),
],
diff --git a/lib/flutter_card_swiper.dart b/lib/flutter_card_swiper.dart
index e42879e..57c3f02 100644
--- a/lib/flutter_card_swiper.dart
+++ b/lib/flutter_card_swiper.dart
@@ -3,7 +3,7 @@
/// animations supporting Android, iOS, Web & Desktop.
library flutter_card_swiper;
-export 'package:flutter_card_swiper/src/card_swiper_controller.dart';
+export 'package:flutter_card_swiper/src/controller/card_swiper_controller.dart';
export 'package:flutter_card_swiper/src/enums.dart';
export 'package:flutter_card_swiper/src/properties/allowed_swipe_direction.dart';
export 'package:flutter_card_swiper/src/typedefs.dart';
diff --git a/lib/src/card_swiper_controller.dart b/lib/src/card_swiper_controller.dart
deleted file mode 100644
index 0f6ae39..0000000
--- a/lib/src/card_swiper_controller.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-import 'package:flutter/foundation.dart';
-import 'package:flutter_card_swiper/src/enums.dart';
-
-/// A controller that can be used to trigger swipes on a CardSwiper widget.
-class CardSwiperController extends ChangeNotifier {
- CardSwiperState? state;
-
- /// Swipe the card by changing the status of the controller
- void swipe() {
- state = CardSwiperState.swipe;
- notifyListeners();
- }
-
- /// Swipe the card to the left side by changing the status of the controller
- void swipeLeft() {
- state = CardSwiperState.swipeLeft;
- notifyListeners();
- }
-
- /// Swipe the card to the right side by changing the status of the controller
- void swipeRight() {
- state = CardSwiperState.swipeRight;
- notifyListeners();
- }
-
- /// Swipe the card to the top side by changing the status of the controller
- void swipeTop() {
- state = CardSwiperState.swipeTop;
- notifyListeners();
- }
-
- /// Swipe the card to the bottom side by changing the status of the controller
- void swipeBottom() {
- state = CardSwiperState.swipeBottom;
- notifyListeners();
- }
-
- // Undo the last swipe by changing the status of the controller
- void undo() {
- state = CardSwiperState.undo;
- notifyListeners();
- }
-}
diff --git a/lib/src/controller/card_swiper_controller.dart b/lib/src/controller/card_swiper_controller.dart
new file mode 100644
index 0000000..beba297
--- /dev/null
+++ b/lib/src/controller/card_swiper_controller.dart
@@ -0,0 +1,26 @@
+import 'dart:async';
+
+import 'package:flutter_card_swiper/src/controller/controller_event.dart';
+import 'package:flutter_card_swiper/src/enums.dart';
+
+/// A controller that can be used to trigger swipes on a CardSwiper widget.
+class CardSwiperController {
+ final _eventController = StreamController.broadcast();
+
+ /// Stream of events that can be used to swipe the card.
+ Stream get events => _eventController.stream;
+
+ /// Swipe the card to a specific direction.
+ void swipe(CardSwiperDirection direction) {
+ _eventController.add(ControllerSwipeEvent(direction));
+ }
+
+ // Undo the last swipe
+ void undo() {
+ _eventController.add(const ControllerUndoEvent());
+ }
+
+ Future dispose() async {
+ await _eventController.close();
+ }
+}
diff --git a/lib/src/controller/controller_event.dart b/lib/src/controller/controller_event.dart
new file mode 100644
index 0000000..f5ad5d6
--- /dev/null
+++ b/lib/src/controller/controller_event.dart
@@ -0,0 +1,15 @@
+import 'package:flutter_card_swiper/flutter_card_swiper.dart';
+
+abstract class ControllerEvent {
+ const ControllerEvent();
+}
+
+class ControllerSwipeEvent extends ControllerEvent {
+ final CardSwiperDirection direction;
+
+ const ControllerSwipeEvent(this.direction);
+}
+
+class ControllerUndoEvent extends ControllerEvent {
+ const ControllerUndoEvent();
+}
diff --git a/lib/src/enums.dart b/lib/src/enums.dart
index 80c89e0..3430fec 100644
--- a/lib/src/enums.dart
+++ b/lib/src/enums.dart
@@ -1,12 +1,3 @@
-enum CardSwiperState {
- swipe,
- swipeLeft,
- swipeRight,
- swipeTop,
- swipeBottom,
- undo
-}
-
enum CardSwiperDirection { none, left, right, top, bottom }
enum SwipeType { none, swipe, back, undo }
diff --git a/lib/src/widget/card_swiper.dart b/lib/src/widget/card_swiper.dart
index dac2ab6..5d129ff 100644
--- a/lib/src/widget/card_swiper.dart
+++ b/lib/src/widget/card_swiper.dart
@@ -3,7 +3,8 @@ import 'dart:math' as math;
import 'package:flutter/widgets.dart';
import 'package:flutter_card_swiper/src/card_animation.dart';
-import 'package:flutter_card_swiper/src/card_swiper_controller.dart';
+import 'package:flutter_card_swiper/src/controller/card_swiper_controller.dart';
+import 'package:flutter_card_swiper/src/controller/controller_event.dart';
import 'package:flutter_card_swiper/src/enums.dart';
import 'package:flutter_card_swiper/src/properties/allowed_swipe_direction.dart';
import 'package:flutter_card_swiper/src/typedefs.dart';
@@ -89,11 +90,6 @@ class CardSwiper extends StatefulWidget {
/// Callback function that is called when the swiper is disabled.
final CardSwiperOnTapDisabled? onTapDisabled;
- /// The direction in which the card is swiped when triggered by the [controller].
- ///
- /// Defaults to [CardSwiperDirection.right].
- final CardSwiperDirection direction;
-
/// Defined the directions in which the card is allowed to be swiped.
/// Defaults to [AllowedSwipeDirection.all]
final AllowedSwipeDirection allowedSwipeDirection;
@@ -142,7 +138,6 @@ class CardSwiper extends StatefulWidget {
this.onTapDisabled,
this.onSwipe,
this.onEnd,
- this.direction = CardSwiperDirection.right,
this.onSwipeDirectionChange,
this.allowedSwipeDirection = const AllowedSwipeDirection.all(),
this.isLoop = true,
@@ -158,10 +153,6 @@ class CardSwiper extends StatefulWidget {
threshold >= 1 && threshold <= 100,
'threshold must be between 1 and 100',
),
- assert(
- direction != CardSwiperDirection.none,
- 'direction must not be none',
- ),
assert(
scale >= 0 && scale <= 1,
'scale must be between 0 and 1',
diff --git a/lib/src/widget/card_swiper_state.dart b/lib/src/widget/card_swiper_state.dart
index 64befea..0b67448 100644
--- a/lib/src/widget/card_swiper_state.dart
+++ b/lib/src/widget/card_swiper_state.dart
@@ -26,7 +26,7 @@ class _CardSwiperState extends State
_undoableIndex.state = widget.initialIndex;
- widget.controller?.addListener(_controllerListener);
+ widget.controller?.events.listen(_controllerListener);
_animationController = AnimationController(
duration: widget.duration,
@@ -65,7 +65,7 @@ class _CardSwiperState extends State
@override
void dispose() {
_animationController.dispose();
- widget.controller?.removeListener(_controllerListener);
+ widget.controller?.dispose();
super.dispose();
}
@@ -157,23 +157,12 @@ class _CardSwiperState extends State
);
}
- void _controllerListener() {
- switch (widget.controller?.state) {
- case CardSwiperState.swipe:
- return _swipe(widget.direction);
- case CardSwiperState.swipeLeft:
- return _swipe(CardSwiperDirection.left);
- case CardSwiperState.swipeRight:
- return _swipe(CardSwiperDirection.right);
- case CardSwiperState.swipeTop:
- return _swipe(CardSwiperDirection.top);
- case CardSwiperState.swipeBottom:
- return _swipe(CardSwiperDirection.bottom);
- case CardSwiperState.undo:
- return _undo();
- default:
- return;
- }
+ void _controllerListener(ControllerEvent event) {
+ return switch (event) {
+ ControllerSwipeEvent(:final direction) => _swipe(direction),
+ ControllerUndoEvent() => _undo(),
+ _ => null
+ };
}
void _animationListener() {
@@ -225,7 +214,7 @@ class _CardSwiperState extends State
void _onEndAnimation() {
final direction = _getEndAnimationDirection();
- final isValidDirection = this._isValidDirection(direction);
+ final isValidDirection = _isValidDirection(direction);
if (isValidDirection) {
_swipe(direction);
diff --git a/test/card_swiper_controller_test.dart b/test/card_swiper_controller_test.dart
index f7109cb..958876a 100644
--- a/test/card_swiper_controller_test.dart
+++ b/test/card_swiper_controller_test.dart
@@ -1,4 +1,5 @@
import 'package:flutter_card_swiper/flutter_card_swiper.dart';
+import 'package:flutter_card_swiper/src/controller/controller_event.dart';
import 'package:flutter_test/flutter_test.dart';
import 'test_helpers/card_builder.dart';
@@ -7,334 +8,125 @@ import 'test_helpers/pump_app.dart';
void main() {
group('CardSwiperController', () {
- test('swipe() should change the state to swipe', () {
+ test('Swipe event adds ControllerSwipeEvent to the stream', () {
final controller = CardSwiperController();
- controller.swipe();
- expect(controller.state, CardSwiperState.swipe);
+ const direction = CardSwiperDirection.right;
+
+ expectLater(
+ controller.events,
+ emits(
+ isA()
+ .having((event) => event.direction, 'direction', direction),
+ ),
+ );
+
+ controller.swipe(direction);
});
- test('swipeLeft() should change the state to swipeLeft', () {
+ test('Undo event adds ControllerUndoEvent to the stream', () {
final controller = CardSwiperController();
- controller.swipeLeft();
- expect(controller.state, CardSwiperState.swipeLeft);
- });
- test('swipeRight() should change the state to swipeRight', () {
- final controller = CardSwiperController();
- controller.swipeRight();
- expect(controller.state, CardSwiperState.swipeRight);
- });
+ expectLater(
+ controller.events,
+ emits(isA()),
+ );
- test('swipeTop() should change the state to swipeTop', () {
- final controller = CardSwiperController();
- controller.swipeTop();
- expect(controller.state, CardSwiperState.swipeTop);
- });
-
- test('swipeBottom() should change the state to swipeBottom', () {
- final controller = CardSwiperController();
- controller.swipeBottom();
- expect(controller.state, CardSwiperState.swipeBottom);
- });
-
- test('undo() changes state to undo', () {
- final controller = CardSwiperController();
controller.undo();
- expect(controller.state, CardSwiperState.undo);
});
- for (final isDisabled in [false, true]) {
- group('isDisabled=$isDisabled', () {
- testWidgets('swipe() should swipe the card to the defined direction',
- (tester) async {
- final controller = CardSwiperController();
- var direction = CardSwiperDirection.none;
+ test('Dispose closes the stream', () {
+ final controller = CardSwiperController();
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- direction: CardSwiperDirection.top,
- onSwipe: (oldIndex, currentIndex, swipeDirection) {
- direction = swipeDirection;
- return true;
- },
- ),
- );
+ expect(controller.events.isBroadcast, isTrue);
- controller.swipe();
- await tester.pumpAndSettle();
+ controller.dispose();
- expect(direction, CardSwiperDirection.top);
- });
+ expect(
+ () => controller.swipe(CardSwiperDirection.left),
+ throwsStateError,
+ );
+ });
- testWidgets('swipeLeft() should swipe the card to the left',
- (tester) async {
- final controller = CardSwiperController();
- var direction = CardSwiperDirection.none;
+ for (final direction in [
+ CardSwiperDirection.left,
+ CardSwiperDirection.right,
+ CardSwiperDirection.top,
+ CardSwiperDirection.bottom,
+ ]) {
+ testWidgets('swipe([direction]) should swipe the card to the [direction]',
+ (tester) async {
+ final controller = CardSwiperController();
+ var detectedDirection = CardSwiperDirection.none;
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- direction: CardSwiperDirection.left,
- onSwipe: (oldIndex, currentIndex, swipeDirection) {
- direction = swipeDirection;
- return true;
- },
- ),
- );
+ await tester.pumpApp(
+ CardSwiper(
+ controller: controller,
+ cardsCount: 10,
+ cardBuilder: genericBuilder,
+ onSwipe: (oldIndex, currentIndex, swipeDirection) {
+ detectedDirection = swipeDirection;
+ return true;
+ },
+ ),
+ );
- controller.swipeLeft();
- await tester.pumpAndSettle();
+ controller.swipe(direction);
+ await tester.pumpAndSettle();
- expect(direction, CardSwiperDirection.left);
- });
+ expect(detectedDirection, direction);
+ });
- testWidgets('swipeRight() should swipe the card to the right',
- (tester) async {
- final controller = CardSwiperController();
- var direction = CardSwiperDirection.none;
+ testWidgets('undo() should undo the last swipe [direction]',
+ (tester) async {
+ final controller = CardSwiperController();
+ var detectedDirection = CardSwiperDirection.none;
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- onSwipe: (oldIndex, currentIndex, swipeDirection) {
- direction = swipeDirection;
- return true;
- },
- ),
- );
+ await tester.pumpApp(
+ CardSwiper(
+ controller: controller,
+ cardsCount: 10,
+ cardBuilder: genericBuilder,
+ onUndo: (_, __, swipeDirection) {
+ detectedDirection = swipeDirection;
+ return true;
+ },
+ ),
+ );
- controller.swipeRight();
- await tester.pumpAndSettle();
+ controller.swipe(direction);
+ await tester.pumpAndSettle();
- expect(direction, CardSwiperDirection.right);
- });
+ expect(find.card(1), findsOneWidget);
- testWidgets('swipeTop() should swipe the card to the top',
- (tester) async {
- final controller = CardSwiperController();
- var direction = CardSwiperDirection.none;
+ controller.undo();
+ await tester.pumpAndSettle();
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- direction: CardSwiperDirection.top,
- onSwipe: (oldIndex, currentIndex, swipeDirection) {
- direction = swipeDirection;
- return true;
- },
- ),
- );
-
- controller.swipeTop();
- await tester.pumpAndSettle();
-
- expect(direction, CardSwiperDirection.top);
- });
-
- testWidgets('swipeBottom() should swipe the card to the bottom',
- (tester) async {
- final controller = CardSwiperController();
- var direction = CardSwiperDirection.none;
-
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- direction: CardSwiperDirection.bottom,
- onSwipe: (oldIndex, currentIndex, swipeDirection) {
- direction = swipeDirection;
- return true;
- },
- ),
- );
-
- controller.swipeBottom();
- await tester.pumpAndSettle();
-
- expect(direction, CardSwiperDirection.bottom);
- });
-
- group('undo()', () {
- testWidgets('should undo the last swipe', (tester) async {
- final controller = CardSwiperController();
-
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- ),
- );
-
- controller.swipe();
- await tester.pumpAndSettle();
-
- expect(find.card(1), findsOneWidget);
-
- controller.undo();
- await tester.pumpAndSettle();
-
- expect(find.card(0), findsOneWidget);
- });
-
- testWidgets('should undo the last swipe left', (tester) async {
- final controller = CardSwiperController();
- var direction = CardSwiperDirection.none;
-
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- onUndo: (_, __, swipeDirection) {
- direction = swipeDirection;
- return true;
- },
- ),
- );
-
- controller.swipeLeft();
- await tester.pumpAndSettle();
-
- expect(find.card(1), findsOneWidget);
-
- controller.undo();
- await tester.pumpAndSettle();
-
- expect(find.card(0), findsOneWidget);
- expect(direction, CardSwiperDirection.left);
- });
-
- testWidgets('should undo the last swipe right', (tester) async {
- final controller = CardSwiperController();
- var direction = CardSwiperDirection.none;
-
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- onUndo: (_, __, swipeDirection) {
- direction = swipeDirection;
- return true;
- },
- ),
- );
-
- controller.swipeRight();
- await tester.pumpAndSettle();
-
- expect(find.card(1), findsOneWidget);
-
- controller.undo();
- await tester.pumpAndSettle();
-
- expect(find.card(0), findsOneWidget);
- expect(direction, CardSwiperDirection.right);
- });
-
- testWidgets('should undo the last swipe top', (tester) async {
- final controller = CardSwiperController();
- var direction = CardSwiperDirection.none;
-
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- onUndo: (_, __, swipeDirection) {
- direction = swipeDirection;
- return true;
- },
- ),
- );
-
- controller.swipeTop();
- await tester.pumpAndSettle();
-
- expect(find.card(1), findsOneWidget);
-
- controller.undo();
- await tester.pumpAndSettle();
-
- expect(find.card(0), findsOneWidget);
- expect(direction, CardSwiperDirection.top);
- });
-
- testWidgets('should undo the last swipe bottom', (tester) async {
- final controller = CardSwiperController();
- var direction = CardSwiperDirection.none;
-
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- onUndo: (_, __, swipeDirection) {
- direction = swipeDirection;
- return true;
- },
- ),
- );
-
- controller.swipeBottom();
- await tester.pumpAndSettle();
-
- expect(find.card(1), findsOneWidget);
-
- controller.undo();
- await tester.pumpAndSettle();
-
- expect(find.card(0), findsOneWidget);
- expect(direction, CardSwiperDirection.bottom);
- });
-
- testWidgets('should not undo if onUndo returns false',
- (tester) async {
- final controller = CardSwiperController();
-
- await tester.pumpApp(
- CardSwiper(
- isDisabled: isDisabled,
- controller: controller,
- cardsCount: 10,
- cardBuilder: genericBuilder,
- onUndo: (_, __, swipeDirection) {
- return false;
- },
- ),
- );
-
- controller.swipe();
- await tester.pumpAndSettle();
-
- controller.undo();
- await tester.pumpAndSettle();
-
- expect(find.card(0), findsNothing);
- });
- });
+ expect(find.card(0), findsOneWidget);
+ expect(detectedDirection, direction);
});
}
+
+ testWidgets('should not undo if onUndo returns false', (tester) async {
+ final controller = CardSwiperController();
+
+ await tester.pumpApp(
+ CardSwiper(
+ controller: controller,
+ cardsCount: 10,
+ cardBuilder: genericBuilder,
+ onUndo: (_, __, swipeDirection) {
+ return false;
+ },
+ ),
+ );
+
+ controller.swipe(CardSwiperDirection.left);
+ await tester.pumpAndSettle();
+
+ controller.undo();
+ await tester.pumpAndSettle();
+
+ expect(find.card(0), findsNothing);
+ });
});
}