diff --git a/LIBCWTCH-GO-MACOS.version b/LIBCWTCH-GO-MACOS.version index 5c6fe988..71778c8a 100644 --- a/LIBCWTCH-GO-MACOS.version +++ b/LIBCWTCH-GO-MACOS.version @@ -1 +1 @@ -2022-11-30-14-27-v1.10.0 \ No newline at end of file +2022-12-05-13-24-v1.10.0-6-g0d05a07 \ No newline at end of file diff --git a/LIBCWTCH-GO.version b/LIBCWTCH-GO.version index e13a9db5..b719558a 100644 --- a/LIBCWTCH-GO.version +++ b/LIBCWTCH-GO.version @@ -1 +1 @@ -2022-11-30-19-28-v1.10.0 \ No newline at end of file +2022-12-05-18-24-v1.10.0-6-g0d05a07 \ No newline at end of file diff --git a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt index a35a3b22..06d41f35 100644 --- a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt +++ b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt @@ -364,6 +364,14 @@ class MainActivity: FlutterActivity() { val pass: String = call.argument("pass") ?: "" Cwtch.loadProfiles(pass) } + "ActivatePeerEngine" -> { + val profile: String = call.argument("profile") ?: "" + Cwtch.activatePeerEngine(profile) + } + "DeactivatePeerEngine" -> { + val profile: String = call.argument("profile") ?: "" + Cwtch.deactivatePeerEngine(profile) + } "ChangePassword" -> { val profile: String = call.argument("ProfileOnion") ?: "" val pass: String = call.argument("OldPass") ?: "" diff --git a/lib/cwtch/cwtch.dart b/lib/cwtch/cwtch.dart index 49c25403..2e920780 100644 --- a/lib/cwtch/cwtch.dart +++ b/lib/cwtch/cwtch.dart @@ -12,6 +12,12 @@ abstract class Cwtch { // ignore: non_constant_identifier_names void CreateProfile(String nick, String pass); + + // ignore: non_constant_identifier_names + void ActivatePeerEngine(String profile); + // ignore: non_constant_identifier_names + void DeactivatePeerEngine(String profile); + // ignore: non_constant_identifier_names void LoadProfiles(String pass); // ignore: non_constant_identifier_names diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index b2d4dea6..874b1226 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -72,7 +72,7 @@ class CwtchNotifier { } EnvironmentConfig.debugLog("NewPeer $data"); // if tag != v1-defaultPassword then it is either encrypted OR it is an unencrypted account created during pre-beta... - profileCN.add(data["Identity"], data["name"], data["picture"], data["defaultPicture"], data["ContactsJson"], data["ServerList"], data["Online"] == "true", data["tag"] != "v1-defaultPassword"); + profileCN.add(data["Identity"], data["name"], data["picture"], data["defaultPicture"], data["ContactsJson"], data["ServerList"], data["Online"] == "true", data["autostart"] == "true", data["tag"] != "v1-defaultPassword"); break; case "ContactCreated": EnvironmentConfig.debugLog("ContactCreated $data"); diff --git a/lib/cwtch/ffi.dart b/lib/cwtch/ffi.dart index a6fc8c33..ae6867fb 100644 --- a/lib/cwtch/ffi.dart +++ b/lib/cwtch/ffi.dart @@ -301,6 +301,24 @@ class CwtchFfi implements Cwtch { malloc.free(ut8pass); } + // ignore: non_constant_identifier_names + void ActivatePeerEngine(String profile) { + var activatePeerEngineC = library.lookup>("c_ActivatePeerEngine"); + final ActivatePeerEngine = activatePeerEngineC.asFunction(); + final ut8profile = profile.toNativeUtf8(); + ActivatePeerEngine(ut8profile, ut8profile.length); + malloc.free(ut8profile); + } + + // ignore: non_constant_identifier_names + void DeactivatePeerEngine(String profile) { + var deactivatePeerEngineC = library.lookup>("c_ActivatePeerEngine"); + final DeactivatePeerEngine = deactivatePeerEngineC.asFunction(); + final ut8profile = profile.toNativeUtf8(); + DeactivatePeerEngine(ut8profile, ut8profile.length); + malloc.free(ut8profile); + } + // ignore: non_constant_identifier_names void LoadProfiles(String pass) { var loadProfileC = library.lookup>("c_LoadProfiles"); diff --git a/lib/cwtch/gomobile.dart b/lib/cwtch/gomobile.dart index e1b650ea..eda73982 100644 --- a/lib/cwtch/gomobile.dart +++ b/lib/cwtch/gomobile.dart @@ -75,6 +75,16 @@ class CwtchGomobile implements Cwtch { cwtchPlatform.invokeMethod("CreateProfile", {"nick": nick, "pass": pass}); } + // ignore: non_constant_identifier_names + void ActivatePeerEngine(String profile) { + cwtchPlatform.invokeMethod("ActivatePeerEngine", {"profile": profile}); + } + + // ignore: non_constant_identifier_names + void DeactivatePeerEngine(String profile) { + cwtchPlatform.invokeMethod("DeactivatePeerEngine", {"profile": profile}); + } + // ignore: non_constant_identifier_names void LoadProfiles(String pass) { cwtchPlatform.invokeMethod("LoadProfiles", {"pass": pass}); diff --git a/lib/models/profile.dart b/lib/models/profile.dart index 177b8e5b..7d24b308 100644 --- a/lib/models/profile.dart +++ b/lib/models/profile.dart @@ -26,6 +26,9 @@ class ProfileInfoState extends ChangeNotifier { // in the constructor if the profile is encrypted with the defacto password. bool _encrypted = true; + bool _autostart = true; + bool _enabled = false; + ProfileInfoState({ required this.onion, nickname = "", @@ -35,6 +38,7 @@ class ProfileInfoState extends ChangeNotifier { contactsJson = "", serversJson = "", online = false, + autostart = true, encrypted = true, String, }) { @@ -43,6 +47,11 @@ class ProfileInfoState extends ChangeNotifier { this._defaultImagePath = defaultImagePath; this._unreadMessages = unreadMessages; this._online = online; + this._enabled = _enabled; + this._autostart = autostart; + if (autostart) { + this._enabled = true; + } this._encrypted = encrypted; _contacts.connectServers(this._servers); @@ -130,6 +139,20 @@ class ProfileInfoState extends ChangeNotifier { notifyListeners(); } + bool get enabled => this._enabled; + + set enabled(bool newVal) { + this._enabled = newVal; + notifyListeners(); + } + + bool get autostart => this._autostart; + + set autostart(bool newVal) { + this._autostart = newVal; + notifyListeners(); + } + String get defaultImagePath => this._defaultImagePath; set defaultImagePath(String newVal) { diff --git a/lib/models/profilelist.dart b/lib/models/profilelist.dart index bb3cd406..14ed466b 100644 --- a/lib/models/profilelist.dart +++ b/lib/models/profilelist.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; @@ -7,11 +9,11 @@ class ProfileListState extends ChangeNotifier { List _profiles = []; int get num => _profiles.length; - void add(String onion, String name, String picture, String defaultPicture, String contactsJson, String serverJson, bool online, bool encrypted) { + void add(String onion, String name, String picture, String defaultPicture, String contactsJson, String serverJson, bool online, bool autostart, bool encrypted) { var idx = _profiles.indexWhere((element) => element.onion == onion); if (idx == -1) { _profiles.add(ProfileInfoState( - onion: onion, nickname: name, imagePath: picture, defaultImagePath: defaultPicture, contactsJson: contactsJson, serversJson: serverJson, online: online, encrypted: encrypted)); + onion: onion, nickname: name, imagePath: picture, defaultImagePath: defaultPicture, contactsJson: contactsJson, serversJson: serverJson, online: online, autostart: autostart, encrypted: encrypted)); } else { _profiles[idx].updateFrom(onion, name, picture, contactsJson, serverJson, online); } diff --git a/lib/views/addeditprofileview.dart b/lib/views/addeditprofileview.dart index 8faac9ee..f6ab0f01 100644 --- a/lib/views/addeditprofileview.dart +++ b/lib/views/addeditprofileview.dart @@ -169,6 +169,45 @@ class _AddEditProfileViewState extends State { ) ])), // We only allow setting password types on profile creation + + // Enabled + Visibility( + visible: Provider.of(context).onion.isNotEmpty, + child: SwitchListTile( + title: Text(AppLocalizations.of(context)!.serverEnabled, style: TextStyle(color: Provider.of(context).current().mainTextColor)), + subtitle: Text(AppLocalizations.of(context)!.serverEnabledDescription), + value: Provider.of(context).enabled, + onChanged: (bool value) { + Provider.of(context).enabled = value; + if (value) { + Provider.of(context, listen: false).cwtch.ActivatePeerEngine(Provider.of(context).onion); + } else { + Provider.of(context, listen: false).cwtch.DeactivatePeerEngine(Provider.of(context).onion); + } + }, + activeTrackColor: Provider.of(context).theme.defaultButtonColor, + inactiveTrackColor: Provider.of(context).theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.negative_heart_24px, color: Provider.of(context).current().mainTextColor), + )), + + // Auto start + SwitchListTile( + title: Text(AppLocalizations.of(context)!.serverAutostartLabel, style: TextStyle(color: Provider.of(context).current().mainTextColor)), + subtitle: Text(AppLocalizations.of(context)!.serverAutostartDescription), + value: Provider.of(context).autostart, + onChanged: (bool value) { + Provider.of(context).autostart = value; + + if (!Provider.of(context).onion.isEmpty) { + Provider.of(context, listen: false).cwtch.SetProfileAttribute(Provider.of(context).onion, "profile.autostart", value ? "true" : "false"); + } + }, + activeTrackColor: Provider.of(context).theme.defaultButtonColor, + inactiveTrackColor: Provider.of(context).theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.favorite_24dp, color: Provider.of(context).current().mainTextColor), + ), + + Visibility( visible: Provider.of(context).onion.isEmpty, child: SizedBox( diff --git a/lib/widgets/contactrow.dart b/lib/widgets/contactrow.dart index 9cc978c4..66332612 100644 --- a/lib/widgets/contactrow.dart +++ b/lib/widgets/contactrow.dart @@ -51,7 +51,7 @@ class _ContactRowState extends State { badgeTextColor: Provider.of(context).theme.portraitContactBadgeTextColor, diameter: 64.0, imagePath: Provider.of(context).isExperimentEnabled(ImagePreviewsExperiment) ? contact.imagePath : contact.defaultImagePath, - maskOut: !contact.isOnline(), + disabled: !contact.isOnline(), border: contact.isOnline() ? Provider.of(context).theme.portraitOnlineBorderColor : contact.isBlocked diff --git a/lib/widgets/profileimage.dart b/lib/widgets/profileimage.dart index cf21f531..15a55934 100644 --- a/lib/widgets/profileimage.dart +++ b/lib/widgets/profileimage.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'dart:math'; +import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:flutter/material.dart'; import 'package:cwtch/themes/opaque.dart'; import 'package:provider/provider.dart'; @@ -17,6 +18,7 @@ class ProfileImage extends StatefulWidget { required this.badgeTextColor, this.maskOut = false, this.tooltip = "", + this.disabled = false, this.badgeEdit = false, this.badgeIcon = null}); final double diameter; @@ -26,6 +28,7 @@ class ProfileImage extends StatefulWidget { final Color badgeColor; final Color badgeTextColor; final bool maskOut; + final bool disabled; final bool badgeEdit; final String tooltip; final Widget? badgeIcon; @@ -79,10 +82,15 @@ class _ProfileImageState extends State { width: widget.diameter, height: widget.diameter, color: widget.border, + foregroundDecoration: widget.disabled ? BoxDecoration( + color: Provider.of(context).theme.portraitBackgroundColor, //Colors.grey, + backgroundBlendMode: BlendMode.color, //saturation, + ) : null, child: Padding( padding: const EdgeInsets.all(2.0), //border size child: ClipOval(clipBehavior: Clip.antiAlias, child: widget.tooltip == "" ? image : Tooltip(message: widget.tooltip, child: image))))), - Visibility( + // badge + Visibility( visible: widget.badgeIcon != null || widget.badgeEdit || widget.badgeCount > 0, child: Positioned( bottom: 0.0, @@ -98,6 +106,23 @@ class _ProfileImageState extends State { : (widget.badgeIcon != null ? widget.badgeIcon : Text(widget.badgeCount > 99 ? "99+" : widget.badgeCount.toString(), style: TextStyle(color: widget.badgeTextColor, fontSize: 8.0))), ), )), + // disabled center icon + Visibility( + visible: widget.disabled, + child: Container( + width: widget.diameter, + height: widget.diameter, + child: + Center( + + + child: ImageIcon( + AssetImage("assets/core/negative_heart_512px.png"), + size: widget.diameter / 1.25, + color: Provider.of(context).theme.portraitOfflineBorderColor, + ) + + ))), ])); } } diff --git a/lib/widgets/profilerow.dart b/lib/widgets/profilerow.dart index b017ec2a..dfc362b0 100644 --- a/lib/widgets/profilerow.dart +++ b/lib/widgets/profilerow.dart @@ -37,6 +37,7 @@ class _ProfileRowState extends State { badgeCount: profile.unreadMessages, badgeColor: Provider.of(context).theme.portraitProfileBadgeColor, badgeTextColor: Provider.of(context).theme.portraitProfileBadgeTextColor, + disabled: !profile.enabled, diameter: 64.0, imagePath: Provider.of(context).isExperimentEnabled(ImagePreviewsExperiment) ? profile.imagePath : profile.defaultImagePath, border: profile.isOnline ? Provider.of(context).theme.portraitOnlineBorderColor : Provider.of(context).theme.portraitOfflineBorderColor)),