merge trunk
continuous-integration/drone/pr Build is failing Details

This commit is contained in:
erinn 2021-12-18 18:39:07 -08:00
commit 09496713d9
59 changed files with 1350 additions and 1856 deletions

View File

@ -79,6 +79,12 @@ class CwtchNotifier {
server.setRunning(data["Intent"] == "running"); server.setRunning(data["Intent"] == "running");
} }
break; break;
case "ServerStatsUpdate":
EnvironmentConfig.debugLog("ServerStatsUpdate $data");
var totalMessages = int.parse(data["TotalMessages"]);
var connections = int.parse(data["Connections"]);
serverListState.updateServerStats(data["Identity"], totalMessages, connections);
break;
case "GroupCreated": case "GroupCreated":
// Retrieve Server Status from Cache... // Retrieve Server Status from Cache...
String status = ""; String status = "";
@ -86,8 +92,8 @@ class CwtchNotifier {
if (serverInfoState != null) { if (serverInfoState != null) {
status = serverInfoState.status; status = serverInfoState.status;
} }
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"]) == null) { if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(int.parse(data["ConversationID"])) == null) {
profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(data["ProfileOnion"], data["ConversationID"], data["GroupID"], profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(data["ProfileOnion"], int.parse(data["ConversationID"]), data["GroupID"],
authorization: ContactAuthorization.approved, authorization: ContactAuthorization.approved,
imagePath: data["PicturePath"], imagePath: data["PicturePath"],
nickname: data["GroupName"], nickname: data["GroupName"],
@ -95,7 +101,7 @@ class CwtchNotifier {
server: data["GroupServer"], server: data["GroupServer"],
isGroup: true, isGroup: true,
lastMessageTime: DateTime.now())); lastMessageTime: DateTime.now()));
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["GroupID"], DateTime.now()); profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(int.parse(data["ConversationID"]), DateTime.now());
} }
break; break;
case "PeerDeleted": case "PeerDeleted":
@ -299,12 +305,6 @@ class CwtchNotifier {
} }
} }
break; break;
case "AcceptGroupInvite":
EnvironmentConfig.debugLog("accept group invite");
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.authorization = ContactAuthorization.approved;
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["GroupID"], DateTime.fromMillisecondsSinceEpoch(0));
break;
case "ServerStateChange": case "ServerStateChange":
// Update the Server Cache // Update the Server Cache
profileCN.getProfile(data["ProfileOnion"])?.updateServerStatusCache(data["GroupServer"], data["ConnectionState"]); profileCN.getProfile(data["ProfileOnion"])?.updateServerStatusCache(data["GroupServer"], data["ConnectionState"]);
@ -315,19 +315,6 @@ class CwtchNotifier {
}); });
profileCN.getProfile(data["ProfileOnion"])?.contactList.resort(); profileCN.getProfile(data["ProfileOnion"])?.contactList.resort();
break; break;
case "SetGroupAttribute":
if (data["Key"] == "local.name") {
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"]) != null) {
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.nickname = data["Data"];
}
} else if (data["Key"] == "local.archived") {
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"]) != null) {
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.isArchived = data["Data"] == "true";
}
} else {
EnvironmentConfig.debugLog("unhandled set group attribute event: ${data['Key']}");
}
break;
case "SetPeerAttribute": case "SetPeerAttribute":
if (data["Key"] == "local.name") { if (data["Key"] == "local.name") {
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"]) != null) { if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"]) != null) {
@ -378,6 +365,12 @@ class CwtchNotifier {
break; break;
case "ImportingProfileEvent": case "ImportingProfileEvent":
break; break;
case "StartingStorageMigration":
appState.SetModalState(ModalState.storageMigration);
break;
case "DoneStorageMigration":
appState.SetModalState(ModalState.none);
break;
default: default:
EnvironmentConfig.debugLog("unhandled event: $type"); EnvironmentConfig.debugLog("unhandled event: $type");
} }

View File

@ -1,6 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'package:cwtch/config.dart'; import 'package:cwtch/config.dart';
import 'package:cwtch/notification_manager.dart'; import 'package:cwtch/notification_manager.dart';
import 'package:cwtch/themes/cwtch.dart';
import 'package:cwtch/views/messageview.dart'; import 'package:cwtch/views/messageview.dart';
import 'package:cwtch/widgets/rightshiftfixer.dart'; import 'package:cwtch/widgets/rightshiftfixer.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@ -21,10 +22,10 @@ import 'models/servers.dart';
import 'views/profilemgrview.dart'; import 'views/profilemgrview.dart';
import 'views/splashView.dart'; import 'views/splashView.dart';
import 'dart:io' show Platform, exit; import 'dart:io' show Platform, exit;
import 'opaque.dart'; import 'themes/opaque.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
var globalSettings = Settings(Locale("en", ''), OpaqueDark()); var globalSettings = Settings(Locale("en", ''), CwtchDark());
var globalErrorHandler = ErrorHandler(); var globalErrorHandler = ErrorHandler();
var globalTorStatus = TorStatus(); var globalTorStatus = TorStatus();
var globalAppState = AppState(); var globalAppState = AppState();
@ -109,7 +110,7 @@ class FlwtchState extends State<Flwtch> {
supportedLocales: AppLocalizations.supportedLocales, supportedLocales: AppLocalizations.supportedLocales,
title: 'Cwtch', title: 'Cwtch',
theme: mkThemeData(settings), theme: mkThemeData(settings),
home: appState.cwtchInit == true ? ShiftRightFixer(child: ProfileMgrView()) : SplashView(), home: (!appState.cwtchInit || appState.modalState != ModalState.none) ? SplashView() : ShiftRightFixer(child: ProfileMgrView()),
), ),
); );
}, },

View File

@ -5,7 +5,7 @@ import 'package:cwtch/errorHandler.dart';
import 'package:cwtch/settings.dart'; import 'package:cwtch/settings.dart';
import 'licenses.dart'; import 'licenses.dart';
import 'main.dart'; import 'main.dart';
import 'opaque.dart'; import 'themes/opaque.dart';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
@ -14,7 +14,7 @@ import 'dart:typed_data';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:glob/glob.dart'; import 'package:glob/glob.dart';
var globalSettings = Settings(Locale("en", ''), OpaqueDark()); var globalSettings = Settings(Locale("en", ''), CwtchDark());
var globalErrorHandler = ErrorHandler(); var globalErrorHandler = ErrorHandler();
void main() { void main() {

View File

@ -26,8 +26,14 @@ class ChatMessage {
}; };
} }
enum ModalState {
none,
storageMigration
}
class AppState extends ChangeNotifier { class AppState extends ChangeNotifier {
bool cwtchInit = false; bool cwtchInit = false;
ModalState modalState = ModalState.none;
bool cwtchIsClosing = false; bool cwtchIsClosing = false;
String appError = ""; String appError = "";
String? _selectedProfile; String? _selectedProfile;
@ -47,6 +53,11 @@ class AppState extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
void SetModalState(ModalState newState) {
modalState = newState;
notifyListeners();
}
String? get selectedProfile => _selectedProfile; String? get selectedProfile => _selectedProfile;
set selectedProfile(String? newVal) { set selectedProfile(String? newVal) {
this._selectedProfile = newVal; this._selectedProfile = newVal;
@ -149,6 +160,7 @@ class ContactListState extends ChangeNotifier {
servers?.addGroup(contact); servers?.addGroup(contact);
} }
}); });
resort();
notifyListeners(); notifyListeners();
} }
@ -157,6 +169,7 @@ class ContactListState extends ChangeNotifier {
if (newContact.isGroup) { if (newContact.isGroup) {
servers?.addGroup(newContact); servers?.addGroup(newContact);
} }
resort();
notifyListeners(); notifyListeners();
} }
@ -164,12 +177,18 @@ class ContactListState extends ChangeNotifier {
_contacts.sort((ContactInfoState a, ContactInfoState b) { _contacts.sort((ContactInfoState a, ContactInfoState b) {
// return -1 = a first in list // return -1 = a first in list
// return 1 = b first in list // return 1 = b first in list
// blocked contacts last // blocked contacts last
if (a.isBlocked == true && b.isBlocked != true) return 1; if (a.isBlocked == true && b.isBlocked != true) return 1;
if (a.isBlocked != true && b.isBlocked == true) return -1; if (a.isBlocked != true && b.isBlocked == true) return -1;
// archive is next... // archive is next...
if (!a.isArchived && b.isArchived) return -1; if (!a.isArchived && b.isArchived) return -1;
if (a.isArchived && !b.isArchived) return 1; if (a.isArchived && !b.isArchived) return 1;
// unapproved top
if (a.isInvitation && !b.isInvitation) return -1;
if (!a.isInvitation && b.isInvitation) return 1;
// special sorting for contacts with no messages in either history // special sorting for contacts with no messages in either history
if (a.lastMessageTime.millisecondsSinceEpoch == 0 && b.lastMessageTime.millisecondsSinceEpoch == 0) { if (a.lastMessageTime.millisecondsSinceEpoch == 0 && b.lastMessageTime.millisecondsSinceEpoch == 0) {
// online contacts first // online contacts first

View File

@ -39,11 +39,34 @@ class ServerListState extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
void updateServerStats(String onion, int newTotalMessages, int newConnections) {
var server = getServer(onion);
if (server != null) {
server.setStats(newTotalMessages, newConnections);
resort();
notifyListeners();
}
}
void delete(String onion) { void delete(String onion) {
_servers.removeWhere((element) => element.onion == onion); _servers.removeWhere((element) => element.onion == onion);
notifyListeners(); notifyListeners();
} }
void resort() {
_servers.sort((ServerInfoState a, ServerInfoState b) {
// return -1 = a first in list
// return 1 = b first in list
if (a.totalMessages > b.totalMessages) {
return -1;
} else if (b.totalMessages > a.totalMessages) {
return 1;
}
return 0;
});
}
List<ServerInfoState> get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier List<ServerInfoState> get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier
} }
@ -55,6 +78,8 @@ class ServerInfoState extends ChangeNotifier {
bool running; bool running;
bool autoStart; bool autoStart;
bool isEncrypted; bool isEncrypted;
int totalMessages = 0;
int connections = 0;
ServerInfoState({required this.onion, required this.serverBundle, required this.running, required this.description, required this.autoStart, required this.isEncrypted}); ServerInfoState({required this.onion, required this.serverBundle, required this.running, required this.description, required this.autoStart, required this.isEncrypted});
@ -72,4 +97,10 @@ class ServerInfoState extends ChangeNotifier {
description = val; description = val;
notifyListeners(); notifyListeners();
} }
void setStats(int newTotalMessages, int newConnections) {
totalMessages = newTotalMessages;
connections = newConnections;
notifyListeners();
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,10 +2,11 @@ import 'dart:collection';
import 'dart:ui'; import 'dart:ui';
import 'dart:core'; import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'opaque.dart'; import 'themes/opaque.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
const TapirGroupsExperiment = "tapir-groups-experiment"; const TapirGroupsExperiment = "tapir-groups-experiment";
@ -38,15 +39,8 @@ class Settings extends ChangeNotifier {
bool streamerMode = false; bool streamerMode = false;
String _downloadPath = ""; String _downloadPath = "";
/// Set the dark theme. void setTheme(String themeId, String mode) {
void setDark() { theme = getTheme(themeId, mode);
theme = OpaqueDark();
notifyListeners();
}
/// Set the Light theme.
void setLight() {
theme = OpaqueLight();
notifyListeners(); notifyListeners();
} }
@ -71,11 +65,7 @@ class Settings extends ChangeNotifier {
/// be sent to the function and new settings will be instantiated based on the contents. /// be sent to the function and new settings will be instantiated based on the contents.
handleUpdate(dynamic settings) { handleUpdate(dynamic settings) {
// Set Theme and notify listeners // Set Theme and notify listeners
if (settings["Theme"] == "light") { this.setTheme(settings["Theme"], settings["ThemeMode"] ?? mode_dark);
this.setLight();
} else {
this.setDark();
}
// Set Locale and notify listeners // Set Locale and notify listeners
switchLocale(Locale(settings["Locale"])); switchLocale(Locale(settings["Locale"]));
@ -254,11 +244,10 @@ class Settings extends ChangeNotifier {
/// Convert this Settings object to a JSON representation for serialization on the /// Convert this Settings object to a JSON representation for serialization on the
/// event bus. /// event bus.
dynamic asJson() { dynamic asJson() {
var themeString = theme.identifier();
return { return {
"Locale": this.locale.languageCode, "Locale": this.locale.languageCode,
"Theme": themeString, "Theme": theme.theme,
"ThemeMode": theme.mode,
"PreviousPid": -1, "PreviousPid": -1,
"BlockUnknownConnections": blockUnknownConnections, "BlockUnknownConnections": blockUnknownConnections,
"StreamerMode": streamerMode, "StreamerMode": streamerMode,

121
lib/themes/cwtch.dart Normal file
View File

@ -0,0 +1,121 @@
import 'dart:ui';
import 'dart:core';
import 'package:flutter/material.dart';
import 'opaque.dart';
const cwtch_theme = "cwtch";
final Color darkGreyPurple = Color(0xFF281831);
final Color deepPurple = Color(0xFF422850);
final Color mauvePurple = Color(0xFF8E64A5);
final Color whiteishPurple = Color(0xFFE3DFE4);
final Color lightGrey = Color(0xFF9E9E9E);
final Color softGreen = Color(0xFFA0FFB0);
final Color softRed = Color(0xFFFFA0B0);
final Color whitePurple = Color(0xFFFFFDFF);
final Color softPurple = Color(0xFFFDF3FC);
final Color purple = Color(0xFFDFB9DE);
final Color brightPurple = Color(0xFFD1B0E0); // not in new: portrait badge color
final Color darkPurple = Color(0xFF350052);
final Color greyPurple = Color(0xFF775F84); // not in new: portrait borders
final Color pink = Color(0xFFE85DA1); // not in new: active button color
final Color hotPink = Color(0xFFD20070); // Color(0xFFD01972);
final Color softGrey = Color(0xFFB3B6B3); // not in new theme: blocked
OpaqueThemeType GetCwtchTheme(String mode) {
if (mode == mode_dark) {
return CwtchDark();
} else {
return CwtchLight();
}
}
class CwtchDark extends OpaqueThemeType {
static final Color background = darkGreyPurple;
static final Color header = darkGreyPurple;
static final Color userBubble = mauvePurple;
static final Color peerBubble = deepPurple;
static final Color font = whiteishPurple;
static final Color settings = whiteishPurple;
static final Color accent = hotPink;
get theme => cwtch_theme;
get mode => mode_dark;
get backgroundMainColor => background; // darkGreyPurple;
get backgroundPaneColor => header; //darkGreyPurple;
get backgroundHilightElementColor => deepPurple;
get mainTextColor => font; //whiteishPurple;
get sendHintTextColor => mauvePurple;
get hilightElementColor => purple;
get defaultButtonColor => accent; //hotPink;
get defaultButtonTextColor => whiteishPurple;
get defaultButtonDisabledColor => lightGrey;
get defaultButtonDisabledTextColor => darkGreyPurple;
get textfieldBackgroundColor => deepPurple;
get textfieldBorderColor => deepPurple;
get textfieldHintColor => mainTextColor; //TODO pick
get textfieldErrorColor => hotPink;
get scrollbarDefaultColor => purple;
get portraitBackgroundColor => deepPurple;
get portraitOnlineBorderColor => whiteishPurple;
get portraitOfflineBorderColor => purple;
get portraitBlockedBorderColor => lightGrey;
get portraitBlockedTextColor => lightGrey;
get portraitContactBadgeColor => hotPink;
get portraitContactBadgeTextColor => whiteishPurple;
get portraitProfileBadgeColor => mauvePurple;
get portraitProfileBadgeTextColor => darkGreyPurple;
get dropShadowColor => mauvePurple;
get toolbarIconColor => settings; //whiteishPurple;
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
get messageFromMeTextColor => font; //whiteishPurple;
get messageFromOtherBackgroundColor => peerBubble; //deepPurple;
get messageFromOtherTextColor => font; //whiteishPurple;
}
class CwtchLight extends OpaqueThemeType {
static final Color background = whitePurple;
static final Color header = softPurple;
static final Color userBubble = purple;
static final Color peerBubble = softPurple;
static final Color font = darkPurple;
static final Color settings = darkPurple;
static final Color accent = hotPink;
get theme => cwtch_theme;
get mode => mode_light;
get backgroundMainColor => background; //whitePurple;
get backgroundPaneColor => header; //softPurple;
get backgroundHilightElementColor => softPurple;
get mainTextColor => settings;
get sendHintTextColor => purple;
get hilightElementColor => purple; //darkPurple; // todo shouldn't be this, too dark, makes font unreadable
get defaultButtonColor => accent; // hotPink;
get defaultButtonTextColor => whitePurple; // ?
get defaultButtonDisabledColor => softGrey;
get textfieldBackgroundColor => purple;
get textfieldBorderColor => purple;
get textfieldHintColor => font; //TODO pick
get textfieldErrorColor => hotPink;
get scrollbarDefaultColor => accent;
get portraitBackgroundColor => softPurple;
get portraitOnlineBorderColor => greyPurple;
get portraitOfflineBorderColor => greyPurple;
get portraitBlockedBorderColor => softGrey;
get portraitBlockedTextColor => softGrey;
get portraitContactBadgeColor => accent;
get portraitContactBadgeTextColor => whitePurple;
get portraitProfileBadgeColor => brightPurple;
get portraitProfileBadgeTextColor => whitePurple;
get dropShadowColor => purple;
get toolbarIconColor => settings; //darkPurple;
get messageFromMeBackgroundColor => userBubble; //brightPurple;
get messageFromMeTextColor => font; //mainTextColor;
get messageFromOtherBackgroundColor => peerBubble; //purple;
get messageFromOtherTextColor => font; //darkPurple;
}

67
lib/themes/ghost.dart Normal file
View File

@ -0,0 +1,67 @@
import 'dart:ui';
import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart';
import 'opaque.dart';
const ghost_theme = "ghost";
OpaqueThemeType GetGhostTheme(String mode) {
if (mode == mode_dark) {
return GhostDark();
} else {
return GhostLight();
}
}
class GhostDark extends CwtchDark {
static final Color background = Color(0xFF0D0D1F);
static final Color header = Color(0xFF0D0D1F);
static final Color userBubble = Color(0xFF1A237E);
static final Color peerBubble = Color(0xFF000051);
static final Color font = Color(0xFFFFFFFF);
static final Color settings = Color(0xFFFDFFFD);
static final Color accent = Color(0xFFD20070);
get theme => ghost_theme;
get mode => mode_dark;
get backgroundMainColor => background; // darkGreyPurple;
get backgroundPaneColor => header; //darkGreyPurple;
get mainTextColor => font; //whiteishPurple;
get defaultButtonColor => accent; //hotPink;
get textfieldHintColor => mainTextColor; //TODO pick
get toolbarIconColor => settings; //whiteishPurple;
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
get messageFromMeTextColor => font; //whiteishPurple;
get messageFromOtherBackgroundColor => peerBubble; //deepPurple;
get messageFromOtherTextColor => font; //whiteishPurple;
}
class GhostLight extends CwtchLight {
static final Color background = Color(0xFFFDFDFF);
static final Color header = Color(0xFFAAB6FE);
static final Color userBubble = Color(0xFFAAB6FE);
static final Color peerBubble = Color(0xFFE8EAF6);
static final Color font = Color(0xFF0D0D1F);
static final Color settings = Color(0xFF0D0D1F);
static final Color accent = Color(0xFFD20070);
get theme => ghost_theme;
get mode => mode_light;
get backgroundMainColor => background; //whitePurple;
get backgroundPaneColor => header; //softPurple;
get mainTextColor => settings;
get defaultButtonColor => accent; // hotPink;
get textfieldHintColor => font; //TODO pick
get scrollbarDefaultColor => accent;
get portraitContactBadgeColor => accent;
get toolbarIconColor => settings; //darkPurple;
get messageFromMeBackgroundColor => userBubble; //brightPurple;
get messageFromMeTextColor => font; //mainTextColor;
get messageFromOtherBackgroundColor => peerBubble; //purple;
get messageFromOtherTextColor => font; //darkPurple;
}

67
lib/themes/mermaid.dart Normal file
View File

@ -0,0 +1,67 @@
import 'dart:ui';
import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart';
import 'opaque.dart';
const mermaid_theme = "mermaid";
OpaqueThemeType GetMermaidTheme(String mode) {
if (mode == mode_dark) {
return MermaidDark();
} else {
return MermaidLight();
}
}
class MermaidDark extends CwtchDark {
static final Color background = Color(0xFF102426);
static final Color header = Color(0xFF102426);
static final Color userBubble = Color(0xFF00838F);
static final Color peerBubble = Color(0xFF00363A);
static final Color font = Color(0xFFFFFFFF);
static final Color settings = Color(0xFFF7FCFD);
static final Color accent = Color(0xFF8E64A5);
get theme => mermaid_theme;
get mode => mode_dark;
get backgroundMainColor => background; // darkGreyPurple;
get backgroundPaneColor => header; //darkGreyPurple;
get mainTextColor => font; //whiteishPurple;
get defaultButtonColor => accent; //hotPink;
get textfieldHintColor => mainTextColor; //TODO pick
get toolbarIconColor => settings; //whiteishPurple;
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
get messageFromMeTextColor => font; //whiteishPurple;
get messageFromOtherBackgroundColor => peerBubble; //deepPurple;
get messageFromOtherTextColor => font; //whiteishPurple;
}
class MermaidLight extends CwtchLight {
static final Color background = Color(0xFFF7FCFD);
static final Color header = Color(0xFF56C8D8);
static final Color userBubble = Color(0xFF56C8D8);
static final Color peerBubble = Color(0xFFB2EBF2);
static final Color font = Color(0xFF102426);
static final Color settings = Color(0xFF102426);
static final Color accent = Color(0xFF8E64A5);
get theme => mermaid_theme;
get mode => mode_light;
get backgroundMainColor => background; //whitePurple;
get backgroundPaneColor => header; //softPurple;
get mainTextColor => settings;
get defaultButtonColor => accent; // hotPink;
get textfieldHintColor => font; //TODO pick
get scrollbarDefaultColor => accent;
get portraitContactBadgeColor => accent;
get toolbarIconColor => settings; //darkPurple;
get messageFromMeBackgroundColor => userBubble; //brightPurple;
get messageFromMeTextColor => font; //mainTextColor;
get messageFromOtherBackgroundColor => peerBubble; //purple;
get messageFromOtherTextColor => font; //darkPurple;
}

67
lib/themes/midnight.dart Normal file
View File

@ -0,0 +1,67 @@
import 'dart:ui';
import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart';
import 'opaque.dart';
const midnight_theme = "midnight";
OpaqueThemeType GetMidnightTheme(String mode) {
if (mode == mode_dark) {
return MidnightDark();
} else {
return MidnightLight();
}
}
class MidnightDark extends CwtchDark {
static final Color background = Color(0xFF1B1B1B);
static final Color header = Color(0xFF1B1B1B);
static final Color userBubble = Color(0xFF373737);
static final Color peerBubble = Color(0xFF212121);
static final Color font = Color(0xFFFFFFFF);
static final Color settings = Color(0xFFFFFDFF);
static final Color accent = Color(0xFFD20070);
get theme => midnight_theme;
get mode => mode_dark;
get backgroundMainColor => background; // darkGreyPurple;
get backgroundPaneColor => header; //darkGreyPurple;
get mainTextColor => font; //whiteishPurple;
get defaultButtonColor => accent; //hotPink;
get textfieldHintColor => mainTextColor; //TODO pick
get toolbarIconColor => settings; //whiteishPurple;
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
get messageFromMeTextColor => font; //whiteishPurple;
get messageFromOtherBackgroundColor => peerBubble; //deepPurple;
get messageFromOtherTextColor => font; //whiteishPurple;
}
class MidnightLight extends CwtchLight {
static final Color background = Color(0xFFFFFDFF);
static final Color header = Color(0xFFE0E0E0);
static final Color userBubble = Color(0xFFE0E0E0);
static final Color peerBubble = Color(0xFFF3F3F3);
static final Color font = Color(0xFF1B1B1B);
static final Color settings = Color(0xFF1B1B1B);
static final Color accent = Color(0xFFD20070);
get theme => midnight_theme;
get mode => mode_light;
get backgroundMainColor => background; //whitePurple;
get backgroundPaneColor => header; //softPurple;
get mainTextColor => settings;
get defaultButtonColor => accent; // hotPink;
get textfieldHintColor => font; //TODO pick
get scrollbarDefaultColor => accent;
get portraitContactBadgeColor => accent;
get toolbarIconColor => settings; //darkPurple;
get messageFromMeBackgroundColor => userBubble; //brightPurple;
get messageFromMeTextColor => font; //mainTextColor;
get messageFromOtherBackgroundColor => peerBubble; //purple;
get messageFromOtherTextColor => font; //darkPurple;
}

67
lib/themes/neon1.dart Normal file
View File

@ -0,0 +1,67 @@
import 'dart:ui';
import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart';
import 'opaque.dart';
const neon1_theme = "neon1";
OpaqueThemeType GetNeon1Theme(String mode) {
if (mode == mode_dark) {
return Neon1Dark();
} else {
return Neon1Light();
}
}
class Neon1Dark extends CwtchDark {
static final Color background = Color(0xFF290826);
static final Color header = Color(0xFF290826);
static final Color userBubble = Color(0xFFD20070);
static final Color peerBubble = Color(0xFF26A9A4);
static final Color font = Color(0xFFFFFFFF);
static final Color settings = Color(0xFFFFFDFF);
static final Color accent = Color(0xFFA604FE);
get theme => neon1_theme;
get mode => mode_dark;
get backgroundMainColor => background; // darkGreyPurple;
get backgroundPaneColor => header; //darkGreyPurple;
get mainTextColor => font; //whiteishPurple;
get defaultButtonColor => accent; //hotPink;
get textfieldHintColor => mainTextColor; //TODO pick
get toolbarIconColor => settings; //whiteishPurple;
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
get messageFromMeTextColor => font; //whiteishPurple;
get messageFromOtherBackgroundColor => peerBubble; //deepPurple;
get messageFromOtherTextColor => font; //whiteishPurple;
}
class Neon1Light extends CwtchLight {
static final Color background = Color(0xFFFFFDFF);
static final Color header = Color(0xFFFF94C2);
static final Color userBubble = Color(0xFFFF94C2);
static final Color peerBubble = Color(0xFFE7F6F6);
static final Color font = Color(0xFF290826);
static final Color settings = Color(0xFF290826);
static final Color accent = Color(0xFFA604FE);
get theme => neon1_theme;
get mode => mode_light;
get backgroundMainColor => background; //whitePurple;
get backgroundPaneColor => header; //softPurple;
get mainTextColor => settings;
get defaultButtonColor => accent; // hotPink;
get textfieldHintColor => font; //TODO pick
get scrollbarDefaultColor => accent;
get portraitContactBadgeColor => accent;
get toolbarIconColor => settings; //darkPurple;
get messageFromMeBackgroundColor => userBubble; //brightPurple;
get messageFromMeTextColor => font; //mainTextColor;
get messageFromOtherBackgroundColor => peerBubble; //purple;
get messageFromOtherTextColor => font; //darkPurple;
}

67
lib/themes/neon2.dart Normal file
View File

@ -0,0 +1,67 @@
import 'dart:ui';
import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart';
import 'opaque.dart';
const neon2_theme = "neon2";
OpaqueThemeType GetNeon2Theme(String mode) {
if (mode == mode_dark) {
return Neon2Dark();
} else {
return Neon2Light();
}
}
class Neon2Dark extends CwtchDark {
static final Color background = Color(0xFF290826);
static final Color header = Color(0xFF290826);
static final Color userBubble = Color(0xFFA604FE);
static final Color peerBubble = Color(0xFF03AD00);
static final Color font = Color(0xFFFFFFFF);
static final Color settings = Color(0xFFFFFDFF);
static final Color accent = Color(0xFFA604FE);
get theme => neon2_theme;
get mode => mode_dark;
get backgroundMainColor => background; // darkGreyPurple;
get backgroundPaneColor => header; //darkGreyPurple;
get mainTextColor => font; //whiteishPurple;
get defaultButtonColor => accent; //hotPink;
get textfieldHintColor => mainTextColor; //TODO pick
get toolbarIconColor => settings; //whiteishPurple;
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
get messageFromMeTextColor => font; //whiteishPurple;
get messageFromOtherBackgroundColor => peerBubble; //deepPurple;
get messageFromOtherTextColor => font; //whiteishPurple;
}
class Neon2Light extends CwtchLight {
static final Color background = Color(0xFFFFFDFF);
static final Color header = Color(0xFFD8C7E1);
static final Color userBubble = Color(0xFFD8C7E1);
static final Color peerBubble = Color(0xFF80E27E);
static final Color font = Color(0xFF290826);
static final Color settings = Color(0xFF290826);
static final Color accent = Color(0xFFA604FE);
get theme => neon2_theme;
get mode => mode_light;
get backgroundMainColor => background; //whitePurple;
get backgroundPaneColor => header; //softPurple;
get mainTextColor => settings;
get defaultButtonColor => accent; // hotPink;
get textfieldHintColor => font; //TODO pick
get scrollbarDefaultColor => accent;
get portraitContactBadgeColor => accent;
get toolbarIconColor => settings; //darkPurple;
get messageFromMeBackgroundColor => userBubble; //brightPurple;
get messageFromMeTextColor => font; //mainTextColor;
get messageFromOtherBackgroundColor => peerBubble; //purple;
get messageFromOtherTextColor => font; //darkPurple;
}

201
lib/themes/opaque.dart Normal file
View File

@ -0,0 +1,201 @@
import 'dart:ui';
import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:cwtch/themes/mermaid.dart';
import 'package:cwtch/themes/neon1.dart';
import 'package:cwtch/themes/pumpkin.dart';
import 'package:cwtch/themes/vampire.dart';
import 'package:cwtch/themes/witch.dart';
import 'package:flutter/material.dart';
import 'package:cwtch/settings.dart';
import 'ghost.dart';
import 'midnight.dart';
import 'neon2.dart';
const mode_light = "light";
const mode_dark = "dark";
final themes = {
cwtch_theme: {mode_light: CwtchLight(), mode_dark: CwtchDark()},
ghost_theme: {mode_light: GhostLight(), mode_dark: GhostDark()},
mermaid_theme: {mode_light: MermaidLight(), mode_dark: MermaidDark()},
midnight_theme: {mode_light: MidnightLight(), mode_dark: MidnightDark()},
neon1_theme: {mode_light: Neon1Light(), mode_dark: Neon1Dark()},
neon2_theme: {mode_light: Neon2Light(), mode_dark: Neon2Dark()},
pumpkin_theme: {mode_light: PumpkinLight(), mode_dark: PumpkinDark()},
witch_theme: {mode_light: WitchLight(), mode_dark: WitchDark()},
vampire_theme: {mode_light: VampireLight(), mode_dark: VampireDark()},
};
OpaqueThemeType getTheme(String themeId, String mode) {
if (themeId == "") {
themeId = cwtch_theme;
}
if (themeId == mode_light) {
themeId = cwtch_theme;
mode = mode_light;
}
if (themeId == mode_dark) {
themeId = cwtch_theme;
mode = mode_dark;
}
var theme = themes[themeId]?[mode];
return theme ?? CwtchDark();
}
Color lighten(Color color, [double amount = 0.15]) {
final hsl = HSLColor.fromColor(color);
final hslLight = hsl.withLightness((hsl.lightness + amount).clamp(0.0, 1.0));
return hslLight.toColor();
}
Color darken(Color color, [double amount = 0.15]) {
final hsl = HSLColor.fromColor(color);
final hslDarken = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
return hslDarken.toColor();
}
abstract class OpaqueThemeType {
static final Color red = Color(0xFFFF0000);
get theme => "dummy";
get mode => mode_light;
// Main screen background color (message pane, item rows)
get backgroundMainColor => red;
// Top pane ane pane colors (settings)
get backgroundPaneColor => red;
get mainTextColor => red;
// pressed row, offline heart
get hilightElementColor => red;
// Selected Row
get backgroundHilightElementColor => red;
// Faded text color for suggestions in textfields
// Todo: implement way more places
get sendHintTextColor => red;
get defaultButtonColor => red;
get defaultButtonActiveColor => /*mode == mode_light ? darken(defaultButtonColor) :*/ lighten(defaultButtonColor);
get defaultButtonTextColor => red;
get defaultButtonDisabledColor => red;
get textfieldBackgroundColor => red;
get textfieldBorderColor => red;
get textfieldHintColor => red;
get textfieldErrorColor => red;
get scrollbarDefaultColor => red;
get portraitBackgroundColor => red;
get portraitOnlineBorderColor => red;
get portraitOfflineBorderColor => red;
get portraitBlockedBorderColor => red;
get portraitBlockedTextColor => red;
get portraitContactBadgeColor => red;
get portraitContactBadgeTextColor => red;
get portraitProfileBadgeColor => red;
get portraitProfileBadgeTextColor => red;
// dropshaddpow
// todo: probably should not be reply icon color in messagerow
get dropShadowColor => red;
get toolbarIconColor => red;
get messageFromMeBackgroundColor => red;
get messageFromMeTextColor => red;
get messageFromOtherBackgroundColor => red;
get messageFromOtherTextColor => red;
// Sizes
double contactOnionTextSize() {
return 18;
}
}
ThemeData mkThemeData(Settings opaque) {
return ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
primarySwatch: Colors.red,
primaryIconTheme: IconThemeData(
color: opaque.current().mainTextColor,
),
primaryColor: opaque.current().backgroundMainColor,
canvasColor: opaque.current().backgroundPaneColor,
backgroundColor: opaque.current().backgroundMainColor,
highlightColor: opaque.current().hilightElementColor,
iconTheme: IconThemeData(
color: opaque.current().toolbarIconColor,
),
cardColor: opaque.current().backgroundMainColor,
appBarTheme: AppBarTheme(
backgroundColor: opaque.current().backgroundPaneColor,
iconTheme: IconThemeData(
color: opaque.current().mainTextColor,
),
titleTextStyle: TextStyle(
color: opaque.current().mainTextColor,
),
actionsIconTheme: IconThemeData(
color: opaque.current().mainTextColor,
)),
//bottomNavigationBarTheme: BottomNavigationBarThemeData(type: BottomNavigationBarType.fixed, backgroundColor: opaque.current().backgroundHilightElementColor), // Can't determine current use
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(opaque.current().defaultButtonColor),
foregroundColor: MaterialStateProperty.all(opaque.current().defaultButtonTextColor),
overlayColor: MaterialStateProperty.all(opaque.current().defaultButtonActiveColor),
padding: MaterialStateProperty.all(EdgeInsets.all(20))),
),
hintColor: opaque.current().textfieldHintColor,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith((states) => states.contains(MaterialState.disabled) ? opaque.current().defaultButtonDisabledColor : opaque.current().defaultButtonColor),
foregroundColor: MaterialStateProperty.all(opaque.current().defaultButtonTextColor),
overlayColor: MaterialStateProperty.resolveWith((states) => (states.contains(MaterialState.pressed) && states.contains(MaterialState.hovered))
? opaque.current().defaultButtonActiveColor
: states.contains(MaterialState.disabled)
? opaque.current().defaultButtonDisabledColor
: null),
enableFeedback: true,
splashFactory: InkRipple.splashFactory,
padding: MaterialStateProperty.all(EdgeInsets.all(20)),
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
)),
),
),
scrollbarTheme: ScrollbarThemeData(isAlwaysShown: false, thumbColor: MaterialStateProperty.all(opaque.current().scrollbarDefaultColor)),
tabBarTheme: TabBarTheme(indicator: UnderlineTabIndicator(borderSide: BorderSide(color: opaque.current().defaultButtonActiveColor))),
dialogTheme: DialogTheme(
backgroundColor: opaque.current().backgroundPaneColor, titleTextStyle: TextStyle(color: opaque.current().mainTextColor), contentTextStyle: TextStyle(color: opaque.current().mainTextColor)),
textTheme: TextTheme(
headline1: TextStyle(color: opaque.current().mainTextColor),
headline2: TextStyle(color: opaque.current().mainTextColor),
headline3: TextStyle(color: opaque.current().mainTextColor),
headline4: TextStyle(color: opaque.current().mainTextColor),
headline5: TextStyle(color: opaque.current().mainTextColor),
headline6: TextStyle(color: opaque.current().mainTextColor),
bodyText1: TextStyle(color: opaque.current().mainTextColor),
bodyText2: TextStyle(color: opaque.current().mainTextColor),
subtitle1: TextStyle(color: opaque.current().mainTextColor),
subtitle2: TextStyle(color: opaque.current().mainTextColor),
caption: TextStyle(color: opaque.current().mainTextColor),
button: TextStyle(color: opaque.current().mainTextColor),
overline: TextStyle(color: opaque.current().mainTextColor)),
switchTheme: SwitchThemeData(
overlayColor: MaterialStateProperty.all(opaque.current().defaultButtonActiveColor),
thumbColor: MaterialStateProperty.all(opaque.current().mainTextColor),
trackColor: MaterialStateProperty.all(opaque.current().dropShadowColor),
),
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: opaque.current().defaultButtonColor, hoverColor: opaque.current().defaultButtonActiveColor, enableFeedback: true, splashColor: opaque.current().defaultButtonActiveColor),
textSelectionTheme: TextSelectionThemeData(
cursorColor: opaque.current().defaultButtonActiveColor, selectionColor: opaque.current().defaultButtonActiveColor, selectionHandleColor: opaque.current().defaultButtonActiveColor),
);
}

67
lib/themes/pumpkin.dart Normal file
View File

@ -0,0 +1,67 @@
import 'dart:ui';
import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart';
import 'opaque.dart';
const pumpkin_theme = "pumpkin";
OpaqueThemeType GetPumpkinTheme(String mode) {
if (mode == mode_dark) {
return PumpkinDark();
} else {
return PumpkinLight();
}
}
class PumpkinDark extends CwtchDark {
static final Color background = Color(0xFF281831);
static final Color header = Color(0xFF281831);
static final Color userBubble = Color(0xFFB53D00);
static final Color peerBubble = Color(0xFF422850);
static final Color font = Color(0xFFFFFFFF);
static final Color settings = Color(0xFFFFFBF6);
static final Color accent = Color(0xFF8E64A5);
get theme => pumpkin_theme;
get mode => mode_dark;
get backgroundMainColor => background; // darkGreyPurple;
get backgroundPaneColor => header; //darkGreyPurple;
get mainTextColor => font; //whiteishPurple;
get defaultButtonColor => accent; //hotPink;
get textfieldHintColor => mainTextColor; //TODO pick
get toolbarIconColor => settings; //whiteishPurple;
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
get messageFromMeTextColor => font; //whiteishPurple;
get messageFromOtherBackgroundColor => peerBubble; //deepPurple;
get messageFromOtherTextColor => font; //whiteishPurple;
}
class PumpkinLight extends CwtchLight {
static final Color background = Color(0xFFFFFBF6);
static final Color header = Color(0xFFFF9800);
static final Color userBubble = Color(0xFFFF9800);
static final Color peerBubble = Color(0xFFD8C7E1);
static final Color font = Color(0xFF281831);
static final Color settings = Color(0xFF281831);
static final Color accent = Color(0xFF8E64A5);
get theme => pumpkin_theme;
get mode => mode_light;
get backgroundMainColor => background; //whitePurple;
get backgroundPaneColor => header; //softPurple;
get mainTextColor => settings;
get defaultButtonColor => accent; // hotPink;
get textfieldHintColor => font; //TODO pick
get scrollbarDefaultColor => accent;
get portraitContactBadgeColor => accent;
get toolbarIconColor => settings; //darkPurple;
get messageFromMeBackgroundColor => userBubble; //brightPurple;
get messageFromMeTextColor => font; //mainTextColor;
get messageFromOtherBackgroundColor => peerBubble; //purple;
get messageFromOtherTextColor => font; //darkPurple;
}

67
lib/themes/vampire.dart Normal file
View File

@ -0,0 +1,67 @@
import 'dart:ui';
import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart';
import 'opaque.dart';
const vampire_theme = "vampire";
OpaqueThemeType GetVampireTheme(String mode) {
if (mode == mode_dark) {
return VampireDark();
} else {
return VampireLight();
}
}
class VampireDark extends CwtchDark {
static final Color background = Color(0xFF281831);
static final Color header = Color(0xFF281831);
static final Color userBubble = Color(0xFF9A1218);
static final Color peerBubble = Color(0xFF422850);
static final Color font = Color(0xFFFFFFFF);
static final Color settings = Color(0xFFFDFFFD);
static final Color accent = Color(0xFF8E64A5);
get theme => vampire_theme;
get mode => mode_dark;
get backgroundMainColor => background; // darkGreyPurple;
get backgroundPaneColor => header; //darkGreyPurple;
get mainTextColor => font; //whiteishPurple;
get defaultButtonColor => accent; //hotPink;
get textfieldHintColor => mainTextColor; //TODO pick
get toolbarIconColor => settings; //whiteishPurple;
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
get messageFromMeTextColor => font; //whiteishPurple;
get messageFromOtherBackgroundColor => peerBubble; //deepPurple;
get messageFromOtherTextColor => font; //whiteishPurple;
}
class VampireLight extends CwtchLight {
static final Color background = Color(0xFFFFFDFD);
static final Color header = Color(0xFFD8C7E1);
static final Color userBubble = Color(0xFFD8C7E1);
static final Color peerBubble = Color(0xFFFFEBEE);
static final Color font = Color(0xFF281831);
static final Color settings = Color(0xFF281831);
static final Color accent = Color(0xFF8E64A5);
get theme => vampire_theme;
get mode => mode_light;
get backgroundMainColor => background; //whitePurple;
get backgroundPaneColor => header; //softPurple;
get mainTextColor => settings;
get defaultButtonColor => accent; // hotPink;
get textfieldHintColor => font; //TODO pick
get scrollbarDefaultColor => accent;
get portraitContactBadgeColor => accent;
get toolbarIconColor => settings; //darkPurple;
get messageFromMeBackgroundColor => userBubble; //brightPurple;
get messageFromMeTextColor => font; //mainTextColor;
get messageFromOtherBackgroundColor => peerBubble; //purple;
get messageFromOtherTextColor => font; //darkPurple;
}

67
lib/themes/witch.dart Normal file
View File

@ -0,0 +1,67 @@
import 'dart:ui';
import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart';
import 'opaque.dart';
const witch_theme = "witch";
OpaqueThemeType GetWitchTheme(String mode) {
if (mode == mode_dark) {
return WitchDark();
} else {
return WitchLight();
}
}
class WitchDark extends CwtchDark {
static final Color background = Color(0xFF0E1E0E);
static final Color header = Color(0xFF0E1E0E);
static final Color userBubble = Color(0xFF1B5E20);
static final Color peerBubble = Color(0xFF003300);
static final Color font = Color(0xFFFFFFFF);
static final Color settings = Color(0xFFFDFFFD);
static final Color accent = Color(0xFFD20070);
get theme => witch_theme;
get mode => mode_dark;
get backgroundMainColor => background; // darkGreyPurple;
get backgroundPaneColor => header; //darkGreyPurple;
get mainTextColor => font; //whiteishPurple;
get defaultButtonColor => accent; //hotPink;
get textfieldHintColor => mainTextColor; //TODO pick
get toolbarIconColor => settings; //whiteishPurple;
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
get messageFromMeTextColor => font; //whiteishPurple;
get messageFromOtherBackgroundColor => peerBubble; //deepPurple;
get messageFromOtherTextColor => font; //whiteishPurple;
}
class WitchLight extends CwtchLight {
static final Color background = Color(0xFFFDFFFD);
static final Color header = Color(0xFF80E27E);
static final Color userBubble = Color(0xFF80E27E);
static final Color peerBubble = Color(0xFFE8F5E9);
static final Color font = Color(0xFF0E1E0E);
static final Color settings = Color(0xFF0E1E0E);
static final Color accent = Color(0xFFD20070);
get theme => witch_theme;
get mode => mode_light;
get backgroundMainColor => background; //whitePurple;
get backgroundPaneColor => header; //softPurple;
get mainTextColor => settings;
get defaultButtonColor => accent; // hotPink;
get textfieldHintColor => font; //TODO pick
get scrollbarDefaultColor => accent;
get portraitContactBadgeColor => accent;
get toolbarIconColor => settings; //darkPurple;
get messageFromMeBackgroundColor => userBubble; //brightPurple;
get messageFromMeTextColor => font; //mainTextColor;
get messageFromOtherBackgroundColor => peerBubble; //purple;
get messageFromOtherTextColor => font; //darkPurple;
}

View File

@ -18,6 +18,9 @@ class TorStatus extends ChangeNotifier {
progress = new_progress; progress = new_progress;
status = new_status; status = new_status;
if (new_progress != 100) {
status = "$new_progress% - $new_status";
}
notifyListeners(); notifyListeners();
} }

View File

@ -163,7 +163,7 @@ class _AddContactViewState extends State<AddContactView> {
} }
}); });
}, },
labelText: '', hintText: '',
) )
]))); ])));
} }
@ -197,11 +197,15 @@ class _AddContactViewState extends State<AddContactView> {
}, },
isExpanded: true, // magic property isExpanded: true, // magic property
value: server, value: server,
items: Provider.of<ProfileInfoState>(context).serverList.servers.map<DropdownMenuItem<String>>((RemoteServerInfoState serverInfo) { items: Provider.of<ProfileInfoState>(context)
.serverList
.servers
.where((serverInfo) => serverInfo.status == "Synced")
.map<DropdownMenuItem<String>>((RemoteServerInfoState serverInfo) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
value: serverInfo.onion, value: serverInfo.onion,
child: Text( child: Text(
serverInfo.onion, serverInfo.description,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
); );
@ -215,7 +219,7 @@ class _AddContactViewState extends State<AddContactView> {
), ),
CwtchTextField( CwtchTextField(
controller: ctrlrGroupName, controller: ctrlrGroupName,
labelText: AppLocalizations.of(context)!.groupNameLabel, hintText: AppLocalizations.of(context)!.groupNameLabel,
onChanged: (newValue) {}, onChanged: (newValue) {},
validator: (value) {}, validator: (value) {},
), ),

View File

@ -18,7 +18,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import '../cwtch_icons_icons.dart'; import '../cwtch_icons_icons.dart';
import '../errorHandler.dart'; import '../errorHandler.dart';
import '../main.dart'; import '../main.dart';
import '../opaque.dart'; import '../themes/opaque.dart';
import '../settings.dart'; import '../settings.dart';
class AddEditProfileView extends StatefulWidget { class AddEditProfileView extends StatefulWidget {
@ -93,7 +93,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
imagePath: Provider.of<ProfileInfoState>(context).imagePath, imagePath: Provider.of<ProfileInfoState>(context).imagePath,
diameter: 120, diameter: 120,
maskOut: false, maskOut: false,
border: theme.theme.portraitOnlineBorderColor(), border: theme.theme.portraitOnlineBorderColor,
badgeTextColor: Colors.red, badgeTextColor: Colors.red,
badgeColor: Colors.red, badgeColor: Colors.red,
) )
@ -106,7 +106,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
CwtchTextField( CwtchTextField(
controller: ctrlrNick, controller: ctrlrNick,
autofocus: false, autofocus: false,
labelText: AppLocalizations.of(context)!.yourDisplayName, hintText: AppLocalizations.of(context)!.yourDisplayName,
validator: (value) { validator: (value) {
if (value.isEmpty) { if (value.isEmpty) {
return AppLocalizations.of(context)!.displayNameTooltip; return AppLocalizations.of(context)!.displayNameTooltip;
@ -147,13 +147,13 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ child: Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Checkbox( Checkbox(
value: usePassword, value: usePassword,
fillColor: MaterialStateProperty.all(theme.current().defaultButtonColor()), fillColor: MaterialStateProperty.all(theme.current().defaultButtonColor),
activeColor: theme.current().defaultButtonActiveColor(), activeColor: theme.current().defaultButtonActiveColor,
onChanged: _handleSwitchPassword, onChanged: _handleSwitchPassword,
), ),
Text( Text(
AppLocalizations.of(context)!.radioUsePassword, AppLocalizations.of(context)!.radioUsePassword,
style: TextStyle(color: theme.current().mainTextColor()), style: TextStyle(color: theme.current().mainTextColor),
), ),
SizedBox( SizedBox(
height: 20, height: 20,

View File

@ -33,7 +33,6 @@ class _AddEditServerViewState extends State<AddEditServerView> {
final ctrlrOnion = TextEditingController(text: ""); final ctrlrOnion = TextEditingController(text: "");
late bool usePassword; late bool usePassword;
//late bool deleted;
@override @override
void initState() { void initState() {
@ -81,22 +80,16 @@ class _AddEditServerViewState extends State<AddEditServerView> {
child: Form( child: Form(
key: _formKey, key: _formKey,
child: Container( child: Container(
margin: EdgeInsets.fromLTRB(30, 0, 30, 10), margin: EdgeInsets.fromLTRB(30, 5, 30, 10),
padding: EdgeInsets.fromLTRB(20, 0, 20, 10), padding: EdgeInsets.fromLTRB(20, 5, 20, 10),
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [
// Onion // Onion
Visibility( Visibility(
visible: serverInfoState.onion.isNotEmpty, visible: serverInfoState.onion.isNotEmpty,
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ child: Column(
SizedBox( mainAxisAlignment: MainAxisAlignment.start,
height: 20, crossAxisAlignment: CrossAxisAlignment.start,
), children: [CwtchLabel(label: AppLocalizations.of(context)!.serverAddress), SelectableText(serverInfoState.onion)])),
CwtchLabel(label: AppLocalizations.of(context)!.serverAddress),
SizedBox(
height: 20,
),
SelectableText(serverInfoState.onion)
])),
// Description // Description
Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
@ -110,7 +103,7 @@ class _AddEditServerViewState extends State<AddEditServerView> {
), ),
CwtchTextField( CwtchTextField(
controller: ctrlrDesc, controller: ctrlrDesc,
labelText: AppLocalizations.of(context)!.fieldDescriptionLabel, hintText: AppLocalizations.of(context)!.fieldDescriptionLabel,
autofocus: false, autofocus: false,
) )
]), ]),
@ -123,7 +116,7 @@ class _AddEditServerViewState extends State<AddEditServerView> {
Visibility( Visibility(
visible: serverInfoState.onion.isNotEmpty, visible: serverInfoState.onion.isNotEmpty,
child: SwitchListTile( child: SwitchListTile(
title: Text(AppLocalizations.of(context)!.serverEnabled, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.serverEnabled, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.serverEnabledDescription), subtitle: Text(AppLocalizations.of(context)!.serverEnabledDescription),
value: serverInfoState.running, value: serverInfoState.running,
onChanged: (bool value) { onChanged: (bool value) {
@ -134,14 +127,14 @@ class _AddEditServerViewState extends State<AddEditServerView> {
Provider.of<FlwtchState>(context, listen: false).cwtch.StopServer(serverInfoState.onion); Provider.of<FlwtchState>(context, listen: false).cwtch.StopServer(serverInfoState.onion);
} }
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(CwtchIcons.negative_heart_24px, color: settings.current().mainTextColor()), secondary: Icon(CwtchIcons.negative_heart_24px, color: settings.current().mainTextColor),
)), )),
// Auto start // Auto start
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.serverAutostartLabel, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.serverAutostartLabel, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.serverAutostartDescription), subtitle: Text(AppLocalizations.of(context)!.serverAutostartDescription),
value: serverInfoState.autoStart, value: serverInfoState.autoStart,
onChanged: (bool value) { onChanged: (bool value) {
@ -151,11 +144,33 @@ class _AddEditServerViewState extends State<AddEditServerView> {
Provider.of<FlwtchState>(context, listen: false).cwtch.SetServerAttribute(serverInfoState.onion, "autostart", value ? "true" : "false"); Provider.of<FlwtchState>(context, listen: false).cwtch.SetServerAttribute(serverInfoState.onion, "autostart", value ? "true" : "false");
} }
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(CwtchIcons.favorite_24dp, color: settings.current().mainTextColor()), secondary: Icon(CwtchIcons.favorite_24dp, color: settings.current().mainTextColor),
), ),
// metrics
Visibility(
visible: serverInfoState.onion.isNotEmpty,
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
SizedBox(
height: 20,
),
Text(AppLocalizations.of(context)!.serverMetricsLabel, style: Provider.of<FlwtchState>(context).biggerFont),
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(AppLocalizations.of(context)!.serverTotalMessagesLabel),
]),
Text(serverInfoState.totalMessages.toString())
]),
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(AppLocalizations.of(context)!.serverConnectionsLabel),
]),
Text(serverInfoState.connections.toString())
]),
])),
// ***** Password ***** // ***** Password *****
// use password toggle // use password toggle
@ -167,13 +182,13 @@ class _AddEditServerViewState extends State<AddEditServerView> {
), ),
Checkbox( Checkbox(
value: usePassword, value: usePassword,
fillColor: MaterialStateProperty.all(settings.current().defaultButtonColor()), fillColor: MaterialStateProperty.all(settings.current().defaultButtonColor),
activeColor: settings.current().defaultButtonActiveColor(), activeColor: settings.current().defaultButtonActiveColor,
onChanged: _handleSwitchPassword, onChanged: _handleSwitchPassword,
), ),
Text( Text(
AppLocalizations.of(context)!.radioUsePassword, AppLocalizations.of(context)!.radioUsePassword,
style: TextStyle(color: settings.current().mainTextColor()), style: TextStyle(color: settings.current().mainTextColor),
), ),
SizedBox( SizedBox(
height: 20, height: 20,

View File

@ -78,7 +78,7 @@ class _ContactsViewState extends State<ContactsView> {
ProfileImage( ProfileImage(
imagePath: Provider.of<ProfileInfoState>(context).imagePath, imagePath: Provider.of<ProfileInfoState>(context).imagePath,
diameter: 42, diameter: 42,
border: Provider.of<Settings>(context).current().portraitOnlineBorderColor(), border: Provider.of<Settings>(context).current().portraitOnlineBorderColor,
badgeTextColor: Colors.red, badgeTextColor: Colors.red,
badgeColor: Colors.red, badgeColor: Colors.red,
), ),
@ -87,7 +87,7 @@ class _ContactsViewState extends State<ContactsView> {
), ),
Expanded( Expanded(
child: Text("%1 » %2".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname).replaceAll("%2", AppLocalizations.of(context)!.titleManageContacts), 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()))), overflow: TextOverflow.ellipsis, style: TextStyle(color: Provider.of<Settings>(context).current().mainTextColor))),
])), ])),
actions: getActions(context), actions: getActions(context),
), ),
@ -114,7 +114,7 @@ class _ContactsViewState extends State<ContactsView> {
})); }));
// Manage known Servers // Manage known Servers
if (Provider.of<Settings>(context, listen: false).isExperimentEnabled(ServerManagementExperiment)) { if (Provider.of<Settings>(context, listen: false).isExperimentEnabled(TapirGroupsExperiment) || Provider.of<Settings>(context, listen: false).isExperimentEnabled(ServerManagementExperiment)) {
actions.add(IconButton( actions.add(IconButton(
icon: Icon(CwtchIcons.dns_24px), icon: Icon(CwtchIcons.dns_24px),
tooltip: AppLocalizations.of(context)!.manageKnownServersButton, tooltip: AppLocalizations.of(context)!.manageKnownServersButton,
@ -139,7 +139,7 @@ class _ContactsViewState extends State<ContactsView> {
Widget _buildFilterable() { Widget _buildFilterable() {
Widget txtfield = CwtchTextField( Widget txtfield = CwtchTextField(
controller: ctrlrFilter, controller: ctrlrFilter,
labelText: AppLocalizations.of(context)!.search, hintText: AppLocalizations.of(context)!.search,
onChanged: (newVal) { onChanged: (newVal) {
Provider.of<ContactListState>(context, listen: false).filter = newVal; Provider.of<ContactListState>(context, listen: false).filter = newVal;
}, },

View File

@ -3,6 +3,16 @@ import 'dart:io';
import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:cwtch/cwtch_icons_icons.dart';
import 'package:cwtch/models/servers.dart'; import 'package:cwtch/models/servers.dart';
import 'package:cwtch/widgets/folderpicker.dart'; import 'package:cwtch/widgets/folderpicker.dart';
import 'package:cwtch/themes/cwtch.dart';
import 'package:cwtch/themes/ghost.dart';
import 'package:cwtch/themes/mermaid.dart';
import 'package:cwtch/themes/midnight.dart';
import 'package:cwtch/themes/neon1.dart';
import 'package:cwtch/themes/neon2.dart';
import 'package:cwtch/themes/opaque.dart';
import 'package:cwtch/themes/pumpkin.dart';
import 'package:cwtch/themes/vampire.dart';
import 'package:cwtch/themes/witch.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cwtch/settings.dart'; import 'package:cwtch/settings.dart';
@ -37,7 +47,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
Widget _buildSettingsList() { Widget _buildSettingsList() {
return Consumer<Settings>(builder: (context, settings, child) { return Consumer<Settings>(builder: (context, settings, child) {
return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) { return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) {
var appIcon = Icon(Icons.info, color: settings.current().mainTextColor()); var appIcon = Icon(Icons.info, color: settings.current().mainTextColor);
return Scrollbar( return Scrollbar(
isAlwaysShown: true, isAlwaysShown: true,
child: SingleChildScrollView( child: SingleChildScrollView(
@ -48,8 +58,8 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
), ),
child: Column(children: [ child: Column(children: [
ListTile( ListTile(
title: Text(AppLocalizations.of(context)!.settingLanguage, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.settingLanguage, style: TextStyle(color: settings.current().mainTextColor)),
leading: Icon(CwtchIcons.change_language, color: settings.current().mainTextColor()), leading: Icon(CwtchIcons.change_language, color: settings.current().mainTextColor),
trailing: DropdownButton( trailing: DropdownButton(
value: Provider.of<Settings>(context).locale.languageCode, value: Provider.of<Settings>(context).locale.languageCode,
onChanged: (String? newValue) { onChanged: (String? newValue) {
@ -65,25 +75,43 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
); );
}).toList())), }).toList())),
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.settingTheme, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.settingTheme, style: TextStyle(color: settings.current().mainTextColor)),
value: settings.current().identifier() == "light", value: settings.current().mode == mode_light,
onChanged: (bool value) { onChanged: (bool value) {
if (value) { if (value) {
settings.setLight(); settings.setTheme(settings.theme.theme, mode_light);
} else { } else {
settings.setDark(); settings.setTheme(settings.theme.theme, mode_dark);
} }
// Save Settings... // Save Settings...
saveSettings(context); saveSettings(context);
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(CwtchIcons.change_theme, color: settings.current().mainTextColor()), secondary: Icon(CwtchIcons.change_theme, color: settings.current().mainTextColor),
), ),
ListTile( ListTile(
title: Text(AppLocalizations.of(context)!.settingUIColumnPortrait, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.themeColorLabel),
leading: Icon(Icons.table_chart, color: settings.current().mainTextColor()), trailing: DropdownButton<String>(
value: Provider.of<Settings>(context).theme.theme,
onChanged: (String? newValue) {
setState(() {
settings.setTheme(newValue!, settings.theme.mode);
saveSettings(context);
});
},
items: themes.keys.map<DropdownMenuItem<String>>((String themeId) {
return DropdownMenuItem<String>(
value: themeId,
child: Text(getThemeName(context, themeId)),
);
}).toList()),
leading: Icon(CwtchIcons.change_theme, color: settings.current().mainTextColor),
),
ListTile(
title: Text(AppLocalizations.of(context)!.settingUIColumnPortrait, style: TextStyle(color: settings.current().mainTextColor)),
leading: Icon(Icons.table_chart, color: settings.current().mainTextColor),
trailing: DropdownButton( trailing: DropdownButton(
value: settings.uiColumnModePortrait.toString(), value: settings.uiColumnModePortrait.toString(),
onChanged: (String? newValue) { onChanged: (String? newValue) {
@ -101,9 +129,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
AppLocalizations.of(context)!.settingUIColumnLandscape, AppLocalizations.of(context)!.settingUIColumnLandscape,
textWidthBasis: TextWidthBasis.longestLine, textWidthBasis: TextWidthBasis.longestLine,
softWrap: true, softWrap: true,
style: TextStyle(color: settings.current().mainTextColor()), style: TextStyle(color: settings.current().mainTextColor),
), ),
leading: Icon(Icons.table_chart, color: settings.current().mainTextColor()), leading: Icon(Icons.table_chart, color: settings.current().mainTextColor),
trailing: Container( trailing: Container(
width: 200.0, width: 200.0,
child: DropdownButton( child: DropdownButton(
@ -123,7 +151,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
); );
}).toList()))), }).toList()))),
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.blockUnknownLabel, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.blockUnknownLabel, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.descriptionBlockUnknownConnections), subtitle: Text(AppLocalizations.of(context)!.descriptionBlockUnknownConnections),
value: settings.blockUnknownConnections, value: settings.blockUnknownConnections,
onChanged: (bool value) { onChanged: (bool value) {
@ -136,12 +164,12 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
// Save Settings... // Save Settings...
saveSettings(context); saveSettings(context);
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(CwtchIcons.block_unknown, color: settings.current().mainTextColor()), secondary: Icon(CwtchIcons.block_unknown, color: settings.current().mainTextColor),
), ),
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.streamerModeLabel, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.streamerModeLabel, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.descriptionStreamerMode), subtitle: Text(AppLocalizations.of(context)!.descriptionStreamerMode),
value: settings.streamerMode, value: settings.streamerMode,
onChanged: (bool value) { onChanged: (bool value) {
@ -149,12 +177,12 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
// Save Settings... // Save Settings...
saveSettings(context); saveSettings(context);
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(CwtchIcons.streamer_bunnymask, color: settings.current().mainTextColor()), secondary: Icon(CwtchIcons.streamer_bunnymask, color: settings.current().mainTextColor),
), ),
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.experimentsEnabled, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.experimentsEnabled, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.descriptionExperiments), subtitle: Text(AppLocalizations.of(context)!.descriptionExperiments),
value: settings.experimentsEnabled, value: settings.experimentsEnabled,
onChanged: (bool value) { onChanged: (bool value) {
@ -166,16 +194,16 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
// Save Settings... // Save Settings...
saveSettings(context); saveSettings(context);
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(CwtchIcons.enable_experiments, color: settings.current().mainTextColor()), secondary: Icon(CwtchIcons.enable_experiments, color: settings.current().mainTextColor),
), ),
Visibility( Visibility(
visible: settings.experimentsEnabled, visible: settings.experimentsEnabled,
child: Column( child: Column(
children: [ children: [
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.enableGroups, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.enableGroups, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.descriptionExperimentsGroups), subtitle: Text(AppLocalizations.of(context)!.descriptionExperimentsGroups),
value: settings.isExperimentEnabled(TapirGroupsExperiment), value: settings.isExperimentEnabled(TapirGroupsExperiment),
onChanged: (bool value) { onChanged: (bool value) {
@ -187,14 +215,14 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
// Save Settings... // Save Settings...
saveSettings(context); saveSettings(context);
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(CwtchIcons.enable_groups, color: settings.current().mainTextColor()), secondary: Icon(CwtchIcons.enable_groups, color: settings.current().mainTextColor),
), ),
Visibility( Visibility(
visible: !Platform.isAndroid && !Platform.isIOS, visible: !Platform.isAndroid && !Platform.isIOS,
child: SwitchListTile( child: SwitchListTile(
title: Text(AppLocalizations.of(context)!.settingServers, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.settingServers, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.settingServersDescription), subtitle: Text(AppLocalizations.of(context)!.settingServersDescription),
value: settings.isExperimentEnabled(ServerManagementExperiment), value: settings.isExperimentEnabled(ServerManagementExperiment),
onChanged: (bool value) { onChanged: (bool value) {
@ -207,12 +235,12 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
// Save Settings... // Save Settings...
saveSettings(context); saveSettings(context);
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(CwtchIcons.dns_24px, color: settings.current().mainTextColor()), secondary: Icon(CwtchIcons.dns_24px, color: settings.current().mainTextColor),
)), )),
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.settingFileSharing, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.settingFileSharing, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.descriptionFileSharing), subtitle: Text(AppLocalizations.of(context)!.descriptionFileSharing),
value: settings.isExperimentEnabled(FileSharingExperiment), value: settings.isExperimentEnabled(FileSharingExperiment),
onChanged: (bool value) { onChanged: (bool value) {
@ -223,15 +251,15 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
} }
saveSettings(context); saveSettings(context);
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(Icons.attach_file, color: settings.current().mainTextColor()), secondary: Icon(Icons.attach_file, color: settings.current().mainTextColor),
), ),
Visibility( Visibility(
visible: settings.isExperimentEnabled(FileSharingExperiment), visible: settings.isExperimentEnabled(FileSharingExperiment),
child: Column(children: [ child: Column(children: [
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.settingImagePreviews, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.settingImagePreviews, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.settingImagePreviewsDescription), subtitle: Text(AppLocalizations.of(context)!.settingImagePreviewsDescription),
value: settings.isExperimentEnabled(ImagePreviewsExperiment), value: settings.isExperimentEnabled(ImagePreviewsExperiment),
onChanged: (bool value) { onChanged: (bool value) {
@ -243,9 +271,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
} }
saveSettings(context); saveSettings(context);
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonActiveColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(Icons.attach_file, color: settings.current().mainTextColor()), secondary: Icon(Icons.attach_file, color: settings.current().mainTextColor),
), ),
Visibility( Visibility(
visible: settings.isExperimentEnabled(ImagePreviewsExperiment) && !Platform.isAndroid, visible: settings.isExperimentEnabled(ImagePreviewsExperiment) && !Platform.isAndroid,
@ -259,7 +287,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
), ),
), ),
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.enableExperimentClickableLinks, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.enableExperimentClickableLinks, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.experimentClickableLinksDescription), subtitle: Text(AppLocalizations.of(context)!.experimentClickableLinksDescription),
value: settings.isExperimentEnabled(ClickableLinksExperiment), value: settings.isExperimentEnabled(ClickableLinksExperiment),
onChanged: (bool value) { onChanged: (bool value) {
@ -270,9 +298,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
} }
saveSettings(context); saveSettings(context);
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonActiveColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(Icons.link, color: settings.current().mainTextColor()), secondary: Icon(Icons.link, color: settings.current().mainTextColor),
), ),
]), ]),
), ),
@ -285,8 +313,8 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
applicationLegalese: '\u{a9} 2021 Open Privacy Research Society', applicationLegalese: '\u{a9} 2021 Open Privacy Research Society',
aboutBoxChildren: <Widget>[ aboutBoxChildren: <Widget>[
Padding( Padding(
padding: EdgeInsets.fromLTRB( padding: EdgeInsets.fromLTRB(24.0 + 10.0 + (appIcon.size ?? 24.0), 16.0, 0.0, 0.0),
24.0 + 10.0 + (appIcon.size ?? 24.0), 16.0, 0.0, 0.0), // About has 24 padding (ln 389) and there appears to be another 10 of padding in the widget // About has 24 padding (ln 389) and there appears to be another 10 of padding in the widget
child: SelectableText(AppLocalizations.of(context)!.versionBuilddate.replaceAll("%1", EnvironmentConfig.BUILD_VER).replaceAll("%2", EnvironmentConfig.BUILD_DATE)), child: SelectableText(AppLocalizations.of(context)!.versionBuilddate.replaceAll("%1", EnvironmentConfig.BUILD_VER).replaceAll("%2", EnvironmentConfig.BUILD_DATE)),
) )
]), ]),
@ -334,6 +362,31 @@ String getLanguageFull(context, String languageCode) {
return languageCode; return languageCode;
} }
/// Since we don't seem to able to dynamically pull translations, this function maps themes to their names
String getThemeName(context, String theme) {
switch (theme) {
case cwtch_theme:
return AppLocalizations.of(context)!.themeNameCwtch;
case ghost_theme:
return AppLocalizations.of(context)!.themeNameGhost;
case mermaid_theme:
return AppLocalizations.of(context)!.themeNameMermaid;
case midnight_theme:
return AppLocalizations.of(context)!.themeNameMidnight;
case neon1_theme:
return AppLocalizations.of(context)!.themeNameNeon1;
case neon2_theme:
return AppLocalizations.of(context)!.themeNameNeon2;
case pumpkin_theme:
return AppLocalizations.of(context)!.themeNamePumpkin;
case vampire_theme:
return AppLocalizations.of(context)!.themeNameVampire;
case witch_theme:
return AppLocalizations.of(context)!.themeNameWitch;
}
return theme;
}
/// Send an UpdateGlobalSettings to the Event Bus /// Send an UpdateGlobalSettings to the Event Bus
saveSettings(context) { saveSettings(context) {
var settings = Provider.of<Settings>(context, listen: false); var settings = Provider.of<Settings>(context, listen: false);

View File

@ -101,7 +101,7 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
), ),
CwtchTextField( CwtchTextField(
controller: ctrlrGroupAddr, controller: ctrlrGroupAddr,
labelText: '', hintText: '',
validator: (value) {}, validator: (value) {},
) )
]), ]),
@ -116,7 +116,7 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
CwtchTextField( CwtchTextField(
controller: TextEditingController(text: Provider.of<ContactInfoState>(context, listen: false).server), controller: TextEditingController(text: Provider.of<ContactInfoState>(context, listen: false).server),
validator: (value) {}, validator: (value) {},
labelText: '', hintText: '',
) )
]), ]),

