From d7a35beb3aef15bad7c5e0600009183baf29098c Mon Sep 17 00:00:00 2001 From: zoe Date: Thu, 29 Sep 2022 19:44:01 +0200 Subject: [PATCH] chat bubble time --- lib/business_logic/posts/posts.dart | 1 + lib/business_logic/posts/sdfsdfdsf.json | 0 lib/dialogues/chatwindow.dart | 159 ++++++++++++++++++++++++ lib/pages/chat/chat.dart | 108 ++++++++++------ 4 files changed, 231 insertions(+), 37 deletions(-) delete mode 100644 lib/business_logic/posts/sdfsdfdsf.json create mode 100644 lib/dialogues/chatwindow.dart diff --git a/lib/business_logic/posts/posts.dart b/lib/business_logic/posts/posts.dart index 6659b67..fa57971 100644 --- a/lib/business_logic/posts/posts.dart +++ b/lib/business_logic/posts/posts.dart @@ -26,6 +26,7 @@ Future> getContextForPost(PostModel model) async { if (r.statusCode != 200) { return MapEntry(r.statusCode, null); } + print(r.body); final json = jsonDecode(r.body); List ancestors = json["ancestors"]!; diff --git a/lib/business_logic/posts/sdfsdfdsf.json b/lib/business_logic/posts/sdfsdfdsf.json deleted file mode 100644 index e69de29..0000000 diff --git a/lib/dialogues/chatwindow.dart b/lib/dialogues/chatwindow.dart new file mode 100644 index 0000000..c747878 --- /dev/null +++ b/lib/dialogues/chatwindow.dart @@ -0,0 +1,159 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:loris/business_logic/chat/chat.dart'; +import 'package:loris/business_logic/posts/posts.dart'; +import 'package:loris/business_logic/timeline/timeline.dart'; +import 'package:loris/global.dart' as global; +import 'package:loris/partials/post.dart'; +import 'package:loris/partials/post_text_renderer.dart'; +import 'package:loris/themes/themes.dart' as themes; + +class Chatwindow extends StatefulWidget { + const Chatwindow({super.key, required this.model}); + final ConversationModel model; + + @override + State createState() => _ChatwindowState(); +} + +class _ChatwindowState extends State { + List models = []; + + Future loadContext(PostModel m) async { + final c = await getContextForPost(m); + if (c.key == 200 && mounted) { + setState(() { + print(c.value!.ancestors); + models = c.value!.ancestors + + [widget.model.lastStatus!] + + c.value!.descendants; + }); + print(models); + } + } + + @override + void initState() { + if (widget.model.lastStatus != null) loadContext(widget.model.lastStatus!); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return BackdropFilter( + filter: + ImageFilter.blur(sigmaX: 10, sigmaY: 10, tileMode: TileMode.mirror), + child: SimpleDialog( + contentPadding: const EdgeInsets.all(0), + backgroundColor: Theme.of(context).colorScheme.surface, + children: [ + Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.background, + borderRadius: const BorderRadius.all(themes.defaultRadius)), + width: global.getWidth(context), + constraints: global.getConstraints(context), + height: MediaQuery.of(context).size.height * 2 / 3, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Flexible( + child: ListView.separated( + shrinkWrap: true, + itemBuilder: (context, index) => + DirectMessage(model: models[index]), + separatorBuilder: (context, index) => const Divider( + color: Colors.transparent, + height: themes.defaultSeperatorHeight, + ), + itemCount: models.length), + ), + Container( + padding: themes.defaultInsideMargins, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.only( + bottomLeft: themes.defaultRadius, + bottomRight: themes.defaultRadius, + topLeft: Radius.circular(0), + topRight: Radius.circular(0)), + border: Border.fromBorderSide(BorderSide( + color: Theme.of(context).colorScheme.secondary, + width: 2, + )), + ), + child: TextField( + minLines: 1, + maxLines: 4, + style: Theme.of(context).textTheme.bodyMedium, + expands: false, + decoration: InputDecoration( + suffix: Wrap( + direction: Axis.horizontal, + alignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + IconButton( + onPressed: () {}, + icon: const Icon(Icons.attach_file)), + IconButton( + onPressed: () {}, + icon: const Icon(Icons.send), + ), + ], + ), + ), + ), + ), + ], + ), + ) + ], + )); + } +} + +class DirectMessage extends StatefulWidget { + const DirectMessage({super.key, required this.model}); + final PostModel model; + + @override + State createState() => _DirectMessageState(); +} + +class _DirectMessageState extends State { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(themes.defaultSeperatorHeight * 2), + child: Align( + alignment: (widget.model.identity == + "${widget.model.account.acct}@${global.settings!.identities[widget.model.identity]!.instanceUrl}") + ? Alignment.centerRight + : Alignment.centerLeft, + child: LayoutBuilder(builder: ((ctx, constraints) { + return Container( + constraints: BoxConstraints(maxWidth: constraints.maxWidth * 0.96), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + border: Border.all( + color: Theme.of(context).colorScheme.secondary, + width: 2, + ), + borderRadius: const BorderRadius.all(themes.defaultRadius)), + padding: themes.defaultInsideMargins, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DisplayName(account: widget.model.account), + PostTextRenderer(input: widget.model.content), + ], + ), + ); + })), + ), + ); + } +} diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index dbe9b2f..4dbf1ee 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:localization/localization.dart'; import 'package:loris/business_logic/chat/chat.dart'; +import 'package:loris/dialogues/chatwindow.dart'; import 'package:loris/partials/loadingbox.dart'; import 'package:loris/partials/post_text_renderer.dart'; import 'package:loris/themes/themes.dart' as themes; @@ -62,7 +63,15 @@ class _ChatState extends State { if (index >= conversations.length) return const LoadingBox(); return ConversationButton( model: conversations[index], - onPressed: () {}, + onTap: () { + showDialog( + barrierColor: Colors.transparent, + context: context, + builder: (context) => Chatwindow( + model: conversations[index], + ), + ); + }, ); }), separatorBuilder: (context, index) => const Divider( @@ -86,53 +95,59 @@ class ConversationButton extends StatelessWidget { const ConversationButton({ super.key, required this.model, - required this.onPressed, + required this.onTap, }); final ConversationModel model; - final void Function() onPressed; + final void Function() onTap; @override Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(themes.defaultRadius), - border: Border.fromBorderSide(BorderSide( - color: Theme.of(context).colorScheme.secondary, width: 2)), - ), - margin: const EdgeInsets.fromLTRB(themes.defaultSeperatorHeight * 2, 0, - themes.defaultSeperatorHeight * 2, 0), - width: global.getWidth(context), - constraints: global.getConstraints(context), - child: InkWell( - borderRadius: const BorderRadius.all(themes.defaultRadius), - onTap: onPressed, - child: Ink( - decoration: BoxDecoration( + return Align( + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(themes.defaultRadius), + color: Theme.of(context).colorScheme.surface, + ), + margin: const EdgeInsets.fromLTRB(themes.defaultSeperatorHeight * 2, 0, + themes.defaultSeperatorHeight * 2, 0), + width: global.getWidth(context), + constraints: global.getConstraints(context), + child: Material( + borderOnForeground: true, + shape: RoundedRectangleBorder( borderRadius: const BorderRadius.all(themes.defaultRadius), - color: Theme.of(context).colorScheme.surface, + side: BorderSide( + color: Theme.of(context).colorScheme.secondary, width: 2), ), - child: Padding( - padding: themes.defaultInsideMargins, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - if (model.unread) + child: InkWell( + borderRadius: const BorderRadius.all(themes.defaultRadius), + onTap: onTap, + child: Padding( + padding: themes.defaultInsideMargins, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Icon(Icons.mark_chat_unread), - SelectableText("unread".i18n()) + ElevatedButton.icon( + onPressed: onTap, + icon: const Icon(Icons.open_in_full), + label: Text("show".i18n())), + if (model.unread) const UnreadIndicator(), ], ), - Wrap( - alignment: WrapAlignment.spaceBetween, - children: [ - if (model.unread) SelectableText(model.getAccountsString()), - SelectableText("${"you-are".i18n()} ${model.identity}"), - ], - ), - if (model.lastStatus != null) - PostTextRenderer(input: model.lastStatus!.content), - ], + Wrap( + alignment: WrapAlignment.spaceBetween, + children: [ + SelectableText(model.getAccountsString()), + SelectableText("${"you-are".i18n()} ${model.identity}"), + ], + ), + if (model.lastStatus != null) + PostTextRenderer(input: model.lastStatus!.content), + ], + ), ), ), ), @@ -140,3 +155,22 @@ class ConversationButton extends StatelessWidget { ); } } + +class UnreadIndicator extends StatefulWidget { + const UnreadIndicator({super.key}); + + @override + State createState() => _UnreadIndicatorState(); +} + +class _UnreadIndicatorState extends State { + @override + Widget build(BuildContext context) { + return Row( + children: [ + const Icon(Icons.mark_unread_chat_alt), + SelectableText("unread".i18n()) + ], + ); + } +}