Merge pull request 'Formatting' (#19) from splash into trunk

Reviewed-on: #19
This commit is contained in:
erinn 2021-03-17 12:30:10 -07:00
commit 827873b68b
22 changed files with 417 additions and 1269 deletions

View File

@ -21,31 +21,32 @@ class CwtchNotifier {
switch (type) {
case "NewPeer":
profileCN.add(ProfileInfoState(
onion: data["Identity"],
nickname: data["name"],
imagePath: data["picture"],
contactsJson: data["ContactsJson"],
onion: data["Identity"],
nickname: data["name"],
imagePath: data["picture"],
contactsJson: data["ContactsJson"],
));
break;
case "PeerCreated":
print("xx peercreated");
profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState(
profileOnion: data["ProfileOnion"],
onion: data["RemotePeer"],
nickname: data["nick"],
status: data["status"],
));
profileOnion: data["ProfileOnion"],
onion: data["RemotePeer"],
nickname: data["nick"],
status: data["status"],
));
break;
case "PeerStateChange":
ContactInfoState contact = profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]);
if (contact == null) {//todo: stopgap, as lc-g is supposed to handle this
print("PSC -> adding "+data["ProfileOnion"]+" :: " + data["RemotePeer"]);
if (contact == null) {
//todo: stopgap, as lc-g is supposed to handle this
print("PSC -> adding " + data["ProfileOnion"] + " :: " + data["RemotePeer"]);
profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState(
profileOnion: data["ProfileOnion"],
onion: data["RemotePeer"],
nickname: data["nick"],
status: data["ConnectionState"],
));
profileOnion: data["ProfileOnion"],
onion: data["RemotePeer"],
nickname: data["nick"],
status: data["ConnectionState"],
));
} else {
contact.status = data["ConnectionState"];
}

View File

