Move word card feedback notification from bottom to top of screen (#4402)
* Initial plan * Replace bottom SnackBar with top overlay notification for word card feedback Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com> * auto-close top token feedback snackbar after delay --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com> Co-authored-by: ggurdin <ggurdin@gmail.com>
This commit is contained in:
parent
9be0dce1fb
commit
c4de304406
1 changed files with 120 additions and 23 deletions
|
|
@ -1,10 +1,13 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/bot/widgets/bot_face_svg.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/overlay.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/token_info_feedback/token_info_feedback_dialog.dart';
|
||||
import 'package:fluffychat/pangea/token_info_feedback/token_info_feedback_request.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class TokenInfoFeedbackButton extends StatelessWidget {
|
||||
final TokenInfoFeedbackRequestData requestData;
|
||||
|
|
@ -37,30 +40,20 @@ class TokenInfoFeedbackButton extends StatelessWidget {
|
|||
}
|
||||
|
||||
void _showSuccessSnackBar(String message, BuildContext context) {
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
messenger.showSnackBar(
|
||||
SnackBar(
|
||||
content: Row(
|
||||
children: [
|
||||
const BotFace(
|
||||
width: 30,
|
||||
expression: BotExpression.idle,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(message),
|
||||
),
|
||||
],
|
||||
),
|
||||
duration: const Duration(seconds: 30),
|
||||
action: SnackBarAction(
|
||||
label: L10n.of(context).close,
|
||||
onPressed: () {
|
||||
messenger.hideCurrentSnackBar();
|
||||
},
|
||||
),
|
||||
),
|
||||
OverlayUtil.showOverlay(
|
||||
overlayKey: "token_feedback_snackbar",
|
||||
context: context,
|
||||
child: _TokenFeedbackNotification(message: message),
|
||||
transformTargetId: '',
|
||||
position: OverlayPositionEnum.top,
|
||||
backDropToDismiss: false,
|
||||
closePrevOverlay: false,
|
||||
canPop: false,
|
||||
);
|
||||
|
||||
Future.delayed(const Duration(seconds: 10), () {
|
||||
MatrixState.pAnyState.closeOverlay("token_feedback_snackbar");
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -72,3 +65,107 @@ class TokenInfoFeedbackButton extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _TokenFeedbackNotification extends StatefulWidget {
|
||||
final String message;
|
||||
|
||||
const _TokenFeedbackNotification({
|
||||
required this.message,
|
||||
});
|
||||
|
||||
@override
|
||||
State<_TokenFeedbackNotification> createState() =>
|
||||
_TokenFeedbackNotificationState();
|
||||
}
|
||||
|
||||
class _TokenFeedbackNotificationState extends State<_TokenFeedbackNotification>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _slideController;
|
||||
late Animation<Offset> _slideAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_slideController = AnimationController(
|
||||
vsync: this,
|
||||
duration: FluffyThemes.animationDuration,
|
||||
);
|
||||
|
||||
_slideAnimation = Tween<Offset>(
|
||||
begin: const Offset(0, -1),
|
||||
end: Offset.zero,
|
||||
).animate(
|
||||
CurvedAnimation(
|
||||
parent: _slideController,
|
||||
curve: Curves.easeOut,
|
||||
),
|
||||
);
|
||||
|
||||
_slideController.forward();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_slideController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _close() async {
|
||||
await _slideController.reverse();
|
||||
if (mounted) {
|
||||
MatrixState.pAnyState.closeOverlay("token_feedback_snackbar");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: SlideTransition(
|
||||
position: _slideAnimation,
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(8.0),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 12.0,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withAlpha(51),
|
||||
blurRadius: 8.0,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const BotFace(
|
||||
width: 30,
|
||||
expression: BotExpression.idle,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
widget.message,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: _close,
|
||||
tooltip: L10n.of(context).close,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue