mo wirin
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
parent
f39335bbc8
commit
e582599d23
|
@ -6,7 +6,6 @@
|
|||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/views/addeditprofileview.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
|
|
|
@ -28,24 +28,25 @@ class CwtchNotifier {
|
|||
));
|
||||
break;
|
||||
case "PeerCreated":
|
||||
print("xx peercreated $data");
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState(
|
||||
profileOnion: data["ProfileOnion"],
|
||||
onion: data["RemotePeer"],
|
||||
nickname: data["nick"],
|
||||
status: data["status"],
|
||||
imagePath: data["picture"],
|
||||
isBlocked: data["authorization"] == "blocked",
|
||||
isInvitation: data["authorization"] == "unknown",
|
||||
savePeerHistory: data["saveConversationHistory"],
|
||||
numMessages: int.parse(data["numMessages"]),
|
||||
numUnread: int.parse(data["unread"]),
|
||||
));
|
||||
break;
|
||||
case "PeerStateChange":
|
||||
ContactInfoState contact = profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]);
|
||||
if (contact == null) {
|
||||
//todo: stopgap, as lc-g is supposed to handle this
|
||||
print("PSC -> adding " + data["ProfileOnion"] + " :: " + data["RemotePeer"]);
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.add(
|
||||
ContactInfoState(profileOnion: data["ProfileOnion"], onion: data["RemotePeer"], nickname: data["name"], status: data["ConnectionState"], isBlocked: data["authorization"] == "blocked", isInvitation: data["authorization"] == "unknown"));
|
||||
} else {
|
||||
contact.status = data["ConnectionState"];
|
||||
if (contact != null) {
|
||||
if (data["ConnectionState"] != null) {
|
||||
contact.status = data["ConnectionState"];
|
||||
}
|
||||
if (data["authorization"] != null) {
|
||||
contact.isInvitation = data["authorization"] == "unknown";
|
||||
contact.isBlocked = data["authorization"] == "blocked";
|
||||
|
|
|
@ -120,21 +120,25 @@ class CwtchGomobile implements Cwtch {
|
|||
void dispose() => {};
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void AcceptContact(String profileOnion, String contactHandle) {
|
||||
cwtchPlatform.invokeMethod("AcceptContact", {"ProfileOnion": profileOnion, "handle": contactHandle});
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void BlockContact(String profileOnion, String contactHandle) {
|
||||
cwtchPlatform.invokeMethod("BlockContact", {"ProfileOnion": profileOnion, "handle": contactHandle});
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void DebugResetContact(String profileOnion, String contactHandle) {
|
||||
cwtchPlatform.invokeMethod("DebugResetContact", {"ProfileOnion": profileOnion, "handle": contactHandle});
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void SendMessage(String profileOnion, String contactHandle, String message) {
|
||||
cwtchPlatform.invokeMethod("SendMessage", {"ProfileOnion": profileOnion, "handle": contactHandle, "message": message});
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'cwtch/cwtch.dart';
|
||||
import 'main.dart';
|
||||
|
||||
////////////////////
|
||||
/// UI State ///
|
||||
|
@ -274,6 +276,40 @@ class ContactInfoState extends ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class MessageState extends ChangeNotifier {
|
||||
final String profileOnion;
|
||||
final String contactHandle;
|
||||
final int messageIndex;
|
||||
String _message;
|
||||
String _timestamp;
|
||||
bool _ackd = false;
|
||||
|
||||
MessageState({
|
||||
BuildContext context,
|
||||
this.profileOnion,
|
||||
this.contactHandle,
|
||||
this.messageIndex,
|
||||
}) {
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.GetMessage(profileOnion, contactHandle, messageIndex).then((jsonMessage) {
|
||||
dynamic messageWrapper = jsonDecode(jsonMessage);
|
||||
dynamic message = jsonDecode(messageWrapper['Message']);
|
||||
this._message = message['d'];
|
||||
this._timestamp = messageWrapper['Timestamp'];
|
||||
this._ackd = messageWrapper['Acknowledged'];
|
||||
});
|
||||
}
|
||||
|
||||
get message => this._message;
|
||||
get timestamp => this._timestamp;
|
||||
get ackd => this._ackd;
|
||||
|
||||
set ackd(bool newVal) {
|
||||
this._ackd = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////
|
||||
/// ACN ///
|
||||
/////////////
|
||||
|
|
|
@ -1350,6 +1350,7 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
accentColor: opaque.current().defaultButtonColor(),
|
||||
buttonColor: opaque.current().defaultButtonColor(),
|
||||
backgroundColor: opaque.current().backgroundMainColor(),
|
||||
highlightColor: opaque.current().hilightElementTextColor(),
|
||||
iconTheme: IconThemeData(
|
||||
color: opaque.current().mainTextColor(),
|
||||
),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_app/errorHandler.dart';
|
||||
import 'package:flutter_app/settings.dart';
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/widgets/contactrow.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../errorHandler.dart';
|
||||
import '../main.dart';
|
||||
import 'addcontactview.dart';
|
||||
import '../model.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
|
|
@ -16,9 +16,11 @@ class MessageView extends StatefulWidget {
|
|||
|
||||
class _MessageViewState extends State<MessageView> {
|
||||
final ctrlrCompose = TextEditingController();
|
||||
final focusNode = FocusNode();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
focusNode.dispose();
|
||||
ctrlrCompose.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
@ -65,13 +67,14 @@ class _MessageViewState extends State<MessageView> {
|
|||
));
|
||||
}
|
||||
|
||||
void _sendMessage() {
|
||||
void _sendMessage([String ignoredParam]) {
|
||||
ChatMessage cm = new ChatMessage(o: 1, d: ctrlrCompose.value.text);
|
||||
Provider.of<FlwtchState>(context, listen:false).cwtch.SendMessage(
|
||||
Provider.of<ContactInfoState>(context, listen:false).profileOnion,
|
||||
Provider.of<ContactInfoState>(context, listen:false).onion,
|
||||
jsonEncode(cm));
|
||||
ctrlrCompose.clear();
|
||||
focusNode.requestFocus();
|
||||
Provider.of<ContactInfoState>(context, listen:false).totalMessages++;
|
||||
}
|
||||
|
||||
|
@ -79,33 +82,48 @@ class _MessageViewState extends State<MessageView> {
|
|||
return Container(
|
||||
color: Opaque.current().backgroundMainColor(),
|
||||
height: 100,
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(child: TextField(controller: ctrlrCompose)),
|
||||
Expanded(child: TextField(
|
||||
controller: ctrlrCompose,
|
||||
focusNode: focusNode,
|
||||
textInputAction: TextInputAction.send,
|
||||
onSubmitted: _sendMessage,
|
||||
)),
|
||||
SizedBox(
|
||||
width: 100,
|
||||
width: 90,
|
||||
height: 80,
|
||||
child: Column(children: <Widget>[
|
||||
ElevatedButton(
|
||||
Padding(padding: EdgeInsets.fromLTRB(2, 2, 2, 2), child: ElevatedButton(
|
||||
child: Icon(Icons.send, color: Opaque.current().mainTextColor()),
|
||||
style: ButtonStyle(
|
||||
fixedSize: MaterialStateProperty.all(Size(86, 40)),
|
||||
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
|
||||
),
|
||||
onPressed: _sendMessage,
|
||||
),
|
||||
)),
|
||||
Row(children: <Widget>[
|
||||
SizedBox(
|
||||
width: 45,
|
||||
Padding(padding: EdgeInsets.all(2), child: SizedBox(
|
||||
width: 41,
|
||||
child: ElevatedButton(
|
||||
child: Icon(Icons.emoji_emotions_outlined, color: Opaque.current().mainTextColor()),
|
||||
style: ButtonStyle(
|
||||
fixedSize: MaterialStateProperty.all(Size(41, 40)),
|
||||
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
|
||||
),
|
||||
onPressed: placeHolder,
|
||||
)),
|
||||
SizedBox(
|
||||
width: 45,
|
||||
))),
|
||||
Padding(padding: EdgeInsets.all(2), child: SizedBox(
|
||||
width: 41,
|
||||
child: ElevatedButton(
|
||||
child: Icon(Icons.attach_file, color: Opaque.current().mainTextColor()),
|
||||
style: ButtonStyle(
|
||||
fixedSize: MaterialStateProperty.all(Size(41, 40)),
|
||||
backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()),
|
||||
),
|
||||
onPressed: placeHolder,
|
||||
)),
|
||||
))),
|
||||
])
|
||||
]),
|
||||
),
|
||||
|
|
|
@ -1,41 +1,14 @@
|
|||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../main.dart';
|
||||
import '../model.dart';
|
||||
import '../opaque.dart';
|
||||
|
||||
class MessageBubble extends StatefulWidget {
|
||||
MessageBubble({Key key, this.profile, this.contactOnion, this.messageIndex});
|
||||
final ProfileInfoState profile;
|
||||
final String contactOnion;
|
||||
final int messageIndex;
|
||||
|
||||
@override
|
||||
_MessageBubbleState createState() => _MessageBubbleState();
|
||||
}
|
||||
|
||||
class _MessageBubbleState extends State<MessageBubble> {
|
||||
String d = "", ts = "";
|
||||
bool ack = false;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
print("requesting message " + widget.messageIndex.toString());
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.GetMessage(widget.profile.onion, widget.contactOnion, widget.messageIndex).then((jsonMessage) {
|
||||
print("got message: " + widget.messageIndex.toString() + ": " + jsonMessage);
|
||||
dynamic messageWrapper = jsonDecode(jsonMessage);
|
||||
dynamic message = jsonDecode(messageWrapper['Message']);
|
||||
setState(() {
|
||||
d = message['d'];
|
||||
ts = messageWrapper['Timestamp'];
|
||||
ack = messageWrapper['Acknowledged'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
|
@ -50,13 +23,13 @@ class _MessageBubbleState extends State<MessageBubble> {
|
|||
),
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
d,
|
||||
Provider.of<MessageState>(context).message,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
Text("" + widget.messageIndex.toString()),
|
||||
ack ? Icon(Icons.check_circle_outline, color: Opaque.current().mainTextColor()) : Icon(Icons.hourglass_bottom_outlined, color: Opaque.current().mainTextColor())
|
||||
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())
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../model.dart';
|
||||
|
@ -12,6 +11,8 @@ class MessageList extends StatefulWidget {
|
|||
|
||||
class _MessageListState extends State<MessageList> {
|
||||
ScrollController ctrlr1 = ScrollController();
|
||||
int lastMessageCount = 0;
|
||||
double lastMaxScroll = 0.0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -20,24 +21,40 @@ class _MessageListState extends State<MessageList> {
|
|||
}
|
||||
|
||||
void _scrollToBottom(bool force) {
|
||||
if (force || ctrlr1.position.pixels >= ctrlr1.position.maxScrollExtent - 3) {
|
||||
ctrlr1.jumpTo(ctrlr1.position.maxScrollExtent);
|
||||
if (ctrlr1.hasClients) {
|
||||
if (force || Provider.of<ContactInfoState>(context, listen: false).totalMessages > lastMessageCount) {
|
||||
if (ctrlr1.position.pixels == lastMaxScroll) {
|
||||
ctrlr1.jumpTo(ctrlr1.position.maxScrollExtent);
|
||||
}
|
||||
|
||||
setState(() {
|
||||
lastMessageCount = Provider.of<ContactInfoState>(context, listen: false).totalMessages;
|
||||
lastMaxScroll = ctrlr1.position.maxScrollExtent;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setState(() => null);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext outerContext) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom(false));
|
||||
return ListView.builder(
|
||||
return Card(child: Scrollbar(
|
||||
isAlwaysShown: true,
|
||||
controller: ctrlr1,
|
||||
itemCount: Provider.of<ContactInfoState>(context).totalMessages,
|
||||
itemBuilder: (context, index) {
|
||||
return MessageBubble(
|
||||
profile: Provider.of<ProfileInfoState>(outerContext),
|
||||
contactOnion: Provider.of<ContactInfoState>(outerContext).onion,
|
||||
messageIndex: index,
|
||||
);
|
||||
},
|
||||
);
|
||||
child: ListView.builder(
|
||||
controller: ctrlr1,
|
||||
itemCount: Provider.of<ContactInfoState>(context).totalMessages,
|
||||
itemBuilder: (context, index) {
|
||||
return ChangeNotifierProvider(create: (_) => MessageState(
|
||||
context: context,
|
||||
profileOnion: Provider.of<ProfileInfoState>(outerContext).onion,
|
||||
contactHandle: Provider.of<ContactInfoState>(outerContext).onion,
|
||||
messageIndex: index,
|
||||
), child: MessageBubble());
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -378,7 +378,7 @@ packages:
|
|||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
version: "2.0.5"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -36,16 +36,14 @@ dependencies:
|
|||
path_provider: ^2.0.0
|
||||
|
||||
# todo: flutter_driver causes version conflict. eg https://github.com/flutter/flutter/issues/44829
|
||||
# testing-related deps
|
||||
# testing-related deps
|
||||
integration_test: ^1.0.0
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_driver:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
#dev_dependencies:
|
||||
# flutter_lokalise: any
|
||||
|
||||
# alternatively: flutter pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/intl/app_localizations.dart lib/l10n/intl_*.arb --api-token X --project-id Y
|
||||
|
|
|
@ -9,7 +9,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_app/opaque.dart';
|
||||
import 'package:flutter_app/settings.dart';
|
||||
import 'package:flutter_app/widgets/buttontextfield.dart';
|
||||
import 'package:flutter_app/widgets/cwtchlabel.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_app/opaque.dart';
|
||||
import 'package:flutter_app/settings.dart';
|
||||
import 'package:flutter_app/widgets/cwtchlabel.dart';
|
||||
import 'package:flutter_app/widgets/textfield.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
|
Loading…
Reference in New Issue