@ -15,52 +15,38 @@ import '../model.dart';
/// Cwtch API ///
/////////////////////
typedef start_cwtch_function = Void Function(
Pointer<Utf8> str, Int32 length, Pointer<Utf8> str2, Int32 length2);
typedef StartCwtchFn = void Function(
Pointer<Utf8> dir, int len, Pointer<Utf8> tor, int torLen);
typedef start_cwtch_function = Void Function(Pointer<Utf8> str, Int32 length, Pointer<Utf8> str2, Int32 length2);
typedef StartCwtchFn = void Function(Pointer<Utf8> dir, int len, Pointer<Utf8> tor, int torLen);
typedef void_from_string_string_function = Void Function(
Pointer<Utf8>, Int32, Pointer<Utf8>, Int32);
typedef VoidFromStringStringFn = void Function(
Pointer<Utf8>, int, Pointer<Utf8>, int);
typedef void_from_string_string_function = Void Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32);
typedef VoidFromStringStringFn = void Function(Pointer<Utf8>, int, Pointer<Utf8>, int);
typedef access_cwtch_eventbus_function = Void Function();
typedef NextEventFn = void Function();
typedef string_to_void_function = Void Function(
Pointer<Utf8> str, Int32 length);
typedef string_to_void_function = Void Function(Pointer<Utf8> str, Int32 length);
typedef StringFn = void Function(Pointer<Utf8> dir, int);
typedef string_string_to_void_function = Void Function(
Pointer<Utf8> str, Int32 length, Pointer<Utf8> str2, Int32 length2);
typedef string_string_to_void_function = Void Function(Pointer<Utf8> str, Int32 length, Pointer<Utf8> str2, Int32 length2);
typedef StringStringFn = void Function(Pointer<Utf8>, int, Pointer<Utf8>, int);
typedef get_json_blob_void_function = Pointer<Utf8> Function();
typedef GetJsonBlobVoidFn = Pointer<Utf8> Function();
typedef get_json_blob_string_function = Pointer<Utf8> Function(
Pointer<Utf8> str, Int32 length);
typedef GetJsonBlobStringFn = Pointer<Utf8> Function(
Pointer<Utf8> str, int len);
typedef get_json_blob_string_function = Pointer<Utf8> Function(Pointer<Utf8> str, Int32 length);
typedef GetJsonBlobStringFn = Pointer<Utf8> Function(Pointer<Utf8> str, int len);
//func NumMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int) (n C.int) {
typedef get_int_from_str_str_function = Int32 Function(
Pointer<Utf8>, Int32, Pointer<Utf8>, Int32);
typedef GetIntFromStrStrFn = int Function(
Pointer<Utf8>, int, Pointer<Utf8>, int);
typedef get_int_from_str_str_function = Int32 Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32);
typedef GetIntFromStrStrFn = int Function(Pointer<Utf8>, int, Pointer<Utf8>, int);
//func GetMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, message_index C.int) *C.char {
typedef get_json_blob_from_str_str_int_function = Pointer<Utf8> Function(
Pointer<Utf8>, Int32, Pointer<Utf8>, Int32, Int32);
typedef GetJsonBlobFromStrStrIntFn = Pointer<Utf8> Function(
Pointer<Utf8>, int, Pointer<Utf8>, int, int);
typedef get_json_blob_from_str_str_int_function = Pointer<Utf8> Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32, Int32);
typedef GetJsonBlobFromStrStrIntFn = Pointer<Utf8> Function(Pointer<Utf8>, int, Pointer<Utf8>, int, int);
//func GetMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, start C.int, end C.int) *C.char {
typedef get_json_blob_from_str_str_int_int_function = Pointer<Utf8> Function(
Pointer<Utf8>, Int32, Pointer<Utf8>, Int32, Int32, Int32);
typedef GetJsonBlobFromStrStrIntIntFn = Pointer<Utf8> Function(
Pointer<Utf8>, int, Pointer<Utf8>, int, int, int);
typedef get_json_blob_from_str_str_int_int_function = Pointer<Utf8> Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32, Int32, Int32);
typedef GetJsonBlobFromStrStrIntIntFn = Pointer<Utf8> Function(Pointer<Utf8>, int, Pointer<Utf8>, int, int, int);
typedef acn_events_function = Pointer<Utf8> Function();
typedef ACNEventsFn = Pointer<Utf8> Function();
@ -86,8 +72,7 @@ class CwtchFfi implements Cwtch {
var cwtchDir = path.join(home, ".cwtch/dev/");
print("cwtchDir $cwtchDir");
var startCwtchC =
library.lookup<NativeFunction<start_cwtch_function>>("c_StartCwtch");
var startCwtchC = library.lookup<NativeFunction<start_cwtch_function>>("c_StartCwtch");
// ignore: non_constant_identifier_names
final StartCwtch = startCwtchC.asFunction<StartCwtchFn>();
@ -96,8 +81,7 @@ class CwtchFfi implements Cwtch {
// Spawn an isolate to listen to events from libcwtch-go and then dispatch them when received on main thread to cwtchNotifier
var _receivePort = ReceivePort();
cwtchIsolate =
await Isolate.spawn(_checkAppbusEvents, _receivePort.sendPort);
cwtchIsolate = await Isolate.spawn(_checkAppbusEvents, _receivePort.sendPort);
_receivePort.listen((message) {
var env = jsonDecode(message);
cwtchNotifier.handleMessage(env["EventType"], env["Data"]);
@ -123,8 +107,7 @@ class CwtchFfi implements Cwtch {
// Steam of appbus events. Call blocks in libcwtch-go GetAppbusEvent. Static so the isolate can use it
static Stream<String> pollAppbusEvents() async* {
var library = DynamicLibrary.open("libCwtch.so");
var getAppbusEventC =
library.lookup<NativeFunction<acn_events_function>>("c_GetAppBusEvent");
var getAppbusEventC = library.lookup<NativeFunction<acn_events_function>>("c_GetAppBusEvent");
final GetAppbusEvent = getAppbusEventC.asFunction<ACNEventsFn>();
while (true) {
@ -136,9 +119,7 @@ class CwtchFfi implements Cwtch {
// ignore: non_constant_identifier_names
void SelectProfile(String onion) async {
var selectProfileC =
library.lookup<NativeFunction<get_json_blob_string_function>>(
"c_SelectProfile");
var selectProfileC = library.lookup<NativeFunction<get_json_blob_string_function>>("c_SelectProfile");
// ignore: non_constant_identifier_names
final SelectProfile = selectProfileC.asFunction<GetJsonBlobStringFn>();
final ut8Onion = onion.toNativeUtf8();
@ -147,9 +128,7 @@ class CwtchFfi implements Cwtch {
// ignore: non_constant_identifier_names
void CreateProfile(String nick, String pass) {
var createProfileC =
library.lookup<NativeFunction<void_from_string_string_function>>(
"c_CreateProfile");
var createProfileC = library.lookup<NativeFunction<void_from_string_string_function>>("c_CreateProfile");
// ignore: non_constant_identifier_names
final CreateProfile = createProfileC.asFunction<VoidFromStringStringFn>();
final utf8nick = nick.toNativeUtf8();
@ -159,8 +138,7 @@ class CwtchFfi implements Cwtch {
// ignore: non_constant_identifier_names
void LoadProfiles(String pass) {
var loadProfileC = library
.lookup<NativeFunction<string_to_void_function>>("c_LoadProfiles");
var loadProfileC = library.lookup<NativeFunction<string_to_void_function>>("c_LoadProfiles");
// ignore: non_constant_identifier_names
final LoadProfiles = loadProfileC.asFunction<StringFn>();
final ut8pass = pass.toNativeUtf8();
@ -168,8 +146,7 @@ class CwtchFfi implements Cwtch {
}
Future<String> ACNEvents() async {
var acnEventsC =
library.lookup<NativeFunction<acn_events_function>>("c_ACNEvents");
var acnEventsC = library.lookup<NativeFunction<acn_events_function>>("c_ACNEvents");
// ignore: non_constant_identifier_names
final ACNEvents = acnEventsC.asFunction<ACNEventsFn>();
@ -179,8 +156,7 @@ class CwtchFfi implements Cwtch {
}
Future<String> ContactEvents() async {
var acnEventsC =
library.lookup<NativeFunction<acn_events_function>>("c_ContactEvents");
var acnEventsC = library.lookup<NativeFunction<acn_events_function>>("c_ContactEvents");
// ignore: non_constant_identifier_names
final ContactEvents = acnEventsC.asFunction<ACNEventsFn>();
@ -190,8 +166,7 @@ class CwtchFfi implements Cwtch {
}
Future<String> GetProfiles() async {
var getProfilesC = library
.lookup<NativeFunction<get_json_blob_void_function>>("c_GetProfiles");
var getProfilesC = library.lookup<NativeFunction<get_json_blob_void_function>>("c_GetProfiles");
// ignore: non_constant_identifier_names
final GetProfiles = getProfilesC.asFunction<GetJsonBlobVoidFn>();
@ -201,8 +176,7 @@ class CwtchFfi implements Cwtch {
}
Future<String> GetContacts(String onion) async {
var getContactsC = library
.lookup<NativeFunction<get_json_blob_string_function>>("c_GetContacts");
var getContactsC = library.lookup<NativeFunction<get_json_blob_string_function>>("c_GetContacts");
// ignore: non_constant_identifier_names
final GetContacts = getContactsC.asFunction<GetJsonBlobStringFn>();
final utf8onion = onion.toNativeUtf8();
@ -212,52 +186,40 @@ class CwtchFfi implements Cwtch {
}
Future<int> NumMessages(String profile, String handle) async {
var numMessagesC = library
.lookup<NativeFunction<get_int_from_str_str_function>>("c_NumMessages");
var numMessagesC = library.lookup<NativeFunction<get_int_from_str_str_function>>("c_NumMessages");
// ignore: non_constant_identifier_names
final NumMessages = numMessagesC.asFunction<GetIntFromStrStrFn>();
final utf8profile = profile.toNativeUtf8();
final utf8handle = handle.toNativeUtf8();
int num = NumMessages(
utf8profile, utf8profile.length, utf8handle, utf8handle.length);
int num = NumMessages(utf8profile, utf8profile.length, utf8handle, utf8handle.length);
return num;
}
Future<String> GetMessage(String profile, String handle, int index) async {
var getMessageC =
library.lookup<NativeFunction<get_json_blob_from_str_str_int_function>>(
"c_GetMessage");
var getMessageC = library.lookup<NativeFunction<get_json_blob_from_str_str_int_function>>("c_GetMessage");
// ignore: non_constant_identifier_names
final GetMessage = getMessageC.asFunction<GetJsonBlobFromStrStrIntFn>();
final utf8profile = profile.toNativeUtf8();
final utf8handle = handle.toNativeUtf8();
Pointer<Utf8> jsonMessageBytes = GetMessage(
utf8profile, utf8profile.length, utf8handle, utf8handle.length, index);
Pointer<Utf8> jsonMessageBytes = GetMessage(utf8profile, utf8profile.length, utf8handle, utf8handle.length, index);
String jsonMessage = jsonMessageBytes.toDartString();
return jsonMessage;
}
Future<String> GetMessages(
String profile, String handle, int start, int end) async {
var getMessagesC = library
.lookup<NativeFunction<get_json_blob_from_str_str_int_int_function>>(
"c_GetMessages");
Future<String> GetMessages(String profile, String handle, int start, int end) async {
var getMessagesC = library.lookup<NativeFunction<get_json_blob_from_str_str_int_int_function>>("c_GetMessages");
// ignore: non_constant_identifier_names
final GetMessages =
getMessagesC.asFunction<GetJsonBlobFromStrStrIntIntFn>();
final GetMessages = getMessagesC.asFunction<GetJsonBlobFromStrStrIntIntFn>();
final utf8profile = profile.toNativeUtf8();
final utf8handle = handle.toNativeUtf8();
Pointer<Utf8> jsonMessagesBytes = GetMessages(utf8profile,
utf8profile.length, utf8handle, utf8handle.length, start, end);
Pointer<Utf8> jsonMessagesBytes = GetMessages(utf8profile, utf8profile.length, utf8handle, utf8handle.length, start, end);
String jsonMessages = jsonMessagesBytes.toDartString();
return jsonMessages;
}
@override
void SendProfileEvent(String onion, String json) {
var sendAppBusEvent =
library.lookup<NativeFunction<string_string_to_void_function>>(
"c_SendProfileEvent");
var sendAppBusEvent = library.lookup<NativeFunction<string_string_to_void_function>>("c_SendProfileEvent");
// ignore: non_constant_identifier_names
final SendAppBusEvent = sendAppBusEvent.asFunction<StringStringFn>();
final utf8onion = onion.toNativeUtf8();
@ -267,8 +229,7 @@ class CwtchFfi implements Cwtch {
@override
void SendAppEvent(String json) {
var sendAppBusEvent = library
.lookup<NativeFunction<string_to_void_function>>("c_SendAppEvent");
var sendAppBusEvent = library.lookup<NativeFunction<string_to_void_function>>("c_SendAppEvent");
// ignore: non_constant_identifier_names
final SendAppBusEvent = sendAppBusEvent.asFunction<StringFn>();
final utf8json = json.toNativeUtf8();

View File

@ -22,8 +22,7 @@ Future startCwtch() async {
*/
class CwtchGomobile implements Cwtch {
static const appInfoPlatform =
const MethodChannel('test.flutter.dev/applicationInfo');
static const appInfoPlatform = const MethodChannel('test.flutter.dev/applicationInfo');
static const cwtchPlatform = const MethodChannel('cwtch');
final appbusEventChannelName = 'test.flutter.dev/eventBus';
@ -48,8 +47,7 @@ class CwtchGomobile implements Cwtch {
var cwtchDir = path.join((await androidHomeDirectory).path, ".cwtch/dev/");
String torPath = path.join(await androidLibraryDir, "libtor.so");
print("gomobile.dart: Start invokeMethod Start($cwtchDir, $torPath)...");
cwtchPlatform
.invokeMethod("Start", {"appDir": cwtchDir, "torPath": torPath});
cwtchPlatform.invokeMethod("Start", {"appDir": cwtchDir, "torPath": torPath});
}
// Handle libcwtch-go events (received via kotlin) and dispatch to the cwtchNotifier
@ -89,26 +87,21 @@ class CwtchGomobile implements Cwtch {
}
Future<int> NumMessages(String profile, String handle) {
return cwtchPlatform
.invokeMethod("NumMessages", {"profile": profile, "contact": handle});
return cwtchPlatform.invokeMethod("NumMessages", {"profile": profile, "contact": handle});
}
Future<String> GetMessage(String profile, String handle, int index) {
print("gomobile.dart GetMessage " + index.toString());
return cwtchPlatform.invokeMethod(
"GetMessage", {"profile": profile, "contact": handle, "index": index});
return cwtchPlatform.invokeMethod("GetMessage", {"profile": profile, "contact": handle, "index": index});
}
Future<String> GetMessages(
String profile, String handle, int start, int end) {
return cwtchPlatform.invokeMethod("GetMessage",
{"profile": profile, "contact": handle, "start": start, "end": end});
Future<String> GetMessages(String profile, String handle, int start, int end) {
return cwtchPlatform.invokeMethod("GetMessage", {"profile": profile, "contact": handle, "start": start, "end": end});
}
@override
void SendProfileEvent(String onion, String jsonEvent) {
cwtchPlatform.invokeMethod(
"SendProfileEvent", {"onion": onion, "jsonEvent": jsonEvent});
cwtchPlatform.invokeMethod("SendProfileEvent", {"onion": onion, "jsonEvent": jsonEvent});
}
@override

View File

@ -86,7 +86,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.''');
/// Go Standard Lib
yield LicenseEntryWithLineBreaks(["crypto, net"], '''Copyright (c) 2009 The Go Authors. All rights reserved.

View File

@ -17,7 +17,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
var globalSettings = Settings(Locale("en", ''), Opaque.dark);
void main() {
LicenseRegistry.addLicense(() => licenses());
runApp(Flwtch());
@ -64,23 +63,16 @@ class FlwtchState extends State<Flwtch> {
appStatus = AppModel(cwtch: cwtch);
}
ChangeNotifierProvider<Settings> getSettingsProvider() =>
ChangeNotifierProvider(create: (context) => globalSettings);
Provider<FlwtchState> getFlwtchStateProvider() =>
Provider<FlwtchState>(create: (_) => this);
ChangeNotifierProvider<ProfileListState> getProfileListProvider() =>
ChangeNotifierProvider(create: (context) => profs);
ChangeNotifierProvider<Settings> getSettingsProvider() => ChangeNotifierProvider(create: (context) => globalSettings);
Provider<FlwtchState> getFlwtchStateProvider() => Provider<FlwtchState>(create: (_) => this);
ChangeNotifierProvider<ProfileListState> getProfileListProvider() => ChangeNotifierProvider(create: (context) => profs);
@override
Widget build(BuildContext context) {
appStatus = AppModel(cwtch: cwtch);
return MultiProvider(
providers: [
getFlwtchStateProvider(),
getProfileListProvider(),
getSettingsProvider()
],
providers: [getFlwtchStateProvider(), getProfileListProvider(), getSettingsProvider()],
builder: (context, widget) {
Provider.of<Settings>(context).initPackageInfo();
return Consumer<Settings>(
@ -103,20 +95,15 @@ class FlwtchState extends State<Flwtch> {
cardColor: opaque.current().backgroundMainColor(),
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
opaque.current().defaultButtonColor()),
foregroundColor: MaterialStateProperty.all(
opaque.current().defaultButtonTextColor()),
overlayColor: MaterialStateProperty.all(
opaque.current().defaultButtonActiveColor()),
backgroundColor: MaterialStateProperty.all(opaque.current().defaultButtonColor()),
foregroundColor: MaterialStateProperty.all(opaque.current().defaultButtonTextColor()),
overlayColor: MaterialStateProperty.all(opaque.current().defaultButtonActiveColor()),
padding: MaterialStateProperty.all(EdgeInsets.all(20))),
),
dialogTheme: DialogTheme(
backgroundColor: opaque.current().backgroundPaneColor(),
titleTextStyle:
TextStyle(color: opaque.current().mainTextColor()),
contentTextStyle:
TextStyle(color: opaque.current().mainTextColor())),
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()),
@ -134,9 +121,7 @@ class FlwtchState extends State<Flwtch> {
),
// from dan: home: cwtchInit == true ? ProfileMgrView(cwtch) : SplashView(),
// from erinn: home: columns.length == 3 ? TripleColumnView() : ProfileMgrView(),
home: cwtchInit == true
? (columns.length == 3 ? TripleColumnView() : ProfileMgrView())
: SplashView(),
home: cwtchInit == true ? (columns.length == 3 ? TripleColumnView() : ProfileMgrView()) : SplashView(),
),
);
},

View File

@ -29,13 +29,7 @@ class ContactModel {
String status;
String imagePath;
ContactModel(
{this.onion,
this.nickname,
this.status,
this.isInvitation,
this.isBlocked,
this.imagePath});
ContactModel({this.onion, this.nickname, this.status, this.isInvitation, this.isBlocked, this.imagePath});
}
//todo: delete
@ -78,12 +72,12 @@ class ProfileListState extends ChangeNotifier {
}
void add(ProfileInfoState newProfile) {
print("ProfileListState: adding " + newProfile.onion +" and notifying");
print("ProfileListState: adding " + newProfile.onion + " and notifying");
_profiles.add(newProfile);
notifyListeners();
}
List<ProfileInfoState> get profiles => _profiles.sublist(0);//todo: copy?? dont want caller able to bypass changenotifier
List<ProfileInfoState> get profiles => _profiles.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier
ProfileInfoState getProfile(String onion) {
int idx = _profiles.indexWhere((element) => element.onion == onion);
@ -106,13 +100,15 @@ class ContactListState extends ChangeNotifier {
}
void updateUnreadMessages(String forOnion, int newVal) {
_contacts.sort((ContactInfoState a, ContactInfoState b) { return b.unreadMessages - a.unreadMessages; });
_contacts.sort((ContactInfoState a, ContactInfoState b) {
return b.unreadMessages - a.unreadMessages;
});
//<todo> if(changed) {
notifyListeners();
//} </todo>
}
List<ContactInfoState> get contacts => _contacts.sublist(0);//todo: copy?? dont want caller able to bypass changenotifier
List<ContactInfoState> get contacts => _contacts.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier
ContactInfoState getContact(String onion) {
int idx = _contacts.indexWhere((element) => element.onion == onion);
@ -127,7 +123,13 @@ class ProfileInfoState extends ChangeNotifier {
String _imagePath = "";
int _unreadMessages = 0;
ProfileInfoState({this.onion, nickname = "", imagePath = "", unreadMessages = 0, contactsJson = "",}){
ProfileInfoState({
this.onion,
nickname = "",
imagePath = "",
unreadMessages = 0,
contactsJson = "",
}) {
this._nickname = nickname;
this._imagePath = imagePath;
this._unreadMessages = unreadMessages;
@ -135,17 +137,15 @@ class ProfileInfoState extends ChangeNotifier {
if (contactsJson != null && contactsJson != "" && contactsJson != "null") {
print("decoding " + contactsJson);
List<dynamic> contacts = jsonDecode(contactsJson);
this._contacts.addAll(
contacts.map((contact){
return ContactInfoState(
profileOnion: this.onion,
onion: contact["onion"],
nickname: contact["name"],
status: contact["status"],
imagePath: contact["picture"],
);
})
);
this._contacts.addAll(contacts.map((contact) {
return ContactInfoState(
profileOnion: this.onion,
onion: contact["onion"],
nickname: contact["name"],
status: contact["status"],
imagePath: contact["picture"],
);
}));
}
}

View File

@ -1,509 +0,0 @@
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND AS CHANGES WILL BE OVERRIDDEN.
// TO EDIT THE THEME, SEE https://git.openprivacy.ca/openprivacy/opaque/
// FOR HOW THIS FILE IS GENERATED, SEE ../regenerate_opaque_theme.sh
import 'dart:ui';
import 'dart:core';
abstract class OpaqueThemeType {
static final Color red = Color(0xFFFF0000);
Color backgroundMainColor(){return red;}
Color backgroundPaneColor(){return red;}
Color backgroundHilightElementColor(){return red;}
Color dividerColor(){return red;}
Color mainTextColor(){return red;}
Color altTextColor(){return red;}
Color hilightElementTextColor(){return red;}
Color defaultButtonColor(){return red;}
Color defaultButtonActiveColor(){return red;}
Color defaultButtonTextColor(){return red;}
Color defaultButtonDisabledColor(){return red;}
Color defaultButtonDisabledTextColor(){return red;}
Color altButtonColor(){return red;}
Color altButtonTextColor(){return red;}
Color altButtonDisabledColor(){return red;}
Color altButtonDisabledTextColor(){return red;}
Color textfieldBackgroundColor(){return red;}
Color textfieldBorderColor(){return red;}
Color textfieldTextColor(){return red;}
Color textfieldErrorColor(){return red;}
Color textfieldButtonColor(){return red;}
Color textfieldButtonTextColor(){return red;}
Color scrollbarDefaultColor(){return red;}
Color scrollbarActiveColor(){return red;}
Color portraitOnlineBorderColor(){return red;}
Color portraitOnlineBackgroundColor(){return red;}
Color portraitOnlineTextColor(){return red;}
Color portraitConnectingBorderColor(){return red;}
Color portraitConnectingBackgroundColor(){return red;}
Color portraitConnectingTextColor(){return red;}
Color portraitOfflineBorderColor(){return red;}
Color portraitOfflineBackgroundColor(){return red;}
Color portraitOfflineTextColor(){return red;}
Color portraitBlockedBorderColor(){return red;}
Color portraitBlockedBackgroundColor(){return red;}
Color portraitBlockedTextColor(){return red;}
Color portraitOnlineBadgeColor(){return red;}
Color portraitOfflineBadgeColor(){return red;}
Color portraitContactBadgeColor(){return red;}
Color portraitContactBadgeTextColor(){return red;}
Color portraitProfileBadgeColor(){return red;}
Color portraitProfileBadgeTextColor(){return red;}
Color portraitOverlayOfflineColor(){return red;}
Color dropShadowColor(){return red;}
Color dropShadowPaneColor(){return red;}
Color toggleColor(){return red;}
Color toggleOnColor(){return red;}
Color toggleOffColor(){return red;}
Color sliderButtonColor(){return red;}
Color sliderBarLeftColor(){return red;}
Color sliderBarRightColor(){return red;}
Color boxCheckedColor(){return red;}
Color toolbarIconColor(){return red;}
Color toolbarMainColor(){return red;}
Color toolbarAltColor(){return red;}
Color statusbarDisconnectedInternetColor(){return red;}
Color statusbarDisconnectedInternetFontColor(){return red;}
Color statusbarDisconnectedTorFontColor(){return red;}
Color statusbarDisconnectedTorColor(){return red;}
Color statusbarConnectingColor(){return red;}
Color statusbarConnectingFontColor(){return red;}
Color statusbarOnlineColor(){return red;}
Color statusbarOnlineFontColor(){return red;}
Color chatOverlayWarningTextColor(){return red;}
Color messageFromMeBackgroundColor(){return red;}
Color messageFromMeTextColor(){return red;}
Color messageFromOtherBackgroundColor(){return red;}
Color messageFromOtherTextColor(){return red;}
Color messageStatusNormalColor(){return red;}
Color messageStatusBlockedColor(){return red;}
Color messageStatusBlockedTextColor(){return red;}
Color messageStatusAlertColor(){return red;}
Color messageStatusAlertTextColor(){return red;}
// ... more to come
}
class CwtchDark extends OpaqueThemeType {
static final Color darkGreyPurple = Color(0xFF281831);
static final Color deepPurple = Color(0xFF422850);
static final Color mauvePurple = Color(0xFF8E64A5);
static final Color purple = Color(0xFFDFB9DE);
static final Color whitePurple = Color(0xFFE3DFE4);
static final Color softPurple = Color(0xFFFDF3FC);
static final Color pink = Color(0xFFE85DA1);
static final Color hotPink = Color(0xFFD01972);
static final Color lightGrey = Color(0xFF9E9E9E);
static final Color softGreen = Color(0xFFA0FFB0);
static final Color softRed = Color(0xFFFFA0B0);
Color backgroundMainColor() { return darkGreyPurple; }
Color backgroundPaneColor() { return darkGreyPurple; }
Color backgroundHilightElementColor() { return deepPurple; }
Color dividerColor() { return deepPurple; }
Color mainTextColor() { return whitePurple; }
Color altTextColor() { return whitePurple; }
Color hilightElementTextColor() { return purple; }
Color defaultButtonColor() { return hotPink; }
Color defaultButtonActiveColor() { return pink; }
Color defaultButtonTextColor() { return whitePurple; }
Color defaultButtonDisabledColor() { return deepPurple; }
Color defaultButtonDisabledTextColor() { return darkGreyPurple; }
Color altButtonColor() { return darkGreyPurple; }
Color altButtonTextColor() { return purple; }
Color altButtonDisabledColor() { return darkGreyPurple; }
Color altButtonDisabledTextColor() { return purple; }
Color textfieldBackgroundColor() { return deepPurple; }
Color textfieldBorderColor() { return deepPurple; }
Color textfieldTextColor() { return purple; }
Color textfieldErrorColor() { return hotPink; }
Color textfieldButtonColor() { return purple; }
Color textfieldButtonTextColor() { return darkGreyPurple; }
Color scrollbarDefaultColor() { return purple; }
Color scrollbarActiveColor() { return hotPink; }
Color portraitOnlineBorderColor() { return whitePurple; }
Color portraitOnlineBackgroundColor() { return whitePurple; }
Color portraitOnlineTextColor() { return whitePurple; }
Color portraitConnectingBorderColor() { return purple; } //mauvePurple
Color portraitConnectingBackgroundColor() { return purple; } //darkGreyPurple
Color portraitConnectingTextColor() { return purple; }
Color portraitOfflineBorderColor() { return purple; }
Color portraitOfflineBackgroundColor() { return purple; }
Color portraitOfflineTextColor() { return purple; }
Color portraitBlockedBorderColor() { return lightGrey; }
Color portraitBlockedBackgroundColor() { return lightGrey; }
Color portraitBlockedTextColor() { return lightGrey; }
Color portraitOnlineBadgeColor() { return softGreen; }
Color portraitOfflineBadgeColor() { return softRed; }
Color portraitContactBadgeColor() { return hotPink; }
Color portraitContactBadgeTextColor() { return whitePurple; }
Color portraitProfileBadgeColor() { return mauvePurple; }
Color portraitProfileBadgeTextColor() { return darkGreyPurple; }
Color portraitOverlayOfflineColor() { return mauvePurple; }
Color dropShadowColor() { return mauvePurple; }
Color dropShadowPaneColor() { return darkGreyPurple; }
Color toggleColor() { return darkGreyPurple; }
Color toggleOnColor() { return whitePurple; }
Color toggleOffColor() { return deepPurple; }
Color sliderButtonColor() { return whitePurple; }
Color sliderBarLeftColor() { return mauvePurple; }
Color sliderBarRightColor() { return mauvePurple; }
Color boxCheckedColor() { return hotPink; }
Color toolbarIconColor() { return whitePurple; }
Color toolbarMainColor() { return darkGreyPurple; }
Color toolbarAltColor() { return deepPurple; }
Color statusbarDisconnectedInternetColor() { return whitePurple; }
Color statusbarDisconnectedInternetFontColor() { return deepPurple; }
Color statusbarDisconnectedTorColor() { return darkGreyPurple; }
Color statusbarDisconnectedTorFontColor() { return whitePurple; }
Color statusbarConnectingColor() { return deepPurple; }
Color statusbarConnectingFontColor() { return whitePurple; }
Color statusbarOnlineColor() { return mauvePurple; }
Color statusbarOnlineFontColor() { return whitePurple; }
Color chatOverlayWarningTextColor() { return purple; }
Color messageFromMeBackgroundColor() { return mauvePurple; }
Color messageFromMeTextColor() { return whitePurple; }
Color messageFromOtherBackgroundColor() { return deepPurple; }
Color messageFromOtherTextColor() { return whitePurple; }
Color messageStatusNormalColor() { return deepPurple; }
Color messageStatusBlockedColor() { return lightGrey; }
Color messageStatusBlockedTextColor() { return whitePurple; }
Color messageStatusAlertColor() { return mauvePurple; }
Color messageStatusAlertTextColor() { return whitePurple; }
}
class CwtchLight extends OpaqueThemeType {
static final Color whitePurple = Color(0xFFFFFDFF);
static final Color softPurple = Color(0xFFFDF3FC);
static final Color purple = Color(0xFFDFB9DE);
static final Color brightPurple = Color(0xFF760388);
static final Color darkPurple = Color(0xFF350052);
static final Color greyPurple = Color(0xFF775F84);
static final Color pink = Color(0xFFE85DA1);
static final Color hotPink = Color(0xFFD01972);
static final Color lightGrey = Color(0xFFB3B6B3);
static final Color softGreen = Color(0xFFA0FFB0);
static final Color softRed = Color(0xFFFFA0B0);
Color backgroundMainColor() { return whitePurple; }
Color backgroundPaneColor() { return softPurple; }
Color backgroundHilightElementColor() { return softPurple; }
Color dividerColor() { return purple; }
Color mainTextColor() { return darkPurple; }
Color altTextColor() { return purple; }
Color hilightElementTextColor() { return darkPurple; }
Color defaultButtonColor() { return hotPink; }
Color defaultButtonActiveColor() { return pink; }
Color defaultButtonTextColor() { return whitePurple; }
Color defaultButtonDisabledColor() { return purple; }
Color defaultButtonDisabledTextColor() { return whitePurple; }
Color altButtonColor() { return whitePurple; }
Color altButtonTextColor() { return purple; }
Color altButtonDisabledColor() { return softPurple; }
Color altButtonDisabledTextColor() { return purple; }
Color textfieldBackgroundColor() { return whitePurple; }
Color textfieldBorderColor() { return purple; }
Color textfieldTextColor() { return purple; }
Color textfieldErrorColor() { return hotPink; }
Color textfieldButtonColor() { return hotPink; }
Color textfieldButtonTextColor() { return whitePurple; }
Color scrollbarDefaultColor() { return darkPurple; }
Color scrollbarActiveColor() { return hotPink; }
Color portraitOnlineBorderColor() { return darkPurple; }
Color portraitOnlineBackgroundColor() { return darkPurple; }
Color portraitOnlineTextColor() { return darkPurple; }
Color portraitConnectingBorderColor() { return greyPurple; }
Color portraitConnectingBackgroundColor() { return greyPurple; }
Color portraitConnectingTextColor() { return greyPurple; }
Color portraitOfflineBorderColor() { return greyPurple; } //purple
Color portraitOfflineBackgroundColor() { return greyPurple; } //purple
Color portraitOfflineTextColor() { return greyPurple; }//purple
Color portraitBlockedBorderColor() { return lightGrey; }
Color portraitBlockedBackgroundColor() { return lightGrey; }
Color portraitBlockedTextColor() { return lightGrey; }
Color portraitOnlineBadgeColor() { return softGreen; }
Color portraitOfflineBadgeColor() { return softRed; }
Color portraitContactBadgeColor() { return hotPink; }
Color portraitContactBadgeTextColor() { return whitePurple; }
Color portraitProfileBadgeColor() { return brightPurple; }
Color portraitProfileBadgeTextColor() { return whitePurple; }
Color portraitOverlayOfflineColor() { return whitePurple; }
Color dropShadowColor() { return purple; }
Color dropShadowPaneColor() { return purple; }
Color toggleColor() { return whitePurple; }
Color toggleOnColor() { return hotPink; }
Color toggleOffColor() { return purple; }
Color sliderButtonColor() { return pink; }
Color sliderBarLeftColor() { return purple; }
Color sliderBarRightColor() { return purple; }
Color boxCheckedColor() { return darkPurple; }
Color toolbarIconColor() { return darkPurple; }
Color toolbarMainColor() { return whitePurple; }
Color toolbarAltColor() { return softPurple; }
Color statusbarDisconnectedInternetColor() { return softPurple; }
Color statusbarDisconnectedInternetFontColor() { return darkPurple; }
Color statusbarDisconnectedTorColor() { return purple; }
Color statusbarDisconnectedTorFontColor() { return darkPurple; }
Color statusbarConnectingColor() { return greyPurple; }
Color statusbarConnectingFontColor() { return whitePurple; }
Color statusbarOnlineColor() { return darkPurple; }
Color statusbarOnlineFontColor() { return whitePurple; }
Color chatOverlayWarningTextColor() { return purple; }
Color messageFromMeBackgroundColor() { return darkPurple; }
Color messageFromMeTextColor() { return whitePurple; }
Color messageFromOtherBackgroundColor() { return purple; }
Color messageFromOtherTextColor() { return darkPurple; }
Color messageStatusNormalColor() { return purple; }
Color messageStatusBlockedColor() { return lightGrey; }
Color messageStatusBlockedTextColor() { return whitePurple; }
Color messageStatusAlertColor() { return hotPink; }
Color messageStatusAlertTextColor() { return whitePurple; }
}
class Opaque extends OpaqueThemeType {
Color backgroundMainColor() { return current().backgroundMainColor(); }
Color backgroundPaneColor() { return current().backgroundPaneColor(); }
Color backgroundHilightElementColor() { return current().backgroundHilightElementColor(); }
Color dividerColor() { return current().dividerColor(); }
Color mainTextColor() { return current().mainTextColor(); }
Color altTextColor() { return current().altTextColor(); }
Color hilightElementTextColor() { return current().hilightElementTextColor(); }
Color defaultButtonColor() { return current().defaultButtonColor(); }
Color defaultButtonActiveColor() { return current().defaultButtonActiveColor(); }
Color defaultButtonTextColor() { return current().defaultButtonTextColor(); }
Color defaultButtonDisabledColor() { return current().defaultButtonDisabledColor(); }
Color defaultButtonDisabledTextColor() { return current().defaultButtonDisabledTextColor(); }
Color altButtonColor() { return current().altButtonColor(); }
Color altButtonTextColor() { return current().altButtonTextColor(); }
Color altButtonDisabledColor() { return current().altButtonDisabledColor(); }
Color altButtonDisabledTextColor() { return current().altButtonDisabledTextColor(); }
Color textfieldBackgroundColor() { return current().textfieldBackgroundColor(); }
Color textfieldBorderColor() { return current().textfieldBorderColor(); }
Color textfieldTextColor() { return current().textfieldTextColor(); }
Color textfieldErrorColor() { return current().textfieldErrorColor(); }
Color textfieldButtonColor() { return current().textfieldButtonColor(); }
Color textfieldButtonTextColor() { return current().textfieldButtonTextColor(); }
Color dropShadowColor() { return current().dropShadowColor(); }
Color dropShadowPaneColor() { return current().dropShadowPaneColor(); }
Color portraitOnlineBorderColor() { return current().portraitOnlineBorderColor(); }
Color portraitOnlineBackgroundColor() { return current().portraitOnlineBackgroundColor(); }
Color portraitOnlineTextColor() { return current().portraitOnlineTextColor(); }
Color portraitConnectingBorderColor() { return current().portraitConnectingBorderColor(); }
Color portraitConnectingBackgroundColor() { return current().portraitConnectingBackgroundColor(); }
Color portraitConnectingTextColor() { return current().portraitConnectingTextColor(); }
Color portraitOfflineBorderColor() { return current().portraitOfflineBorderColor(); }
Color portraitOfflineBackgroundColor() { return current().portraitOfflineBackgroundColor(); }
Color portraitOfflineTextColor() { return current().portraitOfflineTextColor(); }
Color portraitBlockedBorderColor() { return current().portraitBlockedBorderColor(); }
Color portraitBlockedBackgroundColor() { return current().portraitBlockedBackgroundColor(); }
Color portraitBlockedTextColor() { return current().portraitBlockedTextColor(); }
Color portraitOnlineBadgeColor() { return current().portraitOnlineBadgeColor(); }
Color portraitOfflineBadgeColor() { return current().portraitOfflineBadgeColor(); }
Color portraitContactBadgeColor() { return current().portraitContactBadgeColor(); }
Color portraitContactBadgeTextColor() { return current().portraitContactBadgeTextColor(); }
Color portraitProfileBadgeColor() { return current().portraitProfileBadgeColor(); }
Color portraitProfileBadgeTextColor() { return current().portraitProfileBadgeTextColor(); }
Color portraitOverlayOfflineColor() { return current().portraitOverlayOfflineColor(); }
Color toggleColor() { return current().toggleColor(); }
Color toggleOffColor() { return current().toggleOffColor(); }
Color toggleOnColor() { return current().toggleOnColor(); }
Color sliderButtonColor() { return current().sliderButtonColor(); }
Color sliderBarLeftColor() { return current().sliderBarLeftColor(); }
Color sliderBarRightColor() { return current().sliderBarRightColor(); }
Color boxCheckedColor() { return current().boxCheckedColor(); }
Color toolbarIconColor() { return current().toolbarIconColor(); }
Color toolbarMainColor() { return current().toolbarMainColor(); }
Color toolbarAltColor() { return current().toolbarAltColor(); }
Color statusbarDisconnectedInternetColor() { return current().statusbarDisconnectedInternetColor(); }
Color statusbarDisconnectedInternetFontColor() { return current().statusbarDisconnectedInternetFontColor(); }
Color statusbarDisconnectedTorFontColor() { return current().statusbarDisconnectedTorFontColor(); }
Color statusbarDisconnectedTorColor() { return current().statusbarDisconnectedTorColor(); }
Color statusbarConnectingColor() { return current().statusbarConnectingColor(); }
Color statusbarConnectingFontColor() { return current().statusbarConnectingFontColor(); }
Color statusbarOnlineColor() { return current().statusbarOnlineColor(); }
Color statusbarOnlineFontColor() { return current().statusbarOnlineFontColor(); }
Color chatOverlayWarningTextColor() { return current().chatOverlayWarningTextColor(); }
Color messageFromMeBackgroundColor() { return current().messageFromMeBackgroundColor(); }
Color messageFromMeTextColor() { return current().messageFromMeTextColor(); }
Color messageFromOtherBackgroundColor() { return current().messageFromOtherBackgroundColor(); }
Color messageFromOtherTextColor() { return current().messageFromOtherTextColor(); }
Color messageStatusNormalColor() { return current().messageStatusNormalColor(); }
Color messageStatusBlockedColor() { return current().messageStatusBlockedColor(); }
Color messageStatusBlockedTextColor() { return current().messageStatusBlockedTextColor(); }
Color messageStatusAlertColor() { return current().messageStatusAlertColor(); }
Color messageStatusAlertTextColor() { return current().messageStatusAlertTextColor(); }
Color scrollbarDefaultColor() { return current().scrollbarDefaultColor(); }
Color scrollbarActiveColor() { return current().scrollbarActiveColor(); }
var sidePaneMinSizeBase = [200, 400, 600];
int sidePaneMinSize() { return sidePaneMinSizeBase[p[scale]]+200/*for debugging*/; }
var chatPaneMinSizeBase = [300, 400, 500];
int chatPaneMinSize() { return chatPaneMinSizeBase[p[scale]]; }
int doublePaneMinSize() { return sidePaneMinSize() + chatPaneMinSize(); }
static final OpaqueThemeType dark = CwtchDark();
static final OpaqueThemeType light = CwtchLight();
static static Opaque current() { return dark; }
int scale = 2;
static final String gcdOS = "linux";
var p = [0, 1, 1, 1, 2];
var t = [0, 0, 1, 2, 2];
var paddingMinimalBase = [1, 4, 6];
int paddingMinimal() { return paddingMinimalBase[p[scale]]; }
var paddingSmallBase = [3, 10, 15];
int paddingSmall() { return paddingSmallBase[p[scale]]; }
var paddingStandardBase = [8, 20, 30];
int paddingStandard() { return paddingStandardBase[p[scale]]; }
var paddingLargeBase = [10, 30, 40];
int paddingLarge() { return paddingLargeBase[p[scale]]; }
var paddingClickTargetBase = gcdOS == "android" ? [10, 40, 100] : [3, 10, 15];
int paddingClickTarget() { return paddingClickTargetBase[p[scale]]; }
var textSmallPtBase = [8, 12, 16];
int textSmallPt() { return textSmallPtBase[t[scale]]; }
var textMediumPtBase = [10, 16, 24];
int textMediumPt() { return textMediumPtBase[t[scale]]; }
var textLargePtBase = [16, 24, 32];
int textLargePt() { return textLargePtBase[t[scale]]; }
var textSubHeaderPtBase = [12, 18, 26];
int textSubHeaderPt() { return textHeaderPtBase[t[scale]]; }
var textHeaderPtBase = [16, 24, 32];
int textHeaderPt() { return textHeaderPtBase[t[scale]]; }
var uiIconSizeSBase = [8, 16, 24];
int uiIconSizeS() { return uiIconSizeSBase[p[scale]]; }
var uiIconSizeMBase = [24, 32, 48];
int uiIconSizeM() { return uiIconSizeMBase[p[scale]]; }
var uiIconSizeLBase = [32, 48, 60];
int uiIconSizeL() { return uiIconSizeLBase[p[scale]]; }
var uiEmojiSizeBase = [24, 32, 48];
int uiEmojiSize() { return uiEmojiSizeBase[p[scale]]; }
var contactPortraitSizeBase = [60, 72, 84];
int contactPortraitSize() { return contactPortraitSizeBase[p[scale]]; }
int badgeTextSize() { return 12; }
int statusTextSize() { return 12; }
int chatSize() { return textMediumPt(); }
int tabSize() { return textMediumPt(); }
}

View File

@ -47,9 +47,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
ctrlrOnion.text = Provider.of<ProfileInfoState>(context).onion;
return Scaffold(
appBar: AppBar(
title: Text(Provider.of<ProfileInfoState>(context).onion.isEmpty
? AppLocalizations.of(context).addProfileTitle
: AppLocalizations.of(context).editProfileTitle),
title: Text(Provider.of<ProfileInfoState>(context).onion.isEmpty ? AppLocalizations.of(context).addProfileTitle : AppLocalizations.of(context).editProfileTitle),
),
body: _buildForm(),
);
@ -66,8 +64,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
// We used SizedBox for inter-widget height padding in columns, otherwise elements can render a little too close together.
Widget _buildForm() {
return Consumer<Settings>(builder: (context, theme, child) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) {
return Scrollbar(
isAlwaysShown: true,
child: SingleChildScrollView(
@ -81,308 +78,184 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
child: Container(
margin: EdgeInsets.all(30),
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [
Visibility(
visible: Provider.of<ProfileInfoState>(context).onion.isNotEmpty,
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
SizedBox(
width: 120,
height: 120,
child: ClipOval(
child: SizedBox(
width: 120,
height: 120,
child: Container(
color: Colors.white,
width: 120,
height: 120,
child: Image(
image: AssetImage("assets/" + Provider.of<ProfileInfoState>(context).imagePath),
width: 100,
height: 100,
))),
),
)
])),
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
CwtchLabel(label: AppLocalizations.of(context).displayNameLabel),
SizedBox(
height: 20,
),
CwtchTextField(
controller: ctrlrNick,
labelText: AppLocalizations.of(context).yourDisplayName,
validator: (value) {
if (value.isEmpty) {
return "Please enter a display name";
}
return null;
},
),
]),
Visibility(
visible: Provider.of<ProfileInfoState>(context).onion.isNotEmpty,
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
SizedBox(
height: 20,
),
CwtchLabel(label: AppLocalizations.of(context).addressLabel),
SizedBox(
height: 20,
),
CwtchButtonTextField(
controller: ctrlrOnion,
onPressed: _copyOnion,
icon: Icon(Icons.copy),
tooltip: AppLocalizations.of(context).copyBtn,
)
])),
// We only allow setting password types on profile creation
Visibility(
visible: Provider.of<ProfileInfoState>(context).onion.isEmpty,
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Radio(
value: false,
groupValue: usePassword,
onChanged: _handleSwitchPassword,
),
Text(
AppLocalizations.of(context).radioNoPassword,
style: TextStyle(color: theme.current().mainTextColor()),
),
Radio(
value: true,
groupValue: usePassword,
onChanged: _handleSwitchPassword,
),
Text(
AppLocalizations.of(context).radioUsePassword,
style: TextStyle(color: theme.current().mainTextColor()),
),
])),
SizedBox(
height: 20,
),
Visibility(
visible: usePassword,
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
Visibility(
visible:
Provider.of<ProfileInfoState>(context)
.onion
.isNotEmpty,
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: <Widget>[
SizedBox(
width: 120,
height: 120,
child: ClipOval(
child: SizedBox(
width: 120,
height: 120,
child: Container(
color: Colors.white,
width: 120,
height: 120,
child: Image(
image: AssetImage("assets/" +
Provider.of<ProfileInfoState>(
context)
.imagePath),
width: 100,
height: 100,
))),
),
)
])),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
CwtchLabel(
label: AppLocalizations.of(context)
.displayNameLabel),
visible: Provider.of<ProfileInfoState>(context, listen: false).onion.isNotEmpty,
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
CwtchLabel(label: AppLocalizations.of(context).currentPasswordLabel),
SizedBox(
height: 20,
),
CwtchTextField(
controller: ctrlrNick,
labelText:
AppLocalizations.of(context)
.yourDisplayName,
CwtchPasswordField(
controller: ctrlrOldPass,
validator: (value) {
if (value.isEmpty) {
return "Please enter a display name";
// Password field can be empty when just updating the profile, not on creation
if (Provider.of<ProfileInfoState>(context, listen: false).onion.isEmpty && value.isEmpty && usePassword) {
return AppLocalizations.of(context).passwordErrorEmpty;
}
return null;
},
),
]),
Visibility(
visible:
Provider.of<ProfileInfoState>(context)
.onion
.isNotEmpty,
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
SizedBox(
height: 20,
),
CwtchLabel(
label:
AppLocalizations.of(context)
.addressLabel),
SizedBox(
height: 20,
),
CwtchButtonTextField(
controller: ctrlrOnion,
onPressed: _copyOnion,
icon: Icon(Icons.copy),
tooltip:
AppLocalizations.of(context)
.copyBtn,
)
])),
// We only allow setting password types on profile creation
Visibility(
visible:
Provider.of<ProfileInfoState>(context)
.onion
.isEmpty,
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: <Widget>[
Radio(
value: false,
groupValue: usePassword,
onChanged: _handleSwitchPassword,
),
Text(
AppLocalizations.of(context)
.radioNoPassword,
style: TextStyle(
color: theme
.current()
.mainTextColor()),
),
Radio(
value: true,
groupValue: usePassword,
onChanged: _handleSwitchPassword,
),
Text(
AppLocalizations.of(context)
.radioUsePassword,
style: TextStyle(
color: theme
.current()
.mainTextColor()),
),
])),
SizedBox(
height: 20,
),
])),
CwtchLabel(label: AppLocalizations.of(context).password1Label),
SizedBox(
height: 20,
),
Visibility(
visible: usePassword,
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Visibility(
visible:
Provider.of<ProfileInfoState>(
context,
listen: false)
.onion
.isNotEmpty,
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
CwtchLabel(
label: AppLocalizations
.of(context)
.currentPasswordLabel),
SizedBox(
height: 20,
),
CwtchPasswordField(
controller: ctrlrOldPass,
validator: (value) {
// Password field can be empty when just updating the profile, not on creation
if (Provider.of<ProfileInfoState>(
context,
listen:
false)
.onion
.isEmpty &&
value.isEmpty &&
usePassword) {
return AppLocalizations
.of(context)
.passwordErrorEmpty;
}
return null;
},
),
SizedBox(
height: 20,
),
])),
CwtchLabel(
label:
AppLocalizations.of(context)
.password1Label),
SizedBox(
height: 20,
),
CwtchPasswordField(
controller: ctrlrPass,
validator: (value) {
// Password field can be empty when just updating the profile, not on creation
if (Provider.of<ProfileInfoState>(
context,
listen: false)
.onion
.isEmpty &&
value.isEmpty &&
usePassword) {
return AppLocalizations.of(
context)
.passwordErrorEmpty;
}
if (value !=
ctrlrPass2.value.text) {
return AppLocalizations.of(
context)
.passwordErrorMatch;
}
return null;
},
),
SizedBox(
height: 20,
),
CwtchLabel(
label:
AppLocalizations.of(context)
.password2Label),
SizedBox(
height: 20,
),
CwtchPasswordField(
controller: ctrlrPass2,
validator: (value) {
// Password field can be empty when just updating the profile, not on creation
if (Provider.of<ProfileInfoState>(
context,
listen: false)
.onion
.isEmpty &&
value.isEmpty &&
usePassword) {
return AppLocalizations.of(
context)
.passwordErrorEmpty;
}
if (value !=
ctrlrPass.value.text) {
return AppLocalizations.of(
context)
.passwordErrorMatch;
}
return null;
}),
]),
CwtchPasswordField(
controller: ctrlrPass,
validator: (value) {
// Password field can be empty when just updating the profile, not on creation
if (Provider.of<ProfileInfoState>(context, listen: false).onion.isEmpty && value.isEmpty && usePassword) {
return AppLocalizations.of(context).passwordErrorEmpty;
}
if (value != ctrlrPass2.value.text) {
return AppLocalizations.of(context).passwordErrorMatch;
}
return null;
},
),
SizedBox(
height: 20,
),
ElevatedButton(
onPressed: _createPressed,
style: ElevatedButton.styleFrom(
primary: theme
.current()
.defaultButtonColor()),
child: Text(
Provider.of<ProfileInfoState>(context)
.onion
.isEmpty
? AppLocalizations.of(context)
.addNewProfileBtn
: AppLocalizations.of(context)
.saveProfileBtn),
CwtchLabel(label: AppLocalizations.of(context).password2Label),
SizedBox(
height: 20,
),
Visibility(
visible: Provider.of<ProfileInfoState>(
context,
listen: false)
.onion
.isNotEmpty,
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.end,
children: [
SizedBox(
height: 20,
),
Tooltip(message: AppLocalizations.of(context).enterCurrentPasswordForDelete, child:
ElevatedButton.icon(
onPressed: checkCurrentPassword() ? null : () {
showAlertDialog(context);
},
style: ElevatedButton.styleFrom(
primary: theme
.current()
.defaultButtonColor()),
icon: Icon(Icons.delete_forever),
label: Text(
AppLocalizations.of(context)
.deleteBtn),
))
]))
]))))));
CwtchPasswordField(
controller: ctrlrPass2,
validator: (value) {
// Password field can be empty when just updating the profile, not on creation
if (Provider.of<ProfileInfoState>(context, listen: false).onion.isEmpty && value.isEmpty && usePassword) {
return AppLocalizations.of(context).passwordErrorEmpty;
}
if (value != ctrlrPass.value.text) {
return AppLocalizations.of(context).passwordErrorMatch;
}
return null;
}),
]),
),
SizedBox(
height: 20,
),
ElevatedButton(
onPressed: _createPressed,
style: ElevatedButton.styleFrom(primary: theme.current().defaultButtonColor()),
child: Text(Provider.of<ProfileInfoState>(context).onion.isEmpty ? AppLocalizations.of(context).addNewProfileBtn : AppLocalizations.of(context).saveProfileBtn),
),
Visibility(
visible: Provider.of<ProfileInfoState>(context, listen: false).onion.isNotEmpty,
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.end, children: [
SizedBox(
height: 20,
),
Tooltip(
message: AppLocalizations.of(context).enterCurrentPasswordForDelete,
child: ElevatedButton.icon(
onPressed: checkCurrentPassword()
? null
: () {
showAlertDialog(context);
},
style: ElevatedButton.styleFrom(primary: theme.current().defaultButtonColor()),
icon: Icon(Icons.delete_forever),
label: Text(AppLocalizations.of(context).deleteBtn),
))
]))
]))))));
});
});
}
void _copyOnion() {
Clipboard.setData(new ClipboardData(
text: Provider.of<ProfileInfoState>(context, listen: false).onion));
Clipboard.setData(new ClipboardData(text: Provider.of<ProfileInfoState>(context, listen: false).onion));
// TODO Toast
}
@ -393,14 +266,10 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
if (_formKey.currentState.validate()) {
if (Provider.of<ProfileInfoState>(context, listen: false).onion.isEmpty) {
if (usePassword == true) {
Provider.of<FlwtchState>(context, listen: false)
.cwtch
.CreateProfile(ctrlrNick.value.text, ctrlrPass.value.text);
Provider.of<FlwtchState>(context, listen: false).cwtch.CreateProfile(ctrlrNick.value.text, ctrlrPass.value.text);
Navigator.of(context).pop();
} else {
Provider.of<FlwtchState>(context, listen: false)
.cwtch
.CreateProfile(ctrlrNick.value.text, "be gay do crime");
Provider.of<FlwtchState>(context, listen: false).cwtch.CreateProfile(ctrlrNick.value.text, "be gay do crime");
Navigator.of(context).pop();
}
} else {
@ -413,11 +282,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
};
final json = jsonEncode(event);
Provider.of<FlwtchState>(context, listen: false)
.cwtch
.SendProfileEvent(
Provider.of<ProfileInfoState>(context, listen: false).onion,
json);
Provider.of<FlwtchState>(context, listen: false).cwtch.SendProfileEvent(Provider.of<ProfileInfoState>(context, listen: false).onion, json);
Navigator.of(context).pop();
} else {
// At this points passwords have been validated to be the same and not empty
@ -428,26 +293,15 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
};
final updateNameEventJson = jsonEncode(updateNameEvent);
Provider.of<FlwtchState>(context, listen: false)
.cwtch
.SendProfileEvent(
Provider.of<ProfileInfoState>(context, listen: false).onion,
updateNameEventJson);
Provider.of<FlwtchState>(context, listen: false).cwtch.SendProfileEvent(Provider.of<ProfileInfoState>(context, listen: false).onion, updateNameEventJson);
final updatePasswordEvent = {
"EventType": "ChangePassword",
"Data": {
"Password": ctrlrOldPass.text,
"NewPassword": ctrlrPass.text
}
"Data": {"Password": ctrlrOldPass.text, "NewPassword": ctrlrPass.text}
};
final updatePasswordEventJson = jsonEncode(updatePasswordEvent);
Provider.of<FlwtchState>(context, listen: false)
.cwtch
.SendProfileEvent(
Provider.of<ProfileInfoState>(context, listen: false).onion,
updatePasswordEventJson);
Provider.of<FlwtchState>(context, listen: false).cwtch.SendProfileEvent(Provider.of<ProfileInfoState>(context, listen: false).onion, updatePasswordEventJson);
Navigator.of(context).pop();
}
@ -459,7 +313,6 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
bool checkCurrentPassword() {
return ctrlrOldPass.value.text.isEmpty;
}
}
showAlertDialog(BuildContext context) {
@ -467,12 +320,9 @@ showAlertDialog(BuildContext context) {
Widget cancelButton = TextButton(
child: Text("Cancel"),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
foregroundColor: MaterialStateProperty.all(
Opaque.current().defaultButtonTextColor()),
overlayColor: MaterialStateProperty.all(
Opaque.current().defaultButtonActiveColor()),
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
foregroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonTextColor()),
overlayColor: MaterialStateProperty.all(Opaque.current().defaultButtonActiveColor()),
padding: MaterialStateProperty.all(EdgeInsets.all(20))),
onPressed: () {
Navigator.of(context).pop(); // dismiss dialog
@ -480,12 +330,9 @@ showAlertDialog(BuildContext context) {
);
Widget continueButton = TextButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
foregroundColor: MaterialStateProperty.all(
Opaque.current().defaultButtonTextColor()),
overlayColor: MaterialStateProperty.all(
Opaque.current().defaultButtonActiveColor()),
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
foregroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonTextColor()),
overlayColor: MaterialStateProperty.all(Opaque.current().defaultButtonActiveColor()),
padding: MaterialStateProperty.all(EdgeInsets.all(20))),
child: Text(AppLocalizations.of(context).deleteProfileConfirmBtn),
onPressed: () {
@ -511,4 +358,3 @@ showAlertDialog(BuildContext context) {
},
);
}

