slowly massaging things into new state model
This commit is contained in:
parent
a5135365dc
commit
0fea363e4d
|
@ -21,6 +21,8 @@ import cwtch.Cwtch
|
||||||
import io.flutter.plugin.common.EventChannel
|
import io.flutter.plugin.common.EventChannel
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
class MainActivity: FlutterActivity() {
|
class MainActivity: FlutterActivity() {
|
||||||
|
|
||||||
// Channel to get app info
|
// Channel to get app info
|
||||||
|
@ -71,15 +73,14 @@ class MainActivity: FlutterActivity() {
|
||||||
Log.i("MainActivity.kt", "got event chan: " + eventbus_chan + " launching corouting...")
|
Log.i("MainActivity.kt", "got event chan: " + eventbus_chan + " launching corouting...")
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
while(true) {
|
while(true) {
|
||||||
//val jsonEvent = Cwtch.getAppBusEvent()
|
val evt = AppbusEvent(Cwtch.getAppBusEvent())
|
||||||
// Log.i("MainActivity.kt", "got appbusEvent: " + jsonEvent)
|
Log.i("MainActivity.kt", "got appbusEvent: " + evt)
|
||||||
// launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
// //eventbus_chan.invokeMethod("AppbusEvent", jsonEvent)
|
//todo: this elides evt.EventID which may be needed at some point?
|
||||||
//}
|
eventbus_chan.invokeMethod(evt.EventType, evt.Data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
"SelectProfile" -> {
|
"SelectProfile" -> {
|
||||||
val onion = (call.argument("profile") as? String) ?: "";
|
val onion = (call.argument("profile") as? String) ?: "";
|
||||||
|
@ -129,4 +130,24 @@ class MainActivity: FlutterActivity() {
|
||||||
else -> result.notImplemented()
|
else -> result.notImplemented()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// source: https://web.archive.org/web/20210203022531/https://stackoverflow.com/questions/41928803/how-to-parse-json-in-kotlin/50468095
|
||||||
|
// for reference:
|
||||||
|
//
|
||||||
|
// class Response(json: String) : JSONObject(json) {
|
||||||
|
// val type: String? = this.optString("type")
|
||||||
|
// val data = this.optJSONArray("data")
|
||||||
|
// ?.let { 0.until(it.length()).map { i -> it.optJSONObject(i) } } // returns an array of JSONObject
|
||||||
|
// ?.map { Foo(it.toString()) } // transforms each JSONObject of the array into Foo
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// class Foo(json: String) : JSONObject(json) {
|
||||||
|
// val id = this.optInt("id")
|
||||||
|
// val title: String? = this.optString("title")
|
||||||
|
// }
|
||||||
|
class AppbusEvent(json: String) : JSONObject(json) {
|
||||||
|
val EventType = this.optString("EventType")
|
||||||
|
val EventID = this.optString("EventID")
|
||||||
|
val Data = this.optString("Data")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -1,9 +1,12 @@
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_app/model.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'cwtch.dart';
|
import 'cwtch.dart';
|
||||||
|
|
||||||
|
@ -26,14 +29,16 @@ class CwtchGomobile implements Cwtch {
|
||||||
|
|
||||||
Future<String> androidLibraryDir;
|
Future<String> androidLibraryDir;
|
||||||
Future<Directory> androidHomeDirectory;
|
Future<Directory> androidHomeDirectory;
|
||||||
|
ProfileListState profileCN;
|
||||||
|
|
||||||
CwtchGomobile() {
|
CwtchGomobile(ProfileListState profs) {
|
||||||
print("gomobile.dart: CwtchGomobile()");
|
print("gomobile.dart: CwtchGomobile()");
|
||||||
|
profileCN = profs;
|
||||||
androidHomeDirectory = getApplicationDocumentsDirectory();
|
androidHomeDirectory = getApplicationDocumentsDirectory();
|
||||||
androidLibraryDir = appInfoPlatform.invokeMethod('getNativeLibDir');
|
androidLibraryDir = appInfoPlatform.invokeMethod('getNativeLibDir');
|
||||||
|
|
||||||
// final appbusEventChannel = MethodChannel(appbusEventChannelName);
|
final appbusEventChannel = MethodChannel(appbusEventChannelName);
|
||||||
// appbusEventChannel.setMethodCallHandler(this._handleAppbusEvent);
|
appbusEventChannel.setMethodCallHandler(this._handleAppbusEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> Start() async {
|
Future<void> Start() async {
|
||||||
|
@ -46,7 +51,13 @@ class CwtchGomobile implements Cwtch {
|
||||||
|
|
||||||
Future<void> _handleAppbusEvent(MethodCall call) async {
|
Future<void> _handleAppbusEvent(MethodCall call) async {
|
||||||
final String json = call.arguments;
|
final String json = call.arguments;
|
||||||
print("appbus event: ${call.method} $json");
|
var obj = jsonDecode(json);
|
||||||
|
switch (call.method) {
|
||||||
|
case "NewPeer":
|
||||||
|
profileCN.add(ProfileInfoState(onion: obj["Identity"], nickname: obj["ProfileName"], imagePath: obj["Path"]));
|
||||||
|
break;
|
||||||
|
default: print("unhandled gomobile appbus event: $call");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectProfile(String onion) {
|
void SelectProfile(String onion) {
|
||||||
|
|
106
lib/main.dart
106
lib/main.dart
|
@ -1,6 +1,4 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter_app/cwtch/ffi.dart';
|
import 'package:flutter_app/cwtch/ffi.dart';
|
||||||
import 'package:flutter_app/cwtch/gomobile.dart';
|
import 'package:flutter_app/cwtch/gomobile.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -24,112 +22,70 @@ class Flwtch extends StatefulWidget {
|
||||||
|
|
||||||
class FlwtchState extends State<Flwtch> {
|
class FlwtchState extends State<Flwtch> {
|
||||||
final TextStyle biggerFont = const TextStyle(fontSize: 18);
|
final TextStyle biggerFont = const TextStyle(fontSize: 18);
|
||||||
|
|
||||||
// mergenotes: dan's
|
|
||||||
Cwtch cwtch;
|
Cwtch cwtch;
|
||||||
bool cwtchInit = false;
|
bool cwtchInit = false;
|
||||||
|
ProfileInfoState selectedProfile;
|
||||||
// mergenotes: ui stuff
|
|
||||||
ProfileModel selectedProfile;
|
|
||||||
String selectedConversation = "";
|
String selectedConversation = "";
|
||||||
var columns = [1]; // default or 'single column' mode
|
var columns = [1]; // default or 'single column' mode
|
||||||
//var columns = [1, 1, 2];
|
//var columns = [1, 1, 2];
|
||||||
|
|
||||||
AppModel appStatus;
|
AppModel appStatus;
|
||||||
HashMap<String, ProfileModel> profiles;
|
ProfileListState profs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
initState() {
|
initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
cwtchInit = false;
|
cwtchInit = false;
|
||||||
|
profs = ProfileListState();
|
||||||
profiles = new HashMap<String, ProfileModel>();
|
|
||||||
|
|
||||||
print("FlwtchState.initState()");
|
|
||||||
|
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
cwtch = CwtchGomobile();
|
cwtch = CwtchGomobile(profs);
|
||||||
} else {
|
} else {
|
||||||
cwtch = CwtchFfi();
|
cwtch = CwtchFfi();
|
||||||
}
|
}
|
||||||
|
|
||||||
cwtch.Start().then((val) {
|
cwtch.Start().then((val) {
|
||||||
setState(() {
|
setState(() {
|
||||||
cwtchInit = true;
|
cwtchInit = true;
|
||||||
loadProfiles();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
appStatus = AppModel(cwtch: cwtch);
|
appStatus = AppModel(cwtch: cwtch);
|
||||||
// Timing issue? Start may not have inited cwtch yet when we ask for getProfiles...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadProfiles() {
|
ChangeNotifierProvider<OpaqueTheme> getOpaqueProvider() => ChangeNotifierProvider(create: (context) => OpaqueTheme(Opaque.dark));
|
||||||
cwtch.GetProfiles().then((profilesJson) {
|
Provider<FlwtchState> getFlwtchStateProvider() => Provider<FlwtchState>(create: (_) => this);
|
||||||
setState(() {
|
ChangeNotifierProvider<ProfileListState> getProfileListProvider() => ChangeNotifierProvider(create: (context) => profs);
|
||||||
jsonDecode(profilesJson).forEach((profile) {
|
|
||||||
ProfileModel profile1 = new ProfileModel();
|
|
||||||
profile1.onion = profile['onion'];
|
|
||||||
profile1.nickname = profile['name'];
|
|
||||||
profile1.creationDate = "4 jan 2020";
|
|
||||||
profile1.contacts = new HashMap<String, ContactModel>();
|
|
||||||
profile1.imagePath = profile['imagePath'];
|
|
||||||
|
|
||||||
profiles.putIfAbsent(profile1.onion, () => profile1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ChangeNotifierProvider<OpaqueTheme> getOpaqueProvider() {
|
|
||||||
return ChangeNotifierProvider(create: (context) => OpaqueTheme(Opaque.dark));
|
|
||||||
}
|
|
||||||
|
|
||||||
Provider<FlwtchState> getFlwtchStateProvider() {
|
|
||||||
return Provider<FlwtchState>(
|
|
||||||
create: (_) => this,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
appStatus = AppModel(cwtch: cwtch);
|
appStatus = AppModel(cwtch: cwtch);
|
||||||
|
|
||||||
final newTextTheme = Theme.of(context).textTheme.apply(
|
final newTextTheme = Theme.of(context).textTheme.apply(
|
||||||
bodyColor: Opaque.current().mainTextColor(),
|
bodyColor: Opaque.current().mainTextColor(),
|
||||||
displayColor: Opaque.current().mainTextColor(),
|
displayColor: Opaque.current().mainTextColor(),
|
||||||
);
|
);
|
||||||
|
|
||||||
print("FlwtchState.build() cwtchInit: $cwtchInit");
|
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [getFlwtchStateProvider(), getOpaqueProvider()],
|
providers: [getFlwtchStateProvider(), getProfileListProvider(), getOpaqueProvider()],
|
||||||
builder: (context, widget) {
|
builder: (context, widget) {
|
||||||
return MaterialApp(
|
return Consumer<OpaqueTheme>(
|
||||||
title: 'Cwtch',
|
builder: (context, opaque, child) => MaterialApp(
|
||||||
theme: ThemeData(
|
title: 'Cwtch',
|
||||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
theme: ThemeData(
|
||||||
primarySwatch: Colors.red,
|
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||||
primaryColor: Provider.of<OpaqueTheme>(context)
|
primarySwatch: Colors.red,
|
||||||
.current()
|
primaryColor: opaque.current().backgroundMainColor(),
|
||||||
.backgroundMainColor(),
|
canvasColor: opaque.current().backgroundPaneColor(),
|
||||||
canvasColor: Provider.of<OpaqueTheme>(context)
|
accentColor: opaque.current().defaultButtonColor(),
|
||||||
.current()
|
buttonColor: opaque.current().defaultButtonColor(),
|
||||||
.backgroundPaneColor(),
|
textTheme: newTextTheme,
|
||||||
accentColor: Provider.of<OpaqueTheme>(context)
|
),
|
||||||
.current()
|
// from dan: home: cwtchInit == true ? ProfileMgrView(cwtch) : SplashView(),
|
||||||
.defaultButtonColor(),
|
// from erinn: home: columns.length == 3 ? TripleColumnView() : ProfileMgrView(),
|
||||||
buttonColor: Provider.of<OpaqueTheme>(context)
|
home: cwtchInit == true ? (columns.length == 3 ? TripleColumnView() : ProfileMgrView()) : SplashView(),
|
||||||
.current()
|
),
|
||||||
.defaultButtonColor(),
|
);
|
||||||
textTheme: newTextTheme,
|
},
|
||||||
),
|
|
||||||
// from dan: home: cwtchInit == true ? ProfileMgrView(cwtch) : SplashView(),
|
|
||||||
// from erinn: home: columns.length == 3 ? TripleColumnView() : ProfileMgrView(),
|
|
||||||
home: cwtchInit == true
|
|
||||||
? (columns.length == 3
|
|
||||||
? TripleColumnView()
|
|
||||||
: ProfileMgrView())
|
|
||||||
: SplashView(),
|
|
||||||
);},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
114
lib/model.dart
114
lib/model.dart
|
@ -1,10 +1,12 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'cwtch/cwtch.dart';
|
import 'cwtch/cwtch.dart';
|
||||||
|
import 'main.dart';
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
/// UI State ///
|
/// UI State ///
|
||||||
|
@ -53,6 +55,116 @@ class ChatMessage {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
/// Providers ///
|
||||||
|
///////////////////
|
||||||
|
|
||||||
|
class ProfileListState extends ChangeNotifier {
|
||||||
|
List<ProfileInfoState> _onions = [];
|
||||||
|
int get num => _onions.length;
|
||||||
|
|
||||||
|
void addAll(Iterable<ProfileInfoState> newOnions) {
|
||||||
|
_onions.addAll(newOnions);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(ProfileInfoState newOnion) {
|
||||||
|
print("ProfileListState: adding " + newOnion.onion +" and notifying");
|
||||||
|
_onions.add(newOnion);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ProfileInfoState> get onions => _onions.sublist(0);//todo: copy?? dont want caller able to bypass changenotifier
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContactListState extends ChangeNotifier {
|
||||||
|
List<ContactInfoState> _onions = [];
|
||||||
|
int get num => _onions.length;
|
||||||
|
|
||||||
|
void addAll(Iterable<ContactInfoState> newOnions) {
|
||||||
|
_onions.addAll(newOnions);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(ContactInfoState newOnion) {
|
||||||
|
_onions.add(newOnion);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateUnreadMessages(String forOnion, int newVal) {
|
||||||
|
_onions.sort((ContactInfoState a, ContactInfoState b) { return b.unreadMessages - a.unreadMessages; });
|
||||||
|
//<todo> if(changed) {
|
||||||
|
notifyListeners();
|
||||||
|
//} </todo>
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ContactInfoState> get onions => _onions.sublist(0);//todo: copy?? dont want caller able to bypass changenotifier
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfileInfoState extends ChangeNotifier {
|
||||||
|
final String onion;
|
||||||
|
String _nickname = "";
|
||||||
|
String _imagePath = "";
|
||||||
|
int _unreadMessages = 0;
|
||||||
|
|
||||||
|
ProfileInfoState({this.onion, nickname = "", imagePath = "", unreadMessages = 0,}){
|
||||||
|
this._nickname = nickname;
|
||||||
|
this._imagePath = imagePath;
|
||||||
|
this._unreadMessages = unreadMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
String get nickname => this._nickname;
|
||||||
|
set nickname(String newValue) {
|
||||||
|
this.nickname = newValue;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
String get imagePath => this._imagePath;
|
||||||
|
set imagePath(String newVal) {
|
||||||
|
this._imagePath = newVal;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get unreadMessages => this._unreadMessages;
|
||||||
|
set unreadMessages(int newVal) {
|
||||||
|
this._unreadMessages = newVal;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContactInfoState extends ChangeNotifier {
|
||||||
|
final String profileOnion;
|
||||||
|
final String onion;
|
||||||
|
String _nickname;
|
||||||
|
bool _isGroup;
|
||||||
|
bool _isInvitation;
|
||||||
|
bool _isBlocked;
|
||||||
|
String _status;
|
||||||
|
String _imagePath;
|
||||||
|
int _unreadMessages = 0;
|
||||||
|
|
||||||
|
ContactInfoState({this.profileOnion, this.onion, nickname = "", isGroup = false, isInvitation = false, isBlocked = false, status = "", imagePath = "",}) {
|
||||||
|
this._nickname = nickname;
|
||||||
|
this._isGroup = isGroup;
|
||||||
|
this._isInvitation = isInvitation;
|
||||||
|
this._isBlocked = isBlocked;
|
||||||
|
this._status = status;
|
||||||
|
this._imagePath = imagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
get nickname => this._nickname;
|
||||||
|
set nickname(String newVal) {
|
||||||
|
this._nickname = newVal;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
get unreadMessages => this._unreadMessages;
|
||||||
|
set unreadMessages(int newVal) {
|
||||||
|
this._unreadMessages = newVal;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
/// ACN ///
|
/// ACN ///
|
||||||
/////////////
|
/////////////
|
||||||
|
@ -70,6 +182,7 @@ class AppModel {
|
||||||
print(event);
|
print(event);
|
||||||
yield event;
|
yield event;
|
||||||
} else {
|
} else {
|
||||||
|
print("TEST TEST FAIL TEST FAIL 123");
|
||||||
await Future.delayed(Duration(seconds: 1));
|
await Future.delayed(Duration(seconds: 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,6 +194,7 @@ class AppModel {
|
||||||
if (event != "") {
|
if (event != "") {
|
||||||
yield event;
|
yield event;
|
||||||
} else {
|
} else {
|
||||||
|
print("TOR TEST TEST FAIL TEST FAIL 123");
|
||||||
await Future.delayed(Duration(seconds: 1));
|
await Future.delayed(Duration(seconds: 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import '../model.dart';
|
||||||
|
|
||||||
class ContactsView extends StatefulWidget {
|
class ContactsView extends StatefulWidget {
|
||||||
const ContactsView({Key key, this.profile}) : super(key: key);
|
const ContactsView({Key key, this.profile}) : super(key: key);
|
||||||
final ProfileModel profile;
|
final ProfileInfoState profile;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ContactsViewState createState() => _ContactsViewState();
|
_ContactsViewState createState() => _ContactsViewState();
|
||||||
|
|
|
@ -12,7 +12,7 @@ import '../widgets/messagelist.dart';
|
||||||
|
|
||||||
class MessageView extends StatefulWidget {
|
class MessageView extends StatefulWidget {
|
||||||
const MessageView({Key key, this.profile, this.conversationHandle}) : super(key: key);
|
const MessageView({Key key, this.profile, this.conversationHandle}) : super(key: key);
|
||||||
final ProfileModel profile;
|
final ProfileInfoState profile;
|
||||||
final String conversationHandle;
|
final String conversationHandle;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_app/widgets/profilerow.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../main.dart';
|
import '../main.dart';
|
||||||
import '../model.dart';
|
import '../model.dart';
|
||||||
import 'dart:collection';
|
|
||||||
import '../opaque.dart';
|
|
||||||
import 'addeditprofileview.dart';
|
import 'addeditprofileview.dart';
|
||||||
import 'contactsview.dart';
|
|
||||||
import 'doublecolview.dart';
|
|
||||||
import 'globalsettingsview.dart';
|
import 'globalsettingsview.dart';
|
||||||
|
|
||||||
class ProfileMgrView extends StatefulWidget {
|
class ProfileMgrView extends StatefulWidget {
|
||||||
|
@ -29,7 +24,6 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return Scaffold (
|
return Scaffold (
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Profiles'),
|
title: Text('Profiles'),
|
||||||
|
@ -47,19 +41,6 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pushContactList(ProfileModel profile, bool includeDoublePane) {
|
|
||||||
Navigator.of(context).push(
|
|
||||||
MaterialPageRoute<void>(
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return Provider(
|
|
||||||
create: (_) => Provider.of<FlwtchState>(context),
|
|
||||||
child: includeDoublePane ? DoubleColumnView() : ContactsView(profile:profile),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _pushGlobalSettings() {
|
void _pushGlobalSettings() {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute<void>(
|
MaterialPageRoute<void>(
|
||||||
|
@ -75,14 +56,14 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
|
|
||||||
void _pushAddEditProfile({onion: ""}) {
|
void _pushAddEditProfile({onion: ""}) {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute<void>(
|
MaterialPageRoute<void>(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return Provider (
|
return Provider (
|
||||||
create: (_) => Provider.of<FlwtchState>(context, listen: false),
|
create: (_) => Provider.of<FlwtchState>(context, listen: false),
|
||||||
child: AddEditProfileView(profileOnion: onion),
|
child: AddEditProfileView(profileOnion: onion),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,12 +91,7 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
child: const Text('Unlock'),
|
child: const Text('Unlock'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Provider
|
Provider.of<FlwtchState>(context, listen: false).cwtch.LoadProfiles(ctrlrPassword.value.text);
|
||||||
.of<FlwtchState>(context, listen: false)
|
|
||||||
.cwtch
|
|
||||||
.LoadProfiles(ctrlrPassword.value.text);
|
|
||||||
Provider.of<FlwtchState>(context, listen: false)
|
|
||||||
.loadProfiles();
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -126,42 +102,12 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
String getNick(String profile, String contact) {
|
|
||||||
return contact == profile ? "me" : Provider.of<FlwtchState>(context).profiles[profile].contacts[contact].nickname;
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildProfileManager() {
|
Widget _buildProfileManager() {
|
||||||
final tiles = Provider.of<FlwtchState>(context).profiles.values.map(
|
final tiles = Provider.of<ProfileListState>(context).onions.map(
|
||||||
(ProfileModel profile) {
|
(ProfileInfoState profile) {
|
||||||
return ListTile(
|
return ChangeNotifierProvider<ProfileInfoState>(
|
||||||
leading: SizedBox(
|
create: (context) => profile,
|
||||||
width: 60,
|
builder: (context, child) => ProfileRow(profile),
|
||||||
height: 60,
|
|
||||||
child: ClipOval(
|
|
||||||
child: SizedBox(width:60, height:60, child:Container(color:Colors.white, width: 60, height: 60, child: Image(image: AssetImage("assets/" + profile.imagePath), width:50,height:50,))),
|
|
||||||
),
|
|
||||||
) ,
|
|
||||||
trailing: IconButton(icon: Icon(Icons.create, color: Opaque.current().mainTextColor()), onPressed: () { _pushAddEditProfile(onion: profile.onion); }),//(nb: Icons.create is a pencil and we use it for "edit", not create)
|
|
||||||
title: Text(
|
|
||||||
profile.nickname,
|
|
||||||
style: Provider.of<FlwtchState>(context).biggerFont,
|
|
||||||
),
|
|
||||||
subtitle: Text(profile.onion),
|
|
||||||
onTap: () {
|
|
||||||
setState(() {
|
|
||||||
var flwtch = Provider.of<FlwtchState>(context, listen:false);
|
|
||||||
flwtch.cwtch.SelectProfile(profile.onion);
|
|
||||||
flwtch.setState(() {
|
|
||||||
flwtch.selectedProfile = profile;
|
|
||||||
flwtch.selectedConversation = "";
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (flwtch.columns.length) {
|
|
||||||
case 1: _pushContactList(profile, false); break;
|
|
||||||
case 2: _pushContactList(profile, true); break;
|
|
||||||
} // case 3: handled by TripleColumnView
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -173,5 +119,4 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
|
|
||||||
return ListView(children: divided);
|
return ListView(children: divided);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import '../opaque.dart';
|
||||||
|
|
||||||
class MessageBubble extends StatefulWidget {
|
class MessageBubble extends StatefulWidget {
|
||||||
MessageBubble({Key key, this.profile, this.contactOnion, this.messageIndex});
|
MessageBubble({Key key, this.profile, this.contactOnion, this.messageIndex});
|
||||||
final ProfileModel profile;
|
final ProfileInfoState profile;
|
||||||
final String contactOnion;
|
final String contactOnion;
|
||||||
final int messageIndex;
|
final int messageIndex;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import '../model.dart';
|
||||||
import 'messagebubble.dart';
|
import 'messagebubble.dart';
|
||||||
|
|
||||||
class MessageList extends StatefulWidget {
|
class MessageList extends StatefulWidget {
|
||||||
final ProfileModel profile;
|
final ProfileInfoState profile;
|
||||||
final String conversationHandle;
|
final String conversationHandle;
|
||||||
|
|
||||||
const MessageList({Key key, this.profile, this.conversationHandle}) : super(key: key);
|
const MessageList({Key key, this.profile, this.conversationHandle}) : super(key: key);
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_app/views/addeditprofileview.dart';
|
||||||
|
import 'package:flutter_app/views/contactsview.dart';
|
||||||
|
import 'package:flutter_app/views/doublecolview.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../main.dart';
|
||||||
|
import '../model.dart';
|
||||||
|
import '../opaque.dart';
|
||||||
|
|
||||||
|
class ProfileRow extends StatefulWidget {
|
||||||
|
final ProfileInfoState profile;
|
||||||
|
ProfileRow(this.profile);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ProfileRowState createState() => _ProfileRowState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProfileRowState extends State<ProfileRow> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
leading: SizedBox(
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
child: ClipOval(
|
||||||
|
child: SizedBox(width:60, height:60, child:Container(color:Colors.white, width: 60, height: 60, child: Image(image: AssetImage("assets/" + widget.profile.imagePath), width:50,height:50,))),
|
||||||
|
),
|
||||||
|
) ,
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: Icon(Icons.create, color: Provider.of<OpaqueTheme>(context).current().mainTextColor()),
|
||||||
|
onPressed: () { _pushAddEditProfile(onion: widget.profile.onion); },
|
||||||
|
),//(nb: Icons.create is a pencil and we use it for "edit", not create)
|
||||||
|
title: Text(
|
||||||
|
widget.profile.nickname,
|
||||||
|
style: Provider.of<FlwtchState>(context).biggerFont,
|
||||||
|
),
|
||||||
|
subtitle: Text(widget.profile.onion),
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
var flwtch = Provider.of<FlwtchState>(context, listen:false);
|
||||||
|
flwtch.cwtch.SelectProfile(widget.profile.onion);
|
||||||
|
flwtch.setState(() {
|
||||||
|
flwtch.selectedProfile = widget.profile;
|
||||||
|
flwtch.selectedConversation = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (flwtch.columns.length) {
|
||||||
|
case 1: _pushContactList(widget.profile, false); break;
|
||||||
|
case 2: _pushContactList(widget.profile, true); break;
|
||||||
|
} // case 3: handled by TripleColumnView
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pushContactList(ProfileInfoState profile, bool includeDoublePane) {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute<void>(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Provider(
|
||||||
|
create: (_) => Provider.of<FlwtchState>(context),
|
||||||
|
child: includeDoublePane ? DoubleColumnView() : ContactsView(profile:profile),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pushAddEditProfile({onion: ""}) {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute<void>(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Provider (
|
||||||
|
create: (_) => Provider.of<FlwtchState>(context, listen: false),
|
||||||
|
child: AddEditProfileView(profileOnion: onion),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ import 'package:flutter_app/main.dart';
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||||
// Build our app and trigger a frame.
|
// Build our app and trigger a frame.
|
||||||
await tester.pumpWidget(MyApp());
|
await tester.pumpWidget(Flwtch());
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
// Verify that our counter starts at 0.
|
||||||
expect(find.text('0'), findsOneWidget);
|
expect(find.text('0'), findsOneWidget);
|
||||||
|
|
Loading…
Reference in New Issue