View File

@ -106,6 +106,7 @@ class _MessageViewState extends State<MessageView> {
return WillPopScope( return WillPopScope(
onWillPop: _onWillPop, onWillPop: _onWillPop,
child: Scaffold( child: Scaffold(
backgroundColor: Provider.of<Settings>(context).theme.backgroundMainColor,
floatingActionButton: appState.unreadMessagesBelow floatingActionButton: appState.unreadMessagesBelow
? FloatingActionButton( ? FloatingActionButton(
child: Icon(Icons.arrow_downward), child: Icon(Icons.arrow_downward),
@ -122,7 +123,7 @@ class _MessageViewState extends State<MessageView> {
ProfileImage( ProfileImage(
imagePath: Provider.of<ContactInfoState>(context).imagePath, imagePath: Provider.of<ContactInfoState>(context).imagePath,
diameter: 42, diameter: 42,
border: Provider.of<Settings>(context).current().portraitOnlineBorderColor(), border: Provider.of<Settings>(context).current().portraitOnlineBorderColor,
badgeTextColor: Colors.red, badgeTextColor: Colors.red,
badgeColor: Colors.red, badgeColor: Colors.red,
), ),
@ -227,7 +228,7 @@ class _MessageViewState extends State<MessageView> {
bool isOffline = Provider.of<ContactInfoState>(context).isOnline() == false; bool isOffline = Provider.of<ContactInfoState>(context).isOnline() == false;
var composeBox = Container( var composeBox = Container(
color: Provider.of<Settings>(context).theme.backgroundMainColor(), color: Provider.of<Settings>(context).theme.backgroundMainColor,
padding: EdgeInsets.all(2), padding: EdgeInsets.all(2),
margin: EdgeInsets.all(2), margin: EdgeInsets.all(2),
height: 100, height: 100,
@ -235,7 +236,7 @@ class _MessageViewState extends State<MessageView> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: Container( child: Container(
decoration: BoxDecoration(border: Border(top: BorderSide(color: Provider.of<Settings>(context).theme.defaultButtonActiveColor()))), decoration: BoxDecoration(border: Border(top: BorderSide(color: Provider.of<Settings>(context).theme.defaultButtonActiveColor))),
child: RawKeyboardListener( child: RawKeyboardListener(
focusNode: FocusNode(), focusNode: FocusNode(),
onKey: handleKeyPress, onKey: handleKeyPress,
@ -255,12 +256,12 @@ class _MessageViewState extends State<MessageView> {
enabled: !isOffline, enabled: !isOffline,
decoration: InputDecoration( decoration: InputDecoration(
hintText: isOffline ? "" : AppLocalizations.of(context)!.placeholderEnterMessage, hintText: isOffline ? "" : AppLocalizations.of(context)!.placeholderEnterMessage,
hintStyle: TextStyle(color: Provider.of<Settings>(context).theme.altTextColor()), hintStyle: TextStyle(color: Provider.of<Settings>(context).theme.sendHintTextColor),
enabledBorder: InputBorder.none, enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none, focusedBorder: InputBorder.none,
enabled: true, enabled: true,
suffixIcon: ElevatedButton( suffixIcon: ElevatedButton(
child: Icon(CwtchIcons.send_24px, size: 24, color: Provider.of<Settings>(context).theme.defaultButtonTextColor()), child: Icon(CwtchIcons.send_24px, size: 24, color: Provider.of<Settings>(context).theme.defaultButtonTextColor),
onPressed: isOffline ? null : _sendMessage, onPressed: isOffline ? null : _sendMessage,
))), ))),
)))), )))),
@ -280,8 +281,8 @@ class _MessageViewState extends State<MessageView> {
margin: EdgeInsets.all(5), margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5), padding: EdgeInsets.all(5),
color: message.getMetadata().senderHandle != Provider.of<AppState>(context).selectedProfile color: message.getMetadata().senderHandle != Provider.of<AppState>(context).selectedProfile
? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor() ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor
: Provider.of<Settings>(context).theme.messageFromMeBackgroundColor(), : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor,
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Stack(children: [ Stack(children: [
Align( Align(
@ -315,7 +316,7 @@ class _MessageViewState extends State<MessageView> {
children = [composeBox]; children = [composeBox];
} }
return Column(mainAxisSize: MainAxisSize.min, children: children); return Container(color: Provider.of<Settings>(context).theme.backgroundMainColor, child: Column(mainAxisSize: MainAxisSize.min, children: children));
} }
// Send the message if enter is pressed without the shift key... // Send the message if enter is pressed without the shift key...

View File

@ -105,7 +105,7 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
height: 20, height: 20,
), ),
SwitchListTile( SwitchListTile(
title: Text(AppLocalizations.of(context)!.blockBtn, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.blockBtn, style: TextStyle(color: settings.current().mainTextColor)),
value: Provider.of<ContactInfoState>(context).isBlocked, value: Provider.of<ContactInfoState>(context).isBlocked,
onChanged: (bool blocked) { onChanged: (bool blocked) {
// Save local blocked status // Save local blocked status
@ -137,14 +137,14 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
Provider.of<FlwtchState>(context, listen: false).cwtch.SendProfileEvent(profileOnion, setPeerAttributeJson); Provider.of<FlwtchState>(context, listen: false).cwtch.SendProfileEvent(profileOnion, setPeerAttributeJson);
} }
}, },
activeTrackColor: settings.theme.defaultButtonActiveColor(), activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(), inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
secondary: Icon(CwtchIcons.block_peer, color: settings.current().mainTextColor()), secondary: Icon(CwtchIcons.block_peer, color: settings.current().mainTextColor),
), ),
ListTile( ListTile(
title: Text(AppLocalizations.of(context)!.savePeerHistory, style: TextStyle(color: settings.current().mainTextColor())), title: Text(AppLocalizations.of(context)!.savePeerHistory, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.savePeerHistoryDescription), subtitle: Text(AppLocalizations.of(context)!.savePeerHistoryDescription),
leading: Icon(CwtchIcons.peer_history, color: settings.current().mainTextColor()), leading: Icon(CwtchIcons.peer_history, color: settings.current().mainTextColor),
trailing: DropdownButton( trailing: DropdownButton(
value: Provider.of<ContactInfoState>(context).savePeerHistory == "DefaultDeleteHistory" value: Provider.of<ContactInfoState>(context).savePeerHistory == "DefaultDeleteHistory"
? AppLocalizations.of(context)!.dontSavePeerHistory ? AppLocalizations.of(context)!.dontSavePeerHistory

View File

@ -46,20 +46,20 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
return Provider.of<AppState>(context, listen: false).cwtchIsClosing; return Provider.of<AppState>(context, listen: false).cwtchIsClosing;
}, },
child: Scaffold( child: Scaffold(
backgroundColor: settings.theme.backgroundMainColor(), backgroundColor: settings.theme.backgroundMainColor,
appBar: AppBar( appBar: AppBar(
title: Row(children: [ title: Row(children: [
Icon( Icon(
CwtchIcons.cwtch_knott, CwtchIcons.cwtch_knott,
size: 36, size: 36,
color: settings.theme.mainTextColor(), color: settings.theme.mainTextColor,
), ),
SizedBox( SizedBox(
width: 10, width: 10,
), ),
Expanded( Expanded(
child: Text(MediaQuery.of(context).size.width > 600 ? AppLocalizations.of(context)!.titleManageProfiles : AppLocalizations.of(context)!.titleManageProfilesShort, child: Text(MediaQuery.of(context).size.width > 600 ? AppLocalizations.of(context)!.titleManageProfiles : AppLocalizations.of(context)!.titleManageProfilesShort,
style: TextStyle(color: settings.current().mainTextColor()))) style: TextStyle(color: settings.current().mainTextColor)))
]), ]),
actions: getActions(), actions: getActions(),
), ),
@ -93,7 +93,7 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
// Unlock Profiles // Unlock Profiles
actions.add(IconButton( actions.add(IconButton(
icon: Icon(CwtchIcons.lock_open_24px), icon: Icon(CwtchIcons.lock_open_24px),
color: Provider.of<ProfileListState>(context).profiles.isEmpty ? Provider.of<Settings>(context).theme.defaultButtonColor() : Provider.of<Settings>(context).theme.mainTextColor(), color: Provider.of<ProfileListState>(context).profiles.isEmpty ? Provider.of<Settings>(context).theme.defaultButtonColor : Provider.of<Settings>(context).theme.mainTextColor,
tooltip: AppLocalizations.of(context)!.tooltipUnlockProfiles, tooltip: AppLocalizations.of(context)!.tooltipUnlockProfiles,
onPressed: _modalUnlockProfiles, onPressed: _modalUnlockProfiles,
)); ));

View File

@ -62,7 +62,7 @@ class _ProfileServersView extends State<ProfileServersView> {
final importCard = Card( final importCard = Card(
child: ListTile( child: ListTile(
title: Text(AppLocalizations.of(context)!.importLocalServerLabel), title: Text(AppLocalizations.of(context)!.importLocalServerLabel),
leading: Icon(CwtchIcons.add_circle_24px, color: Provider.of<Settings>(context).current().mainTextColor()), leading: Icon(CwtchIcons.add_circle_24px, color: Provider.of<Settings>(context).current().mainTextColor),
trailing: DropdownButton( trailing: DropdownButton(
onChanged: (String? importServer) { onChanged: (String? importServer) {
if (importServer!.isNotEmpty) { if (importServer!.isNotEmpty) {

View File

@ -128,7 +128,7 @@ class _RemoteServerViewState extends State<RemoteServerView> {
child: Column(children: [ child: Column(children: [
Text( Text(
group.nickname, group.nickname,
style: Provider.of<FlwtchState>(context).biggerFont.apply(color: Provider.of<Settings>(context).theme.portraitOnlineBorderColor()), style: Provider.of<FlwtchState>(context).biggerFont.apply(color: Provider.of<Settings>(context).theme.portraitOnlineBorderColor),
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -139,7 +139,7 @@ class _RemoteServerViewState extends State<RemoteServerView> {
group.onion, group.onion,
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(color: Provider.of<Settings>(context).theme.portraitOnlineBorderColor()), style: TextStyle(color: Provider.of<Settings>(context).theme.portraitOnlineBorderColor),
))) )))
])); ]));
} }

View File

@ -30,6 +30,7 @@ class _ServersView extends State<ServersView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Provider.of<Settings>(context, listen: false).theme.backgroundMainColor,
appBar: AppBar( appBar: AppBar(
title: Text(MediaQuery.of(context).size.width > 600 ? AppLocalizations.of(context)!.serversManagerTitleLong : AppLocalizations.of(context)!.serversManagerTitleShort), title: Text(MediaQuery.of(context).size.width > 600 ? AppLocalizations.of(context)!.serversManagerTitleLong : AppLocalizations.of(context)!.serversManagerTitleShort),
actions: getActions(), actions: getActions(),
@ -77,7 +78,7 @@ class _ServersView extends State<ServersView> {
// Unlock Profiles // Unlock Profiles
actions.add(IconButton( actions.add(IconButton(
icon: Icon(CwtchIcons.lock_open_24px), icon: Icon(CwtchIcons.lock_open_24px),
color: Provider.of<ServerListState>(context).servers.isEmpty ? Provider.of<Settings>(context).theme.defaultButtonColor() : Provider.of<Settings>(context).theme.mainTextColor(), color: Provider.of<ServerListState>(context).servers.isEmpty ? Provider.of<Settings>(context).theme.defaultButtonColor : Provider.of<Settings>(context).theme.mainTextColor,
tooltip: AppLocalizations.of(context)!.tooltipUnlockProfiles, tooltip: AppLocalizations.of(context)!.tooltipUnlockProfiles,
onPressed: _modalUnlockServers, onPressed: _modalUnlockServers,
)); ));

View File

@ -1,11 +1,17 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import '../model.dart'; import '../model.dart';
import '../settings.dart'; import '../settings.dart';
class SplashView extends StatelessWidget { class SplashView extends StatefulWidget {
@override
_SplashViewState createState() => _SplashViewState();
}
class _SplashViewState extends State<SplashView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<AppState>( return Consumer<AppState>(
@ -25,11 +31,24 @@ class SplashView extends StatelessWidget {
isAntiAlias: true, isAntiAlias: true,
), ),
Padding( Padding(
padding: const EdgeInsets.all(20.0), padding: const EdgeInsets.all(20.0),
child: Text(appState.appError == "" ? "Loading Cwtch..." : appState.appError, child: Column(children: [
style: TextStyle( Padding(
fontSize: 16.0, color: appState.appError == "" ? Provider.of<Settings>(context).theme.mainTextColor() : Provider.of<Settings>(context).theme.textfieldErrorColor())), padding: EdgeInsets.all(6.0),
), child: Text(
appState.appError != ""
? appState.appError
: appState.modalState == ModalState.none
? AppLocalizations.of(context)!.loadingCwtch
: AppLocalizations.of(context)!.storageMigrationModalMessage,
style: TextStyle(
fontSize: 16.0, color: appState.appError == "" ? Provider.of<Settings>(context).theme.mainTextColor : Provider.of<Settings>(context).theme.textfieldErrorColor))),
Visibility(
visible: appState.modalState == ModalState.storageMigration,
child: LinearProgressIndicator(
color: Provider.of<Settings>(context).theme.defaultButtonActiveColor,
))
])),
Image(image: AssetImage("assets/Open_Privacy_Logo_lightoutline.png")), Image(image: AssetImage("assets/Open_Privacy_Logo_lightoutline.png")),
])), ])),
)); ));

View File

@ -41,30 +41,30 @@ class _CwtchButtonTextFieldState extends State<CwtchButtonTextField> {
enableIMEPersonalizedLearning: false, enableIMEPersonalizedLearning: false,
decoration: InputDecoration( decoration: InputDecoration(
labelText: widget.labelText, labelText: widget.labelText,
labelStyle: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()), labelStyle: TextStyle(color: theme.current().mainTextColor, backgroundColor: theme.current().textfieldBackgroundColor),
suffixIcon: IconButton( suffixIcon: IconButton(
onPressed: widget.onPressed, onPressed: widget.onPressed,
icon: widget.icon, icon: widget.icon,
padding: EdgeInsets.fromLTRB(0.0, 4.0, 2.0, 2.0), padding: EdgeInsets.fromLTRB(0.0, 4.0, 2.0, 2.0),
tooltip: widget.tooltip, tooltip: widget.tooltip,
enableFeedback: true, enableFeedback: true,
color: theme.current().mainTextColor(), color: theme.current().mainTextColor,
highlightColor: theme.current().defaultButtonColor(), highlightColor: theme.current().defaultButtonColor,
focusColor: theme.current().defaultButtonActiveColor(), focusColor: theme.current().defaultButtonActiveColor,
splashColor: theme.current().defaultButtonActiveColor(), splashColor: theme.current().defaultButtonActiveColor,
), ),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
filled: true, filled: true,
fillColor: theme.current().textfieldBackgroundColor(), fillColor: theme.current().textfieldBackgroundColor,
focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0)), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 3.0)),
focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 3.0)),
errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 3.0)),
errorStyle: TextStyle( errorStyle: TextStyle(
color: theme.current().textfieldErrorColor(), color: theme.current().textfieldErrorColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0))), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 3.0))),
); );
}); });
} }

View File

@ -23,7 +23,7 @@ class _ContactRowState extends State<ContactRow> {
var contact = Provider.of<ContactInfoState>(context); var contact = Provider.of<ContactInfoState>(context);
return Card( return Card(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
color: Provider.of<AppState>(context).selectedConversation == contact.onion ? Provider.of<Settings>(context).theme.backgroundHilightElementColor() : null, color: Provider.of<AppState>(context).selectedConversation == contact.identifier ? Provider.of<Settings>(context).theme.backgroundHilightElementColor : null,
borderOnForeground: false, borderOnForeground: false,
margin: EdgeInsets.all(0.0), margin: EdgeInsets.all(0.0),
child: InkWell( child: InkWell(
@ -32,16 +32,16 @@ class _ContactRowState extends State<ContactRow> {
padding: const EdgeInsets.all(6.0), //border size padding: const EdgeInsets.all(6.0), //border size
child: ProfileImage( child: ProfileImage(
badgeCount: contact.unreadMessages, badgeCount: contact.unreadMessages,
badgeColor: Provider.of<Settings>(context).theme.portraitContactBadgeColor(), badgeColor: Provider.of<Settings>(context).theme.portraitContactBadgeColor,
badgeTextColor: Provider.of<Settings>(context).theme.portraitContactBadgeTextColor(), badgeTextColor: Provider.of<Settings>(context).theme.portraitContactBadgeTextColor,
diameter: 64.0, diameter: 64.0,
imagePath: contact.imagePath, imagePath: contact.imagePath,
maskOut: !contact.isOnline(), maskOut: !contact.isOnline(),
border: contact.isOnline() border: contact.isOnline()
? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor
: contact.isBlocked : contact.isBlocked
? Provider.of<Settings>(context).theme.portraitBlockedBorderColor() ? Provider.of<Settings>(context).theme.portraitBlockedBorderColor
: Provider.of<Settings>(context).theme.portraitOfflineBorderColor()), : Provider.of<Settings>(context).theme.portraitOfflineBorderColor),
), ),
Expanded( Expanded(
child: Padding( child: Padding(
@ -55,20 +55,20 @@ class _ContactRowState extends State<ContactRow> {
style: TextStyle( style: TextStyle(
fontSize: Provider.of<Settings>(context).theme.contactOnionTextSize(), fontSize: Provider.of<Settings>(context).theme.contactOnionTextSize(),
color: contact.isBlocked color: contact.isBlocked
? Provider.of<Settings>(context).theme.portraitBlockedTextColor() ? Provider.of<Settings>(context).theme.portraitBlockedTextColor
: Provider.of<Settings>(context).theme.mainTextColor()), //Provider.of<FlwtchState>(context).biggerFont, : Provider.of<Settings>(context).theme.mainTextColor), //Provider.of<FlwtchState>(context).biggerFont,
softWrap: true, softWrap: true,
overflow: TextOverflow.visible, overflow: TextOverflow.visible,
), ),
Visibility( Visibility(
visible: contact.isGroup && contact.status == "Authenticated", visible: contact.isGroup && contact.status == "Authenticated",
child: LinearProgressIndicator( child: LinearProgressIndicator(
color: Provider.of<Settings>(context).theme.defaultButtonActiveColor(), color: Provider.of<Settings>(context).theme.defaultButtonActiveColor,
)), )),
Visibility( Visibility(
visible: !Provider.of<Settings>(context).streamerMode, visible: !Provider.of<Settings>(context).streamerMode,
child: Text(contact.onion, child: Text(contact.onion,
style: TextStyle(color: contact.isBlocked ? Provider.of<Settings>(context).theme.portraitBlockedTextColor() : Provider.of<Settings>(context).theme.mainTextColor())), style: TextStyle(color: contact.isBlocked ? Provider.of<Settings>(context).theme.portraitBlockedTextColor : Provider.of<Settings>(context).theme.mainTextColor)),
) )
], ],
))), ))),
@ -81,7 +81,7 @@ class _ContactRowState extends State<ContactRow> {
iconSize: 16, iconSize: 16,
icon: Icon( icon: Icon(
Icons.favorite, Icons.favorite,
color: Provider.of<Settings>(context).theme.mainTextColor(), color: Provider.of<Settings>(context).theme.mainTextColor,
), ),
tooltip: AppLocalizations.of(context)!.tooltipAcceptContactRequest, tooltip: AppLocalizations.of(context)!.tooltipAcceptContactRequest,
onPressed: _btnApprove, onPressed: _btnApprove,
@ -89,7 +89,7 @@ class _ContactRowState extends State<ContactRow> {
IconButton( IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
iconSize: 16, iconSize: 16,
icon: Icon(Icons.delete, color: Provider.of<Settings>(context).theme.mainTextColor()), icon: Icon(Icons.delete, color: Provider.of<Settings>(context).theme.mainTextColor),
tooltip: AppLocalizations.of(context)!.tooltipRejectContactRequest, tooltip: AppLocalizations.of(context)!.tooltipRejectContactRequest,
onPressed: _btnReject, onPressed: _btnReject,
) )
@ -98,7 +98,7 @@ class _ContactRowState extends State<ContactRow> {
? IconButton( ? IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
iconSize: 16, iconSize: 16,
icon: Icon(Icons.block, color: Provider.of<Settings>(context).theme.mainTextColor()), icon: Icon(Icons.block, color: Provider.of<Settings>(context).theme.mainTextColor),
onPressed: () {}, onPressed: () {},
) )
: Text(dateToNiceString(contact.lastMessageTime))), : Text(dateToNiceString(contact.lastMessageTime))),

