Replace ListTile with Custom Card/Inkwell + New ProfileImage
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
parent
3dbfd9deb9
commit
e356254ff8
|
@ -20,12 +20,7 @@ class CwtchNotifier {
|
||||||
void handleMessage(String type, dynamic data) {
|
void handleMessage(String type, dynamic data) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "NewPeer":
|
case "NewPeer":
|
||||||
profileCN.add(ProfileInfoState(
|
profileCN.add(ProfileInfoState(onion: data["Identity"], nickname: data["name"], imagePath: data["picture"], contactsJson: data["ContactsJson"], online: data["Online"] == "true"));
|
||||||
onion: data["Identity"],
|
|
||||||
nickname: data["name"],
|
|
||||||
imagePath: data["picture"],
|
|
||||||
contactsJson: data["ContactsJson"],
|
|
||||||
));
|
|
||||||
break;
|
break;
|
||||||
case "PeerCreated":
|
case "PeerCreated":
|
||||||
profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState(
|
profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState(
|
||||||
|
@ -64,6 +59,17 @@ class CwtchNotifier {
|
||||||
case "UpdateGlobalSettings":
|
case "UpdateGlobalSettings":
|
||||||
settings.handleUpdate(jsonDecode(data["Data"]));
|
settings.handleUpdate(jsonDecode(data["Data"]));
|
||||||
break;
|
break;
|
||||||
|
case "SetAttribute":
|
||||||
|
if (data["Key"] == "public.name") {
|
||||||
|
profileCN.getProfile(data["ProfileOnion"]).nickname = data["Data"];
|
||||||
|
} else {
|
||||||
|
print("unhandled set attribute event: $type");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "NetworkError":
|
||||||
|
var isOnline = data["Status"] == "Success";
|
||||||
|
profileCN.getProfile(data["ProfileOnion"]).isOnline = isOnline;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
print("unhandled event: $type");
|
print("unhandled event: $type");
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@ class ProfileInfoState extends ChangeNotifier {
|
||||||
String _nickname = "";
|
String _nickname = "";
|
||||||
String _imagePath = "";
|
String _imagePath = "";
|
||||||
int _unreadMessages = 0;
|
int _unreadMessages = 0;
|
||||||
|
bool _online = false;
|
||||||
|
|
||||||
ProfileInfoState({
|
ProfileInfoState({
|
||||||
this.onion,
|
this.onion,
|
||||||
|
@ -131,10 +132,12 @@ class ProfileInfoState extends ChangeNotifier {
|
||||||
imagePath = "",
|
imagePath = "",
|
||||||
unreadMessages = 0,
|
unreadMessages = 0,
|
||||||
contactsJson = "",
|
contactsJson = "",
|
||||||
|
online = false,
|
||||||
}) {
|
}) {
|
||||||
this._nickname = nickname;
|
this._nickname = nickname;
|
||||||
this._imagePath = imagePath;
|
this._imagePath = imagePath;
|
||||||
this._unreadMessages = unreadMessages;
|
this._unreadMessages = unreadMessages;
|
||||||
|
this._online = online;
|
||||||
|
|
||||||
if (contactsJson != null && contactsJson != "" && contactsJson != "null") {
|
if (contactsJson != null && contactsJson != "" && contactsJson != "null") {
|
||||||
print("decoding " + contactsJson);
|
print("decoding " + contactsJson);
|
||||||
|
@ -155,6 +158,13 @@ class ProfileInfoState extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getters and Setters for Online Status
|
||||||
|
bool get isOnline => this._online;
|
||||||
|
set isOnline(bool newValue) {
|
||||||
|
this._online = newValue;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
String get nickname => this._nickname;
|
String get nickname => this._nickname;
|
||||||
set nickname(String newValue) {
|
set nickname(String newValue) {
|
||||||
this._nickname = newValue;
|
this._nickname = newValue;
|
||||||
|
@ -275,7 +285,6 @@ class ContactInfoState extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MessageState extends ChangeNotifier {
|
class MessageState extends ChangeNotifier {
|
||||||
final String profileOnion;
|
final String profileOnion;
|
||||||
final String contactHandle;
|
final String contactHandle;
|
||||||
|
@ -309,7 +318,6 @@ class MessageState extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
/// ACN ///
|
/// ACN ///
|
||||||
/////////////
|
/////////////
|
||||||
|
|
|
@ -77,7 +77,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
title: Text(AppLocalizations.of(context).blockUnknownLabel, style: TextStyle(color: settings.current().mainTextColor())),
|
title: Text(AppLocalizations.of(context).blockUnknownLabel, style: TextStyle(color: settings.current().mainTextColor())),
|
||||||
subtitle: Text(AppLocalizations.of(context).descriptionBlockUnknownConnections),
|
subtitle: Text(AppLocalizations.of(context).descriptionBlockUnknownConnections),
|
||||||
value: settings.blockUnknownConnections,
|
value: settings.blockUnknownConnections,
|
||||||
onChanged: (bool value) {
|
onChanged: (bool value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
settings.forbidUnknownConnections();
|
settings.forbidUnknownConnections();
|
||||||
|
|
|
@ -44,9 +44,9 @@ class _MessageViewState extends State<MessageView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _debugResetContact() {
|
void _debugResetContact() {
|
||||||
Provider.of<FlwtchState>(context, listen: false).cwtch.DebugResetContact(
|
Provider.of<FlwtchState>(context, listen: false)
|
||||||
Provider.of<ContactInfoState>(context, listen: false).profileOnion,
|
.cwtch
|
||||||
Provider.of<ContactInfoState>(context, listen: false).onion);
|
.DebugResetContact(Provider.of<ContactInfoState>(context, listen: false).profileOnion, Provider.of<ContactInfoState>(context, listen: false).onion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pushContactSettings() {
|
void _pushContactSettings() {
|
||||||
|
@ -69,13 +69,11 @@ class _MessageViewState extends State<MessageView> {
|
||||||
|
|
||||||
void _sendMessage([String ignoredParam]) {
|
void _sendMessage([String ignoredParam]) {
|
||||||
ChatMessage cm = new ChatMessage(o: 1, d: ctrlrCompose.value.text);
|
ChatMessage cm = new ChatMessage(o: 1, d: ctrlrCompose.value.text);
|
||||||
Provider.of<FlwtchState>(context, listen:false).cwtch.SendMessage(
|
Provider.of<FlwtchState>(context, listen: false)
|
||||||
Provider.of<ContactInfoState>(context, listen:false).profileOnion,
|
.cwtch
|
||||||
Provider.of<ContactInfoState>(context, listen:false).onion,
|
.SendMessage(Provider.of<ContactInfoState>(context, listen: false).profileOnion, Provider.of<ContactInfoState>(context, listen: false).onion, jsonEncode(cm));
|
||||||
jsonEncode(cm));
|
|
||||||
ctrlrCompose.clear();
|
ctrlrCompose.clear();
|
||||||
focusNode.requestFocus();
|
Provider.of<ContactInfoState>(context, listen: false).totalMessages++;
|
||||||
Provider.of<ContactInfoState>(context, listen:false).totalMessages++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildComposeBox() {
|
Widget _buildComposeBox() {
|
||||||
|
@ -85,45 +83,52 @@ class _MessageViewState extends State<MessageView> {
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(child: TextField(
|
Expanded(
|
||||||
controller: ctrlrCompose,
|
child: TextField(
|
||||||
focusNode: focusNode,
|
controller: ctrlrCompose,
|
||||||
textInputAction: TextInputAction.send,
|
focusNode: focusNode,
|
||||||
onSubmitted: _sendMessage,
|
textInputAction: TextInputAction.send,
|
||||||
|
onSubmitted: _sendMessage,
|
||||||
)),
|
)),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 90,
|
width: 90,
|
||||||
height: 80,
|
height: 80,
|
||||||
child: Column(children: <Widget>[
|
child: Column(children: <Widget>[
|
||||||
Padding(padding: EdgeInsets.fromLTRB(2, 2, 2, 2), child: ElevatedButton(
|
Padding(
|
||||||
child: Icon(Icons.send, color: Opaque.current().mainTextColor()),
|
padding: EdgeInsets.fromLTRB(2, 2, 2, 2),
|
||||||
style: ButtonStyle(
|
child: ElevatedButton(
|
||||||
fixedSize: MaterialStateProperty.all(Size(86, 40)),
|
child: Icon(Icons.send, color: Opaque.current().mainTextColor()),
|
||||||
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
|
style: ButtonStyle(
|
||||||
),
|
fixedSize: MaterialStateProperty.all(Size(86, 40)),
|
||||||
onPressed: _sendMessage,
|
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
|
||||||
)),
|
),
|
||||||
|
onPressed: _sendMessage,
|
||||||
|
)),
|
||||||
Row(children: <Widget>[
|
Row(children: <Widget>[
|
||||||
Padding(padding: EdgeInsets.all(2), child: SizedBox(
|
Padding(
|
||||||
width: 41,
|
padding: EdgeInsets.all(2),
|
||||||
child: ElevatedButton(
|
child: SizedBox(
|
||||||
child: Icon(Icons.emoji_emotions_outlined, color: Opaque.current().mainTextColor()),
|
width: 41,
|
||||||
style: ButtonStyle(
|
child: ElevatedButton(
|
||||||
fixedSize: MaterialStateProperty.all(Size(41, 40)),
|
child: Icon(Icons.emoji_emotions_outlined, color: Opaque.current().mainTextColor()),
|
||||||
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
|
style: ButtonStyle(
|
||||||
),
|
fixedSize: MaterialStateProperty.all(Size(41, 40)),
|
||||||
onPressed: placeHolder,
|
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
|
||||||
))),
|
),
|
||||||
Padding(padding: EdgeInsets.all(2), child: SizedBox(
|
onPressed: placeHolder,
|
||||||
width: 41,
|
))),
|
||||||
child: ElevatedButton(
|
Padding(
|
||||||
child: Icon(Icons.attach_file, color: Opaque.current().mainTextColor()),
|
padding: EdgeInsets.all(2),
|
||||||
style: ButtonStyle(
|
child: SizedBox(
|
||||||
fixedSize: MaterialStateProperty.all(Size(41, 40)),
|
width: 41,
|
||||||
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
|
child: ElevatedButton(
|
||||||
),
|
child: Icon(Icons.attach_file, color: Opaque.current().mainTextColor()),
|
||||||
onPressed: placeHolder,
|
style: ButtonStyle(
|
||||||
))),
|
fixedSize: MaterialStateProperty.all(Size(41, 40)),
|
||||||
|
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
|
||||||
|
),
|
||||||
|
onPressed: placeHolder,
|
||||||
|
))),
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_app/settings.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:flutter_app/widgets/profilerow.dart';
|
import 'package:flutter_app/widgets/profilerow.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -28,6 +29,7 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
backgroundColor: Provider.of<Settings>(context).theme.backgroundMainColor(),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(AppLocalizations.of(context).titleManageProfiles),
|
title: Text(AppLocalizations.of(context).titleManageProfiles),
|
||||||
actions: [
|
actions: [
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_app/views/messageview.dart';
|
import 'package:flutter_app/views/messageview.dart';
|
||||||
|
import 'package:flutter_app/widgets/profileimage.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../main.dart';
|
import '../main.dart';
|
||||||
import '../model.dart';
|
import '../model.dart';
|
||||||
import '../opaque.dart';
|
import '../opaque.dart';
|
||||||
|
import '../settings.dart';
|
||||||
|
|
||||||
class ContactRow extends StatefulWidget {
|
class ContactRow extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
|
@ -15,45 +17,58 @@ class _ContactRowState extends State<ContactRow> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var contact = Provider.of<ContactInfoState>(context);
|
var contact = Provider.of<ContactInfoState>(context);
|
||||||
return ListTile(
|
return Card(
|
||||||
leading: SizedBox(
|
clipBehavior: Clip.antiAlias,
|
||||||
width: 60,
|
child: InkWell(
|
||||||
height: 60,
|
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||||
child: ClipOval(
|
Padding(
|
||||||
child: SizedBox(
|
padding: const EdgeInsets.all(2.0), //border size
|
||||||
width: 60,
|
child: ProfileImage(
|
||||||
height: 60,
|
diameter: 64.0,
|
||||||
child: Container(
|
imagePath: contact.imagePath,
|
||||||
color: Colors.white,
|
border: contact.status == "Authenticated" ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
|
||||||
width: 60,
|
),
|
||||||
height: 60,
|
Expanded(
|
||||||
child: Image(
|
child: Column(
|
||||||
image: AssetImage("assets/" + contact.imagePath),
|
children: [
|
||||||
width: 50,
|
Text(
|
||||||
height: 50,
|
contact.nickname, //(contact.isInvitation ? "invite " : "non-invite ") + (contact.isBlocked ? "blokt" : "nonblokt"),//
|
||||||
))),
|
style: Provider.of<FlwtchState>(context).biggerFont,
|
||||||
),
|
softWrap: true,
|
||||||
),
|
overflow: TextOverflow.visible,
|
||||||
trailing: contact.isInvitation != null && contact.isInvitation
|
),
|
||||||
? Wrap(direction: Axis.vertical, children: <Widget>[
|
Text(contact.status),
|
||||||
IconButton(padding: EdgeInsets.zero, iconSize: 16, icon: Icon(Icons.favorite, color: Opaque.current().mainTextColor()), onPressed: _btnApprove,),
|
],
|
||||||
IconButton(padding: EdgeInsets.zero, iconSize: 16, icon: Icon(Icons.delete, color: Opaque.current().mainTextColor()), onPressed: _btnReject,)])
|
)),
|
||||||
: Text(contact.unreadMessages.toString()), //(nb: Icons.create is a pencil and we use it for "edit", not create)
|
Padding(
|
||||||
title: Text(
|
padding: const EdgeInsets.all(5.0),
|
||||||
contact.nickname,
|
child: contact.isInvitation != null && contact.isInvitation
|
||||||
style: Provider.of<FlwtchState>(context).biggerFont,
|
? Wrap(direction: Axis.vertical, children: <Widget>[
|
||||||
),
|
IconButton(
|
||||||
subtitle: Text(contact.status),
|
padding: EdgeInsets.zero,
|
||||||
onTap: () {
|
iconSize: 16,
|
||||||
setState(() {
|
icon: Icon(Icons.favorite, color: Opaque.current().mainTextColor()),
|
||||||
var flwtch = Provider.of<FlwtchState>(context, listen: false);
|
onPressed: _btnApprove,
|
||||||
flwtch.setState(() => flwtch.selectedConversation = contact.onion);
|
),
|
||||||
|
IconButton(
|
||||||
// case 2/3 handled by Double/TripleColumnView respectively
|
padding: EdgeInsets.zero,
|
||||||
if (flwtch.columns.length == 1) _pushMessageView(contact.onion);
|
iconSize: 16,
|
||||||
});
|
icon: Icon(Icons.delete, color: Opaque.current().mainTextColor()),
|
||||||
},
|
onPressed: _btnReject,
|
||||||
);
|
)
|
||||||
|
])
|
||||||
|
: Text(contact.unreadMessages.toString()), //(nb: Icons.create is a pencil and we use it for "edit", not create)
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pushMessageView(String handle) {
|
void _pushMessageView(String handle) {
|
||||||
|
@ -72,16 +87,15 @@ class _ContactRowState extends State<ContactRow> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _btnApprove() {
|
void _btnApprove() {
|
||||||
Provider.of<FlwtchState>(context, listen: false).cwtch.AcceptContact(
|
Provider.of<FlwtchState>(context, listen: false)
|
||||||
Provider.of<ContactInfoState>(context, listen: false).profileOnion,
|
.cwtch
|
||||||
Provider.of<ContactInfoState>(context, listen: false).onion);
|
.AcceptContact(Provider.of<ContactInfoState>(context, listen: false).profileOnion, Provider.of<ContactInfoState>(context, listen: false).onion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _btnReject() {
|
void _btnReject() {
|
||||||
Provider.of<FlwtchState>(context, listen: false).cwtch.BlockContact(
|
Provider.of<FlwtchState>(context, listen: false)
|
||||||
Provider.of<ContactInfoState>(context, listen: false).profileOnion,
|
.cwtch
|
||||||
Provider.of<ContactInfoState>(context, listen: false).onion);
|
.BlockContact(Provider.of<ContactInfoState>(context, listen: false).profileOnion, Provider.of<ContactInfoState>(context, listen: false).onion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,9 @@ class _MessageBubbleState extends State<MessageBubble> {
|
||||||
subtitle: Row(
|
subtitle: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(Provider.of<MessageState>(context).timestamp),
|
Text(Provider.of<MessageState>(context).timestamp),
|
||||||
Provider.of<MessageState>(context).ackd ? Icon(Icons.check_circle_outline, color: Opaque.current().mainTextColor()) : Icon(Icons.hourglass_bottom_outlined, color: Opaque.current().mainTextColor())
|
Provider.of<MessageState>(context).ackd
|
||||||
|
? Icon(Icons.check_circle_outline, color: Opaque.current().mainTextColor())
|
||||||
|
: Icon(Icons.hourglass_bottom_outlined, color: Opaque.current().mainTextColor())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -40,19 +40,22 @@ class _MessageListState extends State<MessageList> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext outerContext) {
|
Widget build(BuildContext outerContext) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom(false));
|
WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom(false));
|
||||||
return Card(child: Scrollbar(
|
return Card(
|
||||||
|
child: Scrollbar(
|
||||||
isAlwaysShown: true,
|
isAlwaysShown: true,
|
||||||
controller: ctrlr1,
|
controller: ctrlr1,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
controller: ctrlr1,
|
controller: ctrlr1,
|
||||||
itemCount: Provider.of<ContactInfoState>(context).totalMessages,
|
itemCount: Provider.of<ContactInfoState>(context).totalMessages,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return ChangeNotifierProvider(create: (_) => MessageState(
|
return ChangeNotifierProvider(
|
||||||
context: context,
|
create: (_) => MessageState(
|
||||||
profileOnion: Provider.of<ProfileInfoState>(outerContext).onion,
|
context: context,
|
||||||
contactHandle: Provider.of<ContactInfoState>(outerContext).onion,
|
profileOnion: Provider.of<ProfileInfoState>(outerContext).onion,
|
||||||
messageIndex: index,
|
contactHandle: Provider.of<ContactInfoState>(outerContext).onion,
|
||||||
), child: MessageBubble());
|
messageIndex: index,
|
||||||
|
),
|
||||||
|
child: MessageBubble());
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_app/opaque.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../settings.dart';
|
||||||
|
|
||||||
|
class ProfileImage extends StatefulWidget {
|
||||||
|
ProfileImage({this.imagePath, this.diameter, this.border});
|
||||||
|
final double diameter;
|
||||||
|
final String imagePath;
|
||||||
|
final Color border;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ProfileImageState createState() => _ProfileImageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProfileImageState extends State<ProfileImage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ClipOval(
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
child: Container(
|
||||||
|
width: widget.diameter,
|
||||||
|
height: widget.diameter,
|
||||||
|
color: widget.border,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(2.0), //border size
|
||||||
|
child: ClipOval(
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
child: Image(
|
||||||
|
image: AssetImage("assets/" + widget.imagePath),
|
||||||
|
filterQuality: FilterQuality.medium,
|
||||||
|
// We need some theme specific blending here...we might want to consider making this a theme level attribute
|
||||||
|
colorBlendMode: Provider.of<Settings>(context).theme == Opaque.dark ? BlendMode.softLight : BlendMode.darken,
|
||||||
|
color: Provider.of<Settings>(context).theme.backgroundHilightElementColor(),
|
||||||
|
isAntiAlias: true,
|
||||||
|
width: widget.diameter,
|
||||||
|
height: widget.diameter,
|
||||||
|
))),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter_app/views/addeditprofileview.dart';
|
import 'package:flutter_app/views/addeditprofileview.dart';
|
||||||
import 'package:flutter_app/views/contactsview.dart';
|
import 'package:flutter_app/views/contactsview.dart';
|
||||||
import 'package:flutter_app/views/doublecolview.dart';
|
import 'package:flutter_app/views/doublecolview.dart';
|
||||||
|
import 'package:flutter_app/widgets/profileimage.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
@ -19,63 +20,66 @@ class _ProfileRowState extends State<ProfileRow> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var profile = Provider.of<ProfileInfoState>(context);
|
var profile = Provider.of<ProfileInfoState>(context);
|
||||||
return ListTile(
|
return Card(
|
||||||
leading: SizedBox(
|
clipBehavior: Clip.antiAlias,
|
||||||
width: 60,
|
child: InkWell(
|
||||||
height: 60,
|
child: Row(
|
||||||
child: ClipOval(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
child: SizedBox(
|
children: [
|
||||||
width: 60,
|
Padding(
|
||||||
height: 60,
|
padding: const EdgeInsets.all(2.0), //border size
|
||||||
child: Container(
|
child: ProfileImage(
|
||||||
color: Colors.white,
|
diameter: 64.0,
|
||||||
width: 60,
|
imagePath: profile.imagePath,
|
||||||
height: 60,
|
border: profile.isOnline ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor())),
|
||||||
child: Image(
|
Expanded(
|
||||||
excludeFromSemantics: true,
|
child: Column(
|
||||||
image: AssetImage("assets/" + profile.imagePath),
|
children: [
|
||||||
width: 50,
|
Text(
|
||||||
height: 50,
|
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);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
var flwtch = Provider.of<FlwtchState>(context, listen: false);
|
||||||
|
flwtch.cwtch.SelectProfile(profile.onion);
|
||||||
|
flwtch.setState(() {
|
||||||
|
flwtch.selectedProfile = profile;
|
||||||
|
flwtch.selectedConversation = "";
|
||||||
|
});
|
||||||
|
|
||||||
title: Text(
|
switch (flwtch.columns.length) {
|
||||||
profile.nickname,
|
case 1:
|
||||||
semanticsLabel: profile.nickname,
|
_pushContactList(profile, false);
|
||||||
style: Provider.of<FlwtchState>(context).biggerFont,
|
break;
|
||||||
),
|
case 2:
|
||||||
subtitle: ExcludeSemantics(child: Text(profile.onion)),
|
_pushContactList(profile, true);
|
||||||
|
break;
|
||||||
trailing: IconButton(
|
} // case 3: handled by TripleColumnView
|
||||||
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);
|
|
||||||
},
|
|
||||||
), //(nb: Icons.create is a pencil and we use it for "edit", not create)
|
|
||||||
|
|
||||||
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
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pushContactList(ProfileInfoState profile, bool includeDoublePane) {
|
void _pushContactList(ProfileInfoState profile, bool includeDoublePane) {
|
||||||
|
|
Loading…
Reference in New Issue