Upgrade to null safe sdk
This commit is contained in:
parent
0baa2b707f
commit
2394a1daaa
|
@ -26,19 +26,19 @@ abstract class Cwtch {
|
|||
void DebugResetContact(String profileOnion, String contactHandle);
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> ACNEvents();
|
||||
Future<dynamic> ACNEvents();
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> ContactEvents();
|
||||
Future<dynamic> ContactEvents();
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> GetProfiles();
|
||||
Future<dynamic> GetProfiles();
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<int> NumMessages(String profile, String handle);
|
||||
Future<dynamic> NumMessages(String profile, String handle);
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> GetMessage(String profile, String handle, int index);
|
||||
Future<dynamic> GetMessage(String profile, String handle, int index);
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> GetMessages(String profile, String handle, int start, int end);
|
||||
Future<dynamic> GetMessages(String profile, String handle, int start, int end);
|
||||
// ignore: non_constant_identifier_names
|
||||
void SendMessage(String profile, String handle, String message);
|
||||
// ignore: non_constant_identifier_names
|
||||
|
|
|
@ -10,10 +10,10 @@ import '../settings.dart';
|
|||
// Class that handles libcwtch-go events (received either via ffi with an isolate or gomobile over a method channel from kotlin)
|
||||
// Takes Notifiers and triggers them on appropriate events
|
||||
class CwtchNotifier {
|
||||
ProfileListState profileCN;
|
||||
Settings settings;
|
||||
ErrorHandler error;
|
||||
TorStatus torStatus;
|
||||
late ProfileListState profileCN;
|
||||
late Settings settings;
|
||||
late ErrorHandler error;
|
||||
late TorStatus torStatus;
|
||||
|
||||
CwtchNotifier(ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN, TorStatus torStatusCN) {
|
||||
profileCN = pcn;
|
||||
|
@ -74,7 +74,7 @@ class CwtchNotifier {
|
|||
var key = profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]).getMessageKey(idx);
|
||||
if (key == null) break;
|
||||
try {
|
||||
var message = Provider.of<MessageState>(key.currentContext, listen: false);
|
||||
var message = Provider.of<MessageState>(key.currentContext!, listen: false);
|
||||
if (message == null) break;
|
||||
message.ackd = true;
|
||||
} catch (e) {
|
||||
|
@ -94,7 +94,7 @@ class CwtchNotifier {
|
|||
var key = profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["GroupID"]).getMessageKey(idx);
|
||||
if (key == null) break;
|
||||
try {
|
||||
var message = Provider.of<MessageState>(key.currentContext, listen: false);
|
||||
var message = Provider.of<MessageState>(key.currentContext!, listen: false);
|
||||
if (message == null) break;
|
||||
message.ackd = true;
|
||||
} catch (e) {
|
||||
|
@ -109,7 +109,7 @@ class CwtchNotifier {
|
|||
var key = profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["GroupID"]).getMessageKey(idx);
|
||||
if (key == null) break;
|
||||
try {
|
||||
var message = Provider.of<MessageState>(key.currentContext, listen: false);
|
||||
var message = Provider.of<MessageState>(key.currentContext!, listen: false);
|
||||
if (message == null) break;
|
||||
message.error = true;
|
||||
} catch (e) {
|
||||
|
|
|
@ -56,9 +56,9 @@ typedef acn_events_function = Pointer<Utf8> Function();
|
|||
typedef ACNEventsFn = Pointer<Utf8> Function();
|
||||
|
||||
class CwtchFfi implements Cwtch {
|
||||
DynamicLibrary library;
|
||||
CwtchNotifier cwtchNotifier;
|
||||
Isolate cwtchIsolate;
|
||||
late DynamicLibrary library;
|
||||
late CwtchNotifier cwtchNotifier;
|
||||
late Isolate cwtchIsolate;
|
||||
|
||||
CwtchFfi(CwtchNotifier _cwtchNotifier) {
|
||||
if (Platform.isWindows) {
|
||||
|
@ -79,9 +79,9 @@ class CwtchFfi implements Cwtch {
|
|||
String bundledTor = "";
|
||||
Map<String, String> envVars = Platform.environment;
|
||||
if (Platform.isLinux) {
|
||||
home = envVars['HOME'];
|
||||
home = (envVars['HOME'])!;
|
||||
} else if (Platform.isWindows) {
|
||||
home = envVars['UserProfile'];
|
||||
home = (envVars['UserProfile'])!;
|
||||
bundledTor = "Tor\\Tor\\tor.exe";
|
||||
}
|
||||
var cwtchDir = path.join(home, ".cwtch/dev/");
|
||||
|
@ -121,7 +121,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* {
|
||||
DynamicLibrary library;
|
||||
late DynamicLibrary library;
|
||||
if (Platform.isWindows) {
|
||||
library = DynamicLibrary.open("libCwtch.dll");
|
||||
} else if (Platform.isLinux) {
|
||||
|
|
|
@ -26,9 +26,9 @@ class CwtchGomobile implements Cwtch {
|
|||
|
||||
final appbusEventChannelName = 'test.flutter.dev/eventBus';
|
||||
|
||||
Future<String> androidLibraryDir;
|
||||
Future<Directory> androidHomeDirectory;
|
||||
CwtchNotifier cwtchNotifier;
|
||||
late Future<dynamic> androidLibraryDir;
|
||||
late Future<dynamic> androidHomeDirectory;
|
||||
late CwtchNotifier cwtchNotifier;
|
||||
|
||||
CwtchGomobile(CwtchNotifier _cwtchNotifier) {
|
||||
print("gomobile.dart: CwtchGomobile()");
|
||||
|
@ -73,34 +73,34 @@ class CwtchGomobile implements Cwtch {
|
|||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> ACNEvents() {
|
||||
Future<dynamic> ACNEvents() {
|
||||
return cwtchPlatform.invokeMethod("ACNEvents");
|
||||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> ContactEvents() {
|
||||
Future<dynamic> ContactEvents() {
|
||||
return cwtchPlatform.invokeMethod("ContactEvents");
|
||||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> GetProfiles() {
|
||||
Future<dynamic> GetProfiles() {
|
||||
print("gomobile.dart: GetProfiles()");
|
||||
return cwtchPlatform.invokeMethod("GetProfiles");
|
||||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<int> NumMessages(String profile, String handle) {
|
||||
Future<dynamic> NumMessages(String profile, String handle) {
|
||||
return cwtchPlatform.invokeMethod("NumMessages", {"profile": profile, "contact": handle});
|
||||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> GetMessage(String profile, String handle, int index) {
|
||||
Future<dynamic> GetMessage(String profile, String handle, int index) {
|
||||
print("gomobile.dart GetMessage " + index.toString());
|
||||
return cwtchPlatform.invokeMethod("GetMessage", {"profile": profile, "contact": handle, "index": index});
|
||||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> GetMessages(String profile, String handle, int start, int end) {
|
||||
Future<dynamic> GetMessages(String profile, String handle, int start, int end) {
|
||||
return cwtchPlatform.invokeMethod("GetMessage", {"profile": profile, "contact": handle, "start": start, "end": end});
|
||||
}
|
||||
|
||||
|
|
|
@ -35,14 +35,14 @@ class Flwtch extends StatefulWidget {
|
|||
|
||||
class FlwtchState extends State<Flwtch> {
|
||||
final TextStyle biggerFont = const TextStyle(fontSize: 18);
|
||||
Cwtch cwtch;
|
||||
late Cwtch cwtch;
|
||||
bool cwtchInit = false;
|
||||
ProfileInfoState selectedProfile;
|
||||
late ProfileInfoState selectedProfile;
|
||||
String selectedConversation = "";
|
||||
var columns = [1]; // default or 'single column' mode
|
||||
//var columns = [1, 1, 2];
|
||||
AppModel appStatus;
|
||||
ProfileListState profs;
|
||||
late AppModel appStatus;
|
||||
late ProfileListState profs;
|
||||
|
||||
@override
|
||||
initState() {
|
||||
|
|
|
@ -63,6 +63,6 @@ class DiskAssetBundle extends CachingAssetBundle {
|
|||
|
||||
@override
|
||||
Future<ByteData> load(String key) async {
|
||||
return _cache[key];
|
||||
return _cache[key]!;
|
||||
}
|
||||
}
|
||||
|
|
125
lib/model.dart
125
lib/model.dart
|
@ -14,33 +14,11 @@ import 'main.dart';
|
|||
/// UI State ///
|
||||
////////////////////
|
||||
|
||||
//todo: delete
|
||||
class ProfileModel {
|
||||
String onion;
|
||||
String nickname;
|
||||
String creationDate;
|
||||
String imagePath;
|
||||
HashMap<String, ContactModel> contacts;
|
||||
}
|
||||
|
||||
//todo: delete
|
||||
class ContactModel {
|
||||
String onion;
|
||||
String nickname;
|
||||
bool isGroup;
|
||||
bool isInvitation;
|
||||
bool isBlocked;
|
||||
String status;
|
||||
String imagePath;
|
||||
|
||||
ContactModel({this.onion, this.nickname, this.status, this.isInvitation, this.isBlocked, this.imagePath});
|
||||
}
|
||||
|
||||
class ChatMessage {
|
||||
final int o;
|
||||
final String d;
|
||||
|
||||
ChatMessage({this.o, this.d});
|
||||
ChatMessage({required this.o, required this.d});
|
||||
|
||||
ChatMessage.fromJson(Map<String, dynamic> json)
|
||||
: o = json['o'],
|
||||
|
@ -74,16 +52,16 @@ class ProfileListState extends ChangeNotifier {
|
|||
|
||||
ProfileInfoState getProfile(String onion) {
|
||||
int idx = _profiles.indexWhere((element) => element.onion == onion);
|
||||
return idx >= 0 ? _profiles[idx] : null;
|
||||
return idx >= 0 ? _profiles[idx] : ProfileInfoState(onion: onion);
|
||||
}
|
||||
}
|
||||
|
||||
class ContactListState extends ChangeNotifier {
|
||||
List<ContactInfoState> _contacts = [];
|
||||
String _filter;
|
||||
String _filter = "";
|
||||
int get num => _contacts.length;
|
||||
int get numFiltered => isFiltered ? filteredList().length : num;
|
||||
bool get isFiltered => _filter != null && _filter != "";
|
||||
bool get isFiltered => _filter != "";
|
||||
String get filter => _filter;
|
||||
set filter(String newVal) {
|
||||
_filter = newVal;
|
||||
|
@ -142,7 +120,7 @@ class ContactListState extends ChangeNotifier {
|
|||
|
||||
ContactInfoState getContact(String onion) {
|
||||
int idx = _contacts.indexWhere((element) => element.onion == onion);
|
||||
return idx >= 0 ? _contacts[idx] : null;
|
||||
return idx >= 0 ? _contacts[idx] : ContactInfoState("not found", "not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,7 +134,7 @@ class ProfileInfoState extends ChangeNotifier {
|
|||
bool _online = false;
|
||||
|
||||
ProfileInfoState({
|
||||
this.onion,
|
||||
required this.onion,
|
||||
nickname = "",
|
||||
imagePath = "",
|
||||
unreadMessages = 0,
|
||||
|
@ -253,21 +231,21 @@ class ProfileInfoState extends ChangeNotifier {
|
|||
class ContactInfoState extends ChangeNotifier {
|
||||
final String profileOnion;
|
||||
final String onion;
|
||||
String _nickname;
|
||||
late String _nickname;
|
||||
|
||||
bool _isInvitation;
|
||||
bool _isBlocked;
|
||||
String _status;
|
||||
String _imagePath;
|
||||
String _savePeerHistory;
|
||||
int _unreadMessages = 0;
|
||||
int _totalMessages = 0;
|
||||
DateTime _lastMessageTime;
|
||||
Map<String, GlobalKey> keys;
|
||||
late bool _isInvitation;
|
||||
late bool _isBlocked;
|
||||
late String _status;
|
||||
late String _imagePath;
|
||||
late String _savePeerHistory;
|
||||
late int _unreadMessages = 0;
|
||||
late int _totalMessages = 0;
|
||||
late DateTime _lastMessageTime;
|
||||
late Map<String, GlobalKey<MessageBubbleState>> keys;
|
||||
|
||||
// todo: a nicer way to model contacts, groups and other "entities"
|
||||
bool _isGroup;
|
||||
String _server;
|
||||
late bool _isGroup;
|
||||
late String _server;
|
||||
|
||||
ContactInfoState(
|
||||
this.profileOnion,
|
||||
|
@ -293,14 +271,14 @@ class ContactInfoState extends ChangeNotifier {
|
|||
this._totalMessages = numMessages;
|
||||
this._unreadMessages = numUnread;
|
||||
this._savePeerHistory = savePeerHistory;
|
||||
this._lastMessageTime = lastMessageTime;
|
||||
this._lastMessageTime = lastMessageTime == null ? DateTime.fromMillisecondsSinceEpoch(0) : lastMessageTime;
|
||||
this._server = server;
|
||||
keys = Map<String, GlobalKey>();
|
||||
keys = Map<String, GlobalKey<MessageBubbleState>>();
|
||||
}
|
||||
|
||||
get nickname => this._nickname;
|
||||
String get nickname => this._nickname;
|
||||
|
||||
get savePeerHistory => this._savePeerHistory;
|
||||
String get savePeerHistory => this._savePeerHistory;
|
||||
set savePeerHistory(String newVal) {
|
||||
this._savePeerHistory = newVal;
|
||||
notifyListeners();
|
||||
|
@ -311,49 +289,49 @@ class ContactInfoState extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
get isGroup => this._isGroup;
|
||||
bool get isGroup => this._isGroup;
|
||||
set isGroup(bool newVal) {
|
||||
this._isGroup = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
get isBlocked => this._isBlocked;
|
||||
bool get isBlocked => this._isBlocked;
|
||||
set isBlocked(bool newVal) {
|
||||
this._isBlocked = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
get isInvitation => this._isInvitation;
|
||||
bool get isInvitation => this._isInvitation;
|
||||
set isInvitation(bool newVal) {
|
||||
this._isInvitation = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
get status => this._status;
|
||||
String get status => this._status;
|
||||
set status(String newVal) {
|
||||
this._status = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
get unreadMessages => this._unreadMessages;
|
||||
int get unreadMessages => this._unreadMessages;
|
||||
set unreadMessages(int newVal) {
|
||||
this._unreadMessages = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
get totalMessages => this._totalMessages;
|
||||
int get totalMessages => this._totalMessages;
|
||||
set totalMessages(int newVal) {
|
||||
this._totalMessages = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
get imagePath => this._imagePath;
|
||||
String get imagePath => this._imagePath;
|
||||
set imagePath(String newVal) {
|
||||
this._imagePath = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
get lastMessageTime => this._lastMessageTime;
|
||||
DateTime get lastMessageTime => this._lastMessageTime;
|
||||
set lastMessageTime(DateTime newVal) {
|
||||
this._lastMessageTime = newVal;
|
||||
notifyListeners();
|
||||
|
@ -374,7 +352,8 @@ class ContactInfoState extends ChangeNotifier {
|
|||
if (keys[index] == null) {
|
||||
keys[index] = GlobalKey<MessageBubbleState>();
|
||||
}
|
||||
return keys[index];
|
||||
GlobalKey<MessageBubbleState> ret = keys[index]!;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,24 +361,24 @@ class MessageState extends ChangeNotifier {
|
|||
final String profileOnion;
|
||||
final String contactHandle;
|
||||
final int messageIndex;
|
||||
String _message;
|
||||
int _overlay;
|
||||
String _inviteTarget;
|
||||
String _inviteNick;
|
||||
DateTime _timestamp;
|
||||
String _senderOnion;
|
||||
String _senderImage;
|
||||
String _signature = "";
|
||||
bool _ackd = false;
|
||||
bool _error = false;
|
||||
bool _loaded = false;
|
||||
bool _malformed = false;
|
||||
late String _message;
|
||||
late int _overlay;
|
||||
late String _inviteTarget;
|
||||
late String _inviteNick;
|
||||
late DateTime _timestamp;
|
||||
late String _senderOnion;
|
||||
late String _senderImage;
|
||||
late String _signature = "";
|
||||
late bool _ackd = false;
|
||||
late bool _error = false;
|
||||
late bool _loaded = false;
|
||||
late bool _malformed = false;
|
||||
|
||||
MessageState({
|
||||
BuildContext context,
|
||||
this.profileOnion,
|
||||
this.contactHandle,
|
||||
this.messageIndex,
|
||||
required BuildContext context,
|
||||
required this.profileOnion,
|
||||
required this.contactHandle,
|
||||
required this.messageIndex,
|
||||
}) {
|
||||
this._senderOnion = profileOnion;
|
||||
tryLoad(context);
|
||||
|
@ -408,8 +387,8 @@ class MessageState extends ChangeNotifier {
|
|||
get message => this._message;
|
||||
get overlay => this._overlay;
|
||||
get timestamp => this._timestamp;
|
||||
get ackd => this._ackd;
|
||||
get error => this._error;
|
||||
bool get ackd => this._ackd;
|
||||
bool get error => this._error;
|
||||
get malformed => this._malformed;
|
||||
get senderOnion => this._senderOnion;
|
||||
get senderImage => this._senderImage;
|
||||
|
@ -444,7 +423,7 @@ class MessageState extends ChangeNotifier {
|
|||
dynamic message = jsonDecode(messageWrapper['Message']);
|
||||
this._message = message['d'];
|
||||
this._overlay = int.parse(message['o'].toString());
|
||||
this._timestamp = DateTime.tryParse(messageWrapper['Timestamp']);
|
||||
this._timestamp = DateTime.tryParse(messageWrapper['Timestamp'])!;
|
||||
this._senderOnion = messageWrapper['PeerID'];
|
||||
this._senderImage = messageWrapper['ContactImage'];
|
||||
|
||||
|
@ -490,7 +469,7 @@ class MessageState extends ChangeNotifier {
|
|||
|
||||
class AppModel {
|
||||
final Cwtch cwtch;
|
||||
AppModel({this.cwtch});
|
||||
AppModel({required this.cwtch});
|
||||
|
||||
Stream<String> contactEvents() async* {
|
||||
while (true) {
|
||||
|
|
|
@ -11,7 +11,7 @@ class ServerListState extends ChangeNotifier {
|
|||
|
||||
ServerInfoState getServer(String onion) {
|
||||
int idx = _servers.indexWhere((element) => element.onion == onion);
|
||||
return idx >= 0 ? _servers[idx] : null;
|
||||
return idx >= 0 ? _servers[idx] : ServerInfoState(onion: "not found", status: "not found");
|
||||
}
|
||||
|
||||
List<ServerInfoState> get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier
|
||||
|
@ -22,5 +22,5 @@ class ServerInfoState extends ChangeNotifier {
|
|||
final String onion;
|
||||
final String status;
|
||||
|
||||
ServerInfoState({this.onion, this.status});
|
||||
ServerInfoState({required this.onion, required this.status});
|
||||
}
|
||||
|
|
|
@ -1225,7 +1225,7 @@ class Opaque extends OpaqueThemeType {
|
|||
return sidePaneMinSize() + chatPaneMinSize();
|
||||
}
|
||||
|
||||
static OpaqueThemeType _current;
|
||||
static late OpaqueThemeType _current;
|
||||
static final OpaqueThemeType dark = CwtchDark();
|
||||
static final OpaqueThemeType light = CwtchLight();
|
||||
static void setDark() {
|
||||
|
|
|
@ -14,12 +14,12 @@ const TapirGroupsExperiment = "tapir-groups-experiment";
|
|||
/// Settings Pane.
|
||||
class Settings extends ChangeNotifier {
|
||||
Locale locale;
|
||||
PackageInfo packageInfo;
|
||||
late PackageInfo packageInfo;
|
||||
OpaqueThemeType theme;
|
||||
bool experimentsEnabled;
|
||||
late bool experimentsEnabled;
|
||||
HashMap<String, bool> experiments = HashMap.identity();
|
||||
|
||||
bool blockUnknownConnections;
|
||||
late bool blockUnknownConnections;
|
||||
|
||||
/// Set the dark theme.
|
||||
void setDark() {
|
||||
|
|
|
@ -5,6 +5,8 @@ class TorStatus extends ChangeNotifier {
|
|||
String status;
|
||||
bool connected;
|
||||
|
||||
TorStatus({this.connected = false, this.progress = 0, this.status = ""});
|
||||
|
||||
/// Called by the event bus.
|
||||
handleUpdate(int new_progress, String new_status) {
|
||||
if (progress == 100) {
|
||||
|
|
|
@ -36,7 +36,7 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context).titleManageContacts),
|
||||
title: Text(AppLocalizations.of(context)!.titleManageContacts),
|
||||
),
|
||||
body: _buildForm(),
|
||||
);
|
||||
|
@ -46,7 +46,7 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
ctrlrOnion.text = Provider.of<ProfileInfoState>(context).onion;
|
||||
|
||||
/// We display a different number of tabs dependening on the experiment setup
|
||||
bool groupsEnabled = Provider.of<Settings>(context).experimentsEnabled && Provider.of<Settings>(context).experiments[TapirGroupsExperiment];
|
||||
bool groupsEnabled = Provider.of<Settings>(context).experimentsEnabled && Provider.of<Settings>(context).experiments[TapirGroupsExperiment]!;
|
||||
return Consumer<ErrorHandler>(builder: (context, globalErrorHandler, child) {
|
||||
return DefaultTabController(
|
||||
length: groupsEnabled ? 4 : 1,
|
||||
|
@ -62,7 +62,7 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
|
||||
void _copyOnion() {
|
||||
Clipboard.setData(new ClipboardData(text: Provider.of<ProfileInfoState>(context, listen: false).onion));
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context).copiedClipboardNotification));
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.copiedClipboardNotification));
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
tabs: [
|
||||
Tab(
|
||||
icon: Icon(Icons.person_add_rounded),
|
||||
text: AppLocalizations.of(context).addPeer,
|
||||
text: AppLocalizations.of(context)!.addPeer,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
@ -84,11 +84,11 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
tabs: [
|
||||
Tab(
|
||||
icon: Icon(Icons.person_add_rounded),
|
||||
text: AppLocalizations.of(context).addPeer,
|
||||
text: AppLocalizations.of(context)!.addPeer,
|
||||
),
|
||||
Tab(icon: Icon(Icons.backup), text: AppLocalizations.of(context).titleManageServers),
|
||||
Tab(icon: Icon(Icons.group), text: AppLocalizations.of(context).createGroup),
|
||||
Tab(icon: Icon(Icons.group_add), text: AppLocalizations.of(context).joinGroup),
|
||||
Tab(icon: Icon(Icons.backup), text: AppLocalizations.of(context)!.titleManageServers),
|
||||
Tab(icon: Icon(Icons.group), text: AppLocalizations.of(context)!.createGroup),
|
||||
Tab(icon: Icon(Icons.group_add), text: AppLocalizations.of(context)!.joinGroup),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
autovalidateMode: AutovalidateMode.always,
|
||||
key: _formKey,
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
CwtchLabel(label: AppLocalizations.of(context).profileOnionLabel),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.profileOnionLabel),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -111,12 +111,12 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
controller: ctrlrOnion,
|
||||
onPressed: _copyOnion,
|
||||
icon: Icon(Icons.copy),
|
||||
tooltip: AppLocalizations.of(context).copyBtn,
|
||||
tooltip: AppLocalizations.of(context)!.copyBtn,
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).pasteAddressToAddContact),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.pasteAddressToAddContact),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -127,9 +127,9 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
return null;
|
||||
}
|
||||
if (globalErrorHandler.invalidImportStringError) {
|
||||
return AppLocalizations.of(context).invalidImportString;
|
||||
return AppLocalizations.of(context)!.invalidImportString;
|
||||
} else if (globalErrorHandler.contactAlreadyExistsError) {
|
||||
return AppLocalizations.of(context).contactAlreadyExists;
|
||||
return AppLocalizations.of(context)!.contactAlreadyExists;
|
||||
} else if (globalErrorHandler.explicitAddContactSuccess) {}
|
||||
return null;
|
||||
},
|
||||
|
@ -144,12 +144,13 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
if (globalErrorHandler.explicitAddContactSuccess) {
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context).successfullAddedContact + peerAddr));
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.successfullAddedContact + peerAddr));
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
});
|
||||
},
|
||||
labelText: '',
|
||||
)
|
||||
])));
|
||||
}
|
||||
|
@ -176,13 +177,13 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CwtchLabel(label: AppLocalizations.of(context).server),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.server),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
DropdownButton(
|
||||
onChanged: (newServer) {
|
||||
server = newServer;
|
||||
server = newServer.toString();
|
||||
},
|
||||
value: server,
|
||||
items: Provider.of<ProfileInfoState>(context).serverList.servers.map<DropdownMenuItem<String>>((ServerInfoState serverInfo) {
|
||||
|
@ -194,17 +195,22 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).groupName),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.groupName),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchTextField(controller: ctrlrGroupName, labelText: AppLocalizations.of(context).groupNameLabel, onChanged: (newValue) {}),
|
||||
CwtchTextField(
|
||||
controller: ctrlrGroupName,
|
||||
labelText: AppLocalizations.of(context)!.groupNameLabel,
|
||||
onChanged: (newValue) {},
|
||||
validator: (value) {},
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
child: Text(AppLocalizations.of(context).createGroupBtn),
|
||||
child: Text(AppLocalizations.of(context)!.createGroupBtn),
|
||||
),
|
||||
],
|
||||
)));
|
||||
|
@ -219,7 +225,7 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
autovalidateMode: AutovalidateMode.always,
|
||||
key: _joinGroupFormKey,
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
CwtchLabel(label: AppLocalizations.of(context).joinGroupTab),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.joinGroupTab),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -230,7 +236,7 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
return null;
|
||||
}
|
||||
if (globalErrorHandler.importBundleError) {
|
||||
return AppLocalizations.of(context).invalidImportString;
|
||||
return AppLocalizations.of(context)!.invalidImportString;
|
||||
} else if (globalErrorHandler.importBundleSuccess) {}
|
||||
return null;
|
||||
},
|
||||
|
@ -240,12 +246,13 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
if (globalErrorHandler.importBundleSuccess) {
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context).successfullAddedContact + importBundle));
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.successfullAddedContact + importBundle));
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
});
|
||||
},
|
||||
labelText: '',
|
||||
)
|
||||
])));
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import '../opaque.dart';
|
|||
import '../settings.dart';
|
||||
|
||||
class AddEditProfileView extends StatefulWidget {
|
||||
const AddEditProfileView({Key key}) : super(key: key);
|
||||
const AddEditProfileView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AddEditProfileViewState createState() => _AddEditProfileViewState();
|
||||
|
@ -30,8 +30,8 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
final ctrlrPass = TextEditingController(text: "");
|
||||
final ctrlrPass2 = TextEditingController(text: "");
|
||||
final ctrlrOnion = TextEditingController(text: "");
|
||||
bool usePassword;
|
||||
bool deleted;
|
||||
late bool usePassword;
|
||||
late bool deleted;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -48,15 +48,15 @@ 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(),
|
||||
);
|
||||
}
|
||||
|
||||
void _handleSwitchPassword(bool value) {
|
||||
void _handleSwitchPassword(bool? value) {
|
||||
setState(() {
|
||||
usePassword = value;
|
||||
usePassword = value!;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -88,16 +88,18 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
diameter: 120,
|
||||
maskOut: false,
|
||||
border: theme.theme.portraitOnlineBorderColor(),
|
||||
badgeTextColor: Colors.red,
|
||||
badgeColor: Colors.red,
|
||||
)
|
||||
])),
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
CwtchLabel(label: AppLocalizations.of(context).displayNameLabel),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.displayNameLabel),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchTextField(
|
||||
controller: ctrlrNick,
|
||||
labelText: AppLocalizations.of(context).yourDisplayName,
|
||||
labelText: AppLocalizations.of(context)!.yourDisplayName,
|
||||
validator: (value) {
|
||||
if (value.isEmpty) {
|
||||
return "Please enter a display name";
|
||||
|
@ -112,7 +114,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).addressLabel),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.addressLabel),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -120,7 +122,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
controller: ctrlrOnion,
|
||||
onPressed: _copyOnion,
|
||||
icon: Icon(Icons.copy),
|
||||
tooltip: AppLocalizations.of(context).copyBtn,
|
||||
tooltip: AppLocalizations.of(context)!.copyBtn,
|
||||
)
|
||||
])),
|
||||
// We only allow setting password types on profile creation
|
||||
|
@ -132,7 +134,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
onChanged: _handleSwitchPassword,
|
||||
),
|
||||
Text(
|
||||
AppLocalizations.of(context).radioUsePassword,
|
||||
AppLocalizations.of(context)!.radioUsePassword,
|
||||
style: TextStyle(color: theme.current().mainTextColor()),
|
||||
),
|
||||
])),
|
||||
|
@ -145,7 +147,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
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),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.currentPasswordLabel),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -154,7 +156,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
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 AppLocalizations.of(context)!.passwordErrorEmpty;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
@ -163,7 +165,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
height: 20,
|
||||
),
|
||||
])),
|
||||
CwtchLabel(label: AppLocalizations.of(context).password1Label),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.password1Label),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -172,10 +174,10 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
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 AppLocalizations.of(context)!.passwordErrorEmpty;
|
||||
}
|
||||
if (value != ctrlrPass2.value.text) {
|
||||
return AppLocalizations.of(context).passwordErrorMatch;
|
||||
return AppLocalizations.of(context)!.passwordErrorMatch;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
@ -183,7 +185,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).password2Label),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.password2Label),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -192,10 +194,10 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
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 AppLocalizations.of(context)!.passwordErrorEmpty;
|
||||
}
|
||||
if (value != ctrlrPass.value.text) {
|
||||
return AppLocalizations.of(context).passwordErrorMatch;
|
||||
return AppLocalizations.of(context)!.passwordErrorMatch;
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
|
@ -211,7 +213,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
child: ElevatedButton(
|
||||
onPressed: _createPressed,
|
||||
child: Text(
|
||||
Provider.of<ProfileInfoState>(context).onion.isEmpty ? AppLocalizations.of(context).addNewProfileBtn : AppLocalizations.of(context).saveProfileBtn,
|
||||
Provider.of<ProfileInfoState>(context).onion.isEmpty ? AppLocalizations.of(context)!.addNewProfileBtn : AppLocalizations.of(context)!.saveProfileBtn,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
@ -225,7 +227,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
height: 20,
|
||||
),
|
||||
Tooltip(
|
||||
message: AppLocalizations.of(context).enterCurrentPasswordForDelete,
|
||||
message: AppLocalizations.of(context)!.enterCurrentPasswordForDelete,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: checkCurrentPassword()
|
||||
? null
|
||||
|
@ -234,7 +236,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
},
|
||||
style: ElevatedButton.styleFrom(primary: theme.current().defaultButtonColor()),
|
||||
icon: Icon(Icons.delete_forever),
|
||||
label: Text(AppLocalizations.of(context).deleteBtn),
|
||||
label: Text(AppLocalizations.of(context)!.deleteBtn),
|
||||
))
|
||||
]))
|
||||
]))))));
|
||||
|
@ -251,7 +253,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
// This will run all the validations in the form including
|
||||
// checking that display name is not empty, and an actual check that the passwords
|
||||
// match (and are provided if the user has requested an encrypted profile).
|
||||
if (_formKey.currentState.validate()) {
|
||||
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);
|
||||
|
@ -322,7 +324,7 @@ showAlertDialog(BuildContext context) {
|
|||
foregroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonTextColor()),
|
||||
overlayColor: MaterialStateProperty.all(Opaque.current().defaultButtonActiveColor()),
|
||||
padding: MaterialStateProperty.all(EdgeInsets.all(20))),
|
||||
child: Text(AppLocalizations.of(context).deleteProfileConfirmBtn),
|
||||
child: Text(AppLocalizations.of(context)!.deleteProfileConfirmBtn),
|
||||
onPressed: () {
|
||||
// TODO Actually Delete the Peer
|
||||
Navigator.of(context).pop(); // dismiss dialog
|
||||
|
@ -331,7 +333,7 @@ showAlertDialog(BuildContext context) {
|
|||
|
||||
// set up the AlertDialog
|
||||
AlertDialog alert = AlertDialog(
|
||||
title: Text(AppLocalizations.of(context).deleteProfileConfirmBtn),
|
||||
title: Text(AppLocalizations.of(context)!.deleteProfileConfirmBtn),
|
||||
actions: [
|
||||
cancelButton,
|
||||
continueButton,
|
||||
|
|
|
@ -12,14 +12,14 @@ import '../model.dart';
|
|||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
class ContactsView extends StatefulWidget {
|
||||
const ContactsView({Key key}) : super(key: key);
|
||||
const ContactsView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ContactsViewState createState() => _ContactsViewState();
|
||||
}
|
||||
|
||||
class _ContactsViewState extends State<ContactsView> {
|
||||
TextEditingController ctrlrFilter;
|
||||
late TextEditingController ctrlrFilter;
|
||||
bool showSearchBar = false;
|
||||
|
||||
@override
|
||||
|
@ -37,13 +37,15 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
imagePath: Provider.of<ProfileInfoState>(context).imagePath,
|
||||
diameter: 42,
|
||||
border: Provider.of<Settings>(context).theme.portraitOnlineBorderColor(),
|
||||
badgeTextColor: Colors.red,
|
||||
badgeColor: Colors.red,
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"%1 » %2".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname ?? Provider.of<ProfileInfoState>(context).onion ?? '').replaceAll("%2", "Contacts"),
|
||||
"%1 » %2".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname).replaceAll("%2", "Contacts"),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)), //todo
|
||||
]),
|
||||
|
@ -66,7 +68,7 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _pushAddContact,
|
||||
tooltip: AppLocalizations.of(context).tooltipAddContact,
|
||||
tooltip: AppLocalizations.of(context)!.tooltipAddContact,
|
||||
child: const Icon(Icons.person_add_sharp),
|
||||
),
|
||||
body: showSearchBar || Provider.of<ContactListState>(context).isFiltered ? _buildFilterable() : _buildContactList(),
|
||||
|
@ -75,16 +77,18 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
|
||||
Widget _buildFilterable() {
|
||||
Widget txtfield = CwtchTextField(
|
||||
controller: ctrlrFilter,
|
||||
labelText: AppLocalizations.of(context).search,
|
||||
onChanged: (newVal) {
|
||||
Provider.of<ContactListState>(context, listen: false).filter = newVal;
|
||||
});
|
||||
controller: ctrlrFilter,
|
||||
labelText: AppLocalizations.of(context)!.search,
|
||||
onChanged: (newVal) {
|
||||
Provider.of<ContactListState>(context, listen: false).filter = newVal;
|
||||
},
|
||||
validator: (value) {},
|
||||
);
|
||||
return Column(children: [Padding(padding: EdgeInsets.all(8), child: txtfield), Expanded(child: _buildContactList())]);
|
||||
}
|
||||
|
||||
Widget _buildContactList() {
|
||||
final tiles = Provider.of<ContactListState>(context).filteredList().map((ContactInfoState contact) {
|
||||
final tiles = Provider.of<ContactListState>(context).contacts.map((ContactInfoState contact) {
|
||||
return ChangeNotifierProvider<ContactInfoState>.value(key: ValueKey(contact.profileOnion + "" + contact.onion), value: contact, builder: (_, __) => ContactRow());
|
||||
});
|
||||
final divided = ListTile.divideTiles(
|
||||
|
@ -119,7 +123,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);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@ class _DoubleColumnViewState extends State<DoubleColumnView> {
|
|||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: flwtch.columns[0],
|
||||
child: ContactsView(),
|
||||
child: ContactsView(
|
||||
key: widget.key,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: flwtch.columns[1],
|
||||
|
|
|
@ -24,7 +24,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(),
|
||||
);
|
||||
|
@ -43,13 +43,13 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
),
|
||||
child: Column(children: [
|
||||
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(Icons.language, color: settings.current().mainTextColor()),
|
||||
trailing: DropdownButton(
|
||||
value: Provider.of<Settings>(context).locale.languageCode,
|
||||
onChanged: (String newValue) {
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
settings.switchLocale(Locale(newValue, ''));
|
||||
settings.switchLocale(Locale(newValue!, ''));
|
||||
saveSettings(context);
|
||||
});
|
||||
},
|
||||
|
@ -60,7 +60,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
);
|
||||
}).toList())),
|
||||
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() == Opaque.light,
|
||||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
|
@ -75,11 +75,11 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
secondary: Icon(Icons.lightbulb_outline, color: settings.current().mainTextColor()),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(/*AppLocalizations.of(context).settingLanguage*/ "UI Columns", style: TextStyle(color: settings.current().mainTextColor())),
|
||||
title: Text(/*AppLocalizations.of(context)!.settingLanguage*/ "UI Columns", style: TextStyle(color: settings.current().mainTextColor())),
|
||||
leading: Icon(Icons.table_chart, color: settings.current().mainTextColor()),
|
||||
trailing: DropdownButton(
|
||||
value: "Single",
|
||||
onChanged: (String newValue) {
|
||||
onChanged: (String? newValue) {
|
||||
if (newValue == "Double (1:2)") {
|
||||
Provider.of<FlwtchState>(context).columns = [1, 2];
|
||||
} else if (newValue == "Double (1:4)") {
|
||||
|
@ -95,8 +95,8 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
);
|
||||
}).toList())),
|
||||
SwitchListTile(
|
||||
title: Text(AppLocalizations.of(context).blockUnknownLabel, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context).descriptionBlockUnknownConnections),
|
||||
title: Text(AppLocalizations.of(context)!.blockUnknownLabel, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context)!.descriptionBlockUnknownConnections),
|
||||
value: settings.blockUnknownConnections,
|
||||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
|
@ -111,8 +111,8 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
secondary: Icon(Icons.app_blocking, color: settings.current().mainTextColor()),
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(AppLocalizations.of(context).experimentsEnabled, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context).descriptionExperiments),
|
||||
title: Text(AppLocalizations.of(context)!.experimentsEnabled, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context)!.descriptionExperiments),
|
||||
value: settings.experimentsEnabled,
|
||||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
|
@ -130,9 +130,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
child: Column(
|
||||
children: [
|
||||
SwitchListTile(
|
||||
title: Text(AppLocalizations.of(context).enableGroups, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context).descriptionExperimentsGroups),
|
||||
value: settings.experiments.containsKey(TapirGroupsExperiment) && settings.experiments[TapirGroupsExperiment],
|
||||
title: Text(AppLocalizations.of(context)!.enableGroups, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context)!.descriptionExperimentsGroups),
|
||||
value: settings.experiments.containsKey(TapirGroupsExperiment) && settings.experiments[TapirGroupsExperiment]!,
|
||||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
settings.enableExperiment(TapirGroupsExperiment);
|
||||
|
@ -156,7 +156,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
height: 128,
|
||||
)),
|
||||
applicationName: "Cwtch (Flutter UI)",
|
||||
applicationVersion: AppLocalizations.of(context).version.replaceAll("%1", constructVersionString(Provider.of<Settings>(context).packageInfo)),
|
||||
applicationVersion: AppLocalizations.of(context)!.version.replaceAll("%1", constructVersionString(Provider.of<Settings>(context).packageInfo)),
|
||||
applicationLegalese: '\u{a9} 2021 Open Privacy Research Society',
|
||||
),
|
||||
]))));
|
||||
|
@ -177,22 +177,22 @@ String constructVersionString(PackageInfo pinfo) {
|
|||
/// an individual language code. There might be a more efficient way of doing this.
|
||||
String getLanguageFull(context, String languageCode) {
|
||||
if (languageCode == "en") {
|
||||
return AppLocalizations.of(context).localeEn;
|
||||
return AppLocalizations.of(context)!.localeEn;
|
||||
}
|
||||
if (languageCode == "es") {
|
||||
return AppLocalizations.of(context).localeEs;
|
||||
return AppLocalizations.of(context)!.localeEs;
|
||||
}
|
||||
if (languageCode == "fr") {
|
||||
return AppLocalizations.of(context).localeFr;
|
||||
return AppLocalizations.of(context)!.localeFr;
|
||||
}
|
||||
if (languageCode == "pt") {
|
||||
return AppLocalizations.of(context).localePt;
|
||||
return AppLocalizations.of(context)!.localePt;
|
||||
}
|
||||
if (languageCode == "de") {
|
||||
return AppLocalizations.of(context).localeDe;
|
||||
return AppLocalizations.of(context)!.localeDe;
|
||||
}
|
||||
if (languageCode == "it") {
|
||||
return AppLocalizations.of(context).localeIt;
|
||||
return AppLocalizations.of(context)!.localeIt;
|
||||
}
|
||||
return languageCode;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(Provider.of<ContactInfoState>(context).nickname + " " + AppLocalizations.of(context).conversationSettings),
|
||||
title: Text(Provider.of<ContactInfoState>(context).nickname + " " + AppLocalizations.of(context)!.conversationSettings),
|
||||
),
|
||||
body: _buildSettingsList(),
|
||||
);
|
||||
|
@ -68,24 +68,28 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
|
|||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).groupAddr),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.groupAddr),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchTextField(
|
||||
controller: ctrlrGroupAddr,
|
||||
labelText: '',
|
||||
validator: (value) {},
|
||||
)
|
||||
]),
|
||||
Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).server),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.server),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchTextField(
|
||||
controller: TextEditingController(text: Provider.of<ContactInfoState>(context, listen: false).server),
|
||||
validator: (value) {},
|
||||
labelText: '',
|
||||
)
|
||||
]),
|
||||
// Nickname Save Button
|
||||
|
@ -93,7 +97,7 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
|
|||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).displayNameLabel),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.displayNameLabel),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -107,14 +111,14 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
|
|||
Provider.of<FlwtchState>(context, listen: false).cwtch.SetGroupAttribute(profileOnion, handle, "local.name", ctrlrNick.text);
|
||||
},
|
||||
icon: Icon(Icons.save),
|
||||
tooltip: AppLocalizations.of(context).saveBtn,
|
||||
tooltip: AppLocalizations.of(context)!.saveBtn,
|
||||
)
|
||||
]),
|
||||
Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).conversationSettings),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.conversationSettings),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -127,7 +131,7 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
|
|||
|
||||
void _copyOnion() {
|
||||
Clipboard.setData(new ClipboardData(text: Provider.of<ContactInfoState>(context, listen: false).onion));
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context).copiedClipboardNotification));
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.copiedClipboardNotification));
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
));
|
||||
}
|
||||
|
||||
void _sendMessage([String ignoredParam]) {
|
||||
void _sendMessage([String? ignoredParam]) {
|
||||
ChatMessage cm = new ChatMessage(o: 1, d: ctrlrCompose.value.text);
|
||||
Provider.of<FlwtchState>(context, listen: false)
|
||||
.cwtch
|
||||
|
@ -95,7 +95,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
_sendMessageHelper();
|
||||
}
|
||||
|
||||
void _sendInvitation([String ignoredParam]) {
|
||||
void _sendInvitation([String? ignoredParam]) {
|
||||
Provider.of<FlwtchState>(context, listen: false)
|
||||
.cwtch
|
||||
.SendInvitation(Provider.of<ContactInfoState>(context, listen: false).profileOnion, Provider.of<ContactInfoState>(context, listen: false).onion, this.selectedContact);
|
||||
|
@ -167,7 +167,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(AppLocalizations.of(bcontext).invitationLabel),
|
||||
Text(AppLocalizations.of(bcontext)!.invitationLabel),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -182,7 +182,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
height: 20,
|
||||
),
|
||||
ElevatedButton(
|
||||
child: Text(AppLocalizations.of(bcontext).inviteBtn, semanticsLabel: AppLocalizations.of(bcontext).inviteBtn),
|
||||
child: Text(AppLocalizations.of(bcontext)!.inviteBtn, semanticsLabel: AppLocalizations.of(bcontext)!.inviteBtn),
|
||||
onPressed: () {
|
||||
this._sendInvitation();
|
||||
Navigator.pop(bcontext);
|
||||
|
|
|
@ -59,7 +59,7 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
padding: EdgeInsets.all(2),
|
||||
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
CwtchLabel(label: AppLocalizations.of(context).displayNameLabel),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.displayNameLabel),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -78,7 +78,7 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
Provider.of<FlwtchState>(context, listen: false).cwtch.SendProfileEvent(profileOnion, setPeerAttributeJson);
|
||||
},
|
||||
icon: Icon(Icons.save),
|
||||
tooltip: AppLocalizations.of(context).saveBtn,
|
||||
tooltip: AppLocalizations.of(context)!.saveBtn,
|
||||
)
|
||||
]),
|
||||
|
||||
|
@ -87,7 +87,7 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).addressLabel),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.addressLabel),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
@ -95,19 +95,19 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
controller: TextEditingController(text: Provider.of<ContactInfoState>(context, listen: false).onion),
|
||||
onPressed: _copyOnion,
|
||||
icon: Icon(Icons.copy),
|
||||
tooltip: AppLocalizations.of(context).copyBtn,
|
||||
tooltip: AppLocalizations.of(context)!.copyBtn,
|
||||
)
|
||||
]),
|
||||
Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchLabel(label: AppLocalizations.of(context).conversationSettings),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.conversationSettings),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
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,
|
||||
onChanged: (bool blocked) {
|
||||
// Save local blocked status
|
||||
|
@ -138,15 +138,15 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
secondary: Icon(Icons.block, color: settings.current().mainTextColor()),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(AppLocalizations.of(context).savePeerHistory, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context).savePeerHistoryDescription),
|
||||
title: Text(AppLocalizations.of(context)!.savePeerHistory, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context)!.savePeerHistoryDescription),
|
||||
leading: Icon(Icons.history_sharp, color: settings.current().mainTextColor()),
|
||||
trailing: DropdownButton(
|
||||
value: Provider.of<ContactInfoState>(context).savePeerHistory == "DefaultDeleteHistory"
|
||||
? AppLocalizations.of(context).dontSavePeerHistory
|
||||
? AppLocalizations.of(context)!.dontSavePeerHistory
|
||||
: (Provider.of<ContactInfoState>(context).savePeerHistory == "SaveHistory"
|
||||
? AppLocalizations.of(context).savePeerHistory
|
||||
: AppLocalizations.of(context).dontSavePeerHistory),
|
||||
? AppLocalizations.of(context)!.savePeerHistory
|
||||
: AppLocalizations.of(context)!.dontSavePeerHistory),
|
||||
onChanged: (newValue) {
|
||||
setState(() {
|
||||
// Set whether or not to dave the Contact History...
|
||||
|
@ -154,7 +154,7 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
var onion = Provider.of<ContactInfoState>(context, listen: false).onion;
|
||||
const SaveHistoryKey = "SavePeerHistory";
|
||||
|
||||
if (newValue == AppLocalizations.of(context).savePeerHistory) {
|
||||
if (newValue == AppLocalizations.of(context)!.savePeerHistory) {
|
||||
Provider.of<ContactInfoState>(context, listen: false).savePeerHistory = "SaveHistory";
|
||||
final setPeerAttribute = {
|
||||
"EventType": "SetPeerAttribute",
|
||||
|
@ -174,7 +174,7 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
}
|
||||
});
|
||||
},
|
||||
items: [AppLocalizations.of(context).savePeerHistory, AppLocalizations.of(context).dontSavePeerHistory].map<DropdownMenuItem<String>>((String value) {
|
||||
items: [AppLocalizations.of(context)!.savePeerHistory, AppLocalizations.of(context)!.dontSavePeerHistory].map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
|
@ -188,7 +188,7 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
|
||||
void _copyOnion() {
|
||||
Clipboard.setData(new ClipboardData(text: Provider.of<ContactInfoState>(context, listen: false).onion));
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context).copiedClipboardNotification));
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.copiedClipboardNotification));
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,24 +39,24 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
|||
child: Scaffold(
|
||||
backgroundColor: Provider.of<Settings>(context).theme.backgroundMainColor(),
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context).titleManageProfiles),
|
||||
title: Text(AppLocalizations.of(context)!.titleManageProfiles),
|
||||
actions: [
|
||||
IconButton(icon: TorIcon(), onPressed: _pushTorStatus),
|
||||
IconButton(icon: Icon(Icons.bug_report_outlined), onPressed: _setLoggingLevelDebug),
|
||||
IconButton(
|
||||
icon: Icon(Icons.lock_open),
|
||||
tooltip: AppLocalizations.of(context).tooltipUnlockProfiles,
|
||||
tooltip: AppLocalizations.of(context)!.tooltipUnlockProfiles,
|
||||
onPressed: _modalUnlockProfiles,
|
||||
),
|
||||
IconButton(icon: Icon(Icons.settings), tooltip: AppLocalizations.of(context).tooltipOpenSettings, onPressed: _pushGlobalSettings),
|
||||
IconButton(icon: Icon(Icons.settings), tooltip: AppLocalizations.of(context)!.tooltipOpenSettings, onPressed: _pushGlobalSettings),
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _pushAddEditProfile,
|
||||
tooltip: AppLocalizations.of(context).addNewProfileBtn,
|
||||
tooltip: AppLocalizations.of(context)!.addNewProfileBtn,
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
semanticLabel: AppLocalizations.of(context).addNewProfileBtn,
|
||||
semanticLabel: AppLocalizations.of(context)!.addNewProfileBtn,
|
||||
),
|
||||
),
|
||||
body: _buildProfileManager(), //_buildSuggestions(),
|
||||
|
@ -122,12 +122,13 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(AppLocalizations.of(context).enterProfilePassword),
|
||||
Text(AppLocalizations.of(context)!.enterProfilePassword),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
CwtchPasswordField(
|
||||
controller: ctrlrPassword,
|
||||
validator: (value) {},
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
|
@ -136,7 +137,7 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
|||
Spacer(),
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
child: Text(AppLocalizations.of(context).unlock, semanticsLabel: AppLocalizations.of(context).unlock),
|
||||
child: Text(AppLocalizations.of(context)!.unlock, semanticsLabel: AppLocalizations.of(context)!.unlock),
|
||||
onPressed: () {
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.LoadProfiles(ctrlrPassword.value.text);
|
||||
ctrlrPassword.text = "";
|
||||
|
|
|
@ -44,7 +44,7 @@ class _TorStatusView extends State<TorStatusView> {
|
|||
ListTile(
|
||||
leading: TorIcon(),
|
||||
title: Text("Tor Status"),
|
||||
subtitle: Text(torStatus.progress == 100 ? AppLocalizations.of(context).networkStatusOnline : torStatus.status),
|
||||
subtitle: Text(torStatus.progress == 100 ? AppLocalizations.of(context)!.networkStatusOnline : torStatus.status),
|
||||
trailing: ElevatedButton(
|
||||
child: Text("Reset"),
|
||||
onPressed: () {
|
||||
|
|
|
@ -9,7 +9,7 @@ import '../model.dart';
|
|||
// Pass an onChanged handler to access value
|
||||
class DropdownContacts extends StatefulWidget {
|
||||
DropdownContacts({
|
||||
this.onChanged,
|
||||
required this.onChanged,
|
||||
});
|
||||
final Function(dynamic) onChanged;
|
||||
|
||||
|
@ -18,18 +18,18 @@ class DropdownContacts extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _DropdownContactsState extends State<DropdownContacts> {
|
||||
String selected;
|
||||
late String selected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DropdownButton(
|
||||
value: this.selected,
|
||||
items: Provider.of<ProfileInfoState>(context, listen: false).contactList.contacts.map<DropdownMenuItem<String>>((ContactInfoState contact) {
|
||||
return DropdownMenuItem<String>(value: contact.onion, child: Text(contact.nickname ?? contact.onion));
|
||||
return DropdownMenuItem<String>(value: contact.onion, child: Text(contact.nickname));
|
||||
}).toList(),
|
||||
onChanged: (newVal) {
|
||||
setState(() {
|
||||
this.selected = newVal;
|
||||
this.selected = newVal.toString();
|
||||
});
|
||||
if (widget.onChanged != null) {
|
||||
widget.onChanged(newVal);
|
||||
|
|
|
@ -5,9 +5,9 @@ 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, this.readonly = true});
|
||||
CwtchButtonTextField({required this.controller, required this.onPressed, required this.icon, required this.tooltip, this.readonly = true});
|
||||
final TextEditingController controller;
|
||||
final Function onPressed;
|
||||
final Function()? onPressed;
|
||||
final Icon icon;
|
||||
final String tooltip;
|
||||
final bool readonly;
|
||||
|
|
|
@ -123,7 +123,7 @@ class _ContactRowState extends State<ContactRow> {
|
|||
|
||||
String dateToNiceString(DateTime date) {
|
||||
if (date.millisecondsSinceEpoch == 0) {
|
||||
return AppLocalizations.of(context).dateNever;
|
||||
return AppLocalizations.of(context)!.dateNever;
|
||||
}
|
||||
// If the last message was over a day ago, just state the date
|
||||
if (DateTime.now().difference(date).inDays > 1) {
|
||||
|
|
|
@ -6,7 +6,7 @@ import '../settings.dart';
|
|||
// Callers must provide a label text
|
||||
// TODO: Integrate this with a settings "zoom" / accessibility setting
|
||||
class CwtchLabel extends StatefulWidget {
|
||||
CwtchLabel({this.label});
|
||||
CwtchLabel({required this.label});
|
||||
final String label;
|
||||
|
||||
@override
|
||||
|
|
|
@ -37,11 +37,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
var senderDisplayStr = "";
|
||||
if (Provider.of<MessageState>(context).senderOnion != null) {
|
||||
var contact = Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageState>(context).senderOnion);
|
||||
if (contact == null) {
|
||||
senderDisplayStr = Provider.of<MessageState>(context).senderOnion;
|
||||
} else {
|
||||
senderDisplayStr = contact.nickname ?? contact.onion;
|
||||
}
|
||||
senderDisplayStr = contact.nickname;
|
||||
}
|
||||
var wdgSender = Center(
|
||||
widthFactor: 1,
|
||||
|
|
|
@ -31,7 +31,7 @@ class MessageBubbleState extends State<MessageBubble> {
|
|||
if (contact == null) {
|
||||
senderDisplayStr = Provider.of<MessageState>(context).senderOnion;
|
||||
} else {
|
||||
senderDisplayStr = contact.nickname ?? contact.onion;
|
||||
senderDisplayStr = contact.nickname;
|
||||
}
|
||||
}
|
||||
var wdgSender = SelectableText(senderDisplayStr,
|
||||
|
|
|
@ -14,7 +14,7 @@ import 'messagebubble.dart';
|
|||
import 'messageloadingbubble.dart';
|
||||
|
||||
class MessageRow extends StatefulWidget {
|
||||
MessageRow({Key key}) : super(key: key);
|
||||
MessageRow({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MessageRowState createState() => _MessageRowState();
|
||||
|
@ -52,10 +52,12 @@ class _MessageRowState extends State<MessageRow> {
|
|||
child: Padding(
|
||||
padding: EdgeInsets.all(4.0),
|
||||
child: ProfileImage(
|
||||
diameter: 48.0,
|
||||
imagePath: Provider.of<MessageState>(context).senderImage ?? contact.imagePath,
|
||||
//maskOut: contact.status != "Authenticated",
|
||||
border: contact.status == "Authenticated" ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor())));
|
||||
diameter: 48.0,
|
||||
imagePath: Provider.of<MessageState>(context).senderImage ?? contact.imagePath,
|
||||
//maskOut: contact.status != "Authenticated",
|
||||
border: contact.status == "Authenticated" ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor(),
|
||||
badgeTextColor: Colors.red, badgeColor: Colors.red,
|
||||
)));
|
||||
|
||||
widgetRow = <Widget>[
|
||||
wdgPortrait,
|
||||
|
@ -76,7 +78,7 @@ class _MessageRowState extends State<MessageRow> {
|
|||
case 101:
|
||||
return InvitationBubble();
|
||||
}
|
||||
return null;
|
||||
return MalformedBubble();
|
||||
}
|
||||
|
||||
void _btnAdd() {
|
||||
|
@ -94,7 +96,7 @@ class _MessageRowState extends State<MessageRow> {
|
|||
final setPeerAttributeJson = jsonEncode(setPeerAttribute);
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.SendProfileEvent(profileOnion, setPeerAttributeJson);
|
||||
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context).successfullAddedContact));
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.successfullAddedContact));
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import '../settings.dart';
|
|||
// Provides a styled Password Input Field for use in Form Widgets.
|
||||
// Callers must provide a text controller, label helper text and a validator.
|
||||
class CwtchPasswordField extends StatefulWidget {
|
||||
CwtchPasswordField({this.controller, this.validator});
|
||||
CwtchPasswordField({required this.controller, required this.validator});
|
||||
final TextEditingController controller;
|
||||
final FormFieldValidator validator;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:provider/provider.dart';
|
|||
import '../settings.dart';
|
||||
|
||||
class ProfileImage extends StatefulWidget {
|
||||
ProfileImage({this.imagePath, this.diameter, this.border, this.badgeCount = 0, this.badgeColor, this.badgeTextColor, this.maskOut = false});
|
||||
ProfileImage({required this.imagePath, required this.diameter, required this.border, this.badgeCount = 0, required this.badgeColor, required this.badgeTextColor, this.maskOut = false});
|
||||
final double diameter;
|
||||
final String imagePath;
|
||||
final Color border;
|
||||
|
|
|
@ -55,7 +55,7 @@ class _ProfileRowState extends State<ProfileRow> {
|
|||
)),
|
||||
IconButton(
|
||||
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()),
|
||||
onPressed: () {
|
||||
_pushAddEditProfile(onion: profile.onion, displayName: profile.nickname, profileImage: profile.imagePath);
|
||||
|
|
|
@ -7,7 +7,7 @@ doNothing(String x) {}
|
|||
// Provides a styled Text Field for use in Form Widgets.
|
||||
// Callers must provide a text controller, label helper text and a validator.
|
||||
class CwtchTextField extends StatefulWidget {
|
||||
CwtchTextField({this.controller, this.labelText, this.validator, this.onChanged = doNothing});
|
||||
CwtchTextField({required this.controller, required this.labelText, required this.validator, this.onChanged = doNothing});
|
||||
final TextEditingController controller;
|
||||
final String labelText;
|
||||
final FormFieldValidator validator;
|
||||
|
|
|
@ -23,8 +23,8 @@ class _TorIconState extends State<TorIcon> {
|
|||
color: Provider.of<Settings>(context).theme.mainTextColor(),
|
||||
colorBlendMode: BlendMode.srcIn,
|
||||
semanticLabel: Provider.of<TorStatus>(context).progress == 100
|
||||
? AppLocalizations.of(context).networkStatusOnline
|
||||
: (Provider.of<TorStatus>(context).progress == 0 ? AppLocalizations.of(context).networkStatusDisconnected : AppLocalizations.of(context).networkStatusAttemptingTor),
|
||||
? AppLocalizations.of(context)!.networkStatusOnline
|
||||
: (Provider.of<TorStatus>(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +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,
|
||||
);
|
||||
},
|
||||
|
|
26
pubspec.lock
26
pubspec.lock
|
@ -63,7 +63,7 @@ packages:
|
|||
name: cupertino_icons
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
version: "1.0.3"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -84,7 +84,7 @@ packages:
|
|||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
version: "6.1.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
@ -128,7 +128,7 @@ packages:
|
|||
name: http
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.13.1"
|
||||
version: "0.13.3"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -184,42 +184,42 @@ packages:
|
|||
name: package_info_plus
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
package_info_plus_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.0.2"
|
||||
package_info_plus_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.1.1"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
package_info_plus_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
package_info_plus_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -261,7 +261,7 @@ packages:
|
|||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -296,7 +296,7 @@ packages:
|
|||
name: provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.3.2+3"
|
||||
version: "5.0.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -385,7 +385,7 @@ packages:
|
|||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
version: "2.1.1"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -394,5 +394,5 @@ packages:
|
|||
source: hosted
|
||||
version: "0.2.0"
|
||||
sdks:
|
||||
dart: ">=2.12.0 <3.0.0"
|
||||
dart: ">=2.13.0 <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
|
|
|
@ -18,12 +18,12 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
provider: "4.3.2+3"
|
||||
provider: 5.0.0
|
||||
package_info_plus: ^1.0.0
|
||||
#intl_translation: any
|
||||
flutter_localizations:
|
||||
|
|
Loading…
Reference in New Issue