View File

@ -18,11 +18,7 @@ class _ContactsViewState extends State<ContactsView> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("%1's contacts".replaceAll(
"%1",
Provider.of<ProfileInfoState>(context).nickname ??
Provider.of<ProfileInfoState>(context).onion ??
'')), //todo
title: Text("%1's contacts".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname ?? Provider.of<ProfileInfoState>(context).onion ?? '')), //todo
actions: [
IconButton(
icon: Icon(Icons.copy),
@ -41,9 +37,12 @@ class _ContactsViewState extends State<ContactsView> {
Widget _buildContactList() {
final tiles = Provider.of<ContactListState>(context).contacts.map((ContactInfoState contact) {
return ChangeNotifierProvider<ContactInfoState>.value(value: contact, child: ContactRow());
return ChangeNotifierProvider<ContactInfoState>.value(value: contact, child: ContactRow());
});
final divided = ListTile.divideTiles(context: context, tiles: tiles, ).toList();
final divided = ListTile.divideTiles(
context: context,
tiles: tiles,
).toList();
return ListView(children: divided);
}
@ -59,9 +58,7 @@ class _ContactsViewState extends State<ContactsView> {
}
void _copyOnion() {
final snackBar = SnackBar(
content: Text(
AppLocalizations.of(context).copiedClipboardNotification)); //todo
final snackBar = SnackBar(content: Text(AppLocalizations.of(context).copiedClipboardNotification)); //todo
// Find the Scaffold in the widget tree and use it to show a SnackBar.
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}

View File

@ -26,10 +26,7 @@ class _DoubleColumnViewState extends State<DoubleColumnView> {
child: flwtch.selectedConversation == ""
? Center(child: Text("pick a contact"))
: //dev
Container(
child: MessageView(
profile: flwtch.selectedProfile,
conversationHandle: flwtch.selectedConversation)),
Container(child: MessageView(profile: flwtch.selectedProfile, conversationHandle: flwtch.selectedConversation)),
),
],
);

View File

@ -25,9 +25,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations
.of(context)
.cwtchSettingsTitle),
title: Text(AppLocalizations.of(context).cwtchSettingsTitle),
),
body: _buildSettingsList(),
);
@ -35,122 +33,97 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
Widget _buildSettingsList() {
return Consumer<Settings>(builder: (context, settings, child) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return Scrollbar(
isAlwaysShown: true,
child: SingleChildScrollView(
clipBehavior: Clip.antiAlias,
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(children: [
ListTile(
title: Text(AppLocalizations
.of(context)
.settingLanguage,
style: TextStyle(color: settings.current().mainTextColor())),
leading:
Icon(Icons.language, color: settings.current().mainTextColor()),
trailing: DropdownButton(
value: Provider
.of<Settings>(context)
.locale
.languageCode,
onChanged: (String newValue) {
setState(() {
settings.switchLocale(Locale(newValue, ''));
saveSettings(context);
});
},
items: AppLocalizations.supportedLocales
.map<DropdownMenuItem<String>>((Locale value) {
return DropdownMenuItem<String>(
value: value.languageCode,
child: Text(getLanguageFull(context, value.languageCode)),
);
}).toList())),
SwitchListTile(
title: Text(AppLocalizations
.of(context)
.settingTheme,
style: TextStyle(color: settings.current().mainTextColor())),
value: settings.current() == Opaque.light,
onChanged: (bool value) {
if (value) {
settings.setLight();
} else {
settings.setDark();
}
// Save Settings...
saveSettings(context);
},
secondary: Icon(Icons.lightbulb_outline,
color: settings.current().mainTextColor()),
),
SwitchListTile(
title: Text(AppLocalizations
.of(context)
.experimentsEnabled,
style: TextStyle(color: settings.current().mainTextColor())),
value: settings.experimentsEnabled,
onChanged: (bool value) {
if (value) {
settings.enableExperiments();
} else {
settings.disableExperiments();
}
// Save Settings...
saveSettings(context);
},
secondary: Icon(Icons.science,
color: settings.current().mainTextColor()),
),
Visibility(visible: settings.experimentsEnabled, child: Column(children: [
SwitchListTile(
title: Text(AppLocalizations
.of(context)
.enableGroups,
style: TextStyle(color: settings.current().mainTextColor())),
value: settings.experiments.containsKey("tapir-groups-experiment") && settings.experiments["tapir-groups-experiment"],
onChanged: (bool value) {
if (value) {
settings.enableExperiment("tapir-groups-experiment");
} else {
settings.disableExperiment("tapir-groups-experiment");
}
// Save Settings...
saveSettings(context);
return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) {
return Scrollbar(
isAlwaysShown: true,
child: SingleChildScrollView(
clipBehavior: Clip.antiAlias,
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(children: [
ListTile(
title: Text(AppLocalizations.of(context).settingLanguage, style: TextStyle(color: settings.current().mainTextColor())),
leading: Icon(Icons.language, color: settings.current().mainTextColor()),
trailing: DropdownButton(
value: Provider.of<Settings>(context).locale.languageCode,
onChanged: (String newValue) {
setState(() {
settings.switchLocale(Locale(newValue, ''));
saveSettings(context);
});
},
secondary: Icon(Icons.group_sharp,
color: settings.current().mainTextColor()),
),
],)),
AboutListTile(
icon: Icon(Icons.info, color: settings.current().mainTextColor()),
applicationIcon: Padding(
padding: EdgeInsets.all(20),
child: Image(
image: AssetImage("assets/knott.png"),
width: 128,
height: 128,
)),
applicationName: "Cwtch (Flutter UI)",
applicationVersion: AppLocalizations
.of(context)
.version
.replaceAll(
"%1",
constructVersionString(
Provider
.of<Settings>(context)
.packageInfo)),
applicationLegalese: '\u{a9} 2021 Open Privacy Research Society',
),
]))));
});
items: AppLocalizations.supportedLocales.map<DropdownMenuItem<String>>((Locale value) {
return DropdownMenuItem<String>(
value: value.languageCode,
child: Text(getLanguageFull(context, value.languageCode)),
);
}).toList())),
SwitchListTile(
title: Text(AppLocalizations.of(context).settingTheme, style: TextStyle(color: settings.current().mainTextColor())),
value: settings.current() == Opaque.light,
onChanged: (bool value) {
if (value) {
settings.setLight();
} else {
settings.setDark();
}
// Save Settings...
saveSettings(context);
},
secondary: Icon(Icons.lightbulb_outline, color: settings.current().mainTextColor()),
),
SwitchListTile(
title: Text(AppLocalizations.of(context).experimentsEnabled, style: TextStyle(color: settings.current().mainTextColor())),
value: settings.experimentsEnabled,
onChanged: (bool value) {
if (value) {
settings.enableExperiments();
} else {
settings.disableExperiments();
}
// Save Settings...
saveSettings(context);
},
secondary: Icon(Icons.science, color: settings.current().mainTextColor()),
),
Visibility(
visible: settings.experimentsEnabled,
child: Column(
children: [
SwitchListTile(
title: Text(AppLocalizations.of(context).enableGroups, style: TextStyle(color: settings.current().mainTextColor())),
value: settings.experiments.containsKey("tapir-groups-experiment") && settings.experiments["tapir-groups-experiment"],
onChanged: (bool value) {
if (value) {
settings.enableExperiment("tapir-groups-experiment");
} else {
settings.disableExperiment("tapir-groups-experiment");
}
// Save Settings...
saveSettings(context);
},
secondary: Icon(Icons.group_sharp, color: settings.current().mainTextColor()),
),
],
)),
AboutListTile(
icon: Icon(Icons.info, color: settings.current().mainTextColor()),
applicationIcon: Padding(
padding: EdgeInsets.all(20),
child: Image(
image: AssetImage("assets/knott.png"),
width: 128,
height: 128,
)),
applicationName: "Cwtch (Flutter UI)",
applicationVersion: AppLocalizations.of(context).version.replaceAll("%1", constructVersionString(Provider.of<Settings>(context).packageInfo)),
applicationLegalese: '\u{a9} 2021 Open Privacy Research Society',
),
]))));
});
});
}
}
@ -195,7 +168,5 @@ saveSettings(context) {
"Data": {"Data": jsonEncode(settings.asJson())},
};
final updateSettingsEventJson = jsonEncode(updateSettingsEvent);
Provider.of<FlwtchState>(context, listen: false)
.cwtch
.SendAppEvent(updateSettingsEventJson);
Provider.of<FlwtchState>(context, listen: false).cwtch.SendAppEvent(updateSettingsEventJson);
}

