Improve signalR protocol compatibility
This commit is contained in:
parent
04ae0687f8
commit
f305fcd23c
5 changed files with 58 additions and 105 deletions
|
@ -7,7 +7,7 @@ import 'package:contacts_plus_plus/models/users/user.dart';
|
||||||
import 'package:contacts_plus_plus/models/users/user_profile.dart';
|
import 'package:contacts_plus_plus/models/users/user_profile.dart';
|
||||||
import 'package:contacts_plus_plus/models/users/user_status.dart';
|
import 'package:contacts_plus_plus/models/users/user_status.dart';
|
||||||
|
|
||||||
class FriendApi {
|
class ContactApi {
|
||||||
static Future<List<Friend>> getFriendsList(ApiClient client, {DateTime? lastStatusUpdate}) async {
|
static Future<List<Friend>> getFriendsList(ApiClient client, {DateTime? lastStatusUpdate}) async {
|
||||||
final response = await client.get("/users/${client.userId}/contacts${lastStatusUpdate != null ? "?lastStatusUpdate=${lastStatusUpdate.toUtc().toIso8601String()}" : ""}");
|
final response = await client.get("/users/${client.userId}/contacts${lastStatusUpdate != null ? "?lastStatusUpdate=${lastStatusUpdate.toUtc().toIso8601String()}" : ""}");
|
||||||
client.checkResponse(response);
|
client.checkResponse(response);
|
|
@ -7,7 +7,7 @@ import 'package:flutter/widgets.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
import 'package:contacts_plus_plus/apis/friend_api.dart';
|
import 'package:contacts_plus_plus/apis/contact_api.dart';
|
||||||
import 'package:contacts_plus_plus/apis/message_api.dart';
|
import 'package:contacts_plus_plus/apis/message_api.dart';
|
||||||
import 'package:contacts_plus_plus/apis/user_api.dart';
|
import 'package:contacts_plus_plus/apis/user_api.dart';
|
||||||
import 'package:contacts_plus_plus/clients/notification_client.dart';
|
import 'package:contacts_plus_plus/clients/notification_client.dart';
|
||||||
|
@ -15,16 +15,17 @@ import 'package:contacts_plus_plus/models/users/friend.dart';
|
||||||
import 'package:contacts_plus_plus/clients/api_client.dart';
|
import 'package:contacts_plus_plus/clients/api_client.dart';
|
||||||
import 'package:contacts_plus_plus/config.dart';
|
import 'package:contacts_plus_plus/config.dart';
|
||||||
import 'package:contacts_plus_plus/models/message.dart';
|
import 'package:contacts_plus_plus/models/message.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
enum EventType {
|
enum EventType {
|
||||||
unknown,
|
undefined,
|
||||||
message,
|
invocation,
|
||||||
unknown1,
|
streamItem,
|
||||||
unknown2,
|
completion,
|
||||||
unknown3,
|
streamInvocation,
|
||||||
unknown4,
|
cancelInvocation,
|
||||||
keepAlive,
|
ping,
|
||||||
error;
|
close;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EventTarget {
|
enum EventTarget {
|
||||||
|
@ -32,7 +33,9 @@ enum EventTarget {
|
||||||
messageSent,
|
messageSent,
|
||||||
receiveMessage,
|
receiveMessage,
|
||||||
messagesRead,
|
messagesRead,
|
||||||
receiveSessionUpdate;
|
receiveSessionUpdate,
|
||||||
|
removeSession,
|
||||||
|
receiveStatusUpdate;
|
||||||
|
|
||||||
factory EventTarget.parse(String? text) {
|
factory EventTarget.parse(String? text) {
|
||||||
if (text == null) return EventTarget.unknown;
|
if (text == null) return EventTarget.unknown;
|
||||||
|
@ -127,7 +130,7 @@ class MessagingClient extends ChangeNotifier {
|
||||||
_autoRefresh?.cancel();
|
_autoRefresh?.cancel();
|
||||||
_autoRefresh = Timer(_autoRefreshDuration, () => refreshFriendsList());
|
_autoRefresh = Timer(_autoRefreshDuration, () => refreshFriendsList());
|
||||||
|
|
||||||
final friends = await FriendApi.getFriendsList(_apiClient, lastStatusUpdate: lastUpdateUtc);
|
final friends = await ContactApi.getFriendsList(_apiClient, lastStatusUpdate: lastUpdateUtc);
|
||||||
for (final friend in friends) {
|
for (final friend in friends) {
|
||||||
await _updateFriend(friend);
|
await _updateFriend(friend);
|
||||||
}
|
}
|
||||||
|
@ -136,16 +139,9 @@ class MessagingClient extends ChangeNotifier {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendMessage(Message message) async {
|
void sendMessage(Message message) {
|
||||||
final msgBody = message.toMap();
|
final msgBody = message.toMap();
|
||||||
final data = {
|
_send("SendMessage", body: msgBody);
|
||||||
"type": EventType.message.index,
|
|
||||||
"target": "SendMessage",
|
|
||||||
"arguments": [
|
|
||||||
msgBody
|
|
||||||
],
|
|
||||||
};
|
|
||||||
_sendData(data);
|
|
||||||
final cache = getUserMessageCache(message.recipientId) ?? _createUserMessageCache(message.recipientId);
|
final cache = getUserMessageCache(message.recipientId) ?? _createUserMessageCache(message.recipientId);
|
||||||
cache.addMessage(message);
|
cache.addMessage(message);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -153,14 +149,7 @@ class MessagingClient extends ChangeNotifier {
|
||||||
|
|
||||||
void markMessagesRead(MarkReadBatch batch) {
|
void markMessagesRead(MarkReadBatch batch) {
|
||||||
final msgBody = batch.toMap();
|
final msgBody = batch.toMap();
|
||||||
final data = {
|
_send("MarkMessagesRead", body: msgBody);
|
||||||
"type": EventType.message.index,
|
|
||||||
"target": "MarkMessagesRead",
|
|
||||||
"arguments": [
|
|
||||||
msgBody
|
|
||||||
],
|
|
||||||
};
|
|
||||||
_sendData(data);
|
|
||||||
clearUnreadsForUser(batch.senderId);
|
clearUnreadsForUser(batch.senderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,6 +270,7 @@ class MessagingClient extends ChangeNotifier {
|
||||||
_wsChannel!.done.then((error) => _onDisconnected(error));
|
_wsChannel!.done.then((error) => _onDisconnected(error));
|
||||||
_wsChannel!.listen(_handleEvent, onDone: () => _onDisconnected("Connection closed."), onError: _onDisconnected);
|
_wsChannel!.listen(_handleEvent, onDone: () => _onDisconnected("Connection closed."), onError: _onDisconnected);
|
||||||
_wsChannel!.add(_negotiationPacket);
|
_wsChannel!.add(_negotiationPacket);
|
||||||
|
_send("InitializeStatus");
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<WebSocket> _tryConnect() async {
|
Future<WebSocket> _tryConnect() async {
|
||||||
|
@ -301,34 +291,38 @@ class MessagingClient extends ChangeNotifier {
|
||||||
|
|
||||||
void _handleEvent(event) {
|
void _handleEvent(event) {
|
||||||
final body = jsonDecode((event.toString().replaceAll(_eofChar, "")));
|
final body = jsonDecode((event.toString().replaceAll(_eofChar, "")));
|
||||||
final int rawType = body["type"] ?? 0;
|
final int? rawType = body["type"];
|
||||||
|
if (rawType == null) {
|
||||||
|
_logger.warning("Received empty event, content was $event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (rawType > EventType.values.length) {
|
if (rawType > EventType.values.length) {
|
||||||
_logger.info("Unhandled event type $rawType: $body");
|
_logger.info("Unhandled event type $rawType: $body");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (EventType.values[rawType]) {
|
switch (EventType.values[rawType]) {
|
||||||
case EventType.unknown1:
|
case EventType.streamItem:
|
||||||
case EventType.unknown2:
|
case EventType.completion:
|
||||||
case EventType.unknown3:
|
case EventType.streamInvocation:
|
||||||
case EventType.unknown4:
|
case EventType.cancelInvocation:
|
||||||
case EventType.unknown:
|
case EventType.undefined:
|
||||||
_logger.info("Received unknown event: $rawType: $body");
|
_logger.info("Received unhandled event: $rawType: $body");
|
||||||
break;
|
break;
|
||||||
case EventType.message:
|
case EventType.invocation:
|
||||||
_logger.info("Received message-event.");
|
_logger.info("Received invocation-event.");
|
||||||
_handleMessageEvent(body);
|
_handleInvocation(body);
|
||||||
break;
|
break;
|
||||||
case EventType.keepAlive:
|
case EventType.ping:
|
||||||
_logger.info("Received keep-alive.");
|
_logger.info("Received keep-alive.");
|
||||||
break;
|
break;
|
||||||
case EventType.error:
|
case EventType.close:
|
||||||
_logger.severe("Received error-event: ${body["error"]}");
|
_logger.severe("Received close-event: ${body["error"]}");
|
||||||
// Should we trigger a manual reconnect here or just let the remote service close the connection?
|
// Should we trigger a manual reconnect here or just let the remote service close the connection?
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleMessageEvent(body) async {
|
void _handleInvocation(body) async {
|
||||||
final target = EventTarget.parse(body["target"]);
|
final target = EventTarget.parse(body["target"]);
|
||||||
final args = body["arguments"];
|
final args = body["arguments"];
|
||||||
switch (target) {
|
switch (target) {
|
||||||
|
@ -366,15 +360,31 @@ class MessagingClient extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
break;
|
break;
|
||||||
|
case EventTarget.receiveStatusUpdate:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case EventTarget.removeSession:
|
||||||
case EventTarget.receiveSessionUpdate:
|
case EventTarget.receiveSessionUpdate:
|
||||||
// TODO: Handle session updates
|
// TODO: Handle session updates
|
||||||
_logger.info("Received session update");
|
_logger.info("Received unhandled invocation event.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _sendData(data) {
|
String _send(String target, {Map? body}) {
|
||||||
|
final invocationId = const Uuid().v4();
|
||||||
|
final data = {
|
||||||
|
"type": EventType.invocation.index,
|
||||||
|
"invocationId": invocationId,
|
||||||
|
"target": target,
|
||||||
|
"arguments": [
|
||||||
|
if (body != null)
|
||||||
|
body
|
||||||
|
],
|
||||||
|
};
|
||||||
if (_wsChannel == null) throw "Neos Hub is not connected";
|
if (_wsChannel == null) throw "Neos Hub is not connected";
|
||||||
_wsChannel!.add(jsonEncode(data)+_eofChar);
|
_wsChannel!.add(jsonEncode(data)+_eofChar);
|
||||||
|
return invocationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:contacts_plus_plus/apis/friend_api.dart';
|
import 'package:contacts_plus_plus/apis/contact_api.dart';
|
||||||
import 'package:contacts_plus_plus/auxiliary.dart';
|
import 'package:contacts_plus_plus/auxiliary.dart';
|
||||||
import 'package:contacts_plus_plus/client_holder.dart';
|
import 'package:contacts_plus_plus/client_holder.dart';
|
||||||
import 'package:contacts_plus_plus/models/users/user.dart';
|
import 'package:contacts_plus_plus/models/users/user.dart';
|
||||||
|
@ -55,11 +55,11 @@ class _UserListTileState extends State<UserListTile> {
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
if (_localAdded) {
|
if (_localAdded) {
|
||||||
await FriendApi.removeUserAsFriend(ClientHolder
|
await ContactApi.removeUserAsFriend(ClientHolder
|
||||||
.of(context)
|
.of(context)
|
||||||
.apiClient, user: widget.user);
|
.apiClient, user: widget.user);
|
||||||
} else {
|
} else {
|
||||||
await FriendApi.addUserAsFriend(ClientHolder
|
await ContactApi.addUserAsFriend(ClientHolder
|
||||||
.of(context)
|
.of(context)
|
||||||
.apiClient, user: widget.user);
|
.apiClient, user: widget.user);
|
||||||
}
|
}
|
||||||
|
|
56
pubspec.lock
56
pubspec.lock
|
@ -504,14 +504,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.5.0"
|
||||||
message_pack_dart:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: message_pack_dart
|
|
||||||
sha256: "71b9f0ff60e5896e60b337960bb535380d7dba3297b457ac763ccae807385b59"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.1"
|
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -688,14 +680,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
pool:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pool
|
|
||||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.5.1"
|
|
||||||
process:
|
process:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -776,22 +760,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.27.7"
|
version: "0.27.7"
|
||||||
shelf:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf
|
|
||||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.1"
|
|
||||||
signalr_netcore:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: signalr_netcore
|
|
||||||
sha256: "8f84b4b516c03f3a6872f94e9729d1441d5d223a77c81d0a7d7dae5dd0ce1f2f"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.6"
|
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -821,22 +789,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.5"
|
version: "2.4.5"
|
||||||
sse:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: sse
|
|
||||||
sha256: "3ff9088cac3f45aa8b91336f1962e3ea6c81baaba0bbba361c05f8aa7fb59442"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.1.2"
|
|
||||||
sse_channel:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: sse_channel
|
|
||||||
sha256: ba2b1382b9423c58fa83e1f01a3a40fbaa16a0594aa984870c88bad0b45d4ca4
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.3"
|
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -901,14 +853,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.2"
|
version: "0.9.2"
|
||||||
tuple:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: tuple
|
|
||||||
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.2"
|
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -38,7 +38,6 @@ dependencies:
|
||||||
flutter_secure_storage: ^8.0.0
|
flutter_secure_storage: ^8.0.0
|
||||||
intl: ^0.18.1
|
intl: ^0.18.1
|
||||||
path: ^1.8.2
|
path: ^1.8.2
|
||||||
signalr_netcore: ^1.3.6
|
|
||||||
logging: ^1.1.1
|
logging: ^1.1.1
|
||||||
cached_network_image: ^3.2.3
|
cached_network_image: ^3.2.3
|
||||||
web_socket_channel: ^2.4.0
|
web_socket_channel: ^2.4.0
|
||||||
|
|
Loading…
Reference in a new issue