forked from cwtch.im/cwtch-ui
Merge pull request 'Add Physics to Message Row. Fixes: #132' (#151) from animate into trunk
Reviewed-on: cwtch.im/cwtch-ui#151 Reviewed-by: erinn <erinn@openprivacy.ca>
This commit is contained in:
commit
004e211d0b
|
@ -5,6 +5,7 @@ import 'package:cwtch/models/message.dart';
|
||||||
import 'package:cwtch/views/contactsview.dart';
|
import 'package:cwtch/views/contactsview.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cwtch/widgets/profileimage.dart';
|
import 'package:cwtch/widgets/profileimage.dart';
|
||||||
|
import 'package:flutter/physics.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
@ -20,9 +21,31 @@ class MessageRow extends StatefulWidget {
|
||||||
MessageRowState createState() => MessageRowState();
|
MessageRowState createState() => MessageRowState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageRowState extends State<MessageRow> {
|
class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMixin {
|
||||||
bool showMenu = false;
|
bool showMenu = false;
|
||||||
bool showBlockedMessage = false;
|
bool showBlockedMessage = false;
|
||||||
|
late AnimationController _controller;
|
||||||
|
late Animation<Alignment> _animation;
|
||||||
|
late Alignment _dragAlignment = Alignment.center;
|
||||||
|
Alignment _dragAffinity = Alignment.center;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(vsync: this);
|
||||||
|
_controller.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
_dragAlignment = _animation.value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var fromMe = Provider.of<MessageMetadata>(context).senderHandle == Provider.of<ProfileInfoState>(context).onion;
|
var fromMe = Provider.of<MessageMetadata>(context).senderHandle == Provider.of<ProfileInfoState>(context).onion;
|
||||||
|
@ -30,6 +53,12 @@ class MessageRowState extends State<MessageRow> {
|
||||||
var isBlocked = isContact ? Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageMetadata>(context).senderHandle)!.isBlocked : false;
|
var isBlocked = isContact ? Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageMetadata>(context).senderHandle)!.isBlocked : false;
|
||||||
var actualMessage = Flexible(flex: 3, fit: FlexFit.loose, child: widget.child);
|
var actualMessage = Flexible(flex: 3, fit: FlexFit.loose, child: widget.child);
|
||||||
|
|
||||||
|
_dragAffinity = fromMe ? Alignment.centerRight : Alignment.centerLeft;
|
||||||
|
|
||||||
|
if (_dragAlignment == Alignment.center) {
|
||||||
|
_dragAlignment = fromMe ? Alignment.centerRight : Alignment.centerLeft;
|
||||||
|
}
|
||||||
|
|
||||||
var senderDisplayStr = "";
|
var senderDisplayStr = "";
|
||||||
if (!fromMe) {
|
if (!fromMe) {
|
||||||
ContactInfoState? contact = Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageMetadata>(context).senderHandle);
|
ContactInfoState? contact = Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageMetadata>(context).senderHandle);
|
||||||
|
@ -52,7 +81,7 @@ class MessageRowState extends State<MessageRow> {
|
||||||
Provider.of<AppState>(context, listen: false).selectedIndex = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
|
Provider.of<AppState>(context, listen: false).selectedIndex = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.reply, color: Provider.of<Settings>(context).theme.dropShadowColor())));
|
icon: Icon(Icons.reply, color: Provider.of<Settings>(context).theme.dropShadowColor())));
|
||||||
Widget wdgSpacer = Expanded(child: SizedBox(width: 60, height: 10));
|
Widget wdgSpacer = Flexible(child: SizedBox(width: 60, height: 10));
|
||||||
var widgetRow = <Widget>[];
|
var widgetRow = <Widget>[];
|
||||||
|
|
||||||
if (fromMe) {
|
if (fromMe) {
|
||||||
|
@ -131,10 +160,9 @@ class MessageRowState extends State<MessageRow> {
|
||||||
wdgSpacer,
|
wdgSpacer,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
var size = MediaQuery.of(context).size;
|
||||||
return MouseRegion(
|
return MouseRegion(
|
||||||
// For desktop...
|
// For desktop...
|
||||||
|
|
||||||
onHover: (event) {
|
onHover: (event) {
|
||||||
setState(() {
|
setState(() {
|
||||||
this.showMenu = true;
|
this.showMenu = true;
|
||||||
|
@ -146,14 +174,55 @@ class MessageRowState extends State<MessageRow> {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
|
onPanUpdate: (details) {
|
||||||
|
setState(() {
|
||||||
|
_dragAlignment += Alignment(
|
||||||
|
details.delta.dx / (size.width * 0.5),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onPanDown: (details) {
|
||||||
|
_controller.stop();
|
||||||
|
},
|
||||||
|
onPanEnd: (details) {
|
||||||
|
_runAnimation(details.velocity.pixelsPerSecond, size);
|
||||||
|
Provider.of<AppState>(context, listen: false).selectedIndex = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(2),
|
||||||
|
child: Align(
|
||||||
|
widthFactor: 1,
|
||||||
|
alignment: _dragAlignment,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: widgetRow,
|
||||||
|
)))));
|
||||||
|
}
|
||||||
|
|
||||||
// Swipe to quote on Android
|
void _runAnimation(Offset pixelsPerSecond, Size size) {
|
||||||
onHorizontalDragEnd: Platform.isAndroid
|
_animation = _controller.drive(
|
||||||
? (details) {
|
AlignmentTween(
|
||||||
Provider.of<AppState>(context, listen: false).selectedIndex = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
|
begin: _dragAlignment,
|
||||||
}
|
end: _dragAffinity,
|
||||||
: null,
|
),
|
||||||
child: Padding(padding: EdgeInsets.all(2), child: Row(mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start, children: widgetRow))));
|
);
|
||||||
|
// Calculate the velocity relative to the unit interval, [0,1],
|
||||||
|
// used by the animation controller.
|
||||||
|
final unitsPerSecondX = pixelsPerSecond.dx / size.width;
|
||||||
|
final unitsPerSecondY = pixelsPerSecond.dy / size.height;
|
||||||
|
final unitsPerSecond = Offset(unitsPerSecondX, unitsPerSecondY);
|
||||||
|
final unitVelocity = unitsPerSecond.distance;
|
||||||
|
|
||||||
|
const spring = SpringDescription(
|
||||||
|
mass: 30,
|
||||||
|
stiffness: 1,
|
||||||
|
damping: 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
final simulation = SpringSimulation(spring, 0, 1, -unitVelocity);
|
||||||
|
_controller.animateWith(simulation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _btnGoto() {
|
void _btnGoto() {
|
||||||
|
|
Loading…
Reference in New Issue