View File

@ -5,8 +5,7 @@ import '../opaque.dart';
import '../widgets/messagelist.dart';
class MessageView extends StatefulWidget {
const MessageView({Key key, this.profile, this.conversationHandle})
: super(key: key);
const MessageView({Key key, this.profile, this.conversationHandle}) : super(key: key);
final ProfileInfoState profile;
final String conversationHandle;
@ -35,9 +34,7 @@ class _MessageViewState extends State<MessageView> {
IconButton(icon: Icon(Icons.settings), onPressed: _pushConvoSettings),
],
),
body: MessageList(
profile: widget.profile,
conversationHandle: widget.conversationHandle),
body: MessageList(profile: widget.profile, conversationHandle: widget.conversationHandle),
bottomSheet: _buildComposeBox(),
);
}
@ -62,25 +59,15 @@ class _MessageViewState extends State<MessageView> {
height: 80,
child: Column(children: <Widget>[
ElevatedButton(
child:
Icon(Icons.send, color: Opaque.current().mainTextColor()),
child: Icon(Icons.send, color: Opaque.current().mainTextColor()),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Opaque.current().defaultButtonColor()),
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
),
onPressed: _sendMessage,
),
Row(children: <Widget>[
SizedBox(
width: 45,
child: ElevatedButton(
child: Icon(Icons.emoji_emotions_outlined,
color: Opaque.current().mainTextColor()))),
SizedBox(
width: 45,
child: ElevatedButton(
child: Icon(Icons.attach_file,
color: Opaque.current().mainTextColor()))),
SizedBox(width: 45, child: ElevatedButton(child: Icon(Icons.emoji_emotions_outlined, color: Opaque.current().mainTextColor()))),
SizedBox(width: 45, child: ElevatedButton(child: Icon(Icons.attach_file, color: Opaque.current().mainTextColor()))),
])
]),
),

