Merge branch 'swipe-to-reply' into 'main'

feat: Swipe to reply

Closes #129

See merge request ChristianPauly/fluffychat-flutter!208
This commit is contained in:
Christian Pauly 2020-10-17 09:15:55 +00:00
commit bd597d39c2
3 changed files with 70 additions and 37 deletions

View file

@ -28,6 +28,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:pedantic/pedantic.dart'; import 'package:pedantic/pedantic.dart';
import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:swipe_to_action/swipe_to_action.dart';
import '../components/dialogs/send_file_dialog.dart'; import '../components/dialogs/send_file_dialog.dart';
import '../components/input_bar.dart'; import '../components/input_bar.dart';
@ -343,9 +344,9 @@ class _ChatState extends State<_Chat> {
setState(() => selectedEvents.clear()); setState(() => selectedEvents.clear());
} }
void replyAction() { void replyAction({Event replyTo}) {
setState(() { setState(() {
replyEvent = selectedEvents.first; replyEvent = replyTo ?? selectedEvents.first;
selectedEvents.clear(); selectedEvents.clear();
}); });
inputFocus.requestFocus(); inputFocus.requestFocus();
@ -668,43 +669,67 @@ class _ChatState extends State<_Chat> {
key: ValueKey(i - 1), key: ValueKey(i - 1),
index: i - 1, index: i - 1,
controller: _scrollController, controller: _scrollController,
child: Message(filteredEvents[i - 1], child: Swipeable(
onAvatarTab: (Event event) { key: ValueKey(
sendController.text += filteredEvents[i - 1].eventId),
' ${event.senderId}'; background: Container(
}, color: Theme.of(context)
onSelect: (Event event) { .primaryColor
if (!event.redacted) { .withAlpha(100),
if (selectedEvents padding: EdgeInsets.symmetric(
.contains(event)) { horizontal: 12.0),
setState( alignment: Alignment.centerLeft,
() => selectedEvents child: Row(
.remove(event), children: [
); Icon(Icons.reply),
} else { SizedBox(width: 2.0),
setState( Text(L10n.of(context).reply)
() => ],
selectedEvents.add(event), ),
),
direction: SwipeDirection.startToEnd,
onSwipe: (direction) {
replyAction(
replyTo: filteredEvents[i - 1]);
},
child: Message(filteredEvents[i - 1],
onAvatarTab: (Event event) {
sendController.text +=
' ${event.senderId}';
},
onSelect: (Event event) {
if (!event.redacted) {
if (selectedEvents
.contains(event)) {
setState(
() => selectedEvents
.remove(event),
);
} else {
setState(
() => selectedEvents
.add(event),
);
}
selectedEvents.sort(
(a, b) => a.originServerTs
.compareTo(
b.originServerTs),
); );
} }
selectedEvents.sort( },
(a, b) => a.originServerTs scrollToEventId: (String eventId) =>
.compareTo( _scrollToEventId(eventId,
b.originServerTs), context: context),
); longPressSelect:
} selectedEvents.isEmpty,
}, selected: selectedEvents.contains(
scrollToEventId: (String eventId) => filteredEvents[i - 1]),
_scrollToEventId(eventId, timeline: timeline,
context: context), nextEvent: i >= 2
longPressSelect: ? filteredEvents[i - 2]
selectedEvents.isEmpty, : null),
selected: selectedEvents ),
.contains(filteredEvents[i - 1]),
timeline: timeline,
nextEvent: i >= 2
? filteredEvents[i - 2]
: null),
); );
}); });
}, },

View file

@ -877,6 +877,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0-nullsafety.1" version: "1.1.0-nullsafety.1"
swipe_to_action:
dependency: "direct main"
description:
name: swipe_to_action
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0"
synchronized: synchronized:
dependency: transitive dependency: transitive
description: description:

View file

@ -70,6 +70,7 @@ dependencies:
flutter_blurhash: ^0.5.0 flutter_blurhash: ^0.5.0
sentry: ">=3.0.0 <4.0.0" sentry: ">=3.0.0 <4.0.0"
scroll_to_index: ^1.0.6 scroll_to_index: ^1.0.6
swipe_to_action: ^0.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: