LCOV - code coverage report
Current view: top level - lib/views - peersettingsview.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 244 0.0 %
Date: 2026-09-01 20:32:38 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:cwtch/config.dart';
       2             : import 'package:cwtch/cwtch_icons_icons.dart';
       3             : import 'package:cwtch/models/appstate.dart';
       4             : import 'package:cwtch/models/contact.dart';
       5             : import 'package:cwtch/models/profile.dart';
       6             : import 'package:cwtch/widgets/profileimage.dart';
       7             : import 'package:flutter/services.dart';
       8             : import 'package:cwtch/widgets/buttontextfield.dart';
       9             : import 'package:cwtch/widgets/cwtchlabel.dart';
      10             : import 'package:flutter/material.dart';
      11             : import 'package:cwtch/settings.dart';
      12             : import 'package:provider/provider.dart';
      13             : import 'package:cwtch/l10n/app_localizations.dart';
      14             : 
      15             : import '../main.dart';
      16             : import '../themes/opaque.dart';
      17             : 
      18             : /// Peer Settings View Provides  way to Configure .
      19             : class PeerSettingsView extends StatefulWidget {
      20           0 :   @override
      21           0 :   _PeerSettingsViewState createState() => _PeerSettingsViewState();
      22             : }
      23             : 
      24             : class _PeerSettingsViewState extends State<PeerSettingsView> {
      25           0 :   @override
      26             :   void dispose() {
      27           0 :     super.dispose();
      28             :   }
      29             : 
      30             :   final ctrlrNick = TextEditingController(text: "");
      31             :   ScrollController peerSettingsScrollController = ScrollController();
      32             : 
      33           0 :   @override
      34             :   void initState() {
      35           0 :     super.initState();
      36           0 :     final nickname = Provider.of<ContactInfoState>(context, listen: false).nickname;
      37           0 :     if (nickname.isNotEmpty) {
      38           0 :       ctrlrNick.text = nickname;
      39             :     }
      40             :   }
      41             : 
      42           0 :   @override
      43             :   Widget build(BuildContext context) {
      44           0 :     var handle = Provider.of<ContactInfoState>(context).nickname;
      45           0 :     if (handle.isEmpty) {
      46           0 :       handle = Provider.of<ContactInfoState>(context).onion;
      47             :     }
      48           0 :     return Scaffold(
      49           0 :       appBar: AppBar(
      50           0 :         title: Container(
      51           0 :           height: Provider.of<Settings>(context).fontScaling * 24.0,
      52             :           clipBehavior: Clip.hardEdge,
      53           0 :           decoration: BoxDecoration(),
      54           0 :           child: Text(handle + " " + AppLocalizations.of(context)!.conversationSettings),
      55             :         ),
      56             :       ),
      57           0 :       body: _buildSettingsList(),
      58             :     );
      59             :   }
      60             : 
      61           0 :   Widget _buildSettingsList() {
      62           0 :     return Consumer<Settings>(
      63           0 :       builder: (context, settings, child) {
      64           0 :         return LayoutBuilder(
      65           0 :           builder: (BuildContext context, BoxConstraints viewportConstraints) {
      66           0 :             String? acnCircuit = Provider.of<ContactInfoState>(context).acnCircuit;
      67             : 
      68           0 :             Widget path = Text(Provider.of<ContactInfoState>(context).status);
      69             : 
      70             :             if (acnCircuit != null) {
      71           0 :               var hops = acnCircuit.split(",");
      72           0 :               if (hops.length == 3) {
      73             :                 List<Widget> paths = hops
      74           0 :                     .map((String countryCodeAndIp) {
      75           0 :                       var parts = countryCodeAndIp.split(":");
      76           0 :                       var country = parts[0];
      77           0 :                       var ip = parts[1];
      78           0 :                       return RichText(
      79             :                         textAlign: TextAlign.left,
      80           0 :                         text: TextSpan(
      81             :                           text: country,
      82           0 :                           style: TextStyle(fontWeight: FontWeight.bold, fontSize: 10, fontFamily: "RobotoMono"),
      83           0 :                           children: [
      84           0 :                             TextSpan(
      85           0 :                               text: " ($ip)",
      86           0 :                               style: TextStyle(fontSize: 8, fontWeight: FontWeight.normal),
      87             :                             ),
      88             :                           ],
      89             :                         ),
      90             :                       );
      91             :                     })
      92           0 :                     .toList(growable: true);
      93             : 
      94           0 :                 paths.add(
      95           0 :                   RichText(
      96           0 :                     text: TextSpan(
      97           0 :                       text: AppLocalizations.of(context)!.labelTorNetwork,
      98           0 :                       style: TextStyle(fontWeight: FontWeight.normal, fontSize: 8, fontFamily: "monospace"),
      99             :                     ),
     100             :                   ),
     101             :                 );
     102             : 
     103           0 :                 path = Column(children: paths);
     104             :               }
     105             :             }
     106             : 
     107           0 :             List<Widget> evWidgets = Provider.of<ContactInfoState>(context, listen: false).contactEvents.map((ev) {
     108           0 :               return ListTile(
     109           0 :                 title: Text(ev.summary, style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle)),
     110           0 :                 subtitle: Text(ev.timestamp.toLocal().toIso8601String(), style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle)),
     111             :               );
     112           0 :             }).toList();
     113             : 
     114           0 :             bool canCopy = !Provider.of<ContactInfoState>(context, listen: false).isManaged || Provider.of<ContactInfoState>(context, listen: false).modeLine.contains('o');
     115             : 
     116           0 :             return Scrollbar(
     117             :               trackVisibility: true,
     118           0 :               controller: peerSettingsScrollController,
     119           0 :               child: SingleChildScrollView(
     120             :                 clipBehavior: Clip.antiAlias,
     121           0 :                 controller: peerSettingsScrollController,
     122           0 :                 child: ConstrainedBox(
     123           0 :                   constraints: BoxConstraints(minHeight: viewportConstraints.maxHeight),
     124           0 :                   child: Container(
     125           0 :                     color: settings.theme.backgroundPaneColor,
     126           0 :                     padding: EdgeInsets.all(12),
     127           0 :                     child: Column(
     128             :                       mainAxisAlignment: MainAxisAlignment.start,
     129             :                       crossAxisAlignment: CrossAxisAlignment.center,
     130           0 :                       children: [
     131           0 :                         Column(
     132             :                           crossAxisAlignment: CrossAxisAlignment.center,
     133           0 :                           children: [
     134           0 :                             ProfileImage(
     135           0 :                               imagePath: Provider.of<Settings>(context).isExperimentEnabled(ImagePreviewsExperiment)
     136           0 :                                   ? Provider.of<ContactInfoState>(context).imagePath
     137           0 :                                   : Provider.of<ContactInfoState>(context).defaultImagePath,
     138             :                               diameter: 120,
     139             :                               maskOut: false,
     140           0 :                               border: settings.theme.portraitOnlineBorderColor,
     141           0 :                               badgeTextColor: settings.theme.portraitContactBadgeTextColor,
     142           0 :                               badgeColor: settings.theme.portraitContactBadgeColor,
     143             :                               badgeEdit: false,
     144             :                             ),
     145           0 :                             SizedBox(
     146           0 :                               width: MediaQuery.of(context).size.width / 2,
     147           0 :                               child: Column(
     148           0 :                                 children: [
     149           0 :                                   Padding(
     150           0 :                                     padding: EdgeInsets.all(1),
     151           0 :                                     child: SelectableText(Provider.of<ContactInfoState>(context, listen: false).attributes[0] ?? "", textAlign: TextAlign.center),
     152             :                                   ),
     153           0 :                                   Padding(
     154           0 :                                     padding: EdgeInsets.all(1),
     155           0 :                                     child: SelectableText(Provider.of<ContactInfoState>(context, listen: false).attributes[1] ?? "", textAlign: TextAlign.center),
     156             :                                   ),
     157           0 :                                   Padding(
     158           0 :                                     padding: EdgeInsets.all(1),
     159           0 :                                     child: SelectableText(Provider.of<ContactInfoState>(context, listen: false).attributes[2] ?? "", textAlign: TextAlign.center),
     160             :                                   ),
     161             :                                 ],
     162             :                               ),
     163             :                             ),
     164             :                           ],
     165             :                         ),
     166             : 
     167           0 :                         Column(
     168             :                           mainAxisAlignment: MainAxisAlignment.start,
     169             :                           crossAxisAlignment: CrossAxisAlignment.start,
     170           0 :                           children: [
     171           0 :                             CwtchLabel(label: AppLocalizations.of(context)!.displayNameLabel),
     172           0 :                             SizedBox(height: 20),
     173           0 :                             CwtchButtonTextField(
     174           0 :                               controller: ctrlrNick,
     175             :                               readonly: false,
     176           0 :                               onPressed: () {
     177           0 :                                 var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
     178           0 :                                 var conversation = Provider.of<ContactInfoState>(context, listen: false).identifier;
     179           0 :                                 Provider.of<ContactInfoState>(context, listen: false).localNickname = ctrlrNick.text;
     180           0 :                                 Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, conversation, "profile.name", ctrlrNick.text);
     181           0 :                                 final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.nickChangeSuccess));
     182           0 :                                 ScaffoldMessenger.of(context).showSnackBar(snackBar);
     183             :                               },
     184           0 :                               icon: Icon(Icons.save),
     185           0 :                               tooltip: AppLocalizations.of(context)!.saveBtn,
     186             :                             ),
     187             :                           ],
     188             :                         ),
     189             : 
     190             :                         // Address Copy Button
     191           0 :                         Visibility(
     192           0 :                           visible: settings.streamerMode == false,
     193           0 :                           child: Column(
     194             :                             mainAxisAlignment: MainAxisAlignment.start,
     195             :                             crossAxisAlignment: CrossAxisAlignment.start,
     196           0 :                             children: [
     197           0 :                               SizedBox(height: 20),
     198           0 :                               CwtchLabel(label: AppLocalizations.of(context)!.addressLabel),
     199           0 :                               SizedBox(height: 20),
     200           0 :                               CwtchButtonTextField(
     201           0 :                                 controller: TextEditingController(
     202           0 :                                   text: (Provider.of<ContactInfoState>(context, listen: false).isManaged ? "grwp-" : "") + Provider.of<ContactInfoState>(context, listen: false).onion,
     203             :                                 ),
     204           0 :                                 onPressed: canCopy ? _copyOnion : null,
     205           0 :                                 icon: canCopy ? Icon(CwtchIcons.copy_address) : null,
     206           0 :                                 tooltip: AppLocalizations.of(context)!.copyBtn,
     207             :                               ),
     208             :                             ],
     209             :                           ),
     210             :                         ),
     211           0 :                         Visibility(visible: Provider.of<ContactInfoState>(context, listen: false).isManaged && canCopy, child: Text(AppLocalizations.of(context)!.anyoneCanJoin)),
     212           0 :                         Visibility(visible: Provider.of<ContactInfoState>(context, listen: false).isManaged && !canCopy, child: Text(AppLocalizations.of(context)!.inviteRequired)),
     213           0 :                         Column(
     214             :                           mainAxisAlignment: MainAxisAlignment.start,
     215             :                           crossAxisAlignment: CrossAxisAlignment.start,
     216           0 :                           children: [
     217           0 :                             SizedBox(height: 20),
     218           0 :                             CwtchLabel(label: AppLocalizations.of(context)!.conversationSettings),
     219           0 :                             SizedBox(height: 20),
     220           0 :                             ListTile(
     221           0 :                               leading: Icon(CwtchIcons.onion_on, color: settings.current().mainTextColor),
     222             :                               isThreeLine: true,
     223           0 :                               title: Text(AppLocalizations.of(context)!.labelACNCircuitInfo),
     224           0 :                               subtitle: Text(AppLocalizations.of(context)!.descriptionACNCircuitInfo),
     225             :                               trailing: path,
     226             :                             ),
     227           0 :                             SizedBox(height: 20),
     228           0 :                             Material(
     229           0 :                               child: SwitchListTile(
     230           0 :                                 title: Text(AppLocalizations.of(context)!.blockBtn, style: TextStyle(color: settings.current().mainTextColor)),
     231           0 :                                 value: Provider.of<ContactInfoState>(context).isBlocked,
     232           0 :                                 onChanged: (bool blocked) {
     233           0 :                                   Provider.of<ContactInfoState>(context, listen: false).blocked = blocked;
     234             : 
     235           0 :                                   var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
     236           0 :                                   var identifier = Provider.of<ContactInfoState>(context, listen: false).identifier;
     237             : 
     238             :                                   if (blocked) {
     239           0 :                                     Provider.of<FlwtchState>(context, listen: false).cwtch.BlockContact(profileOnion, identifier);
     240             :                                   } else {
     241           0 :                                     Provider.of<FlwtchState>(context, listen: false).cwtch.UnblockContact(profileOnion, identifier);
     242             :                                   }
     243             :                                 },
     244           0 :                                 activeTrackColor: settings.theme.defaultButtonColor,
     245           0 :                                 inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
     246           0 :                                 secondary: Icon(CwtchIcons.block_peer, color: settings.current().mainTextColor),
     247             :                               ),
     248             :                             ),
     249           0 :                             Material(
     250           0 :                               child: ListTile(
     251           0 :                                 title: Text(AppLocalizations.of(context)!.savePeerHistory, style: TextStyle(color: settings.current().mainTextColor)),
     252           0 :                                 subtitle: Text(AppLocalizations.of(context)!.savePeerHistoryDescription),
     253           0 :                                 leading: Icon(CwtchIcons.peer_history, color: settings.current().mainTextColor),
     254           0 :                                 trailing: DropdownButton(
     255             :                                   value:
     256           0 :                                       (Provider.of<ContactInfoState>(context).savePeerHistory == "DefaultDeleteHistory" || Provider.of<ContactInfoState>(context).savePeerHistory == "HistoryDefault")
     257           0 :                                       ? AppLocalizations.of(context)!.conversationNotificationPolicyDefault
     258           0 :                                       : (Provider.of<ContactInfoState>(context).savePeerHistory == "SaveHistory"
     259           0 :                                             ? AppLocalizations.of(context)!.savePeerHistory
     260           0 :                                             : AppLocalizations.of(context)!.dontSavePeerHistory),
     261           0 :                                   onChanged: (newValue) {
     262           0 :                                     setState(() {
     263             :                                       // Set whether or not to dave the Contact History...
     264           0 :                                       var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
     265           0 :                                       var identifier = Provider.of<ContactInfoState>(context, listen: false).identifier;
     266             :                                       const SaveHistoryKey = "profile.SavePeerHistory";
     267             :                                       const SaveHistory = "SaveHistory";
     268             :                                       const DelHistory = "DeleteHistoryConfirmed";
     269             :                                       const HistoryDefault = "HistoryDefault";
     270             : 
     271             :                                       // NOTE: .savePeerHistory is used to show ephemeral warnings so it's state is important to update.
     272           0 :                                       if (newValue == AppLocalizations.of(context)!.conversationNotificationPolicyDefault) {
     273           0 :                                         Provider.of<ContactInfoState>(context, listen: false).savePeerHistory = HistoryDefault;
     274           0 :                                         Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, SaveHistoryKey, HistoryDefault);
     275           0 :                                       } else if (newValue == AppLocalizations.of(context)!.savePeerHistory) {
     276           0 :                                         Provider.of<ContactInfoState>(context, listen: false).savePeerHistory = SaveHistory;
     277           0 :                                         Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, SaveHistoryKey, SaveHistory);
     278             :                                       } else {
     279           0 :                                         Provider.of<ContactInfoState>(context, listen: false).savePeerHistory = DelHistory;
     280           0 :                                         Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, SaveHistoryKey, DelHistory);
     281             :                                       }
     282             :                                     });
     283             :                                   },
     284             :                                   items:
     285           0 :                                       [
     286           0 :                                         AppLocalizations.of(context)!.conversationNotificationPolicyDefault,
     287           0 :                                         AppLocalizations.of(context)!.savePeerHistory,
     288           0 :                                         AppLocalizations.of(context)!.dontSavePeerHistory,
     289           0 :                                       ].map<DropdownMenuItem<String>>((String value) {
     290           0 :                                         return DropdownMenuItem<String>(
     291             :                                           value: value,
     292           0 :                                           child: Text(value, style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
     293             :                                         );
     294           0 :                                       }).toList(),
     295             :                                 ),
     296             :                               ),
     297             :                             ),
     298           0 :                             Material(
     299           0 :                               child: ListTile(
     300           0 :                                 title: Text(AppLocalizations.of(context)!.conversationNotificationPolicySettingLabel, style: TextStyle(color: settings.current().mainTextColor)),
     301           0 :                                 subtitle: Text(AppLocalizations.of(context)!.conversationNotificationPolicySettingDescription),
     302           0 :                                 leading: Icon(CwtchIcons.chat_bubble_empy, color: settings.current().mainTextColor),
     303           0 :                                 trailing: DropdownButton(
     304           0 :                                   value: Provider.of<ContactInfoState>(context).notificationsPolicy,
     305           0 :                                   items: ConversationNotificationPolicy.values.map<DropdownMenuItem<ConversationNotificationPolicy>>((ConversationNotificationPolicy value) {
     306           0 :                                     return DropdownMenuItem<ConversationNotificationPolicy>(
     307             :                                       value: value,
     308           0 :                                       child: Text(value.toName(context), style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
     309             :                                     );
     310           0 :                                   }).toList(),
     311           0 :                                   onChanged: (ConversationNotificationPolicy? newVal) {
     312           0 :                                     Provider.of<ContactInfoState>(context, listen: false).notificationsPolicy = newVal!;
     313           0 :                                     var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
     314           0 :                                     var identifier = Provider.of<ContactInfoState>(context, listen: false).identifier;
     315             :                                     const NotificationPolicyKey = "profile.notification-policy";
     316           0 :                                     Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, NotificationPolicyKey, newVal.toString());
     317             :                                   },
     318             :                                 ),
     319             :                               ),
     320             :                             ),
     321             :                           ],
     322             :                         ),
     323           0 :                         Column(
     324             :                           mainAxisAlignment: MainAxisAlignment.end,
     325             :                           crossAxisAlignment: CrossAxisAlignment.end,
     326           0 :                           children: [
     327           0 :                             SizedBox(height: 20),
     328           0 :                             Row(
     329             :                               crossAxisAlignment: CrossAxisAlignment.center,
     330             :                               mainAxisAlignment: MainAxisAlignment.end,
     331           0 :                               children: [
     332           0 :                                 Tooltip(
     333           0 :                                   message: AppLocalizations.of(context)!.archiveConversation,
     334           0 :                                   child: OutlinedButton.icon(
     335           0 :                                     onPressed: () {
     336           0 :                                       var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
     337           0 :                                       var handle = Provider.of<ContactInfoState>(context, listen: false).identifier;
     338             :                                       // locally update cache...
     339           0 :                                       Provider.of<ContactInfoState>(context, listen: false).isArchived = true;
     340           0 :                                       Provider.of<FlwtchState>(context, listen: false).cwtch.ArchiveConversation(profileOnion, handle);
     341           0 :                                       Future.delayed(Duration(milliseconds: 500), () {
     342           0 :                                         Provider.of<AppState>(context, listen: false).selectedConversation = null;
     343           0 :                                         Navigator.of(context).popUntil((route) => route.settings.name == "conversations"); // dismiss dialog
     344             :                                       });
     345             :                                     },
     346           0 :                                     icon: Icon(Icons.archive),
     347           0 :                                     label: Text(AppLocalizations.of(context)!.archiveConversation),
     348             :                                   ),
     349             :                                 ),
     350             :                               ],
     351             :                             ),
     352           0 :                             SizedBox(height: 20),
     353           0 :                             Row(
     354             :                               crossAxisAlignment: CrossAxisAlignment.center,
     355             :                               mainAxisAlignment: MainAxisAlignment.end,
     356           0 :                               children: [
     357           0 :                                 Tooltip(
     358           0 :                                   message: AppLocalizations.of(context)!.leaveConversation,
     359           0 :                                   child: OutlinedButton.icon(
     360           0 :                                     onPressed: () {
     361           0 :                                       showAlertDialog(context);
     362             :                                     },
     363           0 :                                     icon: Icon(CwtchIcons.leave_group),
     364           0 :                                     label: Text(AppLocalizations.of(context)!.leaveConversation),
     365             :                                   ),
     366             :                                 ),
     367             :                               ],
     368             :                             ),
     369             :                           ],
     370             :                         ),
     371           0 :                         Visibility(
     372           0 :                           visible: EnvironmentConfig.BUILD_VER == dev_version,
     373             :                           maintainSize: false,
     374           0 :                           child: Column(children: evWidgets),
     375             :                         ),
     376             :                       ],
     377             :                     ),
     378             :                   ),
     379             :                 ),
     380             :               ),
     381             :             );
     382             :           },
     383             :         );
     384             :       },
     385             :     );
     386             :   }
     387             : 
     388           0 :   void _copyOnion() {
     389           0 :     String prefix = Provider.of<ContactInfoState>(context, listen: false).isManaged ? "grwp-" : "";
     390           0 :     Clipboard.setData(new ClipboardData(text: prefix + Provider.of<ContactInfoState>(context, listen: false).onion));
     391           0 :     final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.copiedToClipboardNotification));
     392           0 :     ScaffoldMessenger.of(context).showSnackBar(snackBar);
     393             :   }
     394             : 
     395           0 :   showAlertDialog(BuildContext context) {
     396             :     // set up the buttons
     397           0 :     Widget cancelButton = ElevatedButton(
     398           0 :       child: Text(AppLocalizations.of(context)!.cancel),
     399           0 :       style: ButtonStyle(padding: MaterialStateProperty.all(EdgeInsets.all(20))),
     400           0 :       onPressed: () {
     401           0 :         Navigator.of(context).pop(); // dismiss dialog
     402             :       },
     403             :     );
     404           0 :     Widget continueButton = ElevatedButton(
     405           0 :       style: ButtonStyle(padding: MaterialStateProperty.all(EdgeInsets.all(20))),
     406           0 :       child: Text(AppLocalizations.of(context)!.yesLeave),
     407           0 :       onPressed: () {
     408           0 :         var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
     409           0 :         var identifier = Provider.of<ContactInfoState>(context, listen: false).identifier;
     410           0 :         if (Provider.of<ContactInfoState>(context, listen: false).isManaged) {
     411             :           // remove ourselves from the group
     412           0 :           Provider.of<FlwtchState>(context, listen: false).cwtch.KickMember(profileOnion, identifier, profileOnion);
     413             :         }
     414             :         // locally update cache...
     415           0 :         Provider.of<ProfileInfoState>(context, listen: false).contactList.removeContact(identifier);
     416           0 :         Provider.of<FlwtchState>(context, listen: false).cwtch.DeleteContact(profileOnion, identifier);
     417           0 :         Future.delayed(Duration(milliseconds: 500), () {
     418           0 :           Provider.of<AppState>(context, listen: false).selectedConversation = null;
     419           0 :           Navigator.of(context).popUntil((route) => route.settings.name == "conversations"); // dismiss dialog
     420             :         });
     421             :       },
     422             :     );
     423             : 
     424             :     // set up the AlertDialog
     425           0 :     AlertDialog alert = AlertDialog(title: Text(AppLocalizations.of(context)!.reallyLeaveThisGroupPrompt), actions: [cancelButton, continueButton]);
     426             : 
     427             :     // show the dialog
     428           0 :     showDialog(
     429             :       context: context,
     430           0 :       builder: (BuildContext context) {
     431             :         return alert;
     432             :       },
     433             :     );
     434             :   }
     435             : }

Generated by: LCOV version 1.14