From 1eaec8b00a03c66037c1af4afb1d1984b6e98d29 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 3 Jun 2021 11:32:25 -0700 Subject: [PATCH 01/15] Custom Icons + Small Fixes --- assets/fonts/CwtchIcons.ttf | Bin 0 -> 18488 bytes lib/config.dart | 2 +- lib/cwtch_icons_icons.dart | 105 ++++++++++++++++++++++++++++++ lib/model.dart | 23 +++++-- lib/views/addcontactview.dart | 7 +- lib/views/addeditprofileview.dart | 3 +- lib/views/contactsview.dart | 3 +- lib/views/globalsettingsview.dart | 19 ++++-- lib/views/groupsettingsview.dart | 5 +- lib/views/messageview.dart | 5 +- lib/views/peersettingsview.dart | 7 +- lib/views/profilemgrview.dart | 9 ++- lib/widgets/invitationbubble.dart | 2 - lib/widgets/malformedbubble.dart | 19 ++---- lib/widgets/messagerow.dart | 2 +- lib/widgets/passwordfield.dart | 5 +- lib/widgets/textfield.dart | 4 +- lib/widgets/tor_icon.dart | 10 +-- pubspec.yaml | 5 ++ 19 files changed, 183 insertions(+), 52 deletions(-) create mode 100644 assets/fonts/CwtchIcons.ttf create mode 100644 lib/cwtch_icons_icons.dart diff --git a/assets/fonts/CwtchIcons.ttf b/assets/fonts/CwtchIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a2dd204283366254a2e49ada78961c0d12922983 GIT binary patch literal 18488 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 this._timestamp; bool get ackd => this._ackd; bool get error => this._error; - get malformed => this._malformed; + bool get malformed => this._malformed; + bool get loaded => this._loaded; get senderOnion => this._senderOnion; get senderImage => this._senderImage; - get loaded => this._loaded; get signature => this._signature; get isInvite => this.overlay == 100 || this.overlay == 101; get inviteTarget => this._inviteTarget; @@ -423,13 +423,22 @@ class MessageState extends ChangeNotifier { notifyListeners(); } + set malformed(bool newVal) { + this._malformed = newVal; + notifyListeners(); + } + + set loaded(bool newVal) { + this._loaded = newVal; + notifyListeners(); + } + void tryLoad(BuildContext context) { Provider.of(context, listen: false).cwtch.GetMessage(profileOnion, contactHandle, messageIndex).then((jsonMessage) { try { dynamic messageWrapper = jsonDecode(jsonMessage); if (messageWrapper['Message'] == null || messageWrapper['Message'] == '' || messageWrapper['Message'] == '{}') { this._senderOnion = profileOnion; - //todo: remove once sent group messages are prestored Future.delayed(const Duration(milliseconds: 2), () { tryLoad(context); }); @@ -463,7 +472,7 @@ class MessageState extends ChangeNotifier { } } - this._loaded = true; + this.loaded = true; //update ackd and error last as they are changenotified this.ackd = messageWrapper['Acknowledged']; @@ -471,7 +480,9 @@ class MessageState extends ChangeNotifier { this.error = true; } } catch (e) { - this._malformed = true; + this._overlay = -1; + this.loaded = true; + this.malformed = true; } }); } diff --git a/lib/views/addcontactview.dart b/lib/views/addcontactview.dart index 2ab248c..6446aca 100644 --- a/lib/views/addcontactview.dart +++ b/lib/views/addcontactview.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:cwtch/errorHandler.dart'; @@ -80,7 +81,7 @@ class _AddContactViewState extends State { return TabBar( tabs: [ Tab( - icon: Icon(Icons.person_add_rounded), + icon: Icon(CwtchIcons.add_peer), text: AppLocalizations.of(context)!.addPeer, ), ], @@ -92,11 +93,11 @@ class _AddContactViewState extends State { return TabBar( tabs: [ Tab( - icon: Icon(Icons.person_add_rounded), + icon: Icon(CwtchIcons.add_peer), text: AppLocalizations.of(context)!.tooltipAddContact, ), //Tab(icon: Icon(Icons.backup), text: AppLocalizations.of(context)!.titleManageServers), - Tab(icon: Icon(Icons.group), text: AppLocalizations.of(context)!.createGroup), + Tab(icon: Icon(CwtchIcons.add_group), text: AppLocalizations.of(context)!.createGroup), ], ); } diff --git a/lib/views/addeditprofileview.dart b/lib/views/addeditprofileview.dart index b991c41..c27308c 100644 --- a/lib/views/addeditprofileview.dart +++ b/lib/views/addeditprofileview.dart @@ -99,6 +99,7 @@ class _AddEditProfileViewState extends State { ), CwtchTextField( controller: ctrlrNick, + autofocus: true, labelText: AppLocalizations.of(context)!.yourDisplayName, validator: (value) { if (value.isEmpty) { @@ -167,7 +168,7 @@ class _AddEditProfileViewState extends State { height: 20, ), ])), - CwtchLabel(label: AppLocalizations.of(context)!.password1Label), + CwtchLabel(label: AppLocalizations.of(context)!.newPassword), SizedBox( height: 20, ), diff --git a/lib/views/contactsview.dart b/lib/views/contactsview.dart index 1c5c077..d52709b 100644 --- a/lib/views/contactsview.dart +++ b/lib/views/contactsview.dart @@ -1,3 +1,4 @@ +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/material.dart'; import 'package:cwtch/views/torstatusview.dart'; import 'package:cwtch/widgets/contactrow.dart'; @@ -66,7 +67,7 @@ class _ContactsViewState extends State { floatingActionButton: FloatingActionButton( onPressed: _pushAddContact, tooltip: AppLocalizations.of(context)!.tooltipAddContact, - child: const Icon(Icons.person_add_sharp), + child: const Icon(CwtchIcons.person_add_alt_1_24px), ), body: showSearchBar || Provider.of(context).isFiltered ? _buildFilterable() : _buildContactList()); } diff --git a/lib/views/globalsettingsview.dart b/lib/views/globalsettingsview.dart index b776d77..1e8caf7 100644 --- a/lib/views/globalsettingsview.dart +++ b/lib/views/globalsettingsview.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:io'; +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:flutter/material.dart'; import 'package:cwtch/opaque.dart'; @@ -46,7 +47,7 @@ class _GlobalSettingsViewState extends State { child: Column(children: [ ListTile( title: Text(AppLocalizations.of(context)!.settingLanguage, style: TextStyle(color: settings.current().mainTextColor())), - leading: Icon(Icons.language, color: settings.current().mainTextColor()), + leading: Icon(CwtchIcons.change_language, color: settings.current().mainTextColor()), trailing: DropdownButton( value: Provider.of(context).locale.languageCode, onChanged: (String? newValue) { @@ -74,7 +75,9 @@ class _GlobalSettingsViewState extends State { // Save Settings... saveSettings(context); }, - secondary: Icon(Icons.lightbulb_outline, color: settings.current().mainTextColor()), + activeTrackColor: settings.theme.defaultButtonActiveColor(), + inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), + secondary: Icon(CwtchIcons.change_theme, color: settings.current().mainTextColor()), ), ListTile( title: Text(/*AppLocalizations.of(context)!.settingLanguage*/ "UI Columns", style: TextStyle(color: settings.current().mainTextColor())), @@ -111,7 +114,9 @@ class _GlobalSettingsViewState extends State { // Save Settings... saveSettings(context); }, - secondary: Icon(Icons.app_blocking, color: settings.current().mainTextColor()), + activeTrackColor: settings.theme.defaultButtonActiveColor(), + inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), + secondary: Icon(CwtchIcons.block_unknown, color: settings.current().mainTextColor()), ), SwitchListTile( title: Text(AppLocalizations.of(context)!.experimentsEnabled, style: TextStyle(color: settings.current().mainTextColor())), @@ -126,7 +131,9 @@ class _GlobalSettingsViewState extends State { // Save Settings... saveSettings(context); }, - secondary: Icon(Icons.science, color: settings.current().mainTextColor()), + activeTrackColor: settings.theme.defaultButtonActiveColor(), + inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), + secondary: Icon(CwtchIcons.enable_experiments, color: settings.current().mainTextColor()), ), Visibility( visible: settings.experimentsEnabled, @@ -145,7 +152,9 @@ class _GlobalSettingsViewState extends State { // Save Settings... saveSettings(context); }, - secondary: Icon(Icons.group_sharp, color: settings.current().mainTextColor()), + activeTrackColor: settings.theme.defaultButtonActiveColor(), + inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), + secondary: Icon(CwtchIcons.enable_groups, color: settings.current().mainTextColor()), ), ], )), diff --git a/lib/views/groupsettingsview.dart b/lib/views/groupsettingsview.dart index c4efe5d..422138e 100644 --- a/lib/views/groupsettingsview.dart +++ b/lib/views/groupsettingsview.dart @@ -1,3 +1,4 @@ +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/services.dart'; import 'package:cwtch/model.dart'; import 'package:cwtch/widgets/buttontextfield.dart'; @@ -135,12 +136,12 @@ class _GroupSettingsViewState extends State { height: 20, ), Tooltip( - message: AppLocalizations.of(context)!.rejectGroupBtn, + message: AppLocalizations.of(context)!.leaveGroup, child: ElevatedButton.icon( onPressed: () { showAlertDialog(context); }, - icon: Icon(Icons.delete), + icon: Icon(CwtchIcons.delete_24px), label: Text(AppLocalizations.of(context)!.leaveGroup), )) ]) diff --git a/lib/views/messageview.dart b/lib/views/messageview.dart index 1955481..04e4e99 100644 --- a/lib/views/messageview.dart +++ b/lib/views/messageview.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cwtch/views/peersettingsview.dart'; @@ -49,7 +50,7 @@ class _MessageViewState extends State { //IconButton(icon: Icon(Icons.chat), onPressed: _pushContactSettings), //IconButton(icon: Icon(Icons.list), onPressed: _pushContactSettings), //IconButton(icon: Icon(Icons.push_pin), onPressed: _pushContactSettings), - IconButton(icon: Icon(Icons.settings), tooltip: AppLocalizations.of(context)!.conversationSettings, onPressed: _pushContactSettings), + IconButton(icon: Provider.of(context, listen: false).isGroup == true ? Icon(CwtchIcons.group_settings_24px) : Icon(CwtchIcons.peer_settings_24px), tooltip: AppLocalizations.of(context)!.conversationSettings, onPressed: _pushContactSettings), ], ), body: Padding(padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 108.0), child: MessageList()), @@ -138,7 +139,7 @@ class _MessageViewState extends State { tooltip: "Send a contact or group invite", onPressed: () => _modalSendInvitation(context)), suffixIcon: IconButton( - icon: Icon(Icons.send, size: 24, color: Provider.of(context).theme.mainTextColor()), + icon: Icon(CwtchIcons.send_24px, size: 24, color: Provider.of(context).theme.mainTextColor()), tooltip: "Send Message", onPressed: _sendMessage, ), diff --git a/lib/views/peersettingsview.dart b/lib/views/peersettingsview.dart index ca9b5d4..7bd3cb3 100644 --- a/lib/views/peersettingsview.dart +++ b/lib/views/peersettingsview.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/services.dart'; import 'package:cwtch/model.dart'; import 'package:cwtch/widgets/buttontextfield.dart'; @@ -138,12 +139,14 @@ class _PeerSettingsViewState extends State { Provider.of(context, listen: false).cwtch.SendProfileEvent(profileOnion, setPeerAttributeJson); } }, - secondary: Icon(Icons.block, color: settings.current().mainTextColor()), + activeTrackColor: settings.theme.defaultButtonActiveColor(), + inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), + secondary: Icon(CwtchIcons.block_peer, color: settings.current().mainTextColor()), ), ListTile( title: Text(AppLocalizations.of(context)!.savePeerHistory, style: TextStyle(color: settings.current().mainTextColor())), subtitle: Text(AppLocalizations.of(context)!.savePeerHistoryDescription), - leading: Icon(Icons.history_sharp, color: settings.current().mainTextColor()), + leading: Icon(CwtchIcons.peer_history, color: settings.current().mainTextColor()), trailing: DropdownButton( value: Provider.of(context).savePeerHistory == "DefaultDeleteHistory" ? AppLocalizations.of(context)!.dontSavePeerHistory diff --git a/lib/views/profilemgrview.dart b/lib/views/profilemgrview.dart index 65ffdce..2b977d6 100644 --- a/lib/views/profilemgrview.dart +++ b/lib/views/profilemgrview.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/material.dart'; import 'package:cwtch/settings.dart'; import 'package:cwtch/views/torstatusview.dart'; @@ -11,6 +12,7 @@ import 'package:provider/provider.dart'; import '../main.dart'; import '../model.dart'; import '../opaque.dart'; +import '../torstatus.dart'; import 'addeditprofileview.dart'; import 'globalsettingsview.dart'; @@ -57,10 +59,13 @@ class _ProfileMgrViewState extends State { Expanded(child: Text(AppLocalizations.of(context)!.titleManageProfiles, style: TextStyle(color: settings.current().mainTextColor()))) ]), actions: [ - IconButton(icon: TorIcon(), onPressed: _pushTorStatus), + IconButton(icon: TorIcon(), onPressed: _pushTorStatus, tooltip: Provider.of(context).progress == 100 + ? AppLocalizations.of(context)!.networkStatusOnline + : (Provider.of(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor), + ), IconButton(icon: Icon(Icons.bug_report_outlined), onPressed: _setLoggingLevelDebug), IconButton( - icon: Icon(Icons.lock_open), + icon: Icon(CwtchIcons.lock_open_24px), tooltip: AppLocalizations.of(context)!.tooltipUnlockProfiles, onPressed: _modalUnlockProfiles, ), diff --git a/lib/widgets/invitationbubble.dart b/lib/widgets/invitationbubble.dart index 0187b15..00f6094 100644 --- a/lib/widgets/invitationbubble.dart +++ b/lib/widgets/invitationbubble.dart @@ -133,7 +133,6 @@ class InvitationBubbleState extends State { child: Row(children: [ SelectableText( chrome, - key: Key(myKey), focusNode: _focus, style: TextStyle( color: Provider.of(context).theme.messageFromMeTextColor(), @@ -161,7 +160,6 @@ class InvitationBubbleState extends State { child: Row(children: [ SelectableText( chrome, - key: Key(myKey), focusNode: _focus, style: TextStyle( color: Provider.of(context).theme.messageFromOtherTextColor(), diff --git a/lib/widgets/malformedbubble.dart b/lib/widgets/malformedbubble.dart index cc8bfcd..8c1339a 100644 --- a/lib/widgets/malformedbubble.dart +++ b/lib/widgets/malformedbubble.dart @@ -1,10 +1,6 @@ -import 'dart:convert'; -import 'dart:ffi'; - +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import '../settings.dart'; final Color malformedColor = Color(0xFFE85DA1); @@ -40,15 +36,10 @@ class MalformedBubbleState extends State { widthFactor: 1, child: Padding( padding: EdgeInsets.all(4), - child: Image( - image: AssetImage("assets/core/broken_heart_24.png"), - filterQuality: FilterQuality.medium, - // We need some theme specific blending here...we might want to consider making this a theme level attribute - colorBlendMode: BlendMode.srcIn, - color: Provider.of(context).theme.mainTextColor(), - isAntiAlias: false, - width: 32, - height: 32))), + child: Icon( + CwtchIcons.favorite_black_24dp_broken, + size: 24, + ))), Center( widthFactor: 1.0, child: Column( diff --git a/lib/widgets/messagerow.dart b/lib/widgets/messagerow.dart index 764ad5a..9c30359 100644 --- a/lib/widgets/messagerow.dart +++ b/lib/widgets/messagerow.dart @@ -34,7 +34,7 @@ class _MessageRowState extends State { Widget wdgBubble = Flexible( flex: 3, fit: FlexFit.loose, - child: malformed ? MalformedBubble() : (Provider.of(context).loaded == true ? widgetForOverlay(Provider.of(context).overlay) : MessageLoadingBubble())); + child: Provider.of(context).loaded == true ? widgetForOverlay(Provider.of(context).overlay) : MessageLoadingBubble()); Widget wdgIcons = Icon(Icons.delete_forever_outlined, color: Provider.of(context).theme.dropShadowColor()); Widget wdgSpacer = Expanded(child: SizedBox(width: 60, height: 10)); var widgetRow = []; diff --git a/lib/widgets/passwordfield.dart b/lib/widgets/passwordfield.dart index 7b8804d..5b095a0 100644 --- a/lib/widgets/passwordfield.dart +++ b/lib/widgets/passwordfield.dart @@ -1,3 +1,4 @@ +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../settings.dart'; @@ -5,7 +6,7 @@ import '../settings.dart'; // Provides a styled Password Input Field for use in Form Widgets. // Callers must provide a text controller, label helper text and a validator. class CwtchPasswordField extends StatefulWidget { - CwtchPasswordField({required this.controller, required this.validator, this.action, this.autofocus = true}); + CwtchPasswordField({required this.controller, required this.validator, this.action, this.autofocus = false}); final TextEditingController controller; final FormFieldValidator validator; final Function(String)? action; @@ -43,7 +44,7 @@ class _CwtchTextFieldState extends State { obscureText = !obscureText; }); }, - icon: Icon((obscureText ? Icons.remove_red_eye : Icons.remove_red_eye_outlined), semanticLabel: label), + icon: Icon((obscureText ? CwtchIcons.eye_closed : CwtchIcons.eye_open), semanticLabel: label), tooltip: label, color: theme.current().mainTextColor(), highlightColor: theme.current().defaultButtonColor(), diff --git a/lib/widgets/textfield.dart b/lib/widgets/textfield.dart index 4addae7..4b68593 100644 --- a/lib/widgets/textfield.dart +++ b/lib/widgets/textfield.dart @@ -7,11 +7,12 @@ doNothing(String x) {} // Provides a styled Text Field for use in Form Widgets. // Callers must provide a text controller, label helper text and a validator. class CwtchTextField extends StatefulWidget { - CwtchTextField({required this.controller, required this.labelText, this.validator = null, this.onChanged = doNothing}); + CwtchTextField({required this.controller, required this.labelText, this.validator = null, this.autofocus=false, this.onChanged = doNothing}); final TextEditingController controller; final String labelText; final FormFieldValidator? validator; final Function(String) onChanged; + final bool autofocus; @override _CwtchTextFieldState createState() => _CwtchTextFieldState(); @@ -25,6 +26,7 @@ class _CwtchTextFieldState extends State { controller: widget.controller, validator: widget.validator, onChanged: widget.onChanged, + autofocus: widget.autofocus, decoration: InputDecoration( labelText: widget.labelText, labelStyle: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()), diff --git a/lib/widgets/tor_icon.dart b/lib/widgets/tor_icon.dart index eb0c2bf..8ebf1ad 100644 --- a/lib/widgets/tor_icon.dart +++ b/lib/widgets/tor_icon.dart @@ -1,3 +1,4 @@ +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/cupertino.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -16,14 +17,9 @@ class _TorIconState extends State { @override Widget build(BuildContext context) { return RepaintBoundary( - child: Image( - image: AssetImage(Provider.of(context).progress == 0 - ? "assets/core/Tor_OFF.png" - : (Provider.of(context).progress == 100 ? "assets/core/Tor_icon.png" : "assets/core/Tor_Booting_up.png")), - // Color the onion per the text color... + child: Icon(Provider.of(context).progress == 0 ? CwtchIcons.onion_off : (Provider.of(context).progress == 100 ? CwtchIcons.onion_on: CwtchIcons.onion_waiting), color: Provider.of(context).theme.mainTextColor(), - colorBlendMode: BlendMode.srcIn, - semanticLabel: Provider.of(context).progress == 100 + semanticLabel: Provider.of(context).progress == 100 ? AppLocalizations.of(context)!.networkStatusOnline : (Provider.of(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor), )); diff --git a/pubspec.yaml b/pubspec.yaml index 34fc3c2..3bcc763 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -95,6 +95,11 @@ flutter: - assets/profiles/ - assets/servers/ + fonts: + - family: CwtchIcons + fonts: + - asset: assets/fonts/CwtchIcons.ttf + # To add custom fonts to your application, add a fonts section here, # in this "flutter" section. Each entry in this list should have a # "family" key with the font family name, and a "fonts" key with a From c6c9899a780e3a43aadecbe19bf20a3f3ee582ad Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Thu, 3 Jun 2021 12:37:17 -0700 Subject: [PATCH 02/15] windows: .ico and app name and menu name --- README.md | 14 ++++++++++---- windows/CMakeLists.txt | 4 ++-- .../flutter/generated_plugin_registrant.cc | 5 +++-- windows/flutter/generated_plugin_registrant.h | 2 -- windows/flutter/generated_plugins.cmake | 1 + windows/runner/Runner.rc | 12 ++++++------ windows/runner/main.cpp | 2 +- windows/runner/resources/app_icon.ico | Bin 33772 -> 67646 bytes 8 files changed, 23 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 3830e2b..da68d86 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # flwtch -A new Flutter application. +A Flutter based Cwtch UI ## Getting Started @@ -8,13 +8,19 @@ click the play button in android studio ### Linux -- libCwtch-go: the result of `make linux`, `libCwtch.so` should be in the link path +- libCwtch-go: required to be on the link path (linux/cwtch.destktop demonstrates with `env LD_LIBRARY_PATH=./lib/` on the front of the comman) + - fetch-libcwtch-go.sh will fetch a prebuilt version + - or compile from source from libcwtch-go with `make linux` - `tor` should be in the PATH ### Windows -- libCwtch-go: the result of `make windows`, `libCwtch.dll` should be placed in the source root -- tor is bundled in `windors/Tor` +- run `fetch-libcwtch-go.ps1` to get `libCwtch.dll` which is required to run +- run `fetch-tor-win.ps1` to fetch Tor for windows + +#### Issues + +- Flutter engine has a [known bug](https://github.com/flutter/flutter/issues/75675) around the Right Shift key being sticky. We have implemented the mostly work around, but until it is fixed, right shift occasionally acts permenent. If this happens, just tap left shift and it will reset ## l10n diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index a8e51aa..a1c031b 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.15) -project(flutter_app LANGUAGES CXX) +project(cwtch LANGUAGES CXX) -set(BINARY_NAME "flutter_app") +set(BINARY_NAME "cwtch") cmake_policy(SET CMP0063 NEW) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8b6d468..9deaa4e 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -2,10 +2,11 @@ // Generated file. Do not edit. // -// clang-format off - #include "generated_plugin_registrant.h" +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + WindowSizePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("WindowSizePlugin")); } diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h index dc139d8..9846246 100644 --- a/windows/flutter/generated_plugin_registrant.h +++ b/windows/flutter/generated_plugin_registrant.h @@ -2,8 +2,6 @@ // Generated file. Do not edit. // -// clang-format off - #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 4d10c25..154f238 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + window_size ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index 930c3e7..345f820 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -89,13 +89,13 @@ BEGIN BEGIN BLOCK "040904e4" BEGIN - VALUE "CompanyName", "com.example" "\0" - VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "CompanyName", "Open Privacy Research Society" "\0" + VALUE "FileDescription", "Cwtch Instant Messenger" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "flutter_app" "\0" - VALUE "LegalCopyright", "Copyright (C) 2021 com.example. All rights reserved." "\0" - VALUE "OriginalFilename", "flutter_app.exe" "\0" - VALUE "ProductName", "flutter_app" "\0" + VALUE "InternalName", "cwtch" "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 Open Privacy Research Society. All rights reserved." "\0" + VALUE "OriginalFilename", "cwtch.exe" "\0" + VALUE "ProductName", "Cwtch" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" END END diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp index b67fe12..f52513a 100644 --- a/windows/runner/main.cpp +++ b/windows/runner/main.cpp @@ -30,7 +30,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(&run_loop, project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"flutter_app", origin, size)) { + if (!window.CreateAndShow(L"cwtch", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index c04e20caf6370ebb9253ad831cc31de4a9c965f6..7e2acda6c8744da8d2b3757e5036779a0c96c916 100644 GIT binary patch literal 67646 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 From dbdb62b8e2a10715b10a54071512fb1d36bc8730 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Thu, 3 Jun 2021 14:34:21 -0700 Subject: [PATCH 03/15] windows icon sizing and WNDCLASSEX for small icon --- windows/runner/Runner.rc | 11 +++++++- windows/runner/resource.h | 11 +++++++- windows/runner/resources/app_icon.ico | Bin 67646 -> 0 bytes windows/runner/resources/knot_128.ico | Bin 0 -> 67646 bytes windows/runner/resources/knot_16.ico | Bin 0 -> 1150 bytes windows/runner/resources/knot_256.ico | Bin 0 -> 25028 bytes windows/runner/resources/knot_32.ico | Bin 0 -> 4286 bytes windows/runner/resources/knot_48.ico | Bin 0 -> 9662 bytes windows/runner/resources/knot_64.ico | Bin 0 -> 16958 bytes windows/runner/win32_window.cpp | 37 +++++++++++++++++++++++--- 10 files changed, 54 insertions(+), 5 deletions(-) delete mode 100644 windows/runner/resources/app_icon.ico create mode 100644 windows/runner/resources/knot_128.ico create mode 100644 windows/runner/resources/knot_16.ico create mode 100644 windows/runner/resources/knot_256.ico create mode 100644 windows/runner/resources/knot_32.ico create mode 100644 windows/runner/resources/knot_48.ico create mode 100644 windows/runner/resources/knot_64.ico diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index 345f820..d0b3323 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -52,7 +52,16 @@ END // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDI_APP_ICON ICON "resources\\app_icon.ico" +IDI_APP_ICON_LG ICON "resources\\knot_256.ico" +IDI_APP_ICON_SM ICON "resources\\knot_64.ico" + +IDI_APP_ICON_256 ICON "resources\\knot_256.ico" +IDI_APP_ICON_128 ICON "resources\\knot_128.ico" +IDI_APP_ICON_64 ICON "resources\\knot_64.ico" +IDI_APP_ICON_48 ICON "resources\\knot_48.ico" +IDI_APP_ICON_32 ICON "resources\\knot_32.ico" +IDI_APP_ICON_16 ICON "resources\\knot_16.ico" + ///////////////////////////////////////////////////////////////////////////// diff --git a/windows/runner/resource.h b/windows/runner/resource.h index 66a65d1..48e5f82 100644 --- a/windows/runner/resource.h +++ b/windows/runner/resource.h @@ -2,7 +2,16 @@ // Microsoft Visual C++ generated include file. // Used by Runner.rc // -#define IDI_APP_ICON 101 +#define IDI_APP_ICON_LG 101 +#define IDI_APP_ICON_SM 102 + +#define IDI_APP_ICON_256 103 +#define IDI_APP_ICON_128 104 +#define IDI_APP_ICON_64 105 +#define IDI_APP_ICON_48 106 +#define IDI_APP_ICON_32 107 +#define IDI_APP_ICON_16 108 + // Next default values for new objects // diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico deleted file mode 100644 index 7e2acda6c8744da8d2b3757e5036779a0c96c916..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67646 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 AdH?_b literal 0 HcmV?d00001 diff --git a/windows/runner/resources/knot_16.ico b/windows/runner/resources/knot_16.ico new file mode 100644 index 0000000000000000000000000000000000000000..42fa6e969cbf60aaf593720f74ed7d5bf2189ea9 GIT binary patch literal 1150 zcma)6%WhIp6g?UT#)%y?Moml{`U%ECCw6M$(3B5Ai8Xd$qJe=!BbcTzsB{8|2?M;WDvtZJI+!6KZdBII!>9Yp=cbIc4k${#I5PKJT;V*BHCS z7<+()5F%%BY?pm*RI62^D2h2j5F8$l=gVX=$+uc9%l`g8QD68}DwPkNPUldk)2*da zscxguIMrx05^x#u-E?6xUe@dN1Gn3~)o! zfu^np_A23tBb`o*;M36Wa}V{qgLPakmp{eh@gK!vF%yYIb~r8;i@k#O6ZDhvdc6u@ ze}T(rv)NX2xtt!g4t+k~MxjvX!l$v*>3mF@QB#}AWE8{Uu7j@qe zUZqmqlgs6IQRgU|&F=AjhyzPR+*K--_Rw!1>oeZZ{6hX)%2z6tlz#^}_xXI({u>Mi zzb)z~4WUp-HX4nV>W@aF+r%xC$!7Ywe}2DzgZjwl^96^)u}+u;{~F{UJQJXI0{=EK z(Y{Mbcoetu|f zxC?5ITebuDlb>JmgZFE(SR}Ypp=EhI&hL-GU|53=0h&+LYV|W{zSR8z&;0)4Y#8aB jj>qGr_jhoUvH9A@|BClq31io9pDiAtcLQMNc;x;Aov18m literal 0 HcmV?d00001 diff --git a/windows/runner/resources/knot_256.ico b/windows/runner/resources/knot_256.ico new file mode 100644 index 0000000000000000000000000000000000000000..2e0f50a18b8e62655fff877e27ecc1e9ddba62dc GIT binary patch literal 25028 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 z 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 literal 0 HcmV?d00001 diff --git a/windows/runner/resources/knot_32.ico b/windows/runner/resources/knot_32.ico new file mode 100644 index 0000000000000000000000000000000000000000..da12547828b6625a2818d84998670c4bf27963e7 GIT binary patch literal 4286 zcmb_gTTE0}6ukp}V3P_zZR}4)O%wcU3SVtwF>T6^*rq9wD*jY!ZQ7(Xnl_|BM}efa zi5jGU0}+G@2=dS>6+sw4gh3E_LwN`ci0BM&v*3F#BopG2>I$Sf%opbitd!N1c zTKgO&NrQj>{u2L6d47`gx+F;f_+Us1#)sn@@Vs{C&YjX1k&$n2fIXXvu&}W00|Ns_+2NU+o0GG$vPNcRW-RKd zsi~=z%*@QsZ3;Yl@oH^tZKM8?krCt7t5<(0EG&%d#>26tr6oBhCugL*ygWWHFYoK- z=H_~iKYjXiAt)$lr)Q=mNvqZFd-39hY%-ai@87@wE$WMpkN@Dog9j$~GQ7IFDlacD z%OxcxF;-ifJ3BjD=|fFT%~?P8$=gb$2^UavpPHSoFE6Wi9c z{?DF0vlJB-4LaC+S7*g89vkGA@4mq@<*L+0xRYyLaziBJ%tRWW5p+5`x9Pf$eeRBOl|Noaur6 z6Dun#^8Ea~oS&a>6g3$h9v)O#S($*k)S*VAv39F^eMCgWj*gCwUivK_);zeT`{Kom z{fmo>tfgjy!Cl}MD-nw;boI3casHn)qly`c1y0TB|fUniX#l`1{J;n=o&wt=RLp4* zqoYFp_U+px4*c*7ZG?n`?BQBKdJY&(=R0DPu^zr*PuVl$e*OA&9d*RU#_k>)8#9sn zS$7fFjLcKAj=`G$4K zy+SsM_JV_h{ZF4h{W0I8qN3h2o6QPF5vM{7+101;p})U>sj;!~5$)r<0CK*l*A{p1 z4c~udK3QwWfYu7e+?5k@bH#gS^`yYWL57RdLWm#F-BfdL}Kk$0&KjQ!X z>^$P=8;zQ-8pH828Eg zbA>;0ePUwb34tfnRUXVZ#UFBG!=K< z{vp1ppHD+W!@B$<&SdB(Q#WtkwDkh0x8ooDR`c%+I8BE-%(voE$tUdeLC%hU5es5x zUH-)$^1!Ledd83ZiyS9A@-K8qhYlTL|512Z*%s1zlRZP_TTfTPMxy#UvTRvFsdj)KFT5MwEqHA z->W$vy+JvT9XN16-G6ybwCle#?&^WfTsjZFo&txILe?oisPT;$bVE+bk1O47%xwd& zT8Mqrs&WT##t&+Iv){7*$n9?EcPRp0;{4gY9zO`%qQ9U%&M;mZasEW^f3oU&>HJN8 z!1*T85#PYuhMm8~{R3xU+xFoZ=GXv}m0L%8^MzXB;&oDRDyDMh9f8*+DU~F-2 zeg})+@Z|n2>%C=JtC3|%l4T!1S@!e6yH=JpI3mUkVR|S|tI=!F6$oZO{P%*76z{Lq j)a=oF562Dh!*`Bxjxvy literal 0 HcmV?d00001 diff --git a/windows/runner/resources/knot_48.ico b/windows/runner/resources/knot_48.ico new file mode 100644 index 0000000000000000000000000000000000000000..169ba2c7b942a537f3c80a98efc3144a492efdb7 GIT binary patch literal 9662 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 kZrNnvLpCvADxXG`Z=h($ literal 0 HcmV?d00001 diff --git a/windows/runner/resources/knot_64.ico b/windows/runner/resources/knot_64.ico new file mode 100644 index 0000000000000000000000000000000000000000..74a28e03b82a2cea8e750e027e024b0d2bebcf61 GIT binary patch literal 16958 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 literal 0 HcmV?d00001 diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index c10f08d..ad68d53 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -1,4 +1,5 @@ #include "win32_window.h" +#include "winuser.h" #include @@ -70,19 +71,49 @@ WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; const wchar_t* WindowClassRegistrar::GetWindowClass() { if (!class_registered_) { - WNDCLASS window_class{}; + WNDCLASSEX window_class{}; + window_class.cbSize = sizeof(WNDCLASSEX); window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); window_class.lpszClassName = kWindowClassName; window_class.style = CS_HREDRAW | CS_VREDRAW; window_class.cbClsExtra = 0; window_class.cbWndExtra = 0; window_class.hInstance = GetModuleHandle(nullptr); + int icon_sz = GetSystemMetrics(SM_CXICON); + int iconh_id = IDI_APP_ICON_32; + if (icon_sz > 128) { + iconh_id = IDI_APP_ICON_256; + } else if (icon_sz > 64) { + iconh_id = IDI_APP_ICON_128; + } else if (icon_sz > 48) { + iconh_id = IDI_APP_ICON_64; + } else if (icon_sz > 32) { + iconh_id = IDI_APP_ICON_48; + } window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(iconh_id)); + + + int icon_sm_sz = GetSystemMetrics(SM_CXSMICON); + int iconsmh_id = IDI_APP_ICON_16; + if (icon_sm_sz > 128) { + iconsmh_id = IDI_APP_ICON_256; + } else if (icon_sm_sz > 64) { + iconsmh_id = IDI_APP_ICON_128; + } else if (icon_sm_sz > 48) { + iconsmh_id = IDI_APP_ICON_64; + } else if (icon_sm_sz > 32) { + iconsmh_id = IDI_APP_ICON_48; + } else if (icon_sm_sz > 16) { + iconsmh_id = IDI_APP_ICON_32; + } + window_class.hIconSm = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(iconsmh_id)); + window_class.hbrBackground = 0; window_class.lpszMenuName = nullptr; window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); + RegisterClassEx(&window_class); class_registered_ = true; } return kWindowClassName; From 0858e4fd2bb63ddcdca15362e7025a7f8c2ecdd4 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Thu, 3 Jun 2021 21:16:54 -0700 Subject: [PATCH 04/15] case insensitive search + onion search only from start --- lib/model.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/model.dart b/lib/model.dart index 97d7c83..71ce029 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -64,13 +64,13 @@ class ContactListState extends ChangeNotifier { bool get isFiltered => _filter != ""; String get filter => _filter; set filter(String newVal) { - _filter = newVal; + _filter = newVal.toLowerCase(); notifyListeners(); } List filteredList() { if (!isFiltered) return contacts; - return _contacts.where((ContactInfoState c) => c.onion.contains(_filter) || (c.nickname.contains(_filter))).toList(); + return _contacts.where((ContactInfoState c) => c.onion.toLowerCase().startsWith(_filter) || (c.nickname.toLowerCase().contains(_filter))).toList(); } void addAll(Iterable newContacts) { From f4f885fcea156739b3c7be424b985e2b8649c172 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 4 Jun 2021 11:13:52 -0700 Subject: [PATCH 05/15] New experiment checking method. --- lib/config.dart | 2 +- lib/cwtch_icons_icons.dart | 2 +- lib/model.dart | 6 +++--- lib/settings.dart | 15 ++++++++++++++- lib/views/addcontactview.dart | 4 ++-- lib/views/globalsettingsview.dart | 2 +- lib/views/messageview.dart | 5 ++++- lib/views/profilemgrview.dart | 11 +++++++---- lib/widgets/malformedbubble.dart | 3 +-- lib/widgets/messagerow.dart | 6 ++---- lib/widgets/textfield.dart | 2 +- lib/widgets/tor_icon.dart | 5 +++-- 12 files changed, 40 insertions(+), 23 deletions(-) diff --git a/lib/config.dart b/lib/config.dart index 281f4c0..7d0c4b8 100644 --- a/lib/config.dart +++ b/lib/config.dart @@ -3,4 +3,4 @@ const dev_version = "development"; class EnvironmentConfig { static const BUILD_VER = String.fromEnvironment('BUILD_VER', defaultValue: dev_version); static const BUILD_DATE = String.fromEnvironment('BUILD_DATE', defaultValue: "now"); -} \ No newline at end of file +} diff --git a/lib/cwtch_icons_icons.dart b/lib/cwtch_icons_icons.dart index 127cfcf..c9f51b0 100644 --- a/lib/cwtch_icons_icons.dart +++ b/lib/cwtch_icons_icons.dart @@ -11,7 +11,7 @@ /// fonts: /// - asset: assets/fonts/CwtchIcons.ttf /// -/// +/// /// import 'package:flutter/widgets.dart'; diff --git a/lib/model.dart b/lib/model.dart index 71ce029..a07fb07 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -480,9 +480,9 @@ class MessageState extends ChangeNotifier { this.error = true; } } catch (e) { - this._overlay = -1; - this.loaded = true; - this.malformed = true; + this._overlay = -1; + this.loaded = true; + this.malformed = true; } }); } diff --git a/lib/settings.dart b/lib/settings.dart index cc59de2..0b52cbb 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -16,7 +16,8 @@ class Settings extends ChangeNotifier { Locale locale; late PackageInfo packageInfo; OpaqueThemeType theme; - late bool experimentsEnabled; + // explicitly set experiments to false until told otherwise... + bool experimentsEnabled = false; HashMap experiments = HashMap.identity(); late bool blockUnknownConnections; @@ -38,6 +39,18 @@ class Settings extends ChangeNotifier { return theme; } + /// isExperimentEnabled can be used to safely check whether a particular + /// experiment is enabled + bool isExperimentEnabled(String experiment) { + if (this.experimentsEnabled) { + if (this.experiments.containsKey(experiment)) { + // We now know it cannot be null... + return this.experiments[experiment]! == true; + } + } + return false; + } + /// Called by the event bus. When new settings are loaded from a file the JSON will /// be sent to the function and new settings will be instantiated based on the contents. handleUpdate(dynamic settings) { diff --git a/lib/views/addcontactview.dart b/lib/views/addcontactview.dart index 6446aca..ead0518 100644 --- a/lib/views/addcontactview.dart +++ b/lib/views/addcontactview.dart @@ -50,8 +50,8 @@ class _AddContactViewState extends State { Widget _buildForm() { ctrlrOnion.text = Provider.of(context).onion; - /// We display a different number of tabs dependening on the experiment setup - bool groupsEnabled = Provider.of(context).experimentsEnabled && Provider.of(context).experiments[TapirGroupsExperiment]!; + /// We display a different number of tabs depending on the experiment setup + bool groupsEnabled = Provider.of(context).isExperimentEnabled(TapirGroupsExperiment); return Consumer(builder: (context, globalErrorHandler, child) { return DefaultTabController( length: groupsEnabled ? 2 : 1, diff --git a/lib/views/globalsettingsview.dart b/lib/views/globalsettingsview.dart index 1e8caf7..c17c6f0 100644 --- a/lib/views/globalsettingsview.dart +++ b/lib/views/globalsettingsview.dart @@ -142,7 +142,7 @@ class _GlobalSettingsViewState extends State { SwitchListTile( title: Text(AppLocalizations.of(context)!.enableGroups, style: TextStyle(color: settings.current().mainTextColor())), subtitle: Text(AppLocalizations.of(context)!.descriptionExperimentsGroups), - value: settings.experiments.containsKey(TapirGroupsExperiment) && settings.experiments[TapirGroupsExperiment]!, + value: settings.isExperimentEnabled(TapirGroupsExperiment), onChanged: (bool value) { if (value) { settings.enableExperiment(TapirGroupsExperiment); diff --git a/lib/views/messageview.dart b/lib/views/messageview.dart index 04e4e99..6131854 100644 --- a/lib/views/messageview.dart +++ b/lib/views/messageview.dart @@ -50,7 +50,10 @@ class _MessageViewState extends State { //IconButton(icon: Icon(Icons.chat), onPressed: _pushContactSettings), //IconButton(icon: Icon(Icons.list), onPressed: _pushContactSettings), //IconButton(icon: Icon(Icons.push_pin), onPressed: _pushContactSettings), - IconButton(icon: Provider.of(context, listen: false).isGroup == true ? Icon(CwtchIcons.group_settings_24px) : Icon(CwtchIcons.peer_settings_24px), tooltip: AppLocalizations.of(context)!.conversationSettings, onPressed: _pushContactSettings), + IconButton( + icon: Provider.of(context, listen: false).isGroup == true ? Icon(CwtchIcons.group_settings_24px) : Icon(CwtchIcons.peer_settings_24px), + tooltip: AppLocalizations.of(context)!.conversationSettings, + onPressed: _pushContactSettings), ], ), body: Padding(padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 108.0), child: MessageList()), diff --git a/lib/views/profilemgrview.dart b/lib/views/profilemgrview.dart index 2b977d6..e0f708f 100644 --- a/lib/views/profilemgrview.dart +++ b/lib/views/profilemgrview.dart @@ -59,10 +59,13 @@ class _ProfileMgrViewState extends State { Expanded(child: Text(AppLocalizations.of(context)!.titleManageProfiles, style: TextStyle(color: settings.current().mainTextColor()))) ]), actions: [ - IconButton(icon: TorIcon(), onPressed: _pushTorStatus, tooltip: Provider.of(context).progress == 100 - ? AppLocalizations.of(context)!.networkStatusOnline - : (Provider.of(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor), - ), + IconButton( + icon: TorIcon(), + onPressed: _pushTorStatus, + tooltip: Provider.of(context).progress == 100 + ? AppLocalizations.of(context)!.networkStatusOnline + : (Provider.of(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor), + ), IconButton(icon: Icon(Icons.bug_report_outlined), onPressed: _setLoggingLevelDebug), IconButton( icon: Icon(CwtchIcons.lock_open_24px), diff --git a/lib/widgets/malformedbubble.dart b/lib/widgets/malformedbubble.dart index 8c1339a..fea7c1a 100644 --- a/lib/widgets/malformedbubble.dart +++ b/lib/widgets/malformedbubble.dart @@ -1,7 +1,6 @@ import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/material.dart'; - final Color malformedColor = Color(0xFFE85DA1); // MalformedBubble is displayed in the case of a malformed message @@ -38,7 +37,7 @@ class MalformedBubbleState extends State { padding: EdgeInsets.all(4), child: Icon( CwtchIcons.favorite_black_24dp_broken, - size: 24, + size: 24, ))), Center( widthFactor: 1.0, diff --git a/lib/widgets/messagerow.dart b/lib/widgets/messagerow.dart index 9c30359..8f02b96 100644 --- a/lib/widgets/messagerow.dart +++ b/lib/widgets/messagerow.dart @@ -31,10 +31,8 @@ class _MessageRowState extends State { fromMe = false; } - Widget wdgBubble = Flexible( - flex: 3, - fit: FlexFit.loose, - child: Provider.of(context).loaded == true ? widgetForOverlay(Provider.of(context).overlay) : MessageLoadingBubble()); + Widget wdgBubble = + Flexible(flex: 3, fit: FlexFit.loose, child: Provider.of(context).loaded == true ? widgetForOverlay(Provider.of(context).overlay) : MessageLoadingBubble()); Widget wdgIcons = Icon(Icons.delete_forever_outlined, color: Provider.of(context).theme.dropShadowColor()); Widget wdgSpacer = Expanded(child: SizedBox(width: 60, height: 10)); var widgetRow = []; diff --git a/lib/widgets/textfield.dart b/lib/widgets/textfield.dart index 4b68593..cd396c7 100644 --- a/lib/widgets/textfield.dart +++ b/lib/widgets/textfield.dart @@ -7,7 +7,7 @@ doNothing(String x) {} // Provides a styled Text Field for use in Form Widgets. // Callers must provide a text controller, label helper text and a validator. class CwtchTextField extends StatefulWidget { - CwtchTextField({required this.controller, required this.labelText, this.validator = null, this.autofocus=false, this.onChanged = doNothing}); + CwtchTextField({required this.controller, required this.labelText, this.validator = null, this.autofocus = false, this.onChanged = doNothing}); final TextEditingController controller; final String labelText; final FormFieldValidator? validator; diff --git a/lib/widgets/tor_icon.dart b/lib/widgets/tor_icon.dart index 8ebf1ad..796e2a5 100644 --- a/lib/widgets/tor_icon.dart +++ b/lib/widgets/tor_icon.dart @@ -17,9 +17,10 @@ class _TorIconState extends State { @override Widget build(BuildContext context) { return RepaintBoundary( - child: Icon(Provider.of(context).progress == 0 ? CwtchIcons.onion_off : (Provider.of(context).progress == 100 ? CwtchIcons.onion_on: CwtchIcons.onion_waiting), + child: Icon( + Provider.of(context).progress == 0 ? CwtchIcons.onion_off : (Provider.of(context).progress == 100 ? CwtchIcons.onion_on : CwtchIcons.onion_waiting), color: Provider.of(context).theme.mainTextColor(), - semanticLabel: Provider.of(context).progress == 100 + semanticLabel: Provider.of(context).progress == 100 ? AppLocalizations.of(context)!.networkStatusOnline : (Provider.of(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor), )); From dcefa305809815a837abb4f960653602f4926a8e Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 4 Jun 2021 13:17:40 -0700 Subject: [PATCH 06/15] Disconnected and Ephemeral Warnings --- lib/l10n/intl_de.arb | 1 + lib/l10n/intl_en.arb | 1 + lib/l10n/intl_es.arb | 1 + lib/l10n/intl_fr.arb | 1 + lib/l10n/intl_it.arb | 1 + lib/l10n/intl_pt.arb | 1 + lib/opaque.dart | 16 ++++++++-------- lib/widgets/messagelist.dart | 25 ++++++++++++++++++------- 8 files changed, 32 insertions(+), 15 deletions(-) diff --git a/lib/l10n/intl_de.arb b/lib/l10n/intl_de.arb index 3d1a360..902c84b 100644 --- a/lib/l10n/intl_de.arb +++ b/lib/l10n/intl_de.arb @@ -17,6 +17,7 @@ "builddate": "Aufgebaut auf: %2", "bulletinsBtn": "Meldungen", "chatBtn": "Chat", + "chatHistoryDefault": "", "contactAlreadyExists": "", "conversationSettings": "", "copiedClipboardNotification": "in die Zwischenablage kopiert", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 8ce8f99..2f37d53 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -17,6 +17,7 @@ "builddate": "Built on: %2", "bulletinsBtn": "Bulletins", "chatBtn": "Chat", + "chatHistoryDefault": "This conversation will be deleted when Cwtch is closed! Message history can be enabled per-conversation via the Settings menu in the upper right.", "contactAlreadyExists": "Contact Already Exists", "conversationSettings": "Conversation Settings", "copiedClipboardNotification": "Copied to clipboard", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index 02694e9..f4ad2b9 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -17,6 +17,7 @@ "builddate": "Basado en: %2", "bulletinsBtn": "Boletines", "chatBtn": "Chat", + "chatHistoryDefault": "", "contactAlreadyExists": "", "conversationSettings": "", "copiedClipboardNotification": "Copiado al portapapeles", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 59bee35..6df2f99 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -17,6 +17,7 @@ "builddate": "", "bulletinsBtn": "Bulletins", "chatBtn": "Discuter", + "chatHistoryDefault": "", "contactAlreadyExists": "", "conversationSettings": "", "copiedClipboardNotification": "Copié dans le presse-papier", diff --git a/lib/l10n/intl_it.arb b/lib/l10n/intl_it.arb index fd1d432..fee6328 100644 --- a/lib/l10n/intl_it.arb +++ b/lib/l10n/intl_it.arb @@ -17,6 +17,7 @@ "builddate": "Costruito il: %2", "bulletinsBtn": "Bollettini", "chatBtn": "Chat", + "chatHistoryDefault": "", "contactAlreadyExists": "", "conversationSettings": "", "copiedClipboardNotification": "Copiato negli Appunti", diff --git a/lib/l10n/intl_pt.arb b/lib/l10n/intl_pt.arb index ef4ab54..772eb42 100644 --- a/lib/l10n/intl_pt.arb +++ b/lib/l10n/intl_pt.arb @@ -17,6 +17,7 @@ "builddate": "", "bulletinsBtn": "Boletins", "chatBtn": "Chat", + "chatHistoryDefault": "", "contactAlreadyExists": "", "conversationSettings": "", "copiedClipboardNotification": "Copiado", diff --git a/lib/opaque.dart b/lib/opaque.dart index 268646f..5615486 100644 --- a/lib/opaque.dart +++ b/lib/opaque.dart @@ -1357,14 +1357,14 @@ ThemeData mkThemeData(Settings opaque) { ), cardColor: opaque.current().backgroundMainColor(), appBarTheme: AppBarTheme( - backgroundColor: opaque.current().backgroundPaneColor(), - titleTextStyle: TextStyle( - color: opaque.current().mainTextColor(), - ), - actionsIconTheme: IconThemeData( - color: opaque.current().mainTextColor(), - ), - ), + backgroundColor: opaque.current().backgroundPaneColor(), + titleTextStyle: TextStyle( + color: opaque.current().mainTextColor(), + ), + actionsIconTheme: IconThemeData( + color: opaque.current().mainTextColor(), + )), + bottomNavigationBarTheme: BottomNavigationBarThemeData(type: BottomNavigationBarType.fixed, backgroundColor: opaque.current().backgroundHilightElementColor()), textButtonTheme: TextButtonThemeData( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(opaque.current().defaultButtonColor()), diff --git a/lib/widgets/messagelist.dart b/lib/widgets/messagelist.dart index dd89b23..1101353 100644 --- a/lib/widgets/messagelist.dart +++ b/lib/widgets/messagelist.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; - +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import '../model.dart'; import '../settings.dart'; import 'messagerow.dart'; @@ -17,10 +17,21 @@ class _MessageListState extends State { Widget build(BuildContext outerContext) { return RepaintBoundary( child: Container( - child: Scrollbar( - isAlwaysShown: true, - controller: ctrlr1, - child: Container( + child: Column(children: [ + Visibility( + visible: Provider.of(context).isOnline() == false || Provider.of(context).savePeerHistory != "SaveHistory", + child: Container( + padding: EdgeInsets.all(5.0), + color: Provider.of(context).theme.defaultButtonActiveColor(), + child: Provider.of(context).isOnline() == false + ? Text(Provider.of(context).isGroup ? AppLocalizations.of(context)!.serverConnectivityDisconnected : AppLocalizations.of(context)!.peerOfflineMessage) + : (Provider.of(context).savePeerHistory != "SaveHistory" ? Text(AppLocalizations.of(context)!.chatHistoryDefault) : Text("")), + )), + Expanded( + child: Scrollbar( + isAlwaysShown: true, + controller: ctrlr1, + child: Container( // Only show broken heart is the contact is offline... decoration: BoxDecoration( image: Provider.of(outerContext).isOnline() @@ -51,7 +62,7 @@ class _MessageListState extends State { return RepaintBoundary(child: MessageRow(key: Provider.of(bcontext).getMessageKey(idx))); }); }, - ), - )))); + )))) + ]))); } } From b2cee259cbb7e7995437d3d9f5119605648fe839 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 4 Jun 2021 14:38:29 -0700 Subject: [PATCH 07/15] Clean conversation warning logic --- lib/cwtch/cwtchNotifier.dart | 2 ++ lib/widgets/contactrow.dart | 2 +- lib/widgets/messagelist.dart | 14 +++++++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index 89565b4..b25034d 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -190,6 +190,7 @@ class CwtchNotifier { ServerInfoState? serverInfoState = profileCN.getProfile(data["ProfileOnion"])?.serverList.getServer(groupInvite["ServerHost"]); if (serverInfoState != null) { status = serverInfoState.status; + print("Found Server Status in Cache $status"); } if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(groupInvite["GroupID"]) == null) { @@ -207,6 +208,7 @@ class CwtchNotifier { break; case "AcceptGroupInvite": print("accept group invite: $data"); + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.isInvitation = false; profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["GroupID"], DateTime.now()); break; diff --git a/lib/widgets/contactrow.dart b/lib/widgets/contactrow.dart index f76f5a8..b7ea3aa 100644 --- a/lib/widgets/contactrow.dart +++ b/lib/widgets/contactrow.dart @@ -50,7 +50,7 @@ class _ContactRowState extends State { ))), Padding( padding: const EdgeInsets.all(5.0), - child: contact.isInvitation != null && contact.isInvitation + child: contact.isInvitation == true ? Wrap(direction: Axis.vertical, children: [ IconButton( padding: EdgeInsets.zero, diff --git a/lib/widgets/messagelist.dart b/lib/widgets/messagelist.dart index 1101353..e6d43d6 100644 --- a/lib/widgets/messagelist.dart +++ b/lib/widgets/messagelist.dart @@ -15,17 +15,25 @@ class _MessageListState extends State { @override Widget build(BuildContext outerContext) { + bool showEphemeralWarning = (Provider.of(context).isGroup == false && Provider.of(context).savePeerHistory != "SaveHistory"); + bool showOfflineWarning = Provider.of(context).isOnline() == false; + bool showMessageWarning = showEphemeralWarning || showOfflineWarning; return RepaintBoundary( child: Container( child: Column(children: [ Visibility( - visible: Provider.of(context).isOnline() == false || Provider.of(context).savePeerHistory != "SaveHistory", + visible: showMessageWarning, child: Container( padding: EdgeInsets.all(5.0), color: Provider.of(context).theme.defaultButtonActiveColor(), - child: Provider.of(context).isOnline() == false + child: showOfflineWarning ? Text(Provider.of(context).isGroup ? AppLocalizations.of(context)!.serverConnectivityDisconnected : AppLocalizations.of(context)!.peerOfflineMessage) - : (Provider.of(context).savePeerHistory != "SaveHistory" ? Text(AppLocalizations.of(context)!.chatHistoryDefault) : Text("")), + // Only show the ephemeral status for peer conversations, not for groups... + : (showEphemeralWarning + ? Text(AppLocalizations.of(context)!.chatHistoryDefault) + : + // We are not allowed to put null here, so put an empty text widge + Text("")), )), Expanded( child: Scrollbar( From d27d9b674144c21a6396a98c90c2ec1ea75c02e1 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 4 Jun 2021 14:39:03 -0700 Subject: [PATCH 08/15] Remove print --- lib/cwtch/cwtchNotifier.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index b25034d..021f94c 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -190,7 +190,6 @@ class CwtchNotifier { ServerInfoState? serverInfoState = profileCN.getProfile(data["ProfileOnion"])?.serverList.getServer(groupInvite["ServerHost"]); if (serverInfoState != null) { status = serverInfoState.status; - print("Found Server Status in Cache $status"); } if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(groupInvite["GroupID"]) == null) { From 3f4c313d733dfa807a613e5fe2ab3041fe30ab4b Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 4 Jun 2021 15:00:09 -0700 Subject: [PATCH 09/15] Fix heart color --- assets/core/negative_heart_24px.svg | 16 ++++++++-------- lib/widgets/messagelist.dart | 11 +++++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/assets/core/negative_heart_24px.svg b/assets/core/negative_heart_24px.svg index 6042d52..f25b904 100644 --- a/assets/core/negative_heart_24px.svg +++ b/assets/core/negative_heart_24px.svg @@ -17,10 +17,10 @@ style="enable-background:new 0 0 24 24;" xml:space="preserve" sodipodi:docname="negative_heart_24px.svg" - inkscape:export-filename="/home/sarah/AndroidStudioProjects/flutter_app/assets/core/negative_heart_512px.png" - inkscape:export-xdpi="4096" - inkscape:export-ydpi="4096" - inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">image/svg+xml