diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index b8fcd02..7743dbf 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -25,7 +25,8 @@ class CwtchNotifier { void handleMessage(String type, dynamic data) { switch (type) { case "NewPeer": - profileCN.add(ProfileInfoState(onion: data["Identity"], nickname: data["name"], imagePath: data["picture"], contactsJson: data["ContactsJson"], online: data["Online"] == "true")); + profileCN.add(ProfileInfoState( + onion: data["Identity"], nickname: data["name"], imagePath: data["picture"], contactsJson: data["ContactsJson"], serversJson: data["ServerList"], online: data["Online"] == "true")); break; case "PeerCreated": profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState( @@ -39,6 +40,7 @@ class CwtchNotifier { savePeerHistory: data["saveConversationHistory"], numMessages: int.parse(data["numMessages"]), numUnread: int.parse(data["unread"]), + isGroup: data["isGroup"], lastMessageTime: DateTime.now(), //show at the top of the contact list even if no messages yet )); break; @@ -81,6 +83,9 @@ class CwtchNotifier { print("acn status: $data"); torStatus.handleUpdate(int.parse(data["Progress"]), data["Status"]); break; + case "UpdateServerInfo": + profileCN.getProfile(data["ProfileOnion"]).replaceServers(data["ServerList"]); + break; default: print("unhandled event: $type"); } diff --git a/lib/l10n/intl_de.arb b/lib/l10n/intl_de.arb index f507e43..f8cdf6c 100644 --- a/lib/l10n/intl_de.arb +++ b/lib/l10n/intl_de.arb @@ -41,6 +41,7 @@ "dateLastMonth": "", "dateLastYear": "", "dateMinutesAgo": "", + "dateMonthsAgo": "", "dateNever": "", "dateRightNow": "", "dateWeeksAgo": "", @@ -138,6 +139,7 @@ "themeLight": "Licht", "titleManageContacts": "", "titleManageProfiles": "", + "titleManageServers": "", "titlePlaceholder": "Titel...", "todoPlaceholder": "noch zu erledigen", "tooltipAddContact": "", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 48430a4..78fecfd 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -41,6 +41,7 @@ "dateLastMonth": "Last Month", "dateLastYear": "Last Year", "dateMinutesAgo": "Minutes Ago", + "dateMonthsAgo": "Months Ago", "dateNever": "Never", "dateRightNow": "Right Now", "dateWeeksAgo": "Weeks Ago", @@ -138,6 +139,7 @@ "themeLight": "Light", "titleManageContacts": "Manage Contacts", "titleManageProfiles": "Manage Cwtch Profiles", + "titleManageServers": "Manage Servers", "titlePlaceholder": "title...", "todoPlaceholder": "Todo...", "tooltipAddContact": "Add a new contact", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index 6f94a2b..0234709 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -41,6 +41,7 @@ "dateLastMonth": "", "dateLastYear": "", "dateMinutesAgo": "", + "dateMonthsAgo": "", "dateNever": "", "dateRightNow": "", "dateWeeksAgo": "", @@ -138,6 +139,7 @@ "themeLight": "Claro", "titleManageContacts": "", "titleManageProfiles": "", + "titleManageServers": "", "titlePlaceholder": "título...", "todoPlaceholder": "Por hacer...", "tooltipAddContact": "", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 5d249ec..2c5fa91 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -41,6 +41,7 @@ "dateLastMonth": "", "dateLastYear": "", "dateMinutesAgo": "", + "dateMonthsAgo": "", "dateNever": "", "dateRightNow": "", "dateWeeksAgo": "", @@ -138,6 +139,7 @@ "themeLight": "", "titleManageContacts": "", "titleManageProfiles": "", + "titleManageServers": "", "titlePlaceholder": "titre...", "todoPlaceholder": "A faire...", "tooltipAddContact": "", diff --git a/lib/l10n/intl_it.arb b/lib/l10n/intl_it.arb index 0d6e216..e306073 100644 --- a/lib/l10n/intl_it.arb +++ b/lib/l10n/intl_it.arb @@ -41,6 +41,7 @@ "dateLastMonth": "", "dateLastYear": "", "dateMinutesAgo": "", + "dateMonthsAgo": "", "dateNever": "", "dateRightNow": "", "dateWeeksAgo": "", @@ -138,6 +139,7 @@ "themeLight": "Chiaro", "titleManageContacts": "", "titleManageProfiles": "", + "titleManageServers": "", "titlePlaceholder": "titolo...", "todoPlaceholder": "Da fare...", "tooltipAddContact": "", diff --git a/lib/l10n/intl_pt.arb b/lib/l10n/intl_pt.arb index e63e8c2..c5ec9f8 100644 --- a/lib/l10n/intl_pt.arb +++ b/lib/l10n/intl_pt.arb @@ -41,6 +41,7 @@ "dateLastMonth": "", "dateLastYear": "", "dateMinutesAgo": "", + "dateMonthsAgo": "", "dateNever": "", "dateRightNow": "", "dateWeeksAgo": "", @@ -138,6 +139,7 @@ "themeLight": "", "titleManageContacts": "", "titleManageProfiles": "", + "titleManageServers": "", "titlePlaceholder": "título…", "todoPlaceholder": "Afazer…", "tooltipAddContact": "", diff --git a/lib/model.dart b/lib/model.dart index 76071d1..75c686b 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; +import 'package:flutter_app/models/servers.dart'; import 'package:provider/provider.dart'; import 'dart:async'; import 'dart:collection'; @@ -34,16 +35,6 @@ class ContactModel { ContactModel({this.onion, this.nickname, this.status, this.isInvitation, this.isBlocked, this.imagePath}); } -//todo: delete -class DanMessageModel { - // ignore: non_constant_identifier_names - String Timestamp; - // ignore: non_constant_identifier_names - bool Acknowledged; - // ignore: non_constant_identifier_names - String Message; -} - class ChatMessage { final int o; final String d; @@ -123,6 +114,7 @@ class ContactListState extends ChangeNotifier { class ProfileInfoState extends ChangeNotifier { ContactListState _contacts = ContactListState(); + ServerListState _servers = ServerListState(); final String onion; String _nickname = ""; String _imagePath = ""; @@ -135,6 +127,7 @@ class ProfileInfoState extends ChangeNotifier { imagePath = "", unreadMessages = 0, contactsJson = "", + serversJson = "", online = false, }) { this._nickname = nickname; @@ -164,6 +157,20 @@ class ProfileInfoState extends ChangeNotifier { this._contacts.updateLastMessageTime(this._contacts._contacts.first.onion, this._contacts._contacts.first.lastMessageTime); } } + + this.replaceServers(serversJson); + } + + // Parse out the server list json into our server info state struct... + void replaceServers(String serversJson) { + if (serversJson != null && serversJson != "" && serversJson != "null") { + print("got servers $serversJson"); + List servers = jsonDecode(serversJson); + this._servers.replace(servers.map((server) { + // TODO Keys... + return ServerInfoState(onion: server["onion"], status: server["status"]); + })); + } } // Getters and Setters for Online Status @@ -192,6 +199,7 @@ class ProfileInfoState extends ChangeNotifier { } ContactListState get contactList => this._contacts; + ServerListState get serverList => this._servers; @override void dispose() { diff --git a/lib/models/servers.dart b/lib/models/servers.dart new file mode 100644 index 0000000..dfc6202 --- /dev/null +++ b/lib/models/servers.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +class ServerListState extends ChangeNotifier { + List _servers = []; + + void replace(Iterable newServers) { + _servers.clear(); + _servers.addAll(newServers); + notifyListeners(); + } + + ServerInfoState getServer(String onion) { + int idx = _servers.indexWhere((element) => element.onion == onion); + return idx >= 0 ? _servers[idx] : null; + } + + List get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier + +} + +class ServerInfoState extends ChangeNotifier { + final String onion; + final String status; + + ServerInfoState({this.onion, this.status}); +} diff --git a/lib/views/addcontactview.dart b/lib/views/addcontactview.dart index 4e88448..7a01526 100644 --- a/lib/views/addcontactview.dart +++ b/lib/views/addcontactview.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_app/errorHandler.dart'; +import 'package:flutter_app/models/servers.dart'; import 'package:flutter_app/settings.dart'; import 'package:flutter_app/widgets/buttontextfield.dart'; import 'package:flutter_app/widgets/cwtchlabel.dart'; @@ -24,8 +25,11 @@ class AddContactView extends StatefulWidget { class _AddContactViewState extends State { final _formKey = GlobalKey(); + final _createGroupFormKey = GlobalKey(); final ctrlrOnion = TextEditingController(text: ""); final ctrlrContact = TextEditingController(text: ""); + final ctrlrGroupName = TextEditingController(text: ""); + String server = ""; @override Widget build(BuildContext context) { @@ -49,7 +53,7 @@ class _AddContactViewState extends State { (groupsEnabled ? getTabBarWithGroups() : getTabBarWithAddPeerOnly()), Expanded( child: TabBarView( - children: (groupsEnabled ? [addPeerTab(), addGroupTab(), joinGroupTab()] : [addPeerTab()]), + children: (groupsEnabled ? [addPeerTab(), manageServersTab(), addGroupTab(), joinGroupTab()] : [addPeerTab()]), )), ])); }); @@ -81,6 +85,7 @@ class _AddContactViewState extends State { icon: Icon(Icons.person_add_rounded), text: AppLocalizations.of(context).addPeer, ), + Tab(icon: Icon(Icons.backup), text: AppLocalizations.of(context).titleManageServers), Tab(icon: Icon(Icons.group), text: AppLocalizations.of(context).createGroup), Tab(icon: Icon(Icons.group_add), text: AppLocalizations.of(context).joinGroup), ], @@ -150,11 +155,78 @@ class _AddContactViewState extends State { /// TODO Add Group Pane Widget addGroupTab() { - return Icon(Icons.group_add); + // TODO We should replace with with a "Paste in Server Key Bundle" + if (Provider.of(context).serverList.servers.isEmpty) { + return Text("You need to add a server before you can create a group."); + } + + // if we haven't picked a server yet, pick the first one in the list... + if (server.isEmpty) { + server = Provider.of(context).serverList.servers.first.onion; + } + + return Container( + margin: EdgeInsets.all(30), + padding: EdgeInsets.all(20), + child: Form( + autovalidateMode: AutovalidateMode.always, + key: _createGroupFormKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CwtchLabel(label: AppLocalizations.of(context).server), + SizedBox( + height: 20, + ), + DropdownButton( + onChanged: (newServer) { + server = newServer; + }, + value: server, + items: Provider.of(context).serverList.servers.map>((ServerInfoState serverInfo) { + return DropdownMenuItem( + value: serverInfo.onion, + child: Text(serverInfo.onion), + ); + }).toList()), + SizedBox( + height: 20, + ), + CwtchLabel(label: AppLocalizations.of(context).groupName), + SizedBox( + height: 20, + ), + CwtchTextField(controller: ctrlrGroupName, labelText: AppLocalizations.of(context).groupNameLabel, onChanged: (newValue) {}), + SizedBox( + height: 20, + ), + ElevatedButton( + onPressed: () {}, + child: Text(AppLocalizations.of(context).createGroupBtn), + ), + ], + ))); } /// TODO Join Group Pane Widget joinGroupTab() { return Icon(Icons.group); } + + /// TODO Manage Servers Tab + Widget manageServersTab() { + final tiles = Provider.of(context).serverList.servers.map((ServerInfoState server) { + return ChangeNotifierProvider.value( + value: server, + child: ListTile( + title: Text(server.onion), + )); + }); + final divided = ListTile.divideTiles( + context: context, + tiles: tiles, + ).toList(); + return ListView(children: divided); + } } diff --git a/lib/widgets/contactrow.dart b/lib/widgets/contactrow.dart index 7ee68a6..47b4528 100644 --- a/lib/widgets/contactrow.dart +++ b/lib/widgets/contactrow.dart @@ -30,7 +30,7 @@ class _ContactRowState extends State { badgeTextColor: Provider.of(context).theme.portraitContactBadgeTextColor(), diameter: 64.0, imagePath: contact.imagePath, - maskOut: contact.status != "Authenticated", + maskOut: contact.isGroup ? false : contact.status != "Authenticated", border: contact.status == "Authenticated" ? Provider.of(context).theme.portraitOnlineBorderColor() : Provider.of(context).theme.portraitOfflineBorderColor()), ), Expanded( diff --git a/pubspec.lock b/pubspec.lock index 78cf820..538007c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -135,7 +135,7 @@ packages: name: integration_test url: "https://pub.dartlang.org" source: hosted - version: "1.0.2+2" + version: "1.0.2+3" intl: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c70e4d1..1b576c7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -85,6 +85,7 @@ flutter: - assets/ - assets/core/ - assets/profiles/ + - assets/servers/ # To add custom fonts to your application, add a fonts section here, # in this "flutter" section. Each entry in this list should have a