import 'dart:async'; import 'package:drift/drift.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/database/daos/contacts.dao.dart'; import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/views/components/alert_dialog.dart'; import 'package:twonly/src/views/components/avatar_icon.component.dart'; import 'package:twonly/src/views/components/better_list_title.dart'; import 'package:twonly/src/views/components/flame.dart'; import 'package:twonly/src/views/components/max_flame_list_title.dart'; import 'package:twonly/src/views/components/select_chat_deletion_time.comp.dart'; import 'package:twonly/src/views/components/verified_shield.dart'; import 'package:twonly/src/views/groups/group.view.dart'; import 'package:twonly/src/views/public_profile.view.dart'; class ContactView extends StatefulWidget { const ContactView(this.userId, {super.key}); final int userId; @override State createState() => _ContactViewState(); } class _ContactViewState extends State { Future handleUserRemoveRequest(Contact contact) async { final remove = await showAlertDialog( context, context.lang .contactRemoveTitle(getContactDisplayName(contact, maxLength: 20)), context.lang.contactRemoveBody, ); if (remove) { await twonlyDB.contactsDao.updateContact( contact.userId, const ContactsCompanion( accepted: Value(false), requested: Value(false), deletedByUser: Value(true), ), ); if (mounted) { Navigator.popUntil(context, (route) => route.isFirst); } } } Future handleUserBlockRequest(Contact contact) async { final block = await showAlertDialog( context, context.lang.contactBlockTitle(getContactDisplayName(contact)), context.lang.contactBlockBody, ); if (block) { const update = ContactsCompanion(blocked: Value(true)); if (context.mounted) { await twonlyDB.contactsDao.updateContact(contact.userId, update); } if (mounted) { Navigator.popUntil(context, (route) => route.isFirst); } } } Future handleReportUser(Contact contact) async { final reason = await showReportDialog(context, contact); if (reason == null) return; final res = await apiService.reportUser(contact.userId, reason); if (!mounted) return; if (res.isSuccess) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(context.lang.userGotReported), duration: const Duration(seconds: 3), ), ); } else { showNetworkIssue(context); } } @override Widget build(BuildContext context) { final contact = twonlyDB.contactsDao .getContactByUserId(widget.userId) .watchSingleOrNull(); return Scaffold( appBar: AppBar( title: const Text(''), ), body: StreamBuilder( stream: contact, builder: (context, snapshot) { if (!snapshot.hasData || snapshot.data == null) { return Container(); } final contact = snapshot.data!; return ListView( key: ValueKey(contact.userId), children: [ Padding( padding: const EdgeInsets.all(10), child: AvatarIcon(contactId: contact.userId, fontSize: 30), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only(right: 10), child: VerifiedShield( key: GlobalKey(), contact: contact, ), ), Text( getContactDisplayName(contact, maxLength: 20), style: const TextStyle(fontSize: 20), ), FlameCounterWidget( contactId: contact.userId, prefix: true, ), ], ), if (getContactDisplayName(contact) != contact.username) Center(child: Text('(${contact.username})')), const SizedBox(height: 50), BetterListTile( icon: FontAwesomeIcons.pencil, text: context.lang.contactNickname, onTap: () async { final nickName = await showNicknameChangeDialog(context, contact); if (context.mounted && nickName != null && nickName != '') { final update = ContactsCompanion(nickName: Value(nickName)); await twonlyDB.contactsDao .updateContact(contact.userId, update); } }, ), const Divider(), SelectChatDeletionTimeListTitle( groupId: getUUIDforDirectChat(widget.userId, gUser.userId), ), const Divider(), MaxFlameListTitle( contactId: widget.userId, ), BetterListTile( icon: FontAwesomeIcons.shieldHeart, text: context.lang.contactVerifyNumberTitle, onTap: () async { await Navigator.push( context, MaterialPageRoute( builder: (context) { return const PublicProfileView(); }, ), ); setState(() {}); }, ), // BetterListTile( // icon: FontAwesomeIcons.eraser, // iconSize: 16, // text: context.lang.deleteAllContactMessages, // onTap: () async { // final block = await showAlertDialog( // context, // context.lang.deleteAllContactMessages, // context.lang.deleteAllContactMessagesBody( // getContactDisplayName(contact), // ), // ); // if (block) { // if (context.mounted) { // await twonlyDB.messagesDao // .deleteMessagesByContactId(contact.userId); // } // } // }, // ), BetterListTile( icon: FontAwesomeIcons.flag, text: context.lang.reportUser, onTap: () => handleReportUser(contact), ), BetterListTile( icon: FontAwesomeIcons.ban, text: context.lang.contactBlock, onTap: () => handleUserBlockRequest(contact), ), // BetterListTile( // icon: FontAwesomeIcons.userMinus, // iconSize: 16, // color: Colors.red, // text: context.lang.contactRemove, // onTap: () => handleUserRemoveRequest(contact), // ), ], ); }, ), ); } } Future showNicknameChangeDialog( BuildContext context, Contact contact, ) { final controller = TextEditingController(text: getContactDisplayName(contact)); return showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text(context.lang.contactNickname), content: TextField( controller: controller, autofocus: true, decoration: InputDecoration(hintText: context.lang.contactNicknameNew), ), actions: [ TextButton( child: Text(context.lang.cancel), onPressed: () { Navigator.of(context).pop(); // Close the dialog }, ), TextButton( child: Text(context.lang.ok), onPressed: () { Navigator.of(context) .pop(controller.text); // Return the input text }, ), ], ); }, ); } Future showReportDialog( BuildContext context, Contact contact, ) { final controller = TextEditingController(); return showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text(context.lang.reportUserTitle(getContactDisplayName(contact))), content: TextField( controller: controller, autofocus: true, decoration: InputDecoration(hintText: context.lang.reportUserReason), ), actions: [ TextButton( child: Text(context.lang.cancel), onPressed: () { Navigator.of(context).pop(); }, ), TextButton( child: Text(context.lang.ok), onPressed: () { Navigator.of(context).pop(controller.text); }, ), ], ); }, ); }