Merge pull request 'Experimental Check on Group Invitations + Delete Profile Fixes for Passwordless Profiles' (#214) from launch into trunk
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
Reviewed-on: #214
This commit is contained in:
commit
23b0af77f1
|
@ -1 +1 @@
|
|||
v0.0.2-104-gc1b7e4c-2021-06-22-23-59
|
||||
v0.0.2-108-g3964348-2021-06-24-17-42
|
|
@ -136,7 +136,7 @@ class MainActivity: FlutterActivity() {
|
|||
super.onResume()
|
||||
Log.i("MainActivity.kt", "onResume")
|
||||
if (myReceiver == null) {
|
||||
Log.i("MainActivity.kt", "onResume registering localbroadcastreceiver")
|
||||
Log.i("MainActivity.kt", "onResume registering local broadcast receiver / event bus forwarder")
|
||||
val mc = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS)
|
||||
val filter = IntentFilter("im.cwtch.flwtch.broadcast.SERVICE_EVENT_BUS")
|
||||
myReceiver = MyBroadcastReceiver(mc)
|
||||
|
@ -163,7 +163,7 @@ class MainActivity: FlutterActivity() {
|
|||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
Log.i("MainActivity.kt", "onDestroy")
|
||||
Log.i("MainActivity.kt", "onDestroy - cancelling all WORKER_TAG and pruning old work")
|
||||
WorkManager.getInstance(this).cancelAllWorkByTag(WORKER_TAG)
|
||||
WorkManager.getInstance(this).pruneWork()
|
||||
}
|
||||
|
@ -188,6 +188,8 @@ class MainActivity: FlutterActivity() {
|
|||
val Data = this.optString("Data")
|
||||
}
|
||||
|
||||
// MainActivity.MyBroadcastReceiver receives events from the Cwtch service via im.cwtch.flwtch.broadcast.SERVICE_EVENT_BUS Android local broadcast intents
|
||||
// then it forwards them to the flutter ui engine using the CWTCH_EVENTBUS methodchannel
|
||||
class MyBroadcastReceiver(mc: MethodChannel) : BroadcastReceiver() {
|
||||
val eventBus: MethodChannel = mc
|
||||
|
||||
|
@ -198,5 +200,4 @@ class MainActivity: FlutterActivity() {
|
|||
eventBus.invokeMethod(evtType, evtData)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ class CwtchNotifier {
|
|||
appState.SetAppError(data["Error"]);
|
||||
break;
|
||||
case "NewPeer":
|
||||
profileCN.add(data["Identity"], data["name"], data["picture"], data["ContactsJson"], data["ServerList"], data["Online"] == "true");
|
||||
// if tag != v1-defaultPassword then it is either encrypted OR it is an unencrypted account created during pre-beta...
|
||||
profileCN.add(data["Identity"], data["name"], data["picture"], data["ContactsJson"], data["ServerList"], data["Online"] == "true", data["tag"] != "v1-defaultPassword");
|
||||
break;
|
||||
case "PeerCreated":
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(
|
||||
|
@ -97,7 +98,9 @@ class CwtchNotifier {
|
|||
break;
|
||||
case "NewMessageFromPeer":
|
||||
notificationManager.notify("New Message From Peer!");
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.unreadMessages++;
|
||||
if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != data["RemotePeer"]) {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.unreadMessages++;
|
||||
}
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.totalMessages++;
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["RemotePeer"], DateTime.now());
|
||||
break;
|
||||
|
@ -122,7 +125,9 @@ class CwtchNotifier {
|
|||
case "NewMessageFromGroup":
|
||||
if (data["ProfileOnion"] != data["RemotePeer"]) {
|
||||
//not from me
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.unreadMessages++;
|
||||
if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != data["GroupID"]) {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.unreadMessages++;
|
||||
}
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.totalMessages++;
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["GroupID"], DateTime.now());
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "de",
|
||||
"@@last_modified": "2021-06-16T23:15:48+02:00",
|
||||
"@@last_modified": "2021-06-24T18:24:27+02:00",
|
||||
"groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.",
|
||||
"shutdownCwtchAction": "Shutdown Cwtch",
|
||||
"shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.",
|
||||
"shutdownCwtchDialogTitle": "Shutdown Cwtch?",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "en",
|
||||
"@@last_modified": "2021-06-16T23:15:48+02:00",
|
||||
"@@last_modified": "2021-06-24T18:24:27+02:00",
|
||||
"groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.",
|
||||
"shutdownCwtchAction": "Shutdown Cwtch",
|
||||
"shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.",
|
||||
"shutdownCwtchDialogTitle": "Shutdown Cwtch?",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "es",
|
||||
"@@last_modified": "2021-06-16T23:15:48+02:00",
|
||||
"@@last_modified": "2021-06-24T18:24:27+02:00",
|
||||
"groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.",
|
||||
"shutdownCwtchAction": "Shutdown Cwtch",
|
||||
"shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.",
|
||||
"shutdownCwtchDialogTitle": "Shutdown Cwtch?",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "fr",
|
||||
"@@last_modified": "2021-06-16T23:15:48+02:00",
|
||||
"@@last_modified": "2021-06-24T18:24:27+02:00",
|
||||
"groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.",
|
||||
"shutdownCwtchAction": "Shutdown Cwtch",
|
||||
"shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.",
|
||||
"shutdownCwtchDialogTitle": "Shutdown Cwtch?",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "it",
|
||||
"@@last_modified": "2021-06-16T23:15:48+02:00",
|
||||
"@@last_modified": "2021-06-24T18:24:27+02:00",
|
||||
"groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.",
|
||||
"shutdownCwtchAction": "Shutdown Cwtch",
|
||||
"shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.",
|
||||
"shutdownCwtchDialogTitle": "Shutdown Cwtch?",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "pt",
|
||||
"@@last_modified": "2021-06-16T23:15:48+02:00",
|
||||
"@@last_modified": "2021-06-24T18:24:27+02:00",
|
||||
"groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.",
|
||||
"shutdownCwtchAction": "Shutdown Cwtch",
|
||||
"shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.",
|
||||
"shutdownCwtchDialogTitle": "Shutdown Cwtch?",
|
||||
|
|
|
@ -45,10 +45,6 @@ class Flwtch extends StatefulWidget {
|
|||
class FlwtchState extends State<Flwtch> {
|
||||
final TextStyle biggerFont = const TextStyle(fontSize: 18);
|
||||
late Cwtch cwtch;
|
||||
late ProfileInfoState selectedProfile;
|
||||
String selectedConversation = "";
|
||||
var columns = [1]; // default or 'single column' mode
|
||||
//var columns = [1, 1, 2];
|
||||
late ProfileListState profs;
|
||||
final MethodChannel notificationClickChannel = MethodChannel('im.cwtch.flwtch/notificationClickHandler');
|
||||
final MethodChannel shutdownMethodChannel = MethodChannel('im.cwtch.flwtch/shutdown');
|
||||
|
@ -108,7 +104,7 @@ class FlwtchState extends State<Flwtch> {
|
|||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
title: 'Cwtch',
|
||||
theme: mkThemeData(settings),
|
||||
home: appState.cwtchInit == true ? (columns.length == 3 ? TripleColumnView() : ShiftRightFixer(child: ProfileMgrView())) : SplashView(),
|
||||
home: appState.cwtchInit == true ? ShiftRightFixer(child: ProfileMgrView()) : SplashView(),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -128,24 +124,38 @@ class FlwtchState extends State<Flwtch> {
|
|||
});
|
||||
}
|
||||
|
||||
// Invoked via notificationClickChannel by MyBroadcastReceiver in MainActivity.kt
|
||||
// coder beware: args["RemotePeer"] is actually a handle, and could be eg a groupID
|
||||
Future<void> _externalNotificationClicked(MethodCall call) async {
|
||||
var args = jsonDecode(call.arguments);
|
||||
var profile = profs.getProfile(args["ProfileOnion"])!;
|
||||
var contact = profile.contactList.getContact(args["RemotePeer"])!;
|
||||
contact.unreadMessages = 0;
|
||||
navKey.currentState?.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext builderContext) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider.value(value: profile),
|
||||
ChangeNotifierProvider.value(value: contact),
|
||||
],
|
||||
builder: (context, child) => MessageView(),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// single pane mode pushes; double pane mode reads AppState.selectedProfile/Conversation
|
||||
var isLandscape = Provider.of<AppState>(navKey.currentContext!, listen: false).isLandscape(navKey.currentContext!);
|
||||
if (Provider.of<Settings>(navKey.currentContext!, listen: false).uiColumns(isLandscape).length == 1) {
|
||||
if (navKey.currentContext?.findAncestorWidgetOfExactType<MessageView>() != null) {
|
||||
print("messageview already open; popping before pushing replacement");
|
||||
navKey.currentState?.pop();
|
||||
}
|
||||
navKey.currentState?.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext builderContext) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider.value(value: profile),
|
||||
ChangeNotifierProvider.value(value: contact),
|
||||
],
|
||||
builder: (context, child) => MessageView(),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
} else { //dual pane
|
||||
Provider.of<AppState>(navKey.currentContext!, listen: false).selectedProfile = args["ProfileOnion"];
|
||||
Provider.of<AppState>(navKey.currentContext!, listen: false).selectedConversation = args["RemotePeer"];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -13,7 +13,6 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:glob/glob.dart';
|
||||
import 'package:glob/list_local_fs.dart';
|
||||
|
||||
var globalSettings = Settings(Locale("en", ''), OpaqueDark());
|
||||
var globalErrorHandler = ErrorHandler();
|
||||
|
|
|
@ -38,10 +38,10 @@ class ProfileListState extends ChangeNotifier {
|
|||
List<ProfileInfoState> _profiles = [];
|
||||
int get num => _profiles.length;
|
||||
|
||||
void add(String onion, String name, String picture, String contactsJson, String serverJson, bool online) {
|
||||
void add(String onion, String name, String picture, String contactsJson, String serverJson, bool online, bool encrypted) {
|
||||
var idx = _profiles.indexWhere((element) => element.onion == onion);
|
||||
if (idx == -1) {
|
||||
_profiles.add(ProfileInfoState(onion: onion, nickname: name, imagePath: picture, contactsJson: contactsJson, serversJson: serverJson, online: online));
|
||||
_profiles.add(ProfileInfoState(onion: onion, nickname: name, imagePath: picture, contactsJson: contactsJson, serversJson: serverJson, online: online, encrypted: encrypted));
|
||||
} else {
|
||||
_profiles[idx].updateFrom(onion, name, picture, contactsJson, serverJson, online);
|
||||
}
|
||||
|
@ -64,6 +64,8 @@ class ProfileListState extends ChangeNotifier {
|
|||
class AppState extends ChangeNotifier {
|
||||
bool cwtchInit = false;
|
||||
String appError = "";
|
||||
String? _selectedProfile;
|
||||
String? _selectedConversation;
|
||||
|
||||
void SetCwtchInit() {
|
||||
cwtchInit = true;
|
||||
|
@ -74,6 +76,20 @@ class AppState extends ChangeNotifier {
|
|||
appError = error;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
String? get selectedProfile => _selectedProfile;
|
||||
set selectedProfile(String? newVal) {
|
||||
this._selectedProfile = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
String? get selectedConversation => _selectedConversation;
|
||||
set selectedConversation(String? newVal) {
|
||||
this._selectedConversation = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool isLandscape(BuildContext c) => MediaQuery.of(c).size.width > MediaQuery.of(c).size.height;
|
||||
}
|
||||
|
||||
class ContactListState extends ChangeNotifier {
|
||||
|
@ -161,6 +177,10 @@ class ProfileInfoState extends ChangeNotifier {
|
|||
int _unreadMessages = 0;
|
||||
bool _online = false;
|
||||
|
||||
// assume profiles are encrypted...this will be set to false
|
||||
// in the constructor if the profile is encrypted with the defacto password.
|
||||
bool _encrypted = true;
|
||||
|
||||
ProfileInfoState({
|
||||
required this.onion,
|
||||
nickname = "",
|
||||
|
@ -169,11 +189,13 @@ class ProfileInfoState extends ChangeNotifier {
|
|||
contactsJson = "",
|
||||
serversJson = "",
|
||||
online = false,
|
||||
encrypted = true,
|
||||
}) {
|
||||
this._nickname = nickname;
|
||||
this._imagePath = imagePath;
|
||||
this._unreadMessages = unreadMessages;
|
||||
this._online = online;
|
||||
this._encrypted = encrypted;
|
||||
|
||||
if (contactsJson != null && contactsJson != "" && contactsJson != "null") {
|
||||
List<dynamic> contacts = jsonDecode(contactsJson);
|
||||
|
@ -227,6 +249,9 @@ class ProfileInfoState extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
// Check encrypted status for profile info screen
|
||||
bool get isEncrypted => this._encrypted;
|
||||
|
||||
String get nickname => this._nickname;
|
||||
set nickname(String newValue) {
|
||||
this._nickname = newValue;
|
||||
|
@ -491,6 +516,8 @@ class MessageState extends ChangeNotifier {
|
|||
}
|
||||
|
||||
set loaded(bool newVal) {
|
||||
// quickly-arriving messages get discarded before loading sometimes
|
||||
if (!hasListeners) return;
|
||||
this._loaded = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,13 @@ import 'opaque.dart';
|
|||
|
||||
const TapirGroupsExperiment = "tapir-groups-experiment";
|
||||
|
||||
enum DualpaneMode {
|
||||
Single,
|
||||
Dual1to2,
|
||||
Dual1to4,
|
||||
CopyPortrait,
|
||||
}
|
||||
|
||||
/// Settings govern the *Globally* relevant settings like Locale, Theme and Experiments.
|
||||
/// We also provide access to the version information here as it is also accessed from the
|
||||
/// Settings Pane.
|
||||
|
@ -19,6 +26,8 @@ class Settings extends ChangeNotifier {
|
|||
// explicitly set experiments to false until told otherwise...
|
||||
bool experimentsEnabled = false;
|
||||
HashMap<String, bool> experiments = HashMap.identity();
|
||||
DualpaneMode _uiColumnModePortrait = DualpaneMode.Single;
|
||||
DualpaneMode _uiColumnModeLandscape = DualpaneMode.CopyPortrait;
|
||||
|
||||
bool blockUnknownConnections = false;
|
||||
|
||||
|
@ -73,6 +82,10 @@ class Settings extends ChangeNotifier {
|
|||
// Set the internal experiments map. Casting from the Map<dynamic, dynamic> that we get from JSON
|
||||
experiments = new HashMap<String, bool>.from(settings["Experiments"]);
|
||||
|
||||
// single pane vs dual pane preferences
|
||||
_uiColumnModePortrait = uiColumnModeFromString(settings["UIColumnModePortrait"]);
|
||||
_uiColumnModeLandscape = uiColumnModeFromString(settings["UIColumnModeLandscape"]);
|
||||
|
||||
// Push the experimental settings to Consumers of Settings
|
||||
notifyListeners();
|
||||
}
|
||||
|
@ -134,6 +147,55 @@ class Settings extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
DualpaneMode get uiColumnModePortrait => _uiColumnModePortrait;
|
||||
set uiColumnModePortrait(DualpaneMode newval) {
|
||||
this._uiColumnModePortrait = newval;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
DualpaneMode get uiColumnModeLandscape => _uiColumnModeLandscape;
|
||||
set uiColumnModeLandscape(DualpaneMode newval) {
|
||||
this._uiColumnModeLandscape = newval;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
List<int> uiColumns(bool isLandscape) {
|
||||
var m = (!isLandscape || uiColumnModeLandscape == DualpaneMode.CopyPortrait) ? uiColumnModePortrait : uiColumnModeLandscape;
|
||||
switch(m) {
|
||||
case DualpaneMode.Single: return [1];
|
||||
case DualpaneMode.Dual1to2: return [1, 2];
|
||||
case DualpaneMode.Dual1to4: return [1, 4];
|
||||
}
|
||||
print("impossible column configuration: portrait/$uiColumnModePortrait landscape/$uiColumnModeLandscape");
|
||||
return [1];
|
||||
}
|
||||
|
||||
static List<DualpaneMode> uiColumnModeOptions(bool isLandscape) {
|
||||
if (isLandscape) return [DualpaneMode.CopyPortrait, DualpaneMode.Single, DualpaneMode.Dual1to2, DualpaneMode.Dual1to4,];
|
||||
else return [DualpaneMode.Single, DualpaneMode.Dual1to2, DualpaneMode.Dual1to4];
|
||||
}
|
||||
|
||||
static DualpaneMode uiColumnModeFromString(String m) {
|
||||
switch(m) {
|
||||
case "DualpaneMode.Single": return DualpaneMode.Single;
|
||||
case "DualpaneMode.Dual1to2": return DualpaneMode.Dual1to2;
|
||||
case "DualpaneMode.Dual1to4": return DualpaneMode.Dual1to4;
|
||||
case "DualpaneMode.CopyPortrait": return DualpaneMode.CopyPortrait;
|
||||
}
|
||||
print("Error: ui requested translation of column mode [$m] which doesn't exist");
|
||||
return DualpaneMode.Single;
|
||||
}
|
||||
|
||||
static String uiColumnModeToString(DualpaneMode m) {
|
||||
// todo: translate
|
||||
switch(m) {
|
||||
case DualpaneMode.Single: return "Single";
|
||||
case DualpaneMode.Dual1to2: return "Double (1:2)";
|
||||
case DualpaneMode.Dual1to4: return "Double (1:4)";
|
||||
case DualpaneMode.CopyPortrait: return "Same as portrait mode setting";
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a default settings object.
|
||||
Settings(this.locale, this.theme);
|
||||
|
||||
|
@ -150,7 +212,9 @@ class Settings extends ChangeNotifier {
|
|||
"ExperimentsEnabled": this.experimentsEnabled,
|
||||
"Experiments": experiments,
|
||||
"StateRootPane": 0,
|
||||
"FirstTime": false
|
||||
"FirstTime": false,
|
||||
"UIColumnModePortrait": uiColumnModePortrait.toString(),
|
||||
"UIColumnModeLandscape": uiColumnModeLandscape.toString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
visible: usePassword,
|
||||
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
|
||||
Visibility(
|
||||
visible: Provider.of<ProfileInfoState>(context, listen: false).onion.isNotEmpty,
|
||||
visible: Provider.of<ProfileInfoState>(context, listen: false).onion.isNotEmpty && Provider.of<ProfileInfoState>(context).isEncrypted,
|
||||
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.currentPasswordLabel),
|
||||
SizedBox(
|
||||
|
@ -165,7 +165,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
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) {
|
||||
if (Provider.of<ProfileInfoState>(context).isEncrypted && Provider.of<ProfileInfoState>(context, listen: false).onion.isEmpty && value.isEmpty && usePassword) {
|
||||
return AppLocalizations.of(context)!.passwordErrorEmpty;
|
||||
}
|
||||
if (Provider.of<ErrorHandler>(context).deleteProfileError == true) {
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
|
|||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import '../main.dart';
|
||||
import '../model.dart';
|
||||
import '../settings.dart';
|
||||
import 'contactsview.dart';
|
||||
import 'messageview.dart';
|
||||
|
||||
|
@ -14,24 +15,25 @@ class DoubleColumnView extends StatefulWidget {
|
|||
class _DoubleColumnViewState extends State<DoubleColumnView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var flwtch = Provider.of<FlwtchState>(context);
|
||||
var flwtch = Provider.of<AppState>(context);
|
||||
var cols = Provider.of<Settings>(context).uiColumns(true);
|
||||
return Flex(
|
||||
direction: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: flwtch.columns[0],
|
||||
flex: cols[0],
|
||||
child: ContactsView(
|
||||
key: widget.key,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: flwtch.columns[1],
|
||||
child: flwtch.selectedConversation == ""
|
||||
? Center(child: Text(AppLocalizations.of(context)!.addContactFirst))
|
||||
flex: cols[1],
|
||||
child: flwtch.selectedConversation == null
|
||||
? Card(child:Center(child: Text(AppLocalizations.of(context)!.addContactFirst)))
|
||||
: //dev
|
||||
MultiProvider(providers: [
|
||||
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context)),
|
||||
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context).contactList.getContact(flwtch.selectedConversation)!),
|
||||
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context).contactList.getContact(flwtch.selectedConversation!)!),
|
||||
], child: Container(child: MessageView())),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -80,24 +80,33 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
secondary: Icon(CwtchIcons.change_theme, 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 in Portrait Mode", style: TextStyle(color: settings.current().mainTextColor())),
|
||||
leading: Icon(Icons.table_chart, color: settings.current().mainTextColor()),
|
||||
trailing: DropdownButton(
|
||||
value: "Single",
|
||||
value: settings.uiColumnModePortrait.toString(),
|
||||
onChanged: (String? newValue) {
|
||||
if (newValue == "Double (1:2)") {
|
||||
Provider.of<FlwtchState>(context).columns = [1, 2];
|
||||
} else if (newValue == "Double (1:4)") {
|
||||
Provider.of<FlwtchState>(context).columns = [1, 4];
|
||||
} else {
|
||||
Provider.of<FlwtchState>(context).columns = [1];
|
||||
}
|
||||
settings.uiColumnModePortrait = Settings.uiColumnModeFromString(newValue!);
|
||||
saveSettings(context);
|
||||
},
|
||||
// TODO: Only allow in landscape?
|
||||
items: (Platform.isAndroid ? ["Single"] : ["Single", "Double (1:2)", "Double (1:4)"]).map<DropdownMenuItem<String>>((String value) {
|
||||
items: Settings.uiColumnModeOptions(false).map<DropdownMenuItem<String>>((DualpaneMode value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
value: value.toString(),
|
||||
child: Text(Settings.uiColumnModeToString(value)),
|
||||
);
|
||||
}).toList())),
|
||||
ListTile(
|
||||
title: Text(/*AppLocalizations.of(context)!.settingLanguage*/ "UI Columns in Landscape Mode", style: TextStyle(color: settings.current().mainTextColor())),
|
||||
leading: Icon(Icons.table_chart, color: settings.current().mainTextColor()),
|
||||
trailing: DropdownButton(
|
||||
value: settings.uiColumnModeLandscape.toString(),
|
||||
onChanged: (String? newValue) {
|
||||
settings.uiColumnModeLandscape = Settings.uiColumnModeFromString(newValue!);
|
||||
saveSettings(context);
|
||||
},
|
||||
items: Settings.uiColumnModeOptions(true).map<DropdownMenuItem<String>>((DualpaneMode value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value.toString(),
|
||||
child: Text(Settings.uiColumnModeToString(value)),
|
||||
);
|
||||
}).toList())),
|
||||
SwitchListTile(
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:cwtch/widgets/profileimage.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cwtch/views/peersettingsview.dart';
|
||||
|
@ -42,11 +43,24 @@ class _MessageViewState extends State<MessageView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var appState = Provider.of<AppState>(context);
|
||||
return WillPopScope(
|
||||
onWillPop: _onWillPop,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(Provider.of<ContactInfoState>(context).nickname),
|
||||
// setting leading to null makes it do the default behaviour; container() hides it
|
||||
leading: Provider.of<Settings>(context).uiColumns(appState.isLandscape(context)).length > 1 ? Container() : null,
|
||||
title: Row(children: [
|
||||
ProfileImage(
|
||||
imagePath: Provider.of<ContactInfoState>(context).imagePath,
|
||||
diameter: 42,
|
||||
border: Provider.of<Settings>(context).current().portraitOnlineBorderColor(),
|
||||
badgeTextColor: Colors.red,
|
||||
badgeColor: Colors.red,
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),Text(Provider.of<ContactInfoState>(context).nickname)]),
|
||||
actions: [
|
||||
//IconButton(icon: Icon(Icons.chat), onPressed: _pushContactSettings),
|
||||
//IconButton(icon: Icon(Icons.list), onPressed: _pushContactSettings),
|
||||
|
|
|
@ -42,41 +42,45 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
|||
// Prevents Android back button from closing the app on the profile manager screen
|
||||
// (which would shutdown connections and all kinds of other expensive to generate things)
|
||||
// TODO pop up a dialogue regarding closing the app?
|
||||
builder: (context, settings, child) => WillPopScope(
|
||||
onWillPop: () async {
|
||||
_showShutdown();
|
||||
return closeApp;
|
||||
},
|
||||
child: Scaffold(
|
||||
backgroundColor: settings.theme.backgroundMainColor(),
|
||||
appBar: AppBar(
|
||||
title: Row(children: [
|
||||
Image(
|
||||
image: AssetImage("assets/core/knott-white.png"),
|
||||
filterQuality: FilterQuality.medium,
|
||||
isAntiAlias: true,
|
||||
width: 32,
|
||||
height: 32,
|
||||
colorBlendMode: BlendMode.dstIn,
|
||||
color: Provider.of<Settings>(context).theme.backgroundHilightElementColor(),
|
||||
builder: (context, settings, child) =>
|
||||
WillPopScope(
|
||||
onWillPop: () async {
|
||||
_showShutdown();
|
||||
return closeApp;
|
||||
},
|
||||
child: Scaffold(
|
||||
backgroundColor: settings.theme.backgroundMainColor(),
|
||||
appBar: AppBar(
|
||||
title: Row(children: [
|
||||
Image(
|
||||
image: AssetImage("assets/core/knott-white.png"),
|
||||
filterQuality: FilterQuality.medium,
|
||||
isAntiAlias: true,
|
||||
width: 32,
|
||||
height: 32,
|
||||
colorBlendMode: BlendMode.dstIn,
|
||||
color: Provider
|
||||
.of<Settings>(context)
|
||||
.theme
|
||||
.backgroundHilightElementColor(),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(child: Text(AppLocalizations.of(context)!.titleManageProfiles, style: TextStyle(color: settings.current().mainTextColor())))
|
||||
]),
|
||||
actions: getActions(),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _pushAddEditProfile,
|
||||
tooltip: AppLocalizations.of(context)!.addNewProfileBtn,
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
semanticLabel: AppLocalizations.of(context)!.addNewProfileBtn,
|
||||
),
|
||||
),
|
||||
Expanded(child: Text(AppLocalizations.of(context)!.titleManageProfiles, style: TextStyle(color: settings.current().mainTextColor())))
|
||||
]),
|
||||
actions: getActions(),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _pushAddEditProfile,
|
||||
tooltip: AppLocalizations.of(context)!.addNewProfileBtn,
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
semanticLabel: AppLocalizations.of(context)!.addNewProfileBtn,
|
||||
),
|
||||
),
|
||||
body: _buildProfileManager(),
|
||||
)),
|
||||
body: _buildProfileManager(),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,12 @@ import 'package:cwtch/views/profilemgrview.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import '../main.dart';
|
||||
import '../model.dart';
|
||||
import '../settings.dart';
|
||||
import 'contactsview.dart';
|
||||
import 'messageview.dart';
|
||||
|
||||
// currently unused but maybe one day?
|
||||
class TripleColumnView extends StatefulWidget {
|
||||
@override
|
||||
_TripleColumnViewState createState() => _TripleColumnViewState();
|
||||
|
@ -14,19 +17,22 @@ class TripleColumnView extends StatefulWidget {
|
|||
class _TripleColumnViewState extends State<TripleColumnView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var flwtch = Provider.of<FlwtchState>(context);
|
||||
var appState = Provider.of<AppState>(context);
|
||||
var settings = Provider.of<Settings>(context);
|
||||
var columns = settings.uiColumns(appState.isLandscape(context));
|
||||
|
||||
return Flex(direction: Axis.horizontal, children: <Widget>[
|
||||
Flexible(
|
||||
flex: flwtch.columns[0],
|
||||
flex: columns[0],
|
||||
child: ProfileMgrView(),
|
||||
),
|
||||
Flexible(
|
||||
flex: flwtch.columns[1],
|
||||
child: flwtch.selectedProfile == null ? Center(child: Text(AppLocalizations.of(context)!.createProfileToBegin)) : ContactsView(), //dev
|
||||
flex: columns[1],
|
||||
child: appState.selectedProfile == null ? Center(child: Text(AppLocalizations.of(context)!.createProfileToBegin)) : ContactsView(), //dev
|
||||
),
|
||||
Flexible(
|
||||
flex: flwtch.columns[2],
|
||||
child: flwtch.selectedConversation == ""
|
||||
flex: columns[2],
|
||||
child: appState.selectedConversation == null
|
||||
? Center(child: Text(AppLocalizations.of(context)!.addContactFirst))
|
||||
: //dev
|
||||
Container(child: MessageView()),
|
||||
|
|
|
@ -20,6 +20,8 @@ class _ContactRowState extends State<ContactRow> {
|
|||
var contact = Provider.of<ContactInfoState>(context);
|
||||
return Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
color: Provider.of<AppState>(context).selectedConversation == contact.onion ? Provider.of<Settings>(context).theme.backgroundHilightElementColor() : null,
|
||||
borderOnForeground: false,
|
||||
child: InkWell(
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Padding(
|
||||
|
@ -80,17 +82,19 @@ class _ContactRowState extends State<ContactRow> {
|
|||
]),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
var flwtch = Provider.of<FlwtchState>(context, listen: false);
|
||||
flwtch.setState(() => flwtch.selectedConversation = contact.onion);
|
||||
// case 2/3 handled by Double/TripleColumnView respectively
|
||||
if (flwtch.columns.length == 1) _pushMessageView(contact.onion);
|
||||
// requery instead of using contactinfostate directly because sometimes listview gets confused about data that resorts
|
||||
Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(contact.onion)!.unreadMessages = 0;
|
||||
// triggers update in Double/TripleColumnView
|
||||
Provider.of<AppState>(context, listen: false).selectedConversation = contact.onion;
|
||||
// if in singlepane mode, push to the stack
|
||||
var isLandscape = Provider.of<AppState>(context, listen: false).isLandscape(context);
|
||||
if (Provider.of<Settings>(context, listen: false).uiColumns(isLandscape).length == 1) _pushMessageView(contact.onion);
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
void _pushMessageView(String handle) {
|
||||
Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(handle)!.unreadMessages = 0;
|
||||
var profileOnion = Provider.of<ProfileInfoState>(context, listen: false).onion;
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
|
|
|
@ -35,6 +35,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
isAccepted = Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageState>(context).inviteTarget) != null;
|
||||
var prettyDate = "";
|
||||
var borderRadiousEh = 15.0;
|
||||
var showGroupInvite = Provider.of<Settings>(context).isExperimentEnabled(TapirGroupsExperiment);
|
||||
rejected = Provider.of<MessageState>(context).flags & 0x01 == 0x01;
|
||||
var myKey = Provider.of<MessageState>(context).profileOnion + "::" + Provider.of<MessageState>(context).contactHandle + "::" + Provider.of<MessageState>(context).messageIndex.toString();
|
||||
|
||||
|
@ -66,14 +67,18 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
return MalformedBubble();
|
||||
}
|
||||
|
||||
var wdgMessage = fromMe
|
||||
var wdgMessage = isGroup && !showGroupInvite ?
|
||||
Text(AppLocalizations.of(context)!.groupInviteSettingsWarning) :
|
||||
fromMe
|
||||
? senderInviteChrome(AppLocalizations.of(context)!.sendAnInvitation,
|
||||
isGroup ? Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageState>(context).inviteTarget)!.nickname : Provider.of<MessageState>(context).message, myKey)
|
||||
: (inviteChrome(isGroup ? AppLocalizations.of(context)!.inviteToGroup : AppLocalizations.of(context)!.contactSuggestion, Provider.of<MessageState>(context).inviteNick,
|
||||
Provider.of<MessageState>(context).inviteTarget, myKey));
|
||||
|
||||
Widget wdgDecorations;
|
||||
if (fromMe) {
|
||||
if (isGroup && !showGroupInvite) {
|
||||
wdgDecorations = Text('\u202F');
|
||||
} else if (fromMe) {
|
||||
wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageState>(context).ackd, errored: Provider.of<MessageState>(context).error, fromMe: fromMe, prettyDate: prettyDate);
|
||||
} else if (isAccepted) {
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.accepted + '\u202F');
|
||||
|
@ -109,7 +114,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
child: Padding(
|
||||
padding: EdgeInsets.all(9.0),
|
||||
child: Wrap(runAlignment: WrapAlignment.spaceEvenly, alignment: WrapAlignment.spaceEvenly, runSpacing: 1.0, crossAxisAlignment: WrapCrossAlignment.center, children: [
|
||||
Center(widthFactor: 1, child: Padding(padding: EdgeInsets.all(10.0), child: Icon(CwtchIcons.send_invite, size: 32))),
|
||||
Center(widthFactor: 1, child: Padding(padding: EdgeInsets.all(10.0), child: Icon(isGroup && !showGroupInvite ? CwtchIcons.enable_experiments : CwtchIcons.send_invite, size: 32))),
|
||||
Center(
|
||||
widthFactor: 1.0,
|
||||
child: Column(
|
||||
|
|
|
@ -30,84 +30,96 @@ class _ProfileRowState extends State<ProfileRow> {
|
|||
padding: const EdgeInsets.all(2.0), //border size
|
||||
child: ProfileImage(
|
||||
badgeCount: 0,
|
||||
badgeColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor(),
|
||||
badgeTextColor: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor(),
|
||||
badgeColor: Provider
|
||||
.of<Settings>(context)
|
||||
.theme
|
||||
.portraitProfileBadgeColor(),
|
||||
badgeTextColor: Provider
|
||||
.of<Settings>(context)
|
||||
.theme
|
||||
.portraitProfileBadgeTextColor(),
|
||||
diameter: 64.0,
|
||||
imagePath: profile.imagePath,
|
||||
border: profile.isOnline ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor())),
|
||||
border: profile.isOnline ? Provider
|
||||
.of<Settings>(context)
|
||||
.theme
|
||||
.portraitOnlineBorderColor() : Provider
|
||||
.of<Settings>(context)
|
||||
.theme
|
||||
.portraitOfflineBorderColor())),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
profile.nickname,
|
||||
semanticsLabel: profile.nickname,
|
||||
style: Provider.of<FlwtchState>(context).biggerFont,
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
ExcludeSemantics(
|
||||
child: Text(
|
||||
profile.onion,
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))
|
||||
],
|
||||
)),
|
||||
children: [
|
||||
Text(
|
||||
profile.nickname,
|
||||
semanticsLabel: profile.nickname,
|
||||
style: Provider
|
||||
.of<FlwtchState>(context)
|
||||
.biggerFont,
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
ExcludeSemantics(
|
||||
child: Text(
|
||||
profile.onion,
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))
|
||||
],
|
||||
)),
|
||||
IconButton(
|
||||
enableFeedback: true,
|
||||
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);
|
||||
_pushAddEditProfile(onion: profile.onion, displayName: profile.nickname, profileImage: profile.imagePath, encrypted: profile.isEncrypted);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
var flwtch = Provider.of<FlwtchState>(context, listen: false);
|
||||
flwtch.setState(() {
|
||||
flwtch.selectedProfile = profile;
|
||||
flwtch.selectedConversation = "";
|
||||
});
|
||||
var appState = Provider.of<AppState>(context, listen: false);
|
||||
appState.selectedProfile = profile.onion;
|
||||
appState.selectedConversation = null;
|
||||
|
||||
switch (flwtch.columns.length) {
|
||||
case 1:
|
||||
_pushContactList(profile, false);
|
||||
break;
|
||||
case 2:
|
||||
_pushContactList(profile, true);
|
||||
break;
|
||||
} // case 3: handled by TripleColumnView
|
||||
_pushContactList(profile, appState.isLandscape(context));//orientation == Orientation.landscape);
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
void _pushContactList(ProfileInfoState profile, bool includeDoublePane) {
|
||||
void _pushContactList(ProfileInfoState profile, bool isLandscape) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
settings: RouteSettings(name: "conversations"),
|
||||
builder: (BuildContext buildcontext) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<ProfileInfoState>.value(value: profile),
|
||||
ChangeNotifierProvider<ContactListState>.value(value: profile.contactList),
|
||||
],
|
||||
builder: (context, widget) => includeDoublePane ? DoubleColumnView() : ContactsView(),
|
||||
);
|
||||
return OrientationBuilder(
|
||||
builder: (orientationBuilderContext, orientation) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<ProfileInfoState>.value(value: profile),
|
||||
ChangeNotifierProvider<ContactListState>.value(value: profile.contactList),
|
||||
],
|
||||
builder: (innercontext, widget) {
|
||||
var appState = Provider.of<AppState>(context);
|
||||
var settings = Provider.of<Settings>(context);
|
||||
return settings.uiColumns(appState.isLandscape(innercontext)).length > 1 ? DoubleColumnView() : ContactsView();
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _pushAddEditProfile({onion: "", displayName: "", profileImage: ""}) {
|
||||
void _pushAddEditProfile({onion: "", displayName: "", profileImage: "", encrypted: true}) {
|
||||
Navigator.of(context).push(MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<ProfileInfoState>(
|
||||
create: (_) => ProfileInfoState(onion: onion, nickname: displayName, imagePath: profileImage),
|
||||
create: (_) => ProfileInfoState(onion: onion, nickname: displayName, imagePath: profileImage, encrypted: encrypted),
|
||||
),
|
||||
],
|
||||
builder: (context, widget) => AddEditProfileView(),
|
||||
|
|
|
@ -6,10 +6,6 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <window_size/window_size_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) window_size_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin");
|
||||
window_size_plugin_register_with_registrar(window_size_registrar);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
window_size
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
|
77
pubspec.lock
77
pubspec.lock
|
@ -1,13 +1,13 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
archive:
|
||||
ansicolor:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
name: ansicolor
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
version: "2.0.1"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -42,7 +42,7 @@ packages:
|
|||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -57,13 +57,6 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -111,11 +104,6 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_driver:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
@ -131,11 +119,6 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
fuchsia_remote_debug_protocol:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
glob:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -157,13 +140,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
integration_test:
|
||||
dependency: "direct main"
|
||||
injector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: integration_test
|
||||
name: injector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2+3"
|
||||
version: "2.0.0"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -192,6 +175,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
msix:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: msix
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -213,6 +203,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
package_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -372,13 +369,6 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
sync_http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sync_http
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -392,7 +382,7 @@ packages:
|
|||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
version: "0.4.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -407,20 +397,6 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
webdriver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webdriver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -442,6 +418,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.1.2"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
sdks:
|
||||
dart: ">=2.13.0 <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
|
|
|
@ -37,13 +37,8 @@ dependencies:
|
|||
desktop_notifications: 0.5.0
|
||||
|
||||
glob: any
|
||||
# todo: flutter_driver causes version conflict. eg https://github.com/flutter/flutter/issues/44829
|
||||
# testing-related deps
|
||||
integration_test: ^1.0.0
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_driver:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
msix: ^2.1.3
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <window_size/window_size_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
WindowSizePluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("WindowSizePlugin"));
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
window_size
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
|
Loading…
Reference in New Issue