View File

@ -29,15 +29,12 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
appBar: AppBar(
title: Text(AppLocalizations.of(context).profileName),
actions: [
IconButton(
icon: Icon(Icons.bug_report_outlined),
onPressed: _testChangingContactInfo),
IconButton(icon: Icon(Icons.bug_report_outlined), onPressed: _testChangingContactInfo),
IconButton(
icon: Icon(Icons.lock_open),
onPressed: _modalUnlockProfiles,
),
IconButton(
icon: Icon(Icons.settings), onPressed: _pushGlobalSettings),
IconButton(icon: Icon(Icons.settings), onPressed: _pushGlobalSettings),
],
),
floatingActionButton: FloatingActionButton(
@ -50,7 +47,7 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
}
void _testChangingContactInfo() {
Provider.of<ProfileListState>(context, listen:false).profiles.first.nickname = "yay!";
Provider.of<ProfileListState>(context, listen: false).profiles.first.nickname = "yay!";
}
void _pushGlobalSettings() {
@ -103,9 +100,7 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
ElevatedButton(
child: Text(AppLocalizations.of(context).unlock),
onPressed: () {
Provider.of<FlwtchState>(context, listen: false)
.cwtch
.LoadProfiles(ctrlrPassword.value.text);
Provider.of<FlwtchState>(context, listen: false).cwtch.LoadProfiles(ctrlrPassword.value.text);
Navigator.pop(context);
},
),

View File

@ -22,19 +22,14 @@ class _TripleColumnViewState extends State<TripleColumnView> {
),
Flexible(
flex: flwtch.columns[1],
child: flwtch.selectedProfile == null
? Center(child: Text("pick a profile"))
: ContactsView(), //dev
child: flwtch.selectedProfile == null ? Center(child: Text("pick a profile")) : ContactsView(), //dev
),
Flexible(
flex: flwtch.columns[2],
child: flwtch.selectedConversation == ""
? Center(child: Text("pick a contact"))
: //dev
Container(
child: MessageView(
profile: flwtch.selectedProfile,
conversationHandle: flwtch.selectedConversation)),
Container(child: MessageView(profile: flwtch.selectedProfile, conversationHandle: flwtch.selectedConversation)),
),
]);
}