View File

@ -18,7 +18,7 @@ class _CwtchLabelState extends State<CwtchLabel> {
return Consumer<Settings>(builder: (context, theme, child) { return Consumer<Settings>(builder: (context, theme, child) {
return Text( return Text(
widget.label, widget.label,
style: TextStyle(fontSize: 20, color: theme.current().mainTextColor()), style: TextStyle(fontSize: 20, color: theme.current().mainTextColor),
); );
}); });
} }

View File

@ -88,8 +88,7 @@ class FileBubbleState extends State<FileBubble> {
var wdgSender = Visibility( var wdgSender = Visibility(
visible: widget.interactive, visible: widget.interactive,
child: SelectableText(senderDisplayStr + '\u202F', child: SelectableText(senderDisplayStr + '\u202F',
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor()))); style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)));
var isPreview = false; var isPreview = false;
var wdgMessage = !showFileSharing var wdgMessage = !showFileSharing
? Text(AppLocalizations.of(context)!.messageEnableFileSharing) ? Text(AppLocalizations.of(context)!.messageEnableFileSharing)
@ -98,6 +97,7 @@ class FileBubbleState extends State<FileBubble> {
: (fileChrome(AppLocalizations.of(context)!.messageFileOffered + ":", widget.nameSuggestion, widget.rootHash, widget.fileSize, : (fileChrome(AppLocalizations.of(context)!.messageFileOffered + ":", widget.nameSuggestion, widget.rootHash, widget.fileSize,
Provider.of<ProfileInfoState>(context).downloadSpeed(widget.fileKey()))); Provider.of<ProfileInfoState>(context).downloadSpeed(widget.fileKey())));
Widget wdgDecorations; Widget wdgDecorations;
if (!showFileSharing) { if (!showFileSharing) {
wdgDecorations = Text('\u202F'); wdgDecorations = Text('\u202F');
} else if (fromMe) { } else if (fromMe) {
@ -139,7 +139,7 @@ class FileBubbleState extends State<FileBubble> {
visible: widget.interactive, visible: widget.interactive,
child: LinearProgressIndicator( child: LinearProgressIndicator(
value: Provider.of<ProfileInfoState>(context).downloadProgress(widget.fileKey()), value: Provider.of<ProfileInfoState>(context).downloadProgress(widget.fileKey()),
color: Provider.of<Settings>(context).theme.defaultButtonActiveColor(), color: Provider.of<Settings>(context).theme.defaultButtonActiveColor,
)); ));
} }
} else if (flagStarted) { } else if (flagStarted) {
@ -175,8 +175,8 @@ class FileBubbleState extends State<FileBubble> {
return Container( return Container(
constraints: constraints, constraints: constraints,
decoration: BoxDecoration( decoration: BoxDecoration(
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor(), color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor,
border: Border.all(color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor(), width: 1), border: Border.all(color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor, width: 1),
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(borderRadiousEh), topLeft: Radius.circular(borderRadiousEh),
topRight: Radius.circular(borderRadiousEh), topRight: Radius.circular(borderRadiousEh),
@ -248,7 +248,7 @@ class FileBubbleState extends State<FileBubble> {
SelectableText( SelectableText(
chrome + '\u202F', chrome + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
maxLines: 2, maxLines: 2,
@ -257,7 +257,7 @@ class FileBubbleState extends State<FileBubble> {
SelectableText( SelectableText(
fileName + '\u202F', fileName + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -268,7 +268,7 @@ class FileBubbleState extends State<FileBubble> {
SelectableText( SelectableText(
prettyBytes(fileSize) + '\u202F' + '\n', prettyBytes(fileSize) + '\u202F' + '\n',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
maxLines: 2, maxLines: 2,
@ -277,7 +277,7 @@ class FileBubbleState extends State<FileBubble> {
subtitle: SelectableText( subtitle: SelectableText(
'sha512: ' + rootHash + '\u202F', 'sha512: ' + rootHash + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
fontSize: 10, fontSize: 10,
fontFamily: "monospace", fontFamily: "monospace",
), ),
@ -285,7 +285,7 @@ class FileBubbleState extends State<FileBubble> {
maxLines: 4, maxLines: 4,
textWidthBasis: TextWidthBasis.parent, textWidthBasis: TextWidthBasis.parent,
), ),
leading: Icon(Icons.attach_file, size: 32, color: Provider.of<Settings>(context).theme.messageFromMeTextColor())); leading: Icon(Icons.attach_file, size: 32, color: Provider.of<Settings>(context).theme.messageFromMeTextColor));
} }
// Construct an file chrome // Construct an file chrome
@ -296,7 +296,7 @@ class FileBubbleState extends State<FileBubble> {
SelectableText( SelectableText(
chrome + '\u202F', chrome + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor(), color: Provider.of<Settings>(context).theme.messageFromOtherTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
maxLines: 2, maxLines: 2,
@ -305,7 +305,7 @@ class FileBubbleState extends State<FileBubble> {
SelectableText( SelectableText(
fileName + '\u202F', fileName + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor(), color: Provider.of<Settings>(context).theme.messageFromOtherTextColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -316,7 +316,7 @@ class FileBubbleState extends State<FileBubble> {
SelectableText( SelectableText(
AppLocalizations.of(context)!.labelFilesize + ': ' + prettyBytes(fileSize) + '\u202F' + '\n', AppLocalizations.of(context)!.labelFilesize + ': ' + prettyBytes(fileSize) + '\u202F' + '\n',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor(), color: Provider.of<Settings>(context).theme.messageFromOtherTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
maxLines: 2, maxLines: 2,
@ -325,7 +325,7 @@ class FileBubbleState extends State<FileBubble> {
subtitle: SelectableText( subtitle: SelectableText(
'sha512: ' + rootHash + '\u202F', 'sha512: ' + rootHash + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
fontSize: 10, fontSize: 10,
fontFamily: "monospace", fontFamily: "monospace",
), ),
@ -333,13 +333,13 @@ class FileBubbleState extends State<FileBubble> {
maxLines: 4, maxLines: 4,
textWidthBasis: TextWidthBasis.parent, textWidthBasis: TextWidthBasis.parent,
), ),
leading: Icon(Icons.attach_file, size: 32, color: Provider.of<Settings>(context).theme.messageFromOtherTextColor()), leading: Icon(Icons.attach_file, size: 32, color: Provider.of<Settings>(context).theme.messageFromOtherTextColor),
trailing: Visibility( trailing: Visibility(
visible: speed != "0 B/s", visible: speed != "0 B/s",
child: SelectableText( child: SelectableText(
speed + '\u202F', speed + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
maxLines: 1, maxLines: 1,

View File

@ -56,7 +56,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
var wdgSender = Center( var wdgSender = Center(
widthFactor: 1, widthFactor: 1,
child: SelectableText(senderDisplayStr + '\u202F', child: SelectableText(senderDisplayStr + '\u202F',
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor()))); style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)));
// If we receive an invite for ourselves, treat it as a bug. The UI no longer allows this so it could have only come from // If we receive an invite for ourselves, treat it as a bug. The UI no longer allows this so it could have only come from
// some kind of malfeasance. // some kind of malfeasance.
@ -96,9 +96,8 @@ class InvitationBubbleState extends State<InvitationBubble> {
widthFactor: 1.0, widthFactor: 1.0,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor(), color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor,
border: border: Border.all(color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor, width: 1),
Border.all(color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor(), width: 1),
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(borderRadiousEh), topLeft: Radius.circular(borderRadiousEh),
topRight: Radius.circular(borderRadiousEh), topRight: Radius.circular(borderRadiousEh),
@ -149,7 +148,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
SelectableText( SelectableText(
chrome + '\u202F', chrome + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
maxLines: 2, maxLines: 2,
@ -158,7 +157,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
SelectableText( SelectableText(
targetName + '\u202F', targetName + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
maxLines: 2, maxLines: 2,
@ -173,7 +172,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
SelectableText( SelectableText(
chrome + '\u202F', chrome + '\u202F',
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor(), color: Provider.of<Settings>(context).theme.messageFromOtherTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
textWidthBasis: TextWidthBasis.longestLine, textWidthBasis: TextWidthBasis.longestLine,
@ -181,7 +180,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
), ),
SelectableText( SelectableText(
targetName + '\u202F', targetName + '\u202F',
style: TextStyle(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor()), style: TextStyle(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor),
textAlign: TextAlign.left, textAlign: TextAlign.left,
maxLines: 2, maxLines: 2,
textWidthBasis: TextWidthBasis.longestLine, textWidthBasis: TextWidthBasis.longestLine,

View File

@ -48,7 +48,7 @@ class MessageBubbleState extends State<MessageBubble> {
} }
} }
var wdgSender = SelectableText(senderDisplayStr, var wdgSender = SelectableText(senderDisplayStr,
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor())); style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor));
var wdgMessage; var wdgMessage;
@ -58,7 +58,7 @@ class MessageBubbleState extends State<MessageBubble> {
//key: Key(myKey), //key: Key(myKey),
focusNode: _focus, focusNode: _focus,
style: TextStyle( style: TextStyle(
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor(), color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
textWidthBasis: TextWidthBasis.longestLine, textWidthBasis: TextWidthBasis.longestLine,
@ -75,10 +75,10 @@ class MessageBubbleState extends State<MessageBubble> {
//key: Key(myKey), //key: Key(myKey),
focusNode: _focus, focusNode: _focus,
style: TextStyle( style: TextStyle(
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor(), color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor,
), ),
linkStyle: TextStyle( linkStyle: TextStyle(
color: Provider.of<Settings>(context).current().mainTextColor(), color: Provider.of<Settings>(context).current().mainTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
textWidthBasis: TextWidthBasis.longestLine, textWidthBasis: TextWidthBasis.longestLine,
@ -95,13 +95,11 @@ class MessageBubbleState extends State<MessageBubble> {
child: Container( child: Container(
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: error color: error ? malformedColor : (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor),
? malformedColor
: (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor()),
border: Border.all( border: Border.all(
color: error color: error
? malformedColor ? malformedColor
: (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor()), : (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor),
width: 1), width: 1),
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(borderRadiousEh), topLeft: Radius.circular(borderRadiousEh),

View File

@ -25,8 +25,7 @@ class _MessageBubbleDecoration extends State<MessageBubbleDecoration> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text(widget.prettyDate, Text(widget.prettyDate,
style: style: TextStyle(fontSize: 9.0, color: widget.fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor),
TextStyle(fontSize: 9.0, color: widget.fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor()),
textAlign: widget.fromMe ? TextAlign.right : TextAlign.left), textAlign: widget.fromMe ? TextAlign.right : TextAlign.left),
!widget.fromMe !widget.fromMe
? SizedBox(width: 1, height: 1) ? SizedBox(width: 1, height: 1)
@ -35,14 +34,14 @@ class _MessageBubbleDecoration extends State<MessageBubbleDecoration> {
child: widget.ackd == true child: widget.ackd == true
? Tooltip( ? Tooltip(
message: AppLocalizations.of(context)!.acknowledgedLabel, message: AppLocalizations.of(context)!.acknowledgedLabel,
child: Icon(Icons.check_circle_outline, color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), size: 16)) child: Icon(Icons.check_circle_outline, color: Provider.of<Settings>(context).theme.messageFromMeTextColor, size: 16))
: (widget.errored == true : (widget.errored == true
? Tooltip( ? Tooltip(
message: AppLocalizations.of(context)!.couldNotSendMsgError, message: AppLocalizations.of(context)!.couldNotSendMsgError,
child: Icon(Icons.error_outline, color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), size: 16)) child: Icon(Icons.error_outline, color: Provider.of<Settings>(context).theme.messageFromMeTextColor, size: 16))
: Tooltip( : Tooltip(
message: AppLocalizations.of(context)!.pendingLabel, message: AppLocalizations.of(context)!.pendingLabel,
child: Icon(Icons.hourglass_bottom_outlined, color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), size: 16)))) child: Icon(Icons.hourglass_bottom_outlined, color: Provider.of<Settings>(context).theme.messageFromMeTextColor, size: 16))))
], ],
)); ));
} }

View File

@ -35,65 +35,66 @@ class _MessageListState extends State<MessageList> {
return RepaintBoundary( return RepaintBoundary(
child: Container( child: Container(
color: Provider.of<Settings>(context).theme.backgroundMainColor,
child: Column(children: [ child: Column(children: [
Visibility( Visibility(
visible: showMessageWarning, visible: showMessageWarning,
child: Container( child: Container(
padding: EdgeInsets.all(5.0), padding: EdgeInsets.all(5.0),
color: Provider.of<Settings>(context).theme.defaultButtonActiveColor(), color: Provider.of<Settings>(context).theme.defaultButtonActiveColor,
child: DefaultTextStyle( child: DefaultTextStyle(
style: TextStyle(color: Provider.of<Settings>(context).theme.defaultButtonTextColor()), style: TextStyle(color: Provider.of<Settings>(context).theme.defaultButtonTextColor),
child: showSyncing child: showSyncing
? Text(AppLocalizations.of(context)!.serverNotSynced, textAlign: TextAlign.center) ? Text(AppLocalizations.of(context)!.serverNotSynced, textAlign: TextAlign.center)
: showOfflineWarning : showOfflineWarning
? Text(Provider.of<ContactInfoState>(context).isGroup ? AppLocalizations.of(context)!.serverConnectivityDisconnected : AppLocalizations.of(context)!.peerOfflineMessage, ? Text(Provider.of<ContactInfoState>(context).isGroup ? AppLocalizations.of(context)!.serverConnectivityDisconnected : AppLocalizations.of(context)!.peerOfflineMessage,
textAlign: TextAlign.center) textAlign: TextAlign.center)
// Only show the ephemeral status for peer conversations, not for groups... // Only show the ephemeral status for peer conversations, not for groups...
: (showEphemeralWarning : (showEphemeralWarning
? Text(AppLocalizations.of(context)!.chatHistoryDefault, textAlign: TextAlign.center) ? Text(AppLocalizations.of(context)!.chatHistoryDefault, textAlign: TextAlign.center)
: :
// We are not allowed to put null here, so put an empty text widget // We are not allowed to put null here, so put an empty text widget
Text("")), Text("")),
))), ))),
Expanded( Expanded(
child: Container( child: Container(
// Only show broken heart is the contact is offline... // Only show broken heart is the contact is offline...
decoration: BoxDecoration( decoration: BoxDecoration(
image: Provider.of<ContactInfoState>(outerContext).isOnline() image: Provider.of<ContactInfoState>(outerContext).isOnline()
? null ? null
: DecorationImage( : DecorationImage(
fit: BoxFit.scaleDown, fit: BoxFit.scaleDown,
alignment: Alignment.center, alignment: Alignment.center,
image: AssetImage("assets/core/negative_heart_512px.png"), image: AssetImage("assets/core/negative_heart_512px.png"),
colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.hilightElementTextColor(), BlendMode.srcIn))), colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.hilightElementColor, BlendMode.srcIn))),
// Don't load messages for syncing server... // Don't load messages for syncing server...
child: loadMessages child: loadMessages
? ScrollablePositionedList.builder( ? ScrollablePositionedList.builder(
itemPositionsListener: widget.scrollListener, itemPositionsListener: widget.scrollListener,
itemScrollController: widget.scrollController, itemScrollController: widget.scrollController,
initialScrollIndex: initi > 4 ? initi - 4 : 0, initialScrollIndex: initi > 4 ? initi - 4 : 0,
itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages, itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages,
reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction... reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction...
itemBuilder: (itemBuilderContext, index) { itemBuilder: (itemBuilderContext, index) {
var profileOnion = Provider.of<ProfileInfoState>(outerContext, listen: false).onion; var profileOnion = Provider.of<ProfileInfoState>(outerContext, listen: false).onion;
var contactHandle = Provider.of<ContactInfoState>(outerContext, listen: false).identifier; var contactHandle = Provider.of<ContactInfoState>(outerContext, listen: false).identifier;
var messageIndex = index; var messageIndex = index;
return FutureBuilder( return FutureBuilder(
future: messageHandler(outerContext, profileOnion, contactHandle, messageIndex), future: messageHandler(outerContext, profileOnion, contactHandle, messageIndex),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
var message = snapshot.data as Message; var message = snapshot.data as Message;
var key = Provider.of<ContactInfoState>(outerContext, listen: false).getMessageKey(contactHandle, message.getMetadata().messageID); var key = Provider.of<ContactInfoState>(outerContext, listen: false).getMessageKey(contactHandle, message.getMetadata().messageID);
return message.getWidget(context, key); return message.getWidget(context, key);
} else { } else {
return MessageLoadingBubble(); return MessageLoadingBubble();
} }
}, },
); );
}, },
) )
: null)) : null))
]))); ])));
} }
} }

View File

@ -85,7 +85,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
onPressed: () { onPressed: () {
Provider.of<AppState>(context, listen: false).selectedIndex = Provider.of<MessageMetadata>(context, listen: false).messageID; Provider.of<AppState>(context, listen: false).selectedIndex = Provider.of<MessageMetadata>(context, listen: false).messageID;
}, },
icon: Icon(Icons.reply, color: Provider.of<Settings>(context).theme.dropShadowColor()))); icon: Icon(Icons.reply, color: Provider.of<Settings>(context).theme.dropShadowColor)));
Widget wdgSpacer = Flexible(child: SizedBox(width: 60, height: 10)); Widget wdgSpacer = Flexible(child: SizedBox(width: 60, height: 10));
var widgetRow = <Widget>[]; var widgetRow = <Widget>[];
@ -96,7 +96,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
actualMessage, actualMessage,
]; ];
} else if (isBlocked && !showBlockedMessage) { } else if (isBlocked && !showBlockedMessage) {
Color blockedMessageBackground = Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor(); Color blockedMessageBackground = Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor;
Widget wdgPortrait = Padding(padding: EdgeInsets.all(4.0), child: Icon(CwtchIcons.account_blocked)); Widget wdgPortrait = Padding(padding: EdgeInsets.all(4.0), child: Icon(CwtchIcons.account_blocked));
widgetRow = <Widget>[ widgetRow = <Widget>[
wdgPortrait, wdgPortrait,
@ -118,7 +118,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
AppLocalizations.of(context)!.blockedMessageMessage, AppLocalizations.of(context)!.blockedMessageMessage,
//key: Key(myKey), //key: Key(myKey),
style: TextStyle( style: TextStyle(
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor(), color: Provider.of<Settings>(context).theme.messageFromOtherTextColor,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
textWidthBasis: TextWidthBasis.longestLine, textWidthBasis: TextWidthBasis.longestLine,
@ -152,8 +152,9 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
diameter: 48.0, diameter: 48.0,
imagePath: Provider.of<MessageMetadata>(context).senderImage ?? contact.imagePath, imagePath: Provider.of<MessageMetadata>(context).senderImage ?? contact.imagePath,
//maskOut: contact.status != "Authenticated", //maskOut: contact.status != "Authenticated",
border: contact.status == "Authenticated" ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor(), border: contact.status == "Authenticated" ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor,
badgeTextColor: Colors.red, badgeColor: Colors.red, badgeTextColor: Colors.red,
badgeColor: Colors.red,
tooltip: isContact ? AppLocalizations.of(context)!.contactGoto.replaceFirst("%1", senderDisplayStr) : AppLocalizations.of(context)!.addContact, tooltip: isContact ? AppLocalizations.of(context)!.contactGoto.replaceFirst("%1", senderDisplayStr) : AppLocalizations.of(context)!.addContact,
))); )));
@ -216,8 +217,8 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
Widget _bubbleNew() { Widget _bubbleNew() {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Provider.of<Settings>(context).theme.messageFromMeBackgroundColor(), color: Provider.of<Settings>(context).theme.messageFromMeBackgroundColor,
border: Border.all(color: Provider.of<Settings>(context).theme.messageFromMeBackgroundColor(), width: 1), border: Border.all(color: Provider.of<Settings>(context).theme.messageFromMeBackgroundColor, width: 1),
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(8), topLeft: Radius.circular(8),
topRight: Radius.circular(8), topRight: Radius.circular(8),

View File

@ -53,21 +53,21 @@ class _CwtchTextFieldState extends State<CwtchPasswordField> {
}, },
icon: Icon((obscureText ? CwtchIcons.eye_closed : CwtchIcons.eye_open), semanticLabel: label), icon: Icon((obscureText ? CwtchIcons.eye_closed : CwtchIcons.eye_open), semanticLabel: label),
tooltip: label, tooltip: label,
color: theme.current().mainTextColor(), color: theme.current().mainTextColor,
highlightColor: theme.current().defaultButtonColor(), highlightColor: theme.current().defaultButtonColor,
focusColor: theme.current().defaultButtonActiveColor(), focusColor: theme.current().defaultButtonActiveColor,
splashColor: theme.current().defaultButtonActiveColor(), splashColor: theme.current().defaultButtonActiveColor,
), ),
errorStyle: TextStyle( errorStyle: TextStyle(
color: theme.current().textfieldErrorColor(), color: theme.current().textfieldErrorColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0)), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 3.0)),
focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 3.0)),
errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 3.0)),
filled: true, filled: true,
fillColor: theme.current().textfieldBackgroundColor(), fillColor: theme.current().textfieldBackgroundColor,
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0)), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 3.0)),
), ),
); );
}); });

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cwtch/opaque.dart'; import 'package:cwtch/themes/opaque.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../settings.dart'; import '../settings.dart';
@ -28,11 +28,11 @@ class _ProfileImageState extends State<ProfileImage> {
filterQuality: FilterQuality.medium, filterQuality: FilterQuality.medium,
// We need some theme specific blending here...we might want to consider making this a theme level attribute // We need some theme specific blending here...we might want to consider making this a theme level attribute
colorBlendMode: !widget.maskOut colorBlendMode: !widget.maskOut
? Provider.of<Settings>(context).theme.identifier() == "dark" ? Provider.of<Settings>(context).theme.mode == mode_dark
? BlendMode.softLight ? BlendMode.softLight
: BlendMode.darken : BlendMode.darken
: BlendMode.srcOut, : BlendMode.srcOut,
color: Provider.of<Settings>(context).theme.backgroundHilightElementColor(), color: Provider.of<Settings>(context).theme.portraitBackgroundColor,
isAntiAlias: true, isAntiAlias: true,
width: widget.diameter, width: widget.diameter,
height: widget.diameter, height: widget.diameter,

View File

@ -32,11 +32,11 @@ class _ProfileRowState extends State<ProfileRow> {
padding: const EdgeInsets.all(6.0), //border size padding: const EdgeInsets.all(6.0), //border size
child: ProfileImage( child: ProfileImage(
badgeCount: 0, badgeCount: 0,
badgeColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor(), badgeColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor,
badgeTextColor: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor(), badgeTextColor: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor,
diameter: 64.0, diameter: 64.0,
imagePath: profile.imagePath, imagePath: profile.imagePath,
border: profile.isOnline ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor())), border: profile.isOnline ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor)),
Expanded( Expanded(
child: Column( child: Column(
children: [ children: [
@ -60,7 +60,7 @@ class _ProfileRowState extends State<ProfileRow> {
IconButton( IconButton(
enableFeedback: true, enableFeedback: true,
tooltip: AppLocalizations.of(context)!.editProfile + " " + profile.nickname, tooltip: AppLocalizations.of(context)!.editProfile + " " + profile.nickname,
icon: Icon(Icons.create, color: Provider.of<Settings>(context).current().mainTextColor()), icon: Icon(Icons.create, color: Provider.of<Settings>(context).current().mainTextColor),
onPressed: () { onPressed: () {
_pushEditProfile(onion: profile.onion, displayName: profile.nickname, profileImage: profile.imagePath, encrypted: profile.isEncrypted); _pushEditProfile(onion: profile.onion, displayName: profile.nickname, profileImage: profile.imagePath, encrypted: profile.isEncrypted);
}, },

View File

@ -42,13 +42,13 @@ class QuotedMessageBubbleState extends State<QuotedMessageBubble> {
} }
} }
var wdgSender = SelectableText(senderDisplayStr, var wdgSender = SelectableText(senderDisplayStr,
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor())); style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor));
var wdgMessage = SelectableText( var wdgMessage = SelectableText(
widget.body + '\u202F', widget.body + '\u202F',
focusNode: _focus, focusNode: _focus,
style: TextStyle( style: TextStyle(
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor(), color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor,
), ),
textAlign: TextAlign.left, textAlign: TextAlign.left,
textWidthBasis: TextWidthBasis.longestLine, textWidthBasis: TextWidthBasis.longestLine,
@ -61,11 +61,11 @@ class QuotedMessageBubbleState extends State<QuotedMessageBubble> {
try { try {
var qMessage = (snapshot.data! as Message); var qMessage = (snapshot.data! as Message);
// Swap the background color for quoted tweets.. // Swap the background color for quoted tweets..
var qTextColor = fromMe ? Provider.of<Settings>(context).theme.messageFromOtherTextColor() : Provider.of<Settings>(context).theme.messageFromMeTextColor(); var qTextColor = fromMe ? Provider.of<Settings>(context).theme.messageFromOtherTextColor : Provider.of<Settings>(context).theme.messageFromMeTextColor;
return Container( return Container(
margin: EdgeInsets.all(5), margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5), padding: EdgeInsets.all(5),
color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor() : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor(), color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor,
child: Wrap(runAlignment: WrapAlignment.spaceEvenly, alignment: WrapAlignment.spaceEvenly, runSpacing: 1.0, crossAxisAlignment: WrapCrossAlignment.center, children: [ child: Wrap(runAlignment: WrapAlignment.spaceEvenly, alignment: WrapAlignment.spaceEvenly, runSpacing: 1.0, crossAxisAlignment: WrapCrossAlignment.center, children: [
Center(widthFactor: 1, child: Padding(padding: EdgeInsets.all(10.0), child: Icon(Icons.reply, size: 32, color: qTextColor))), Center(widthFactor: 1, child: Padding(padding: EdgeInsets.all(10.0), child: Icon(Icons.reply, size: 32, color: qTextColor))),
Center(widthFactor: 1.0, child: DefaultTextStyle(child: qMessage.getPreviewWidget(context), style: TextStyle(color: qTextColor))) Center(widthFactor: 1.0, child: DefaultTextStyle(child: qMessage.getPreviewWidget(context), style: TextStyle(color: qTextColor)))
@ -90,13 +90,11 @@ class QuotedMessageBubbleState extends State<QuotedMessageBubble> {
child: Container( child: Container(
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: error color: error ? malformedColor : (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor),
? malformedColor
: (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor()),
border: Border.all( border: Border.all(
color: error color: error
? malformedColor ? malformedColor
: (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor()), : (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor),
width: 1), width: 1),
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(borderRadiousEh), topLeft: Radius.circular(borderRadiousEh),

View File

@ -34,7 +34,7 @@ class _RemoteServerRowState extends State<RemoteServerRow> {
Padding( Padding(
padding: const EdgeInsets.all(6.0), //border size padding: const EdgeInsets.all(6.0), //border size
child: Icon(CwtchIcons.dns_24px, child: Icon(CwtchIcons.dns_24px,
color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor(), size: 64)), color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor, size: 64)),
Expanded( Expanded(
child: Column( child: Column(
children: [ children: [
@ -43,7 +43,7 @@ class _RemoteServerRowState extends State<RemoteServerRow> {
semanticsLabel: description, semanticsLabel: description,
style: Provider.of<FlwtchState>(context) style: Provider.of<FlwtchState>(context)
.biggerFont .biggerFont
.apply(color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()), .apply(color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor),
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -54,7 +54,7 @@ class _RemoteServerRowState extends State<RemoteServerRow> {
server.onion, server.onion,
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()), style: TextStyle(color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor),
))) )))
], ],
)), )),

View File

@ -29,7 +29,7 @@ class _ServerRowState extends State<ServerRow> {
Padding( Padding(
padding: const EdgeInsets.all(6.0), //border size padding: const EdgeInsets.all(6.0), //border size
child: Icon(CwtchIcons.dns_24px, child: Icon(CwtchIcons.dns_24px,
color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor(), size: 64)), color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor, size: 64)),
Expanded( Expanded(
child: Column( child: Column(
children: [ children: [
@ -38,7 +38,7 @@ class _ServerRowState extends State<ServerRow> {
semanticsLabel: server.description, semanticsLabel: server.description,
style: Provider.of<FlwtchState>(context) style: Provider.of<FlwtchState>(context)
.biggerFont .biggerFont
.apply(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()), .apply(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor),
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -49,7 +49,7 @@ class _ServerRowState extends State<ServerRow> {
server.onion, server.onion,
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()), style: TextStyle(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor),
))) )))
], ],
)), )),
@ -58,7 +58,7 @@ class _ServerRowState extends State<ServerRow> {
IconButton( IconButton(
enableFeedback: true, enableFeedback: true,
tooltip: AppLocalizations.of(context)!.copyServerKeys, tooltip: AppLocalizations.of(context)!.copyServerKeys,
icon: Icon(CwtchIcons.address_copy_2, color: Provider.of<Settings>(context).current().mainTextColor()), icon: Icon(CwtchIcons.address_copy_2, color: Provider.of<Settings>(context).current().mainTextColor),
onPressed: () { onPressed: () {
Clipboard.setData(new ClipboardData(text: server.serverBundle)); Clipboard.setData(new ClipboardData(text: server.serverBundle));
}, },
@ -68,7 +68,7 @@ class _ServerRowState extends State<ServerRow> {
IconButton( IconButton(
enableFeedback: true, enableFeedback: true,
tooltip: AppLocalizations.of(context)!.editServerTitle, tooltip: AppLocalizations.of(context)!.editServerTitle,
icon: Icon(Icons.create, color: Provider.of<Settings>(context).current().mainTextColor()), icon: Icon(Icons.create, color: Provider.of<Settings>(context).current().mainTextColor),
onPressed: () { onPressed: () {
_pushEditServer(server); _pushEditServer(server);
}, },

View File

@ -7,9 +7,9 @@ doNothing(String x) {}
// Provides a styled Text Field for use in Form Widgets. // Provides a styled Text Field for use in Form Widgets.
// Callers must provide a text controller, label helper text and a validator. // Callers must provide a text controller, label helper text and a validator.
class CwtchTextField extends StatefulWidget { class CwtchTextField extends StatefulWidget {
CwtchTextField({required this.controller, required this.labelText, this.validator, this.autofocus = false, this.onChanged = doNothing}); CwtchTextField({required this.controller, required this.hintText, this.validator, this.autofocus = false, this.onChanged = doNothing});
final TextEditingController controller; final TextEditingController controller;
final String labelText; final String hintText;
final FormFieldValidator? validator; final FormFieldValidator? validator;
final Function(String) onChanged; final Function(String) onChanged;
final bool autofocus; final bool autofocus;
@ -42,20 +42,19 @@ class _CwtchTextFieldState extends State<CwtchTextField> {
enableIMEPersonalizedLearning: false, enableIMEPersonalizedLearning: false,
focusNode: _focusNode, focusNode: _focusNode,
decoration: InputDecoration( decoration: InputDecoration(
labelText: widget.labelText, hintText: widget.hintText,
labelStyle: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()),
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
filled: true, filled: true,
focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0)), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 3.0)),
focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 3.0)),
errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 3.0)),
errorStyle: TextStyle( errorStyle: TextStyle(
color: theme.current().textfieldErrorColor(), color: theme.current().textfieldErrorColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
fillColor: theme.current().textfieldBackgroundColor(), fillColor: theme.current().textfieldBackgroundColor,
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0))), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 3.0))),
); );
}); });
} }

View File

@ -19,7 +19,7 @@ class _TorIconState extends State<TorIcon> {
return RepaintBoundary( return RepaintBoundary(
child: Icon( child: Icon(
Provider.of<TorStatus>(context).progress == 0 ? CwtchIcons.onion_off : (Provider.of<TorStatus>(context).progress == 100 ? CwtchIcons.onion_on : CwtchIcons.onion_waiting), Provider.of<TorStatus>(context).progress == 0 ? CwtchIcons.onion_off : (Provider.of<TorStatus>(context).progress == 100 ? CwtchIcons.onion_on : CwtchIcons.onion_waiting),
color: Provider.of<Settings>(context).theme.mainTextColor(), color: Provider.of<Settings>(context).theme.mainTextColor,
semanticLabel: Provider.of<TorStatus>(context).progress == 100 semanticLabel: Provider.of<TorStatus>(context).progress == 100
? AppLocalizations.of(context)!.networkStatusOnline ? AppLocalizations.of(context)!.networkStatusOnline
: (Provider.of<TorStatus>(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor), : (Provider.of<TorStatus>(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor),

View File

@ -1,50 +0,0 @@
#!/bin/bash
themes="/home/erinn/go/src/git.openprivacy.ca/openprivacy/opaque/theme"
outfile="./lib/opaque.dart"
if [ -e "$outfile" ]; then
mv "$outfile" "${outfile}.bak"
fi
echo "// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND AS CHANGES WILL BE OVERRIDDEN." > "$outfile"
echo "// TO EDIT THE THEME, SEE https://git.openprivacy.ca/openprivacy/opaque/" >> "$outfile"
echo "// FOR HOW THIS FILE IS GENERATED, SEE ../regenerate_opaque_theme.sh" >> "$outfile"
sed 's/import QtQuick 2\.0//g' "${themes}/ThemeType.qml" | \
sed "s/QtObject ./import 'dart:ui\';\nimport 'dart:core';\nabstract class OpaqueThemeType {\n static final Color red = Color(0xFFFF0000);/g" | \
sed 's/\(property color\|var\)/Color/g' | \
sed 's/\(:\| =\) ".*"/(){return red;}/g' >> "$outfile"
echo -e "\n\n" >> "$outfile"
sed 's/ThemeType/class CwtchDark extends OpaqueThemeType/g' "${themes}/CwtchDark.qml" | \
sed 's/readonly property color \(.*\): "#\(\w*\)"/static final Color \1 = Color(0xFF\2);/g' | \
sed 's/\(\w*\): \(\w*\)/Color \1() { return \2; }/g' >> "$outfile"
echo -e "\n\n" >> "$outfile"
sed 's/ThemeType/class CwtchLight extends OpaqueThemeType/g' "${themes}/CwtchLight.qml" | \
sed 's/readonly property color \(.*\): "#\(\w*\)"/static final Color \1 = Color(0xFF\2);/g' | \
sed 's/\(\w*\): \(\w*\)/Color \1() { return \2; }/g' >> "$outfile"
echo -e "\n\n" >> "$outfile"
sed 's/\(pragma Singleton\|import QtQuick 2\.0\)//g' "${themes}/Theme.qml" | \
sed 's|//.*$||g' | \
sed 's/theme\./current./g' | \
sed 's/property color/property Color/g' | \
sed 's/readonly property Color \(.*\): \([a-zA-Z0-9._]*\)/Color \1() { return \2(); }/g' | \
#to preserve int values: #static int \1() { return \2; }/g' | \
sed 's/readonly property int \(.*\): \(.*\)/int \1() { return \2; }/g' | \
sed 's/readonly property variant \([a-zA-Z0-9._]*\): \(.*\)$/var \1 = \2;/g' | \
sed 's/color/Color/g' | \
sed 's/: \(.+\)/ = \1;/g' | \
sed 's/property ThemeType \(\w*\): \(.*\)../static final OpaqueThemeType \1 = \2();/g' | \
sed 's/final OpaqueThemeType theme = .*$/Opaque current() { return dark; }/' | \
sed 's/^.*themeScaleNew.*$/int scale = 2;\n static final String gcdOS = "linux";/g' | \
sed 's/gcd.os/gcdOS/g' | \
sed 's/return \([a-zA-Z]\+\) ;/return \1();/g' | \
sed 's/return \([a-zA-Z]\+\) + \([a-zA-Z]\+\);/return \1() + \2();/g' | \
sed 's/Item/class Opaque extends OpaqueThemeType/' | \
sed 's/current\./current()./g' >> "$outfile"

View File

@ -5,8 +5,9 @@
// gestures. You can also use WidgetTester to find child widgets in the widget // gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct. // tree, read text, and verify that the values of widget properties are correct.
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cwtch/opaque.dart'; import 'package:cwtch/themes/opaque.dart';
import 'package:cwtch/settings.dart'; import 'package:cwtch/settings.dart';
import 'package:cwtch/widgets/buttontextfield.dart'; import 'package:cwtch/widgets/buttontextfield.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
@ -14,8 +15,8 @@ import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
var settingsEnglishDark = Settings(Locale("en", ''), OpaqueDark()); var settingsEnglishDark = Settings(Locale("en", ''), CwtchDark());
var settingsEnglishLight = Settings(Locale("en", ''), OpaqueLight()); var settingsEnglishLight = Settings(Locale("en", ''), CwtchLight());
ChangeNotifierProvider<Settings> getSettingsEnglishDark() => ChangeNotifierProvider.value(value: settingsEnglishDark); ChangeNotifierProvider<Settings> getSettingsEnglishDark() => ChangeNotifierProvider.value(value: settingsEnglishDark);
void main() { void main() {

View File

@ -5,8 +5,9 @@
// gestures. You can also use WidgetTester to find child widgets in the widget // gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct. // tree, read text, and verify that the values of widget properties are correct.
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cwtch/opaque.dart'; import 'package:cwtch/themes/opaque.dart';
import 'package:cwtch/settings.dart'; import 'package:cwtch/settings.dart';
import 'package:cwtch/widgets/cwtchlabel.dart'; import 'package:cwtch/widgets/cwtchlabel.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
@ -14,8 +15,8 @@ import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
var settingsEnglishDark = Settings(Locale("en", ''), OpaqueDark()); var settingsEnglishDark = Settings(Locale("en", ''), CwtchDark());
var settingsEnglishLight = Settings(Locale("en", ''), OpaqueLight()); var settingsEnglishLight = Settings(Locale("en", ''), CwtchLight());
ChangeNotifierProvider<Settings> getSettingsEnglishDark() => ChangeNotifierProvider.value(value: settingsEnglishDark); ChangeNotifierProvider<Settings> getSettingsEnglishDark() => ChangeNotifierProvider.value(value: settingsEnglishDark);
void main() { void main() {

View File

@ -5,8 +5,9 @@
// gestures. You can also use WidgetTester to find child widgets in the widget // gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct. // tree, read text, and verify that the values of widget properties are correct.
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cwtch/opaque.dart'; import 'package:cwtch/themes/opaque.dart';
import 'package:cwtch/settings.dart'; import 'package:cwtch/settings.dart';
import 'package:cwtch/widgets/profileimage.dart'; import 'package:cwtch/widgets/profileimage.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
@ -14,8 +15,8 @@ import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
var settingsEnglishDark = Settings(Locale("en", ''), OpaqueDark()); var settingsEnglishDark = Settings(Locale("en", ''), CwtchDark());
var settingsEnglishLight = Settings(Locale("en", ''), OpaqueLight()); var settingsEnglishLight = Settings(Locale("en", ''), CwtchLight());
ChangeNotifierProvider<Settings> getSettingsEnglishDark() => ChangeNotifierProvider.value(value: settingsEnglishDark); ChangeNotifierProvider<Settings> getSettingsEnglishDark() => ChangeNotifierProvider.value(value: settingsEnglishDark);
String file(String slug) { String file(String slug) {
@ -33,10 +34,10 @@ void main() {
Widget testWidget = ProfileImage( Widget testWidget = ProfileImage(
imagePath: "profiles/001-centaur.png", imagePath: "profiles/001-centaur.png",
badgeTextColor: settingsEnglishDark.theme.portraitProfileBadgeTextColor(), badgeTextColor: settingsEnglishDark.theme.portraitProfileBadgeTextColor,
badgeColor: settingsEnglishDark.theme.portraitProfileBadgeColor(), badgeColor: settingsEnglishDark.theme.portraitProfileBadgeColor,
maskOut: false, maskOut: false,
border: settingsEnglishDark.theme.portraitOfflineBorderColor(), border: settingsEnglishDark.theme.portraitOfflineBorderColor,
diameter: 64.0, diameter: 64.0,
badgeCount: 10, badgeCount: 10,
); );

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -6,7 +6,8 @@
// tree, read text, and verify that the values of widget properties are correct. // tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cwtch/opaque.dart'; import 'package:cwtch/themes/opaque.dart';
import 'package:cwtch/themes/cwtch.dart';
import 'package:cwtch/settings.dart'; import 'package:cwtch/settings.dart';
import 'package:cwtch/widgets/textfield.dart'; import 'package:cwtch/widgets/textfield.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
@ -14,8 +15,8 @@ import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
var settingsEnglishDark = Settings(Locale("en", ''), OpaqueDark()); var settingsEnglishDark = Settings(Locale("en", ''), CwtchDark());
var settingsEnglishLight = Settings(Locale("en", ''), OpaqueLight()); var settingsEnglishLight = Settings(Locale("en", ''), CwtchLight());
ChangeNotifierProvider<Settings> getSettingsEnglishDark() => ChangeNotifierProvider.value(value: settingsEnglishDark); ChangeNotifierProvider<Settings> getSettingsEnglishDark() => ChangeNotifierProvider.value(value: settingsEnglishDark);
String file(String slug) { String file(String slug) {
@ -27,7 +28,7 @@ void main() {
tester.binding.window.physicalSizeTestValue = Size(800, 300); tester.binding.window.physicalSizeTestValue = Size(800, 300);
final TextEditingController ctrlr1 = TextEditingController(); final TextEditingController ctrlr1 = TextEditingController();
Widget testWidget = CwtchTextField(controller: ctrlr1, validator: (value) { }, labelText: '',); Widget testWidget = CwtchTextField(controller: ctrlr1, validator: (value) { }, hintText: '',);
Widget testHarness = MultiProvider( Widget testHarness = MultiProvider(
providers:[getSettingsEnglishDark()], providers:[getSettingsEnglishDark()],
@ -69,7 +70,7 @@ void main() {
Widget testWidget = CwtchTextField( Widget testWidget = CwtchTextField(
controller: ctrlr1, controller: ctrlr1,
labelText: strLabel1, hintText: strLabel1,
validator: (value) { validator: (value) {
if (value == null || value == "") return strFail1; if (value == null || value == "") return strFail1;
final number = num.tryParse(value); final number = num.tryParse(value);

View File

@ -65,6 +65,11 @@ ShowInstDetails show
!insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH !insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
; Languages -------------------------------- ; Languages --------------------------------
!insertmacro MUI_LANGUAGE "English" !insertmacro MUI_LANGUAGE "English"
@ -81,12 +86,20 @@ Section
FILE /r "..\..\build\windows\runner\Release\" FILE /r "..\..\build\windows\runner\Release\"
#FILESLISTEND #FILESLISTEND
CreateDirectory "$SMPROGRAMS\Cwtch"
# create a shortcut in the start menu programs directory # create a shortcut in the start menu programs directory
CreateDirectory "$SMPROGRAMS\Cwtch"
CreateShortcut "$SMPROGRAMS\Cwtch\Cwtch.lnk" "$INSTDIR\cwtch.exe" "" "$INSTDIR\cwtch.ico" CreateShortcut "$SMPROGRAMS\Cwtch\Cwtch.lnk" "$INSTDIR\cwtch.exe" "" "$INSTDIR\cwtch.ico"
;Store installation folder ;Store installation folder
WriteRegStr HKCU "Software\Cwtch" "installLocation" $INSTDIR WriteRegStr HKCU "Software\Cwtch" "installLocation" $INSTDIR
WriteUninstaller "$INSTDIR\uninstall.exe"
SectionEnd SectionEnd
Section "Uninstall"
RMDir /r /REBOOTOK "$INSTDIR"
DeleteRegKey /ifempty HKCU "Software\Cwtch\installLocation"
SectionEnd