2022-07-04 18:19:26 +00:00
|
|
|
import 'dart:io';
|
|
|
|
|
2022-04-01 22:54:06 +00:00
|
|
|
import 'package:cwtch/cwtch/cwtch.dart';
|
2021-06-24 23:10:45 +00:00
|
|
|
import 'package:cwtch/cwtch_icons_icons.dart';
|
2022-01-18 21:26:52 +00:00
|
|
|
import 'package:cwtch/models/appstate.dart';
|
|
|
|
import 'package:cwtch/models/contact.dart';
|
|
|
|
import 'package:cwtch/models/contactlist.dart';
|
|
|
|
import 'package:cwtch/models/profile.dart';
|
2022-01-27 23:40:45 +00:00
|
|
|
import 'package:cwtch/models/profilelist.dart';
|
2021-11-19 00:09:55 +00:00
|
|
|
import 'package:cwtch/views/profileserversview.dart';
|
2021-06-24 23:10:45 +00:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:cwtch/widgets/contactrow.dart';
|
|
|
|
import 'package:cwtch/widgets/profileimage.dart';
|
|
|
|
import 'package:cwtch/widgets/textfield.dart';
|
2021-11-02 22:10:36 +00:00
|
|
|
import 'package:flutter/services.dart';
|
2021-06-24 23:10:45 +00:00
|
|
|
import 'package:provider/provider.dart';
|
2022-06-20 17:54:06 +00:00
|
|
|
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
2021-06-24 23:10:45 +00:00
|
|
|
import '../main.dart';
|
|
|
|
import '../settings.dart';
|
|
|
|
import 'addcontactview.dart';
|
|
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
2022-09-09 20:53:04 +00:00
|
|
|
import 'package:qr_flutter/qr_flutter.dart';
|
2021-06-24 23:10:45 +00:00
|
|
|
|
2021-07-09 22:16:06 +00:00
|
|
|
import 'messageview.dart';
|
|
|
|
|
2022-09-09 20:53:04 +00:00
|
|
|
enum ShareMenu { copyCode, qrcode }
|
|
|
|
|
2023-04-04 20:58:42 +00:00
|
|
|
enum ProfileStatusMenu { available, away, busy }
|
|
|
|
|
2021-06-24 23:10:45 +00:00
|
|
|
class ContactsView extends StatefulWidget {
|
|
|
|
const ContactsView({Key? key}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
_ContactsViewState createState() => _ContactsViewState();
|
|
|
|
}
|
|
|
|
|
2021-07-09 22:16:06 +00:00
|
|
|
// selectConversation can be called from anywhere to set the active conversation
|
2021-11-18 23:44:54 +00:00
|
|
|
void selectConversation(BuildContext context, int handle) {
|
2022-09-09 19:23:08 +00:00
|
|
|
if (handle == Provider.of<AppState>(context, listen: false).selectedConversation) {
|
|
|
|
return;
|
|
|
|
}
|
2021-07-09 22:16:06 +00:00
|
|
|
// requery instead of using contactinfostate directly because sometimes listview gets confused about data that resorts
|
2022-06-10 22:42:54 +00:00
|
|
|
var unread = Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(handle)!.unreadMessages;
|
2022-04-28 15:57:31 +00:00
|
|
|
var previouslySelected = Provider.of<AppState>(context, listen: false).selectedConversation;
|
|
|
|
if (previouslySelected != null) {
|
2022-05-11 19:43:54 +00:00
|
|
|
Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(previouslySelected)!.unselected();
|
2022-04-28 15:57:31 +00:00
|
|
|
}
|
|
|
|
Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(handle)!.selected();
|
2022-06-20 18:41:31 +00:00
|
|
|
|
2021-07-09 22:16:06 +00:00
|
|
|
// triggers update in Double/TripleColumnView
|
2022-06-10 19:10:17 +00:00
|
|
|
Provider.of<AppState>(context, listen: false).initialScrollIndex = unread;
|
2021-07-09 22:16:06 +00:00
|
|
|
Provider.of<AppState>(context, listen: false).selectedConversation = handle;
|
2021-09-17 20:38:10 +00:00
|
|
|
Provider.of<AppState>(context, listen: false).hoveredIndex = -1;
|
2021-07-09 22:16:06 +00:00
|
|
|
// if in singlepane mode, push to the stack
|
|
|
|
var isLandscape = Provider.of<AppState>(context, listen: false).isLandscape(context);
|
2021-08-16 23:09:03 +00:00
|
|
|
if (Provider.of<Settings>(context, listen: false).uiColumns(isLandscape).length == 1) _pushMessageView(context, handle);
|
2022-06-10 19:10:17 +00:00
|
|
|
|
2022-04-01 22:54:06 +00:00
|
|
|
// Set last message seen time in backend
|
2022-04-06 21:54:53 +00:00
|
|
|
Provider.of<FlwtchState>(context, listen: false)
|
|
|
|
.cwtch
|
|
|
|
.SetConversationAttribute(Provider.of<ProfileInfoState>(context, listen: false).onion, handle, LastMessageSeenTimeKey, DateTime.now().toUtc().toIso8601String());
|
2021-07-09 22:16:06 +00:00
|
|
|
}
|
|
|
|
|
2021-11-18 23:44:54 +00:00
|
|
|
void _pushMessageView(BuildContext context, int handle) {
|
2021-07-09 22:16:06 +00:00
|
|
|
var profileOnion = Provider.of<ProfileInfoState>(context, listen: false).onion;
|
2022-06-21 21:58:09 +00:00
|
|
|
|
2021-07-09 22:16:06 +00:00
|
|
|
Navigator.of(context).push(
|
2022-06-21 21:58:09 +00:00
|
|
|
PageRouteBuilder(
|
|
|
|
settings: RouteSettings(name: "messages"),
|
|
|
|
pageBuilder: (builderContext, a1, a2) {
|
2021-07-09 22:16:06 +00:00
|
|
|
var profile = Provider.of<FlwtchState>(builderContext).profs.getProfile(profileOnion)!;
|
|
|
|
return MultiProvider(
|
|
|
|
providers: [
|
|
|
|
ChangeNotifierProvider.value(value: profile),
|
|
|
|
ChangeNotifierProvider.value(value: profile.contactList.getContact(handle)!),
|
|
|
|
],
|
2021-08-16 23:09:03 +00:00
|
|
|
builder: (context, child) => MessageView(),
|
2021-07-09 22:16:06 +00:00
|
|
|
);
|
|
|
|
},
|
2022-06-21 21:58:09 +00:00
|
|
|
transitionsBuilder: (c, anim, a2, child) => FadeTransition(opacity: anim, child: child),
|
|
|
|
transitionDuration: Duration(milliseconds: 200),
|
2021-07-09 22:16:06 +00:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-06-24 23:10:45 +00:00
|
|
|
class _ContactsViewState extends State<ContactsView> {
|
|
|
|
late TextEditingController ctrlrFilter;
|
|
|
|
bool showSearchBar = false;
|
2022-12-06 00:06:33 +00:00
|
|
|
final scaffoldKey = GlobalKey<ScaffoldMessengerState>();
|
2021-06-24 23:10:45 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
ctrlrFilter = new TextEditingController(text: Provider.of<ContactListState>(context, listen: false).filter);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2022-12-06 20:11:55 +00:00
|
|
|
return ScaffoldMessenger(
|
|
|
|
key: scaffoldKey,
|
|
|
|
child: Scaffold(
|
|
|
|
endDrawerEnableOpenDragGesture: false,
|
|
|
|
drawerEnableOpenDragGesture: false,
|
|
|
|
appBar: AppBar(
|
|
|
|
leading: Stack(children: [
|
|
|
|
Align(
|
|
|
|
alignment: Alignment.center,
|
|
|
|
child: IconButton(
|
|
|
|
icon: Icon(Icons.arrow_back),
|
|
|
|
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
|
|
|
onPressed: () {
|
|
|
|
Provider.of<ProfileInfoState>(context, listen: false).recountUnread();
|
|
|
|
Provider.of<AppState>(context, listen: false).selectedProfile = "";
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
)),
|
|
|
|
Positioned(
|
|
|
|
bottom: 5.0,
|
|
|
|
right: 5.0,
|
|
|
|
child: StreamBuilder<bool>(
|
|
|
|
stream: Provider.of<AppState>(context).getUnreadProfileNotifyStream(),
|
|
|
|
builder: (BuildContext context, AsyncSnapshot<bool> unreadCountSnapshot) {
|
|
|
|
int unreadCount = Provider.of<ProfileListState>(context).generateUnreadCount(Provider.of<AppState>(context).selectedProfile ?? "");
|
|
|
|
|
|
|
|
return Visibility(
|
|
|
|
visible: unreadCount > 0,
|
|
|
|
child: CircleAvatar(
|
|
|
|
radius: 10.0,
|
|
|
|
backgroundColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor,
|
|
|
|
child:
|
|
|
|
Text(unreadCount > 99 ? "99+" : unreadCount.toString(), style: TextStyle(color: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor, fontSize: 8.0)),
|
|
|
|
));
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
]),
|
|
|
|
title: Row(children: [
|
|
|
|
ProfileImage(
|
|
|
|
imagePath: Provider.of<Settings>(context).isExperimentEnabled(ImagePreviewsExperiment)
|
|
|
|
? Provider.of<ProfileInfoState>(context).imagePath
|
|
|
|
: Provider.of<ProfileInfoState>(context).defaultImagePath,
|
|
|
|
diameter: 42,
|
2023-04-04 20:58:42 +00:00
|
|
|
border: Provider.of<ProfileInfoState>(context).getBorderColor(Provider.of<Settings>(context).theme),
|
2022-12-06 20:11:55 +00:00
|
|
|
badgeTextColor: Colors.red,
|
|
|
|
badgeColor: Colors.red,
|
|
|
|
),
|
2023-04-04 20:58:42 +00:00
|
|
|
PopupMenuButton<ProfileStatusMenu>(
|
|
|
|
icon: Icon(Icons.online_prediction),
|
|
|
|
tooltip: AppLocalizations.of(context)!.availabilityStatusTooltip,
|
|
|
|
splashRadius: Material.defaultSplashRadius / 2,
|
|
|
|
onSelected: (ProfileStatusMenu item) {
|
|
|
|
String onion = Provider.of<ProfileInfoState>(context, listen: false).onion;
|
|
|
|
switch (item) {
|
|
|
|
case ProfileStatusMenu.available:
|
|
|
|
Provider.of<FlwtchState>(context, listen: false).cwtch.SetProfileAttribute(onion, "profile.profile-status", "available");
|
|
|
|
break;
|
|
|
|
case ProfileStatusMenu.away:
|
|
|
|
Provider.of<FlwtchState>(context, listen: false).cwtch.SetProfileAttribute(onion, "profile.profile-status", "away");
|
|
|
|
break;
|
|
|
|
case ProfileStatusMenu.busy:
|
|
|
|
Provider.of<FlwtchState>(context, listen: false).cwtch.SetProfileAttribute(onion, "profile.profile-status", "busy");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
itemBuilder: (BuildContext context) => <PopupMenuEntry<ProfileStatusMenu>>[
|
|
|
|
PopupMenuItem<ProfileStatusMenu>(
|
|
|
|
value: ProfileStatusMenu.available,
|
|
|
|
child: Text(AppLocalizations.of(context)!.availabilityStatusAvailable!,),
|
|
|
|
),
|
|
|
|
PopupMenuItem<ProfileStatusMenu>(
|
|
|
|
value: ProfileStatusMenu.away,
|
|
|
|
child: Text(AppLocalizations.of(context)!.availabilityStatusAway!,),
|
|
|
|
),
|
|
|
|
PopupMenuItem<ProfileStatusMenu>(
|
|
|
|
value: ProfileStatusMenu.busy,
|
|
|
|
child: Text(AppLocalizations.of(context)!.availabilityStatusBusy!,),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
2022-12-06 20:11:55 +00:00
|
|
|
SizedBox(
|
|
|
|
width: 10,
|
|
|
|
),
|
|
|
|
Expanded(
|
|
|
|
child: Text("%1 » %2".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname).replaceAll("%2", AppLocalizations.of(context)!.titleManageContacts),
|
|
|
|
overflow: TextOverflow.ellipsis, style: TextStyle(color: Provider.of<Settings>(context).current().mainTextColor))),
|
|
|
|
]),
|
|
|
|
actions: getActions(context),
|
2021-06-24 23:10:45 +00:00
|
|
|
),
|
2022-12-06 20:11:55 +00:00
|
|
|
floatingActionButton: FloatingActionButton(
|
|
|
|
onPressed: _modalAddImportChoice,
|
|
|
|
tooltip: AppLocalizations.of(context)!.tooltipAddContact,
|
|
|
|
child: Icon(
|
|
|
|
CwtchIcons.person_add_alt_1_24px,
|
|
|
|
color: Provider.of<Settings>(context).theme.defaultButtonTextColor,
|
|
|
|
),
|
2021-06-24 23:10:45 +00:00
|
|
|
),
|
2022-12-06 20:11:55 +00:00
|
|
|
body: showSearchBar || Provider.of<ContactListState>(context).isFiltered ? _buildFilterable() : _buildContactList()));
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
2021-08-26 21:56:58 +00:00
|
|
|
|
2021-08-26 21:51:46 +00:00
|
|
|
List<Widget> getActions(context) {
|
|
|
|
var actions = List<Widget>.empty(growable: true);
|
2021-08-26 21:56:58 +00:00
|
|
|
if (Provider.of<Settings>(context).blockUnknownConnections) {
|
2021-08-26 21:51:46 +00:00
|
|
|
actions.add(Tooltip(message: AppLocalizations.of(context)!.blockUnknownConnectionsEnabledDescription, child: Icon(CwtchIcons.block_unknown)));
|
|
|
|
}
|
2021-10-29 23:37:02 +00:00
|
|
|
|
2022-09-09 21:55:58 +00:00
|
|
|
if (Provider.of<Settings>(context, listen: false).isExperimentEnabled(QRCodeExperiment)) {
|
|
|
|
actions.add(PopupMenuButton<ShareMenu>(
|
2022-09-23 15:48:10 +00:00
|
|
|
icon: Icon(CwtchIcons.address_copy),
|
2022-09-09 20:53:04 +00:00
|
|
|
tooltip: AppLocalizations.of(context)!.shareProfileMenuTooltop,
|
2022-01-14 22:19:35 +00:00
|
|
|
splashRadius: Material.defaultSplashRadius / 2,
|
2022-09-09 20:53:04 +00:00
|
|
|
onSelected: (ShareMenu item) {
|
2022-09-10 15:11:08 +00:00
|
|
|
switch (item) {
|
2022-09-09 20:53:04 +00:00
|
|
|
case ShareMenu.copyCode:
|
|
|
|
{
|
2022-09-10 15:11:08 +00:00
|
|
|
Clipboard.setData(new ClipboardData(text: Provider.of<ProfileInfoState>(context, listen: false).onion));
|
2022-09-09 20:53:04 +00:00
|
|
|
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.copiedToClipboardNotification));
|
2022-12-06 00:16:08 +00:00
|
|
|
scaffoldKey.currentState?.showSnackBar(snackBar);
|
2022-09-09 20:53:04 +00:00
|
|
|
}
|
|
|
|
break;
|
2022-09-10 15:11:08 +00:00
|
|
|
case ShareMenu.qrcode:
|
|
|
|
{
|
|
|
|
_showQRCode("cwtch:" + Provider.of<ProfileInfoState>(context, listen: false).onion);
|
|
|
|
}
|
|
|
|
break;
|
2022-09-09 20:53:04 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
itemBuilder: (BuildContext context) => <PopupMenuEntry<ShareMenu>>[
|
|
|
|
PopupMenuItem<ShareMenu>(
|
|
|
|
value: ShareMenu.copyCode,
|
|
|
|
child: Text(AppLocalizations.of(context)!.copyAddress),
|
|
|
|
),
|
|
|
|
PopupMenuItem<ShareMenu>(
|
|
|
|
value: ShareMenu.qrcode,
|
|
|
|
child: Text(AppLocalizations.of(context)!.shareMenuQRCode),
|
|
|
|
),
|
2022-09-09 21:55:58 +00:00
|
|
|
],
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
actions.add(IconButton(
|
2022-09-23 15:48:10 +00:00
|
|
|
icon: Icon(CwtchIcons.address_copy),
|
2022-09-09 21:55:58 +00:00
|
|
|
tooltip: AppLocalizations.of(context)!.copyAddress,
|
|
|
|
splashRadius: Material.defaultSplashRadius / 2,
|
|
|
|
onPressed: () {
|
2022-09-10 15:11:08 +00:00
|
|
|
Clipboard.setData(new ClipboardData(text: Provider.of<ProfileInfoState>(context, listen: false).onion));
|
2022-09-09 21:55:58 +00:00
|
|
|
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.copiedToClipboardNotification));
|
2022-12-06 00:06:33 +00:00
|
|
|
scaffoldKey.currentState?.showSnackBar(snackBar);
|
2022-09-09 21:55:58 +00:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2021-11-20 18:09:06 +00:00
|
|
|
// Manage known Servers
|
2021-12-14 16:34:37 +00:00
|
|
|
if (Provider.of<Settings>(context, listen: false).isExperimentEnabled(TapirGroupsExperiment) || Provider.of<Settings>(context, listen: false).isExperimentEnabled(ServerManagementExperiment)) {
|
2021-11-09 23:27:26 +00:00
|
|
|
actions.add(IconButton(
|
|
|
|
icon: Icon(CwtchIcons.dns_24px),
|
2021-12-15 22:29:27 +00:00
|
|
|
tooltip: AppLocalizations.of(context)!.manageKnownServersButton,
|
2022-01-14 22:19:35 +00:00
|
|
|
splashRadius: Material.defaultSplashRadius / 2,
|
2021-11-09 23:27:26 +00:00
|
|
|
onPressed: () {
|
|
|
|
_pushServers();
|
|
|
|
}));
|
|
|
|
}
|
2021-10-29 23:37:02 +00:00
|
|
|
|
2021-11-02 22:10:36 +00:00
|
|
|
// Search contacts
|
2021-08-26 21:51:46 +00:00
|
|
|
actions.add(IconButton(
|
2021-08-26 21:56:58 +00:00
|
|
|
// need both conditions for displaying initial empty textfield and also allowing filters to be cleared if this widget gets lost/reset
|
2021-08-26 21:51:46 +00:00
|
|
|
icon: Icon(showSearchBar || Provider.of<ContactListState>(context).isFiltered ? Icons.search_off : Icons.search),
|
2022-01-14 22:19:35 +00:00
|
|
|
splashRadius: Material.defaultSplashRadius / 2,
|
2021-08-26 21:51:46 +00:00
|
|
|
onPressed: () {
|
|
|
|
Provider.of<ContactListState>(context, listen: false).filter = "";
|
|
|
|
setState(() {
|
|
|
|
showSearchBar = !showSearchBar;
|
|
|
|
});
|
|
|
|
}));
|
|
|
|
return actions;
|
|
|
|
}
|
2021-06-24 23:10:45 +00:00
|
|
|
|
|
|
|
Widget _buildFilterable() {
|
|
|
|
Widget txtfield = CwtchTextField(
|
|
|
|
controller: ctrlrFilter,
|
2021-12-09 05:40:40 +00:00
|
|
|
hintText: AppLocalizations.of(context)!.search,
|
2021-06-24 23:10:45 +00:00
|
|
|
onChanged: (newVal) {
|
|
|
|
Provider.of<ContactListState>(context, listen: false).filter = newVal;
|
|
|
|
},
|
|
|
|
);
|
|
|
|
return Column(children: [Padding(padding: EdgeInsets.all(8), child: txtfield), Expanded(child: _buildContactList())]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _buildContactList() {
|
|
|
|
final tiles = Provider.of<ContactListState>(context).filteredList().map((ContactInfoState contact) {
|
2022-01-27 23:40:45 +00:00
|
|
|
return MultiProvider(
|
|
|
|
providers: [
|
|
|
|
ChangeNotifierProvider.value(value: contact),
|
|
|
|
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context).serverList),
|
|
|
|
],
|
2022-09-09 19:23:08 +00:00
|
|
|
builder: (context, child) => ContactRow(),
|
2022-01-27 23:40:45 +00:00
|
|
|
);
|
2021-06-24 23:10:45 +00:00
|
|
|
});
|
2022-02-05 00:37:25 +00:00
|
|
|
|
2022-06-20 18:41:31 +00:00
|
|
|
var initialScroll =
|
|
|
|
Provider.of<ProfileInfoState>(context, listen: false).contactList.filteredList().indexWhere((element) => element.identifier == Provider.of<AppState>(context).selectedConversation);
|
|
|
|
if (initialScroll < 0) {
|
|
|
|
initialScroll = 0;
|
|
|
|
}
|
|
|
|
|
2022-06-20 17:54:06 +00:00
|
|
|
var contactList = ScrollablePositionedList.separated(
|
|
|
|
itemScrollController: Provider.of<ProfileInfoState>(context).contactListScrollController,
|
2022-07-25 16:31:29 +00:00
|
|
|
itemCount: Provider.of<ContactListState>(context).numFiltered,
|
2022-06-20 18:41:31 +00:00
|
|
|
initialScrollIndex: initialScroll,
|
|
|
|
shrinkWrap: true,
|
|
|
|
physics: BouncingScrollPhysics(),
|
2022-07-25 16:31:29 +00:00
|
|
|
semanticChildCount: Provider.of<ContactListState>(context).numFiltered,
|
2022-06-20 17:54:06 +00:00
|
|
|
itemBuilder: (context, index) {
|
|
|
|
return tiles.elementAt(index);
|
|
|
|
},
|
|
|
|
separatorBuilder: (BuildContext context, int index) {
|
|
|
|
return Divider(height: 1);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2022-09-09 19:23:08 +00:00
|
|
|
return contactList;
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 19:14:47 +00:00
|
|
|
void _pushAddContact(bool newGroup) {
|
|
|
|
// close modal
|
|
|
|
Navigator.popUntil(context, (route) => route.settings.name == "conversations");
|
|
|
|
|
2022-06-21 21:58:09 +00:00
|
|
|
Navigator.of(context).push(
|
|
|
|
PageRouteBuilder(
|
|
|
|
settings: RouteSettings(name: "addcontact"),
|
|
|
|
pageBuilder: (builderContext, a1, a2) {
|
|
|
|
return MultiProvider(
|
|
|
|
providers: [
|
|
|
|
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context)),
|
|
|
|
],
|
|
|
|
child: AddContactView(newGroup: newGroup),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
transitionsBuilder: (c, anim, a2, child) => FadeTransition(opacity: anim, child: child),
|
|
|
|
transitionDuration: Duration(milliseconds: 200),
|
|
|
|
),
|
|
|
|
);
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
|
2021-11-09 23:27:26 +00:00
|
|
|
void _pushServers() {
|
2023-03-02 21:17:44 +00:00
|
|
|
var profileInfoState = Provider.of<ProfileInfoState>(context, listen: false);
|
|
|
|
|
2022-06-21 21:58:09 +00:00
|
|
|
Navigator.of(context).push(
|
|
|
|
PageRouteBuilder(
|
|
|
|
pageBuilder: (bcontext, a1, a2) {
|
|
|
|
return MultiProvider(
|
2023-03-02 21:17:44 +00:00
|
|
|
providers: [ChangeNotifierProvider.value(value: profileInfoState), Provider.value(value: Provider.of<FlwtchState>(context))],
|
2022-06-21 21:58:09 +00:00
|
|
|
child: ProfileServersView(),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
transitionsBuilder: (c, anim, a2, child) => FadeTransition(opacity: anim, child: child),
|
|
|
|
transitionDuration: Duration(milliseconds: 200),
|
|
|
|
),
|
|
|
|
);
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
2022-04-12 19:14:47 +00:00
|
|
|
|
|
|
|
void _modalAddImportChoice() {
|
|
|
|
bool groupsEnabled = Provider.of<Settings>(context, listen: false).isExperimentEnabled(TapirGroupsExperiment);
|
|
|
|
|
|
|
|
showModalBottomSheet<void>(
|
|
|
|
context: context,
|
|
|
|
isScrollControlled: true,
|
|
|
|
builder: (BuildContext context) {
|
|
|
|
return Padding(
|
|
|
|
padding: MediaQuery.of(context).viewInsets,
|
|
|
|
child: RepaintBoundary(
|
|
|
|
child: Container(
|
2022-07-04 18:19:26 +00:00
|
|
|
height: Platform.isAndroid ? 250 : 200, // bespoke value courtesy of the [TextField] docs
|
2022-04-12 19:14:47 +00:00
|
|
|
child: Center(
|
|
|
|
child: Padding(
|
2022-06-09 21:30:38 +00:00
|
|
|
padding: EdgeInsets.all(2.0),
|
2022-04-12 19:14:47 +00:00
|
|
|
child: Column(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
2022-06-09 21:26:02 +00:00
|
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
|
mainAxisSize: MainAxisSize.max,
|
2022-04-12 19:14:47 +00:00
|
|
|
children: <Widget>[
|
2022-06-09 21:28:24 +00:00
|
|
|
SizedBox(
|
|
|
|
height: 20,
|
|
|
|
),
|
2022-06-09 21:26:02 +00:00
|
|
|
Expanded(
|
|
|
|
child: Tooltip(
|
|
|
|
message: AppLocalizations.of(context)!.tooltipAddContact,
|
|
|
|
child: ElevatedButton(
|
|
|
|
style: ElevatedButton.styleFrom(
|
2022-07-04 18:19:26 +00:00
|
|
|
minimumSize: Size.fromWidth(399),
|
2022-06-09 21:26:02 +00:00
|
|
|
maximumSize: Size.fromWidth(400),
|
|
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(left: Radius.circular(180), right: Radius.circular(180))),
|
|
|
|
),
|
|
|
|
child: Text(
|
|
|
|
AppLocalizations.of(context)!.addContact,
|
|
|
|
semanticsLabel: AppLocalizations.of(context)!.addContact,
|
|
|
|
textAlign: TextAlign.center,
|
2022-06-09 21:28:24 +00:00
|
|
|
style: TextStyle(fontWeight: FontWeight.bold),
|
2022-06-09 21:26:02 +00:00
|
|
|
),
|
|
|
|
onPressed: () {
|
|
|
|
_pushAddContact(false);
|
|
|
|
},
|
|
|
|
))),
|
2022-04-12 19:14:47 +00:00
|
|
|
SizedBox(
|
|
|
|
height: 20,
|
|
|
|
),
|
2022-06-09 21:26:02 +00:00
|
|
|
Expanded(
|
|
|
|
child: Tooltip(
|
|
|
|
message: groupsEnabled ? AppLocalizations.of(context)!.addServerTooltip : AppLocalizations.of(context)!.thisFeatureRequiresGroupExpermientsToBeEnabled,
|
|
|
|
child: ElevatedButton(
|
|
|
|
style: ElevatedButton.styleFrom(
|
2022-07-04 18:19:26 +00:00
|
|
|
minimumSize: Size.fromWidth(399),
|
2022-06-09 21:26:02 +00:00
|
|
|
maximumSize: Size.fromWidth(400),
|
|
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(left: Radius.circular(180), right: Radius.circular(180))),
|
|
|
|
),
|
2022-06-09 21:28:24 +00:00
|
|
|
child: Text(
|
|
|
|
AppLocalizations.of(context)!.addServerTitle,
|
|
|
|
semanticsLabel: AppLocalizations.of(context)!.addServerTitle,
|
|
|
|
textAlign: TextAlign.center,
|
|
|
|
style: TextStyle(fontWeight: FontWeight.bold),
|
|
|
|
),
|
2022-06-09 21:26:02 +00:00
|
|
|
onPressed: groupsEnabled
|
|
|
|
? () {
|
|
|
|
_pushAddContact(false);
|
|
|
|
}
|
|
|
|
: null,
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
SizedBox(
|
|
|
|
height: 20,
|
|
|
|
),
|
|
|
|
Expanded(
|
2022-04-12 19:14:47 +00:00
|
|
|
child: Tooltip(
|
2022-06-09 21:26:02 +00:00
|
|
|
message: groupsEnabled ? AppLocalizations.of(context)!.createGroupTitle : AppLocalizations.of(context)!.thisFeatureRequiresGroupExpermientsToBeEnabled,
|
2022-04-12 19:14:47 +00:00
|
|
|
child: ElevatedButton(
|
2022-06-09 21:26:02 +00:00
|
|
|
style: ElevatedButton.styleFrom(
|
2022-07-04 18:19:26 +00:00
|
|
|
minimumSize: Size.fromWidth(399),
|
2022-06-09 21:26:02 +00:00
|
|
|
maximumSize: Size.fromWidth(400),
|
|
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(left: Radius.circular(180), right: Radius.circular(180))),
|
|
|
|
),
|
2022-06-09 21:28:24 +00:00
|
|
|
child: Text(
|
|
|
|
AppLocalizations.of(context)!.createGroupTitle,
|
|
|
|
semanticsLabel: AppLocalizations.of(context)!.createGroupTitle,
|
|
|
|
textAlign: TextAlign.center,
|
|
|
|
style: TextStyle(fontWeight: FontWeight.bold),
|
|
|
|
),
|
2022-04-12 19:14:47 +00:00
|
|
|
onPressed: groupsEnabled
|
|
|
|
? () {
|
2022-06-09 21:26:02 +00:00
|
|
|
_pushAddContact(true);
|
2022-04-12 19:14:47 +00:00
|
|
|
}
|
|
|
|
: null,
|
2022-06-09 21:26:02 +00:00
|
|
|
))),
|
2022-06-09 21:28:24 +00:00
|
|
|
SizedBox(
|
|
|
|
height: 20,
|
|
|
|
),
|
2022-04-12 19:14:47 +00:00
|
|
|
],
|
|
|
|
))),
|
|
|
|
)));
|
|
|
|
});
|
|
|
|
}
|
2022-09-09 20:53:04 +00:00
|
|
|
|
|
|
|
void _showQRCode(String profile_code) {
|
|
|
|
showModalBottomSheet<dynamic>(
|
2022-09-10 15:11:08 +00:00
|
|
|
context: context,
|
|
|
|
builder: (BuildContext context) {
|
|
|
|
return Wrap(children: <Widget>[
|
|
|
|
Center(
|
|
|
|
child: QrImage(
|
|
|
|
data: profile_code,
|
|
|
|
version: QrVersions.auto,
|
|
|
|
size: 400.0,
|
|
|
|
backgroundColor: Provider.of<Settings>(context).theme.backgroundPaneColor,
|
|
|
|
foregroundColor: Provider.of<Settings>(context).theme.mainTextColor,
|
|
|
|
gapless: false,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
]);
|
|
|
|
},
|
2022-09-09 20:53:04 +00:00
|
|
|
);
|
|
|
|
}
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|