View File

@ -2,12 +2,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_app/settings.dart';
import 'package:provider/provider.dart';
// Provides a styled Text Field for use in Form Widgets.
// Callers must provide a text controller, label helper text and a validator.
class CwtchButtonTextField extends StatefulWidget {
CwtchButtonTextField(
{this.controller, this.onPressed, this.icon, this.tooltip});
CwtchButtonTextField({this.controller, this.onPressed, this.icon, this.tooltip});
final TextEditingController controller;
final Function onPressed;
final Icon icon;
@ -37,32 +35,17 @@ class _CwtchButtonTextFieldState extends State<CwtchButtonTextField> {
),
floatingLabelBehavior: FloatingLabelBehavior.never,
filled: true,
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)),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
borderSide: BorderSide(
color: theme.current().textfieldErrorColor(), 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)),
errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)),
errorStyle: TextStyle(
color: theme.current().textfieldErrorColor(),
fontWeight: FontWeight.bold,
),
fillColor: theme.current().textfieldBackgroundColor(),
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))),
style: TextStyle(
color: theme.current().mainTextColor(),
backgroundColor: theme.current().textfieldBackgroundColor()),
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0))),
style: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()),
);
});
}

View File

@ -20,16 +20,23 @@ class _ContactRowState extends State<ContactRow> {
width: 60,
height: 60,
child: ClipOval(
child: SizedBox(width:60, height:60, child:Container(color:Colors.white, width: 60, height: 60, child: Image(image: AssetImage("assets/"+contact.imagePath), width:50,height:50,))),
child: SizedBox(
width: 60,
height: 60,
child: Container(
color: Colors.white,
width: 60,
height: 60,
child: Image(
image: AssetImage("assets/" + contact.imagePath),
width: 50,
height: 50,
))),
),
),
trailing: contact.isInvitation != null && contact.isInvitation
? Column(children: <Widget>[
Icon(Icons.favorite, color: Opaque.current().mainTextColor()),
Icon(Icons.delete, color: Opaque.current().mainTextColor())
])
: Text(
"99+"), //(nb: Icons.create is a pencil and we use it for "edit", not create)
? Column(children: <Widget>[Icon(Icons.favorite, color: Opaque.current().mainTextColor()), Icon(Icons.delete, color: Opaque.current().mainTextColor())])
: Text("99+"), //(nb: Icons.create is a pencil and we use it for "edit", not create)
title: Text(
contact.nickname,
style: Provider.of<FlwtchState>(context).biggerFont,
@ -53,8 +60,7 @@ class _ContactRowState extends State<ContactRow> {
builder: (BuildContext builderContext) {
return MultiProvider(
providers: [
ChangeNotifierProvider<ProfileInfoState>(
create: (_) => Provider.of<ProfileInfoState>(context)),
ChangeNotifierProvider<ProfileInfoState>(create: (_) => Provider.of<ProfileInfoState>(context)),
],
child: MessageView(conversationHandle: handle),
);

View File

@ -24,15 +24,8 @@ class _MessageBubbleState extends State<MessageBubble> {
super.didChangeDependencies();
print("requesting message " + widget.messageIndex.toString());
Provider.of<FlwtchState>(context)
.cwtch
.GetMessage(
widget.profile.onion, widget.contactOnion, widget.messageIndex)
.then((jsonMessage) {
print("got message: " +
widget.messageIndex.toString() +
": " +
jsonMessage);
Provider.of<FlwtchState>(context).cwtch.GetMessage(widget.profile.onion, widget.contactOnion, widget.messageIndex).then((jsonMessage) {
print("got message: " + widget.messageIndex.toString() + ": " + jsonMessage);
dynamic messageWrapper = jsonDecode(jsonMessage);
dynamic message = jsonDecode(messageWrapper['Message']);
setState(() {
@ -50,9 +43,7 @@ class _MessageBubbleState extends State<MessageBubble> {
child: Container(
decoration: BoxDecoration(
color: Opaque.current().messageFromOtherBackgroundColor(),
border: Border.all(
color: Opaque.current().messageFromOtherBackgroundColor(),
width: 1),
border: Border.all(color: Opaque.current().messageFromOtherBackgroundColor(), width: 1),
borderRadius: BorderRadius.all(
Radius.circular(15.0),
),
@ -65,11 +56,7 @@ class _MessageBubbleState extends State<MessageBubble> {
subtitle: Row(
children: [
Text("" + widget.messageIndex.toString()),
ack
? Icon(Icons.check_circle_outline,
color: Opaque.current().mainTextColor())
: Icon(Icons.hourglass_bottom_outlined,
color: Opaque.current().mainTextColor())
ack ? Icon(Icons.check_circle_outline, color: Opaque.current().mainTextColor()) : Icon(Icons.hourglass_bottom_outlined, color: Opaque.current().mainTextColor())
],
),
),

View File

@ -10,8 +10,7 @@ class MessageList extends StatefulWidget {
final ProfileInfoState profile;
final String conversationHandle;
const MessageList({Key key, this.profile, this.conversationHandle})
: super(key: key);
const MessageList({Key key, this.profile, this.conversationHandle}) : super(key: key);
@override
_MessageListState createState() => _MessageListState();
@ -50,14 +49,8 @@ class _MessageListState extends State<MessageList> {
return;
}
Provider.of<FlwtchState>(context, listen: false)
.cwtch
.NumMessages(
Provider.of<ProfileInfoState>(context, listen: false).onion,
widget.conversationHandle)
.then((n) {
if (n != conversationNumMessages)
setState(() => conversationNumMessages = n);
Provider.of<FlwtchState>(context, listen: false).cwtch.NumMessages(Provider.of<ProfileInfoState>(context, listen: false).onion, widget.conversationHandle).then((n) {
if (n != conversationNumMessages) setState(() => conversationNumMessages = n);
});
}
}

View File

@ -28,28 +28,14 @@ class _CwtchTextFieldState extends State<CwtchPasswordField> {
color: theme.current().textfieldErrorColor(),
fontWeight: FontWeight.bold,
),
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)),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
borderSide: BorderSide(
color: theme.current().textfieldErrorColor(), 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)),
errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)),
filled: true,
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)),
),
style: TextStyle(
color: theme.current().mainTextColor(),
backgroundColor: theme.current().textfieldBackgroundColor()),
style: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()),
);
});
}

View File

@ -37,13 +37,9 @@ class _ProfileRowState extends State<ProfileRow> {
),
),
trailing: IconButton(
icon: Icon(Icons.create,
color: Provider.of<Settings>(context).current().mainTextColor()),
icon: Icon(Icons.create, color: Provider.of<Settings>(context).current().mainTextColor()),
onPressed: () {
_pushAddEditProfile(
onion: profile.onion,
displayName: profile.nickname,
profileImage: profile.imagePath);
_pushAddEditProfile(onion: profile.onion, displayName: profile.nickname, profileImage: profile.imagePath);
},
), //(nb: Icons.create is a pencil and we use it for "edit", not create)
title: Text(
@ -82,8 +78,7 @@ class _ProfileRowState extends State<ProfileRow> {
ChangeNotifierProvider<ProfileInfoState>.value(value: profile),
ChangeNotifierProvider<ContactListState>.value(value: profile.contactList),
],
builder: (context, widget) =>
includeDoublePane ? DoubleColumnView() : ContactsView(),
builder: (context, widget) => includeDoublePane ? DoubleColumnView() : ContactsView(),
);
},
),
@ -96,8 +91,7 @@ class _ProfileRowState extends State<ProfileRow> {
return MultiProvider(
providers: [
ChangeNotifierProvider<ProfileInfoState>(
create: (_) => ProfileInfoState(
onion: onion, nickname: displayName, imagePath: profileImage),
create: (_) => ProfileInfoState(onion: onion, nickname: displayName, imagePath: profileImage),
),
],
builder: (context, widget) => AddEditProfileView(),

View File

@ -23,37 +23,20 @@ class _CwtchTextFieldState extends State<CwtchTextField> {
validator: widget.validator,
decoration: InputDecoration(
labelText: widget.labelText,
labelStyle: TextStyle(
color: theme.current().mainTextColor(),
backgroundColor: theme.current().textfieldBackgroundColor()),
labelStyle: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()),
floatingLabelBehavior: FloatingLabelBehavior.never,
filled: true,
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)),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
borderSide: BorderSide(
color: theme.current().textfieldErrorColor(), 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)),
errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)),
errorStyle: TextStyle(
color: theme.current().textfieldErrorColor(),
fontWeight: FontWeight.bold,
),
fillColor: theme.current().textfieldBackgroundColor(),
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))),
style: TextStyle(
color: theme.current().mainTextColor(),
backgroundColor: theme.current().textfieldBackgroundColor()),
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0))),
style: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()),
);
});
}

View File

@ -18,9 +18,7 @@ class _TorStatusState extends State<TorStatusLabel> {
stream: Provider.of<FlwtchState>(context).appStatus.torStatus(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
return Text(
snapshot.hasData
? snapshot.data
: AppLocalizations.of(context).loadingTor,
snapshot.hasData ? snapshot.data : AppLocalizations.of(context).loadingTor,
style: Theme.of(context).textTheme.headline4,
);
},