mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-22 12:59:21 +00:00
Use WebSocket to update likes
This commit is contained in:
parent
526f698bf4
commit
469e1e1f92
@ -1,5 +1,5 @@
|
|||||||
import 'package:comunic/enums/likes_type.dart';
|
import 'package:comunic/enums/likes_type.dart';
|
||||||
import 'package:comunic/models/api_request.dart';
|
import 'package:comunic/helpers/websocket_helper.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
/// Likes helper
|
/// Likes helper
|
||||||
@ -15,21 +15,15 @@ const LikesAPIMap = {
|
|||||||
|
|
||||||
class LikesHelper {
|
class LikesHelper {
|
||||||
/// Update liking status of an element
|
/// Update liking status of an element
|
||||||
Future<bool> setLiking({
|
Future<void> setLiking({
|
||||||
@required LikesType type,
|
@required LikesType type,
|
||||||
@required bool like,
|
@required bool like,
|
||||||
@required int id,
|
@required int id,
|
||||||
}) async {
|
}) async {
|
||||||
return (await APIRequest(
|
return (await ws("likes/update", {
|
||||||
uri: "likes/update",
|
"type": LikesAPIMap[type],
|
||||||
needLogin: true,
|
"like": like.toString(),
|
||||||
args: {
|
"id": id.toString(),
|
||||||
"type": LikesAPIMap[type],
|
}));
|
||||||
"like": like.toString(),
|
|
||||||
"id": id.toString(),
|
|
||||||
},
|
|
||||||
).exec())
|
|
||||||
.code ==
|
|
||||||
200;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:comunic/helpers/events_helper.dart';
|
import 'package:comunic/helpers/events_helper.dart';
|
||||||
@ -13,6 +14,10 @@ import 'package:web_socket_channel/web_socket_channel.dart';
|
|||||||
class WebSocketHelper {
|
class WebSocketHelper {
|
||||||
static WebSocketChannel _ws;
|
static WebSocketChannel _ws;
|
||||||
|
|
||||||
|
static int _counter = 0;
|
||||||
|
|
||||||
|
static final _requests = Map<String, Completer<dynamic>>();
|
||||||
|
|
||||||
/// Check out whether we are currently connected to WebSocket or not
|
/// Check out whether we are currently connected to WebSocket or not
|
||||||
static bool isConnected() {
|
static bool isConnected() {
|
||||||
return _ws != null && _ws.closeCode == null;
|
return _ws != null && _ws.closeCode == null;
|
||||||
@ -57,11 +62,36 @@ class WebSocketHelper {
|
|||||||
// Notify when the channel is closed
|
// Notify when the channel is closed
|
||||||
onDone: () {
|
onDone: () {
|
||||||
print("WS Channel closed");
|
print("WS Channel closed");
|
||||||
|
|
||||||
|
// Clear Futures queue
|
||||||
|
_requests.clear();
|
||||||
|
|
||||||
EventsHelper.emit(WSClosedEvent());
|
EventsHelper.emit(WSClosedEvent());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send a new message
|
||||||
|
///
|
||||||
|
/// This method might throw an [Exception] in case of failure
|
||||||
|
static Future<dynamic> sendMessage(String title, dynamic data) {
|
||||||
|
if (!isConnected())
|
||||||
|
throw Exception("WS: Trying to send message but websocket is closed!");
|
||||||
|
|
||||||
|
final completer = Completer();
|
||||||
|
|
||||||
|
final id = "freq-${_counter++}";
|
||||||
|
|
||||||
|
final msg = WsMessage(id: id, title: title, data: data).toJSON();
|
||||||
|
|
||||||
|
print("WS Send message: $msg");
|
||||||
|
|
||||||
|
_ws.sink.add(msg);
|
||||||
|
|
||||||
|
_requests[id] = completer;
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
/// Process incoming message
|
/// Process incoming message
|
||||||
static _processMessage(String msgStr) {
|
static _processMessage(String msgStr) {
|
||||||
try {
|
try {
|
||||||
@ -70,7 +100,7 @@ class WebSocketHelper {
|
|||||||
if (!msg.hasId)
|
if (!msg.hasId)
|
||||||
_processUnattendedMessage(msg);
|
_processUnattendedMessage(msg);
|
||||||
else
|
else
|
||||||
throw Exception("Do not know how to process attended message!");
|
_respondRequests(msg);
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
print("WS could not process message: $e");
|
print("WS could not process message: $e");
|
||||||
print(stack);
|
print(stack);
|
||||||
@ -94,4 +124,25 @@ class WebSocketHelper {
|
|||||||
throw Exception("Unknown message type: ${msg.title}");
|
throw Exception("Unknown message type: ${msg.title}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Process responses to requests
|
||||||
|
static _respondRequests(WsMessage msg) {
|
||||||
|
if (!_requests.containsKey(msg.id))
|
||||||
|
throw Exception(
|
||||||
|
"Could not find request ${msg.id} in the requests queue!");
|
||||||
|
|
||||||
|
final completer = _requests.remove(msg.id);
|
||||||
|
|
||||||
|
// Handles errors
|
||||||
|
if (msg.title != "success") {
|
||||||
|
completer.completeError(Exception("Could not process request!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
completer.complete(msg.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function
|
||||||
|
Future<dynamic> ws(String title, dynamic data) =>
|
||||||
|
WebSocketHelper.sendMessage(title, data);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
/// WebSocket message
|
/// WebSocket message
|
||||||
@ -14,12 +16,21 @@ class WsMessage {
|
|||||||
@required this.title,
|
@required this.title,
|
||||||
@required this.data,
|
@required this.data,
|
||||||
}) : assert(id != null),
|
}) : assert(id != null),
|
||||||
assert(title != null);
|
assert(title != null),
|
||||||
|
assert(title.length > 0);
|
||||||
|
|
||||||
/// Construct a message from a JSON document (messages coming from the server)
|
/// Construct a message from a JSON document (messages coming from the server)
|
||||||
static WsMessage fromJSON(final Map<dynamic, dynamic> m) {
|
static WsMessage fromJSON(final Map<dynamic, dynamic> m) {
|
||||||
return WsMessage(id: m["id"], title: m["title"], data: m["data"]);
|
return WsMessage(id: m["id"], title: m["title"], data: m["data"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turn a message into a JSON object to send it to the API
|
||||||
|
String toJSON() =>
|
||||||
|
jsonEncode({
|
||||||
|
"id": id,
|
||||||
|
"title": title,
|
||||||
|
"data": data,
|
||||||
|
});
|
||||||
|
|
||||||
bool get hasId => this.id != null && this.id.isNotEmpty;
|
bool get hasId => this.id != null && this.id.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
@ -71,13 +71,16 @@ class _LikeWidgetState extends SafeState<LikeWidget> {
|
|||||||
/// Toggle like status
|
/// Toggle like status
|
||||||
void _toggleLike() async {
|
void _toggleLike() async {
|
||||||
// As like are not really important, we ignore failures
|
// As like are not really important, we ignore failures
|
||||||
if (await LikesHelper()
|
try {
|
||||||
.setLiking(type: elem.likeType, like: !elem.userLike, id: elem.id)) {
|
await LikesHelper()
|
||||||
|
.setLiking(type: elem.likeType, like: !elem.userLike, id: elem.id);
|
||||||
setState(() {
|
setState(() {
|
||||||
elem.userLike = !elem.userLike;
|
elem.userLike = !elem.userLike;
|
||||||
|
|
||||||
elem.likes += elem.userLike ? 1 : -1;
|
elem.likes += elem.userLike ? 1 : -1;
|
||||||
});
|
});
|
||||||
|
} catch (e, stack) {
|
||||||
|
print("$e\n$stack");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user