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 kotlin.concurrent.thread
|
||||
|
||||
import org.json.JSONObject
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
|
||||
// Channel to get app info
|
||||
|
@ -71,15 +73,14 @@ class MainActivity: FlutterActivity() {
|
|||
Log.i("MainActivity.kt", "got event chan: " + eventbus_chan + " launching corouting...")
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
while(true) {
|
||||
//val jsonEvent = Cwtch.getAppBusEvent()
|
||||
// Log.i("MainActivity.kt", "got appbusEvent: " + jsonEvent)
|
||||
// launch(Dispatchers.Main) {
|
||||
// //eventbus_chan.invokeMethod("AppbusEvent", jsonEvent)
|
||||
//}
|
||||
val evt = AppbusEvent(Cwtch.getAppBusEvent())
|
||||
Log.i("MainActivity.kt", "got appbusEvent: " + evt)
|
||||
launch(Dispatchers.Main) {
|
||||
//todo: this elides evt.EventID which may be needed at some point?
|
||||
eventbus_chan.invokeMethod(evt.EventType, evt.Data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
"SelectProfile" -> {
|
||||
val onion = (call.argument("profile") as? String) ?: "";
|
||||
|
@ -129,4 +130,24 @@ class MainActivity: FlutterActivity() {
|
|||
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 'package:flutter/services.dart';
|
||||
import 'package:flutter_app/model.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'dart:async';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'cwtch.dart';
|
||||
|
||||
|
@ -26,14 +29,16 @@ class CwtchGomobile implements Cwtch {
|
|||
|
||||
Future<String> androidLibraryDir;
|
||||
Future<Directory> androidHomeDirectory;
|
||||
ProfileListState profileCN;
|
||||
|
||||
CwtchGomobile() {
|
||||
CwtchGomobile(ProfileListState profs) {
|
||||
print("gomobile.dart: CwtchGomobile()");
|
||||
profileCN = profs;
|
||||
androidHomeDirectory = getApplicationDocumentsDirectory();
|
||||
androidLibraryDir = appInfoPlatform.invokeMethod('getNativeLibDir');
|
||||
|
||||
// final appbusEventChannel = MethodChannel(appbusEventChannelName);
|
||||
// appbusEventChannel.setMethodCallHandler(this._handleAppbusEvent);
|
||||
final appbusEventChannel = MethodChannel(appbusEventChannelName);
|
||||
appbusEventChannel.setMethodCallHandler(this._handleAppbusEvent);
|
||||
}
|
||||
|
||||
Future<void> Start() async {
|
||||
|
@ -46,7 +51,13 @@ class CwtchGomobile implements Cwtch {
|
|||
|
||||
Future<void> _handleAppbusEvent(MethodCall call) async {
|
||||
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) {
|
||||
|
|
106
lib/main.dart
106
lib/main.dart
|
@ -1,6 +1,4 @@
|
|||
import 'dart:collection';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_app/cwtch/ffi.dart';
|
||||
import 'package:flutter_app/cwtch/gomobile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -24,112 +22,70 @@ class Flwtch extends StatefulWidget {
|
|||
|
||||
class FlwtchState extends State<Flwtch> {
|
||||
final TextStyle biggerFont = const TextStyle(fontSize: 18);
|
||||
|
||||
// mergenotes: dan's
|
||||
Cwtch cwtch;
|
||||
bool cwtchInit = false;
|
||||
|
||||
// mergenotes: ui stuff
|
||||
ProfileModel selectedProfile;
|
||||
ProfileInfoState selectedProfile;
|
||||
String selectedConversation = "";
|
||||
var columns = [1]; // default or 'single column' mode
|
||||
//var columns = [1, 1, 2];
|
||||
|
||||
AppModel appStatus;
|
||||
HashMap<String, ProfileModel> profiles;
|
||||
ProfileListState profs;
|
||||
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
cwtchInit = false;
|
||||
|
||||
profiles = new HashMap<String, ProfileModel>();
|
||||
|
||||
print("FlwtchState.initState()");
|
||||
profs = ProfileListState();
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
cwtch = CwtchGomobile();
|
||||
cwtch = CwtchGomobile(profs);
|
||||
} else {
|
||||
cwtch = CwtchFfi();
|
||||
}
|
||||
|
||||
cwtch.Start().then((val) {
|
||||
setState(() {
|
||||
cwtchInit = true;
|
||||
loadProfiles();
|
||||
});
|
||||
});
|
||||
|
||||
appStatus = AppModel(cwtch: cwtch);
|
||||
// Timing issue? Start may not have inited cwtch yet when we ask for getProfiles...
|
||||
}
|
||||
|
||||
void loadProfiles() {
|
||||
cwtch.GetProfiles().then((profilesJson) {
|
||||
setState(() {
|
||||
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,
|
||||
);
|
||||
}
|
||||
ChangeNotifierProvider<OpaqueTheme> getOpaqueProvider() => ChangeNotifierProvider(create: (context) => OpaqueTheme(Opaque.dark));
|
||||
Provider<FlwtchState> getFlwtchStateProvider() => Provider<FlwtchState>(create: (_) => this);
|
||||
ChangeNotifierProvider<ProfileListState> getProfileListProvider() => ChangeNotifierProvider(create: (context) => profs);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
appStatus = AppModel(cwtch: cwtch);
|
||||
|
||||
final newTextTheme = Theme.of(context).textTheme.apply(
|
||||
bodyColor: Opaque.current().mainTextColor(),
|
||||
displayColor: Opaque.current().mainTextColor(),
|
||||
);
|
||||
bodyColor: Opaque.current().mainTextColor(),
|
||||
displayColor: Opaque.current().mainTextColor(),
|
||||
);
|
||||
|
||||
print("FlwtchState.build() cwtchInit: $cwtchInit");
|
||||
return MultiProvider(
|
||||
providers: [getFlwtchStateProvider(), getOpaqueProvider()],
|
||||
builder: (context, widget) {
|
||||
return MaterialApp(
|
||||
title: 'Cwtch',
|
||||
theme: ThemeData(
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
primarySwatch: Colors.red,
|
||||
primaryColor: Provider.of<OpaqueTheme>(context)
|
||||
.current()
|
||||
.backgroundMainColor(),
|
||||
canvasColor: Provider.of<OpaqueTheme>(context)
|
||||
.current()
|
||||
.backgroundPaneColor(),
|
||||
accentColor: Provider.of<OpaqueTheme>(context)
|
||||
.current()
|
||||
.defaultButtonColor(),
|
||||
buttonColor: Provider.of<OpaqueTheme>(context)
|
||||
.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(),
|
||||
);},
|
||||
providers: [getFlwtchStateProvider(), getProfileListProvider(), getOpaqueProvider()],
|
||||
builder: (context, widget) {
|
||||
return Consumer<OpaqueTheme>(
|
||||
builder: (context, opaque, child) => MaterialApp(
|
||||
title: 'Cwtch',
|
||||
theme: ThemeData(
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
primarySwatch: Colors.red,
|
||||
primaryColor: opaque.current().backgroundMainColor(),
|
||||
canvasColor: opaque.current().backgroundPaneColor(),
|
||||
accentColor: opaque.current().defaultButtonColor(),
|
||||
buttonColor: opaque.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:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'cwtch/cwtch.dart';
|
||||
import 'main.dart';
|
||||
|
||||
////////////////////
|
||||
/// 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 ///
|
||||
/////////////
|
||||
|
@ -70,6 +182,7 @@ class AppModel {
|
|||
print(event);
|
||||
yield event;
|
||||
} else {
|
||||
print("TEST TEST FAIL TEST FAIL 123");
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +194,7 @@ class AppModel {
|
|||
if (event != "") {
|
||||
yield event;
|
||||
} else {
|
||||
print("TOR TEST TEST FAIL TEST FAIL 123");
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import '../model.dart';
|
|||
|
||||
class ContactsView extends StatefulWidget {
|
||||
const ContactsView({Key key, this.profile}) : super(key: key);
|
||||
final ProfileModel profile;
|
||||
final ProfileInfoState profile;
|
||||
|
||||
@override
|
||||
_ContactsViewState createState() => _ContactsViewState();
|
||||
|
|
|
@ -12,7 +12,7 @@ import '../widgets/messagelist.dart';
|
|||
|
||||
class MessageView extends StatefulWidget {
|
||||
const MessageView({Key key, this.profile, this.conversationHandle}) : super(key: key);
|
||||
final ProfileModel profile;
|
||||
final ProfileInfoState profile;
|
||||
final String conversationHandle;
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/widgets/profilerow.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../main.dart';
|
||||
import '../model.dart';
|
||||
import 'dart:collection';
|
||||
import '../opaque.dart';
|
||||
import 'addeditprofileview.dart';
|
||||
import 'contactsview.dart';
|
||||
import 'doublecolview.dart';
|
||||
import 'globalsettingsview.dart';
|
||||
|
||||
class ProfileMgrView extends StatefulWidget {
|
||||
|
@ -29,7 +24,6 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold (
|
||||
appBar: AppBar(
|
||||
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() {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
|
@ -75,14 +56,14 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
|||
|
||||
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),
|
||||
);
|
||||
},
|
||||
)
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) {
|
||||
return Provider (
|
||||
create: (_) => Provider.of<FlwtchState>(context, listen: false),
|
||||
child: AddEditProfileView(profileOnion: onion),
|
||||
);
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -110,12 +91,7 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
|||
ElevatedButton(
|
||||
child: const Text('Unlock'),
|
||||
onPressed: () {
|
||||
Provider
|
||||
.of<FlwtchState>(context, listen: false)
|
||||
.cwtch
|
||||
.LoadProfiles(ctrlrPassword.value.text);
|
||||
Provider.of<FlwtchState>(context, listen: false)
|
||||
.loadProfiles();
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.LoadProfiles(ctrlrPassword.value.text);
|
||||
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() {
|
||||
final tiles = Provider.of<FlwtchState>(context).profiles.values.map(
|
||||
(ProfileModel profile) {
|
||||
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/" + 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
|
||||
});
|
||||
},
|
||||
final tiles = Provider.of<ProfileListState>(context).onions.map(
|
||||
(ProfileInfoState profile) {
|
||||
return ChangeNotifierProvider<ProfileInfoState>(
|
||||
create: (context) => profile,
|
||||
builder: (context, child) => ProfileRow(profile),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -173,5 +119,4 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
|||
|
||||
return ListView(children: divided);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,7 @@ import '../opaque.dart';
|
|||
|
||||
class MessageBubble extends StatefulWidget {
|
||||
MessageBubble({Key key, this.profile, this.contactOnion, this.messageIndex});
|
||||
final ProfileModel profile;
|
||||
final ProfileInfoState profile;
|
||||
final String contactOnion;
|
||||
final int messageIndex;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import '../model.dart';
|
|||
import 'messagebubble.dart';
|
||||
|
||||
class MessageList extends StatefulWidget {
|
||||
final ProfileModel profile;
|
||||
final ProfileInfoState profile;
|
||||
final String conversationHandle;
|
||||
|
||||
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() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(MyApp());
|
||||
await tester.pumpWidget(Flwtch());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
|
|
Loading…
Reference in New Issue