import 'package:flutter/material.dart'; import 'package:localization/localization.dart'; import 'package:loris/business_logic/chat/chat.dart'; import 'package:loris/dialogues/full_post_view.dart'; import 'package:loris/dialogues/profile_view.dart'; import 'package:loris/partials/loadingbox.dart'; import 'package:loris/partials/post.dart'; import 'package:loris/partials/post_text_renderer.dart'; import 'package:loris/themes/themes.dart' as themes; import 'package:loris/global.dart' as global; class Chat extends StatefulWidget { const Chat({super.key}); @override State createState() => _ChatState(); } class _ChatState extends State { List conversations = []; // map that stores max ids for each identity Map maxIds = {}; final scrollController = ScrollController(); bool loading = false; // loads more conversations and properly stores all ids Future updateConversations() async { if (loading) return; loading = true; final models = await getAllConversationModels(maxIds); setState(() { conversations.addAll(models.models); maxIds = models.maxIds; }); loading = false; } @override void initState() { updateConversations(); scrollController.addListener(() { if (scrollController.position.maxScrollExtent - scrollController.offset < MediaQuery.of(context).size.height) { updateConversations(); } }); super.initState(); } @override void dispose() { scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Column( children: [ Expanded( child: ListView.separated( controller: scrollController, shrinkWrap: true, itemBuilder: ((context, index) { if (index >= conversations.length) return const LoadingBox(); return ConversationButton( model: conversations[index], onTap: () { showDialog( barrierColor: Colors.transparent, context: context, builder: (context) { final con = conversations[index]; if (con.lastStatus != null) { return FullPostView( originPostModel: con.lastStatus!); } return ProfileView(model: con.accounts.first); }); }, ); }), separatorBuilder: (context, index) => const Divider( height: themes.defaultSeperatorHeight, color: Colors.transparent, ), itemCount: conversations.length + 1), ), Container( decoration: BoxDecoration( border: Border( top: BorderSide( color: Theme.of(context).colorScheme.primary, width: 2))), ), ], ); } } class ConversationButton extends StatelessWidget { const ConversationButton({ super.key, required this.model, required this.onTap, }); final ConversationModel model; final void Function() onTap; @override Widget build(BuildContext context) { final List people = []; for (var p in model.accounts) { people.add(DisplayName(account: p)); } 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), side: BorderSide( color: Theme.of(context).colorScheme.secondary, width: 2), ), child: InkWell( borderRadius: const BorderRadius.all(themes.defaultRadius), onTap: onTap, child: Padding( padding: themes.defaultInsideMargins, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: people + [ Divider( color: Theme.of(context).hintColor, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ 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: [ SelectableText(model.getAccountsString()), SelectableText( "${"you-are".i18n()} ${model.identity}"), ], ), if (model.lastStatus != null) PostTextRenderer( input: model.lastStatus!.content, identityName: model.identity, ), ], ), ), ), ), ), ); } } 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()) ], ); } }