LCOV - code coverage report
Current view: top level - lib/views - addcontactview.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 124 0.0 %
Date: 2024-08-22 16:58:37 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:cwtch/cwtch_icons_icons.dart';
       2             : import 'package:cwtch/models/profile.dart';
       3             : import 'package:cwtch/models/remoteserver.dart';
       4             : import 'package:flutter/material.dart';
       5             : import 'package:flutter/services.dart';
       6             : import 'package:cwtch/errorHandler.dart';
       7             : import 'package:cwtch/settings.dart';
       8             : import 'package:cwtch/widgets/buttontextfield.dart';
       9             : import 'package:cwtch/widgets/cwtchlabel.dart';
      10             : import 'package:cwtch/widgets/textfield.dart';
      11             : import 'package:flutter_gen/gen_l10n/app_localizations.dart';
      12             : import 'package:provider/provider.dart';
      13             : 
      14             : import '../main.dart';
      15             : 
      16             : /// Add Contact View is the one-stop shop for adding public keys to a Profiles contact list.
      17             : /// We support both Peers and Groups (experiment-pending).
      18             : /// NOTE: This view makes use of the global Error Handler to receive events from the Cwtch Library (for validating
      19             : /// error states caused by incorrect import string or duplicate requests to add a specific contact)
      20             : class AddContactView extends StatefulWidget {
      21             :   final newGroup;
      22             : 
      23           0 :   const AddContactView({Key? key, this.newGroup}) : super(key: key);
      24             : 
      25           0 :   @override
      26           0 :   _AddContactViewState createState() => _AddContactViewState();
      27             : }
      28             : 
      29             : class _AddContactViewState extends State<AddContactView> {
      30             :   final _formKey = GlobalKey<FormState>();
      31             :   final _createGroupFormKey = GlobalKey<FormState>();
      32             :   final ctrlrOnion = TextEditingController(text: "");
      33             :   final ctrlrContact = TextEditingController(text: "");
      34             :   final ctrlrGroupName = TextEditingController(text: "");
      35             :   String server = "";
      36             :   // flutter textfield onChange often fires twice and since we need contexts, we can't easily use a controler/listener
      37             :   String lastContactValue = "";
      38             :   bool failedImport = false;
      39             : 
      40           0 :   @override
      41             :   Widget build(BuildContext context) {
      42             :     //  if we haven't picked a server yet, pick the first one in the list...
      43           0 :     if (server.isEmpty && Provider.of<ProfileInfoState>(context).serverList.servers.isNotEmpty) {
      44           0 :       server = Provider.of<ProfileInfoState>(context).serverList.servers.first.onion;
      45             :     }
      46             : 
      47           0 :     return Scaffold(
      48           0 :       appBar: AppBar(
      49           0 :         title: Text(AppLocalizations.of(context)!.titleManageContacts),
      50             :       ),
      51           0 :       body: _buildForm(),
      52             :     );
      53             :   }
      54             : 
      55           0 :   Widget _buildForm() {
      56           0 :     ctrlrOnion.text = Provider.of<ProfileInfoState>(context).onion;
      57             : 
      58             :     /// We display a different number of tabs depending on the experiment setup
      59           0 :     bool groupsEnabled = Provider.of<Settings>(context, listen: false).isExperimentEnabled(TapirGroupsExperiment);
      60           0 :     return Consumer<ErrorHandler>(builder: (bcontext, globalErrorHandler, child) {
      61           0 :       return DefaultTabController(
      62           0 :           initialIndex: widget.newGroup && groupsEnabled ? 1 : 0,
      63             :           length: groupsEnabled ? 2 : 1,
      64           0 :           child: Column(children: [
      65           0 :             (groupsEnabled ? getTabBarWithGroups() : getTabBarWithAddPeerOnly()),
      66           0 :             Expanded(
      67           0 :                 child: TabBarView(
      68             :               children: (groupsEnabled
      69           0 :                   ? [
      70           0 :                       addPeerTab(bcontext),
      71           0 :                       addGroupTab(bcontext),
      72             :                     ]
      73           0 :                   : [addPeerTab(bcontext)]),
      74             :             )),
      75             :           ]));
      76             :     });
      77             :   }
      78             : 
      79           0 :   void _copyOnion() {
      80           0 :     Clipboard.setData(new ClipboardData(text: Provider.of<ProfileInfoState>(context, listen: false).onion));
      81           0 :     final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.copiedToClipboardNotification));
      82           0 :     ScaffoldMessenger.of(context).showSnackBar(snackBar);
      83             :   }
      84             : 
      85             :   /// A Tab Bar with only the Add Peer Tab
      86           0 :   TabBar getTabBarWithAddPeerOnly() {
      87           0 :     return TabBar(
      88           0 :       tabs: [
      89           0 :         Tab(
      90           0 :           icon: Icon(CwtchIcons.add_peer),
      91           0 :           text: AppLocalizations.of(context)!.addPeer,
      92             :         ),
      93             :       ],
      94             :     );
      95             :   }
      96             : 
      97             :   /// The full tab bar with Join and Add Groups
      98           0 :   TabBar getTabBarWithGroups() {
      99           0 :     return TabBar(
     100           0 :       tabs: [
     101           0 :         Tab(
     102           0 :           icon: Icon(CwtchIcons.add_peer),
     103           0 :           text: AppLocalizations.of(context)!.tooltipAddContact,
     104             :         ),
     105             :         //Tab(icon: Icon(Icons.backup), text: AppLocalizations.of(context)!.titleManageServers),
     106           0 :         Tab(icon: Icon(CwtchIcons.add_group), text: AppLocalizations.of(context)!.createGroup),
     107             :       ],
     108             :     );
     109             :   }
     110             : 
     111             :   /// The Add Peer Tab allows a peer to add a specific non-group peer to their contact lists
     112             :   /// We also provide a convenient way to copy their onion.
     113           0 :   Widget addPeerTab(bcontext) {
     114           0 :     ScrollController controller = ScrollController();
     115           0 :     return Scrollbar(
     116             :         controller: controller,
     117           0 :         child: SingleChildScrollView(
     118             :             clipBehavior: Clip.antiAlias,
     119             :             controller: controller,
     120           0 :             child: Container(
     121           0 :                 margin: EdgeInsets.all(30),
     122           0 :                 padding: EdgeInsets.all(20),
     123           0 :                 child: Form(
     124             :                     autovalidateMode: AutovalidateMode.always,
     125           0 :                     key: _formKey,
     126           0 :                     child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
     127           0 :                       CwtchLabel(label: AppLocalizations.of(context)!.profileOnionLabel),
     128           0 :                       SizedBox(
     129             :                         height: 20,
     130             :                       ),
     131           0 :                       CwtchButtonTextField(
     132           0 :                         controller: ctrlrOnion,
     133           0 :                         onPressed: _copyOnion,
     134             :                         readonly: true,
     135           0 :                         icon: Icon(
     136             :                           CwtchIcons.address_copy,
     137             :                           size: 32,
     138             :                         ),
     139           0 :                         tooltip: AppLocalizations.of(context)!.copyBtn,
     140             :                       ),
     141           0 :                       SizedBox(
     142             :                         height: 20,
     143             :                       ),
     144           0 :                       CwtchLabel(label: AppLocalizations.of(context)!.pasteAddressToAddContact),
     145           0 :                       SizedBox(
     146             :                         height: 20,
     147             :                       ),
     148           0 :                       CwtchTextField(
     149           0 :                         key: Key("txtAddP2P"),
     150           0 :                         controller: ctrlrContact,
     151           0 :                         validator: (value) {
     152           0 :                           if (value == "") {
     153             :                             return null;
     154             :                           }
     155           0 :                           if (failedImport) {
     156           0 :                             return AppLocalizations.of(context)!.invalidImportString;
     157             :                           }
     158             :                           return null;
     159             :                         },
     160           0 :                         onChanged: (String importBundle) async {
     161           0 :                           if (lastContactValue != importBundle) {
     162           0 :                             lastContactValue = importBundle;
     163           0 :                             var profileOnion = Provider.of<ProfileInfoState>(bcontext, listen: false).onion;
     164           0 :                             Provider.of<FlwtchState>(bcontext, listen: false).cwtch.ImportBundle(profileOnion, importBundle.replaceFirst("cwtch:", "")).then((result) {
     165           0 :                               if (result == "importBundle.success") {
     166           0 :                                 failedImport = false;
     167           0 :                                 if (AppLocalizations.of(bcontext) != null) {
     168           0 :                                   final snackBar = SnackBar(content: Text(AppLocalizations.of(bcontext)!.successfullAddedContact + importBundle));
     169           0 :                                   ScaffoldMessenger.of(bcontext).showSnackBar(snackBar);
     170           0 :                                   Navigator.popUntil(bcontext, (route) => route.settings.name == "conversations");
     171             :                                 }
     172             :                               } else {
     173           0 :                                 failedImport = true;
     174             :                               }
     175             :                             });
     176             :                           }
     177             :                         },
     178             :                         hintText: '',
     179             :                       )
     180             :                     ])))));
     181             :   }
     182             : 
     183             :   /// TODO Add Group Pane
     184           0 :   Widget addGroupTab(bcontext) {
     185             :     // TODO We should replace with with a "Paste in Server Key Bundle"
     186           0 :     if (Provider.of<ProfileInfoState>(bcontext).serverList.servers.isEmpty) {
     187           0 :       return Text(AppLocalizations.of(bcontext)!.addServerFirst);
     188             :     }
     189           0 :     ScrollController controller = ScrollController();
     190           0 :     return Scrollbar(
     191             :         controller: controller,
     192           0 :         child: SingleChildScrollView(
     193             :             clipBehavior: Clip.antiAlias,
     194             :             controller: controller,
     195           0 :             child: Container(
     196           0 :                 margin: EdgeInsets.all(30),
     197           0 :                 padding: EdgeInsets.all(20),
     198           0 :                 child: Form(
     199             :                     autovalidateMode: AutovalidateMode.always,
     200           0 :                     key: _createGroupFormKey,
     201           0 :                     child: Column(
     202             :                       mainAxisAlignment: MainAxisAlignment.start,
     203             :                       crossAxisAlignment: CrossAxisAlignment.start,
     204           0 :                       children: [
     205           0 :                         CwtchLabel(label: AppLocalizations.of(context)!.server),
     206           0 :                         SizedBox(
     207             :                           height: 20,
     208             :                         ),
     209           0 :                         DropdownButton(
     210           0 :                             onChanged: (String? newServer) {
     211           0 :                               setState(() {
     212           0 :                                 server = newServer!;
     213             :                               });
     214             :                             },
     215             :                             isExpanded: true, // magic property
     216           0 :                             value: server,
     217           0 :                             items: Provider.of<ProfileInfoState>(bcontext).serverList.servers.map<DropdownMenuItem<String>>((RemoteServerInfoState serverInfo) {
     218           0 :                               return DropdownMenuItem<String>(
     219           0 :                                 value: serverInfo.onion,
     220           0 :                                 child: Text(
     221           0 :                                   serverInfo.description.isNotEmpty ? serverInfo.description : serverInfo.onion,
     222             :                                   overflow: TextOverflow.ellipsis,
     223             :                                 ),
     224             :                               );
     225           0 :                             }).toList()),
     226           0 :                         SizedBox(
     227             :                           height: 20,
     228             :                         ),
     229           0 :                         CwtchLabel(label: AppLocalizations.of(bcontext)!.groupNameLabel),
     230           0 :                         SizedBox(
     231             :                           height: 20,
     232             :                         ),
     233           0 :                         CwtchTextField(
     234           0 :                           controller: ctrlrGroupName,
     235           0 :                           hintText: AppLocalizations.of(bcontext)!.groupNameLabel,
     236           0 :                           onChanged: (newValue) {},
     237           0 :                           validator: (value) {
     238             :                             return null;
     239             :                           },
     240             :                         ),
     241           0 :                         SizedBox(
     242             :                           height: 20,
     243             :                         ),
     244           0 :                         ElevatedButton(
     245           0 :                           onPressed: () {
     246           0 :                             var profileOnion = Provider.of<ProfileInfoState>(bcontext, listen: false).onion;
     247           0 :                             Provider.of<FlwtchState>(bcontext, listen: false).cwtch.CreateGroup(profileOnion, server, ctrlrGroupName.text);
     248           0 :                             Future.delayed(const Duration(milliseconds: 500), () {
     249           0 :                               final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.successfullAddedContact + " " + ctrlrGroupName.text));
     250           0 :                               ScaffoldMessenger.of(bcontext).showSnackBar(snackBar);
     251           0 :                               Navigator.pop(bcontext);
     252             :                             });
     253             :                           },
     254           0 :                           child: Text(AppLocalizations.of(context)!.createGroupBtn),
     255             :                         ),
     256             :                       ],
     257             :                     )))));
     258             :   }
     259             : }

Generated by: LCOV version 1.14