* LCIMClient.cs:

* LCIMPageResult.cs:
* LCIMChatRoom.cs:
* LCIMConversation.cs:
* LCIMConversationQuery.cs:
* LCIMGoAwayController.cs:
* LCIMUnreadController.cs:
* LCWebSocketConnection.cs:
* LCIMMessageController.cs:
* LCIMSessionController.cs:
* LCIMConversationController.cs:

* Program.cs: chore: 完善接口
oneRain 2020-03-27 15:52:34 +08:00
parent bfd14f5b59
commit a1376a346d
12 changed files with 475 additions and 104 deletions

View File

@ -5,7 +5,8 @@ using LeanCloud.Realtime.Protocol;
namespace LeanCloud.Realtime { namespace LeanCloud.Realtime {
public class LCIMChatRoom : LCIMConversation { public class LCIMChatRoom : LCIMConversation {
public LCIMChatRoom(LCIMClient client) : base(client) { public LCIMChatRoom(LCIMClient client) :
base(client) {
} }
public async Task<int> GetOnlineMembersCount() { public async Task<int> GetOnlineMembersCount() {

View File

@ -2,8 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq; using System.Linq;
using Newtonsoft.Json; using System.Collections.ObjectModel;
using Google.Protobuf;
using LeanCloud.Realtime.Protocol; using LeanCloud.Realtime.Protocol;
using LeanCloud.Storage; using LeanCloud.Storage;
@ -29,12 +28,16 @@ namespace LeanCloud.Realtime {
get; set; get; set;
} }
public List<string> MemberIdList { public ReadOnlyCollection<string> MemberIdList {
get; internal set; get {
return new ReadOnlyCollection<string>(ids.ToList());
}
} }
public List<string> MutedMemberIdList { public ReadOnlyCollection<string> MutedMemberIds {
get; internal set; get {
return new ReadOnlyCollection<string>(mutedIds.ToList());
}
} }
public int Unread { public int Unread {
@ -76,6 +79,10 @@ namespace LeanCloud.Realtime {
private Dictionary<string, object> customProperties; private Dictionary<string, object> customProperties;
internal HashSet<string> ids;
internal HashSet<string> mutedIds;
internal LCIMConversation(LCIMClient client) { internal LCIMConversation(LCIMClient client) {
Client = client; Client = client;
customProperties = new Dictionary<string, object>(); customProperties = new Dictionary<string, object>();
@ -286,7 +293,7 @@ namespace LeanCloud.Realtime {
/// 获取对话中成员的角色(只返回管理员) /// 获取对话中成员的角色(只返回管理员)
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public async Task<List<LCIMConversationMemberInfo>> GetAllMemberInfo() { public async Task<ReadOnlyCollection<LCIMConversationMemberInfo>> GetAllMemberInfo() {
return await Client.ConversationController.GetAllMemberInfo(Id); return await Client.ConversationController.GetAllMemberInfo(Id);
} }
@ -299,7 +306,7 @@ namespace LeanCloud.Realtime {
if (string.IsNullOrEmpty(memberId)) { if (string.IsNullOrEmpty(memberId)) {
throw new ArgumentNullException(nameof(memberId)); throw new ArgumentNullException(nameof(memberId));
} }
List<LCIMConversationMemberInfo> members = await GetAllMemberInfo(); ReadOnlyCollection<LCIMConversationMemberInfo> members = await GetAllMemberInfo();
foreach (LCIMConversationMemberInfo member in members) { foreach (LCIMConversationMemberInfo member in members) {
if (member.MemberId == memberId) { if (member.MemberId == memberId) {
return member; return member;
@ -308,11 +315,25 @@ namespace LeanCloud.Realtime {
return null; return null;
} }
public async Task<LCIMPageResult> QueryMutedMembers(int limit = 10, string next = null) { /// <summary>
/// 查询禁言用户
/// </summary>
/// <param name="limit"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task<LCIMPageResult> QueryMutedMembers(int limit = 10,
string next = null) {
return await Client.ConversationController.QueryMutedMembers(Id, limit, next); return await Client.ConversationController.QueryMutedMembers(Id, limit, next);
} }
public async Task<LCIMPageResult> QueryBlockedMembers(int limit = 10, string next = null) { /// <summary>
/// 查询黑名单用户
/// </summary>
/// <param name="limit"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task<LCIMPageResult> QueryBlockedMembers(int limit = 10,
string next = null) {
return await Client.ConversationController.QueryBlockedMembers(Id, limit, next); return await Client.ConversationController.QueryBlockedMembers(Id, limit, next);
} }
@ -342,7 +363,7 @@ namespace LeanCloud.Realtime {
UpdatedAt = DateTime.Parse(conv.Udate); UpdatedAt = DateTime.Parse(conv.Udate);
} }
if (conv.M.Count > 0) { if (conv.M.Count > 0) {
MemberIdList = conv.M.ToList(); ids = new HashSet<string>(conv.M.ToList());
} }
} }
@ -363,10 +384,10 @@ namespace LeanCloud.Realtime {
CreatorId = co as string; CreatorId = co as string;
} }
if (conv.TryGetValue("m", out object mo)) { if (conv.TryGetValue("m", out object mo)) {
MemberIdList = mo as List<string>; ids = new HashSet<string>(mo as List<string>);
} }
if (conv.TryGetValue("mu", out object muo)) { if (conv.TryGetValue("mu", out object muo)) {
MutedMemberIdList = muo as List<string>; mutedIds = new HashSet<string>(muo as List<string>);
} }
} }

View File

@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using LeanCloud.Storage.Internal.Query; using LeanCloud.Storage.Internal.Query;
namespace LeanCloud.Realtime { namespace LeanCloud.Realtime {
@ -22,7 +23,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereEqualTo(string key, object value) { public LCIMConversationQuery WhereEqualTo(string key,
object value) {
Condition.WhereEqualTo(key, value); Condition.WhereEqualTo(key, value);
return this; return this;
} }
@ -33,7 +35,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereNotEqualTo(string key, object value) { public LCIMConversationQuery WhereNotEqualTo(string key,
object value) {
Condition.WhereNotEqualTo(key, value); Condition.WhereNotEqualTo(key, value);
return this; return this;
} }
@ -44,7 +47,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="values"></param> /// <param name="values"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereContainedIn(string key, IEnumerable values) { public LCIMConversationQuery WhereContainedIn(string key,
IEnumerable values) {
Condition.WhereContainedIn(key, values); Condition.WhereContainedIn(key, values);
return this; return this;
} }
@ -55,7 +59,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="values"></param> /// <param name="values"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereContainsAll(string key, IEnumerable values) { public LCIMConversationQuery WhereContainsAll(string key,
IEnumerable values) {
Condition.WhereContainsAll(key, values); Condition.WhereContainsAll(key, values);
return this; return this;
} }
@ -86,7 +91,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="size"></param> /// <param name="size"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereSizeEqualTo(string key, int size) { public LCIMConversationQuery WhereSizeEqualTo(string key,
int size) {
Condition.WhereSizeEqualTo(key, size); Condition.WhereSizeEqualTo(key, size);
return this; return this;
} }
@ -97,7 +103,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereGreaterThan(string key, object value) { public LCIMConversationQuery WhereGreaterThan(string key,
object value) {
Condition.WhereGreaterThan(key, value); Condition.WhereGreaterThan(key, value);
return this; return this;
} }
@ -108,7 +115,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereGreaterThanOrEqualTo(string key, object value) { public LCIMConversationQuery WhereGreaterThanOrEqualTo(string key,
object value) {
Condition.WhereGreaterThanOrEqualTo(key, value); Condition.WhereGreaterThanOrEqualTo(key, value);
return this; return this;
} }
@ -119,7 +127,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereLessThan(string key, object value) { public LCIMConversationQuery WhereLessThan(string key,
object value) {
Condition.WhereLessThan(key, value); Condition.WhereLessThan(key, value);
return this; return this;
} }
@ -130,7 +139,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereLessThanOrEqualTo(string key, object value) { public LCIMConversationQuery WhereLessThanOrEqualTo(string key,
object value) {
Condition.WhereLessThanOrEqualTo(key, value); Condition.WhereLessThanOrEqualTo(key, value);
return this; return this;
} }
@ -141,7 +151,8 @@ namespace LeanCloud.Realtime {
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="prefix"></param> /// <param name="prefix"></param>
/// <returns></returns> /// <returns></returns>
public LCIMConversationQuery WhereStartsWith(string key, string prefix) { public LCIMConversationQuery WhereStartsWith(string key,
string prefix) {
Condition.WhereStartsWith(key, prefix); Condition.WhereStartsWith(key, prefix);
return this; return this;
} }
@ -236,7 +247,7 @@ namespace LeanCloud.Realtime {
/// 查找 /// 查找
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public async Task<List<LCIMConversation>> Find() { public async Task<ReadOnlyCollection<LCIMConversation>> Find() {
return await client.ConversationController.Find(this); return await client.ConversationController.Find(this);
} }
} }

View File

@ -1,13 +1,13 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using LeanCloud.Realtime.Protocol; using LeanCloud.Realtime.Protocol;
using LeanCloud.Storage.Internal; using LeanCloud.Storage.Internal;
using LeanCloud.Storage.Internal.Codec; using LeanCloud.Storage.Internal.Codec;
using LeanCloud.Common; using LeanCloud.Common;
using Google.Protobuf;
namespace LeanCloud.Realtime.Internal.Controller { namespace LeanCloud.Realtime.Internal.Controller {
internal class LCIMConversationController : LCIMController { internal class LCIMConversationController : LCIMController {
@ -15,6 +15,19 @@ namespace LeanCloud.Realtime.Internal.Controller {
} }
#region 内部接口
/// <summary>
/// 创建对话
/// </summary>
/// <param name="members"></param>
/// <param name="name"></param>
/// <param name="transient"></param>
/// <param name="unique"></param>
/// <param name="temporary"></param>
/// <param name="temporaryTtl"></param>
/// <param name="properties"></param>
/// <returns></returns>
internal async Task<LCIMConversation> CreateConv( internal async Task<LCIMConversation> CreateConv(
IEnumerable<string> members = null, IEnumerable<string> members = null,
string name = null, string name = null,
@ -66,12 +79,17 @@ namespace LeanCloud.Realtime.Internal.Controller {
} }
// 合并请求数据 // 合并请求数据
conversation.Name = name; conversation.Name = name;
conversation.MemberIdList = members?.ToList(); conversation.ids = members != null ? new HashSet<string>(members) : null;
// 合并服务端推送的数据 // 合并服务端推送的数据
conversation.MergeFrom(response.ConvMessage); conversation.MergeFrom(response.ConvMessage);
return conversation; return conversation;
} }
/// <summary>
/// 查询成员数量
/// </summary>
/// <param name="convId"></param>
/// <returns></returns>
internal async Task<int> GetMembersCount(string convId) { internal async Task<int> GetMembersCount(string convId) {
ConvCommand conv = new ConvCommand { ConvCommand conv = new ConvCommand {
Cid = convId, Cid = convId,
@ -82,6 +100,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
return response.ConvMessage.Count; return response.ConvMessage.Count;
} }
/// <summary>
/// 标记对话的消息已读
/// </summary>
/// <param name="convId"></param>
/// <param name="message"></param>
/// <returns></returns>
internal async Task Read(string convId, internal async Task Read(string convId,
LCIMMessage message) { LCIMMessage message) {
ReadCommand read = new ReadCommand(); ReadCommand read = new ReadCommand();
@ -96,6 +120,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
await Client.Connection.SendRequest(request); await Client.Connection.SendRequest(request);
} }
/// <summary>
/// 更新对话属性
/// </summary>
/// <param name="convId"></param>
/// <param name="attributes"></param>
/// <returns></returns>
internal async Task<Dictionary<string, object>> UpdateInfo(string convId, internal async Task<Dictionary<string, object>> UpdateInfo(string convId,
Dictionary<string, object> attributes) { Dictionary<string, object> attributes) {
ConvCommand conv = new ConvCommand { ConvCommand conv = new ConvCommand {
@ -116,6 +146,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
return null; return null;
} }
/// <summary>
/// 增加成员
/// </summary>
/// <param name="convId"></param>
/// <param name="clientIds"></param>
/// <returns></returns>
internal async Task<LCIMPartiallySuccessResult> AddMembers(string convId, internal async Task<LCIMPartiallySuccessResult> AddMembers(string convId,
IEnumerable<string> clientIds) { IEnumerable<string> clientIds) {
ConvCommand conv = new ConvCommand { ConvCommand conv = new ConvCommand {
@ -140,6 +176,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
return NewPartiallySuccessResult(allowedIds, errors); return NewPartiallySuccessResult(allowedIds, errors);
} }
/// <summary>
/// 移除成员
/// </summary>
/// <param name="convId"></param>
/// <param name="removeIds"></param>
/// <returns></returns>
internal async Task<LCIMPartiallySuccessResult> RemoveMembers(string convId, internal async Task<LCIMPartiallySuccessResult> RemoveMembers(string convId,
IEnumerable<string> removeIds) { IEnumerable<string> removeIds) {
ConvCommand conv = new ConvCommand { ConvCommand conv = new ConvCommand {
@ -164,6 +206,11 @@ namespace LeanCloud.Realtime.Internal.Controller {
return NewPartiallySuccessResult(allowedIds, errors); return NewPartiallySuccessResult(allowedIds, errors);
} }
/// <summary>
/// 静音
/// </summary>
/// <param name="convId"></param>
/// <returns></returns>
internal async Task Mute(string convId) { internal async Task Mute(string convId) {
ConvCommand conv = new ConvCommand { ConvCommand conv = new ConvCommand {
Cid = convId Cid = convId
@ -173,6 +220,11 @@ namespace LeanCloud.Realtime.Internal.Controller {
await Client.Connection.SendRequest(request); await Client.Connection.SendRequest(request);
} }
/// <summary>
/// 解除静音
/// </summary>
/// <param name="convId"></param>
/// <returns></returns>
internal async Task Unmute(string convId) { internal async Task Unmute(string convId) {
ConvCommand conv = new ConvCommand { ConvCommand conv = new ConvCommand {
Cid = convId Cid = convId
@ -182,6 +234,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
await Client.Connection.SendRequest(request); await Client.Connection.SendRequest(request);
} }
/// <summary>
/// 禁言用户
/// </summary>
/// <param name="convId"></param>
/// <param name="clientIds"></param>
/// <returns></returns>
internal async Task<LCIMPartiallySuccessResult> MuteMembers(string convId, internal async Task<LCIMPartiallySuccessResult> MuteMembers(string convId,
IEnumerable<string> clientIds) { IEnumerable<string> clientIds) {
if (clientIds == null || clientIds.Count() == 0) { if (clientIds == null || clientIds.Count() == 0) {
@ -197,6 +255,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids); return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
} }
/// <summary>
/// 解除用户禁言
/// </summary>
/// <param name="convId"></param>
/// <param name="clientIds"></param>
/// <returns></returns>
internal async Task<LCIMPartiallySuccessResult> UnmuteMembers(string convId, internal async Task<LCIMPartiallySuccessResult> UnmuteMembers(string convId,
IEnumerable<string> clientIds) { IEnumerable<string> clientIds) {
ConvCommand conv = new ConvCommand { ConvCommand conv = new ConvCommand {
@ -209,6 +273,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids); return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
} }
/// <summary>
/// 拉黑成员
/// </summary>
/// <param name="convId"></param>
/// <param name="clientIds"></param>
/// <returns></returns>
internal async Task<LCIMPartiallySuccessResult> BlockMembers(string convId, internal async Task<LCIMPartiallySuccessResult> BlockMembers(string convId,
IEnumerable<string> clientIds) { IEnumerable<string> clientIds) {
BlacklistCommand blacklist = new BlacklistCommand { BlacklistCommand blacklist = new BlacklistCommand {
@ -230,6 +300,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids); return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
} }
/// <summary>
/// 移除成员黑名单
/// </summary>
/// <param name="convId"></param>
/// <param name="clientIds"></param>
/// <returns></returns>
internal async Task<LCIMPartiallySuccessResult> UnblockMembers(string convId, internal async Task<LCIMPartiallySuccessResult> UnblockMembers(string convId,
IEnumerable<string> clientIds) { IEnumerable<string> clientIds) {
BlacklistCommand blacklist = new BlacklistCommand { BlacklistCommand blacklist = new BlacklistCommand {
@ -251,6 +327,13 @@ namespace LeanCloud.Realtime.Internal.Controller {
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids); return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
} }
/// <summary>
/// 修改成员角色
/// </summary>
/// <param name="convId"></param>
/// <param name="memberId"></param>
/// <param name="role"></param>
/// <returns></returns>
internal async Task UpdateMemberRole(string convId, internal async Task UpdateMemberRole(string convId,
string memberId, string memberId,
string role) { string role) {
@ -267,7 +350,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
GenericCommand response = await Client.Connection.SendRequest(request); GenericCommand response = await Client.Connection.SendRequest(request);
} }
internal async Task<List<LCIMConversationMemberInfo>> GetAllMemberInfo(string convId) { /// <summary>
/// 获取所有成员角色
/// </summary>
/// <param name="convId"></param>
/// <returns></returns>
internal async Task<ReadOnlyCollection<LCIMConversationMemberInfo>> GetAllMemberInfo(string convId) {
string path = "classes/_ConversationMemberInfo"; string path = "classes/_ConversationMemberInfo";
string token = await Client.SessionController.GetToken(); string token = await Client.SessionController.GetToken();
Dictionary<string, object> headers = new Dictionary<string, object> { Dictionary<string, object> headers = new Dictionary<string, object> {
@ -280,18 +368,23 @@ namespace LeanCloud.Realtime.Internal.Controller {
Dictionary<string, object> response = await LCApplication.HttpClient.Get<Dictionary<string, object>>(path, Dictionary<string, object> response = await LCApplication.HttpClient.Get<Dictionary<string, object>>(path,
headers: headers, queryParams: queryParams); headers: headers, queryParams: queryParams);
List<object> results = response["results"] as List<object>; List<object> results = response["results"] as List<object>;
List<LCIMConversationMemberInfo> memberList = new List<LCIMConversationMemberInfo>(); return results.Select(item => {
foreach (Dictionary<string, object> item in results) { Dictionary<string, object> memberInfo = item as Dictionary<string, object>;
LCIMConversationMemberInfo member = new LCIMConversationMemberInfo { return new LCIMConversationMemberInfo {
ConversationId = item["cid"] as string, ConversationId = memberInfo["cid"] as string,
MemberId = item["clientId"] as string, MemberId = memberInfo["clientId"] as string,
Role = item["role"] as string Role = memberInfo["role"] as string
}; };
memberList.Add(member); }).ToList().AsReadOnly();
}
return memberList;
} }
/// <summary>
/// 查询禁言成员
/// </summary>
/// <param name="convId"></param>
/// <param name="limit"></param>
/// <param name="next"></param>
/// <returns></returns>
internal async Task<LCIMPageResult> QueryMutedMembers(string convId, internal async Task<LCIMPageResult> QueryMutedMembers(string convId,
int limit = 10, int limit = 10,
string next = null) { string next = null) {
@ -304,11 +397,18 @@ namespace LeanCloud.Realtime.Internal.Controller {
request.ConvMessage = conv; request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request); GenericCommand response = await Client.Connection.SendRequest(request);
return new LCIMPageResult { return new LCIMPageResult {
Results = response.ConvMessage.M.ToList(), Results = new ReadOnlyCollection<string>(response.ConvMessage.M),
Next = response.ConvMessage.Next Next = response.ConvMessage.Next
}; };
} }
/// <summary>
/// 查询黑名单用户
/// </summary>
/// <param name="convId"></param>
/// <param name="limit"></param>
/// <param name="next"></param>
/// <returns></returns>
internal async Task<LCIMPageResult> QueryBlockedMembers(string convId, internal async Task<LCIMPageResult> QueryBlockedMembers(string convId,
int limit = 10, int limit = 10,
string next = null) { string next = null) {
@ -321,12 +421,17 @@ namespace LeanCloud.Realtime.Internal.Controller {
request.BlacklistMessage = black; request.BlacklistMessage = black;
GenericCommand response = await Client.Connection.SendRequest(request); GenericCommand response = await Client.Connection.SendRequest(request);
return new LCIMPageResult { return new LCIMPageResult {
Results = response.BlacklistMessage.BlockedPids.ToList(), Results = new ReadOnlyCollection<string>(response.BlacklistMessage.BlockedPids),
Next = response.BlacklistMessage.Next Next = response.BlacklistMessage.Next
}; };
} }
internal async Task<List<LCIMConversation>> Find(LCIMConversationQuery query) { /// <summary>
/// 查找
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
internal async Task<ReadOnlyCollection<LCIMConversation>> Find(LCIMConversationQuery query) {
GenericCommand command = new GenericCommand { GenericCommand command = new GenericCommand {
Cmd = CommandType.Conv, Cmd = CommandType.Conv,
Op = OpType.Query, Op = OpType.Query,
@ -348,7 +453,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
GenericCommand response = await Connection.SendRequest(command); GenericCommand response = await Connection.SendRequest(command);
JsonObjectMessage results = response.ConvMessage.Results; JsonObjectMessage results = response.ConvMessage.Results;
List<object> convs = JsonConvert.DeserializeObject<List<object>>(results.Data, new LCJsonConverter()); List<object> convs = JsonConvert.DeserializeObject<List<object>>(results.Data, new LCJsonConverter());
List<LCIMConversation> convList = convs.Select(item => { return convs.Select(item => {
Dictionary<string, object> conv = item as Dictionary<string, object>; Dictionary<string, object> conv = item as Dictionary<string, object>;
string convId = conv["objectId"] as string; string convId = conv["objectId"] as string;
if (!Client.ConversationDict.TryGetValue(convId, out LCIMConversation conversation)) { if (!Client.ConversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
@ -359,11 +464,13 @@ namespace LeanCloud.Realtime.Internal.Controller {
} }
conversation.MergeFrom(conv); conversation.MergeFrom(conv);
return conversation; return conversation;
}).ToList(); }).ToList().AsReadOnly();
return convList;
} }
internal async Task<List<LCIMTemporaryConversation>> GetTemporaryConversations(IEnumerable<string> convIds) { internal async Task<List<LCIMTemporaryConversation>> GetTemporaryConversations(IEnumerable<string> convIds) {
if (convIds == null || convIds.Count() == 0) {
return null;
}
ConvCommand convMessage = new ConvCommand(); ConvCommand convMessage = new ConvCommand();
convMessage.TempConvIds.AddRange(convIds); convMessage.TempConvIds.AddRange(convIds);
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Query); GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Query);
@ -393,68 +500,194 @@ namespace LeanCloud.Realtime.Internal.Controller {
return result; return result;
} }
#endregion
#region 消息处理
internal override async Task OnNotification(GenericCommand notification) { internal override async Task OnNotification(GenericCommand notification) {
ConvCommand conv = notification.ConvMessage; ConvCommand convMessage = notification.ConvMessage;
switch (notification.Op) { switch (notification.Op) {
case OpType.Joined: case OpType.Joined:
await OnConversationJoined(conv); await OnJoined(convMessage);
break; break;
case OpType.MembersJoined: case OpType.MembersJoined:
await OnConversationMembersJoined(conv); await OnMembersJoined(convMessage);
break; break;
case OpType.Left: case OpType.Left:
await OnConversationLeft(conv); await OnLeft(convMessage);
break; break;
case OpType.MembersLeft: case OpType.MembersLeft:
await OnConversationMemberLeft(conv); await OnMemberLeft(convMessage);
break;
case OpType.Blocked:
await OnBlocked(convMessage);
break;
case OpType.MembersBlocked:
await OnMembersBlocked(convMessage);
break;
case OpType.MembersUnblocked:
await OnMembersUnblocked(convMessage);
break;
case OpType.Shutuped:
await OnMuted(convMessage);
break;
case OpType.MembersShutuped:
await OnMembersMuted(convMessage);
break;
case OpType.MembersUnshutuped:
await OnMembersUnmuted(convMessage);
break; break;
case OpType.Updated: case OpType.Updated:
await OnConversationPropertiesUpdated(conv); await OnPropertiesUpdated(convMessage);
break; break;
case OpType.MemberInfoChanged: case OpType.MemberInfoChanged:
await OnConversationMemberInfoChanged(conv); await OnMemberInfoChanged(convMessage);
break; break;
default: default:
break; break;
} }
} }
private async Task OnConversationJoined(ConvCommand conv) { /// <summary>
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid); /// 当前用户加入会话
conversation.MergeFrom(conv); /// </summary>
Client.OnInvited?.Invoke(conversation, conv.InitBy); /// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnJoined(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
conversation.MergeFrom(convMessage);
Client.OnInvited?.Invoke(conversation, convMessage.InitBy);
} }
private async Task OnConversationMembersJoined(ConvCommand conv) { /// <summary>
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid); /// 有用户加入会话
conversation.MergeFrom(conv); /// </summary>
Client.OnMembersJoined?.Invoke(conversation, conv.M.ToList(), conv.InitBy); /// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnMembersJoined(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
ReadOnlyCollection<string> joinedIds = new ReadOnlyCollection<string>(convMessage.M);
conversation.ids.Union(joinedIds);
Client.OnMembersJoined?.Invoke(conversation, joinedIds, convMessage.InitBy);
} }
private async Task OnConversationLeft(ConvCommand conv) { /// <summary>
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid); /// 当前用户离开会话
Client.OnKicked?.Invoke(conversation, conv.InitBy); /// </summary>
/// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnLeft(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
Client.OnKicked?.Invoke(conversation, convMessage.InitBy);
// TODO 从内存中清除对话
} }
private async Task OnConversationMemberLeft(ConvCommand conv) { /// <summary>
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid); /// 有成员离开会话
List<string> leftIdList = conv.M.ToList(); /// </summary>
Client.OnMembersLeft?.Invoke(conversation, leftIdList, conv.InitBy); /// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnMemberLeft(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
ReadOnlyCollection<string> leftIdList = new ReadOnlyCollection<string>(convMessage.M);
conversation.ids.RemoveWhere(item => leftIdList.Contains(item));
Client.OnMembersLeft?.Invoke(conversation, leftIdList, convMessage.InitBy);
} }
private async Task OnConversationPropertiesUpdated(ConvCommand conv) { /// <summary>
/// 当前用户被禁言
/// </summary>
/// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnMuted(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
Client.OnMuted?.Invoke(conversation, convMessage.InitBy);
}
/// <summary>
/// 有成员被禁言
/// </summary>
/// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnMembersMuted(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
ReadOnlyCollection<string> mutedMemberIds = new ReadOnlyCollection<string>(convMessage.M);
conversation.mutedIds.Union(mutedMemberIds);
Client.OnMembersMuted?.Invoke(conversation, mutedMemberIds, convMessage.InitBy);
}
/// <summary>
/// 有成员被解除禁言
/// </summary>
/// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnMembersUnmuted(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
ReadOnlyCollection<string> unmutedMemberIds = new ReadOnlyCollection<string>(convMessage.M);
conversation.mutedIds.RemoveWhere(id => unmutedMemberIds.Contains(id));
Client.OnMembersUnmuted?.Invoke(conversation, unmutedMemberIds, convMessage.InitBy);
}
/// <summary>
/// 当前用户被拉黑
/// </summary>
/// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnBlocked(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
Client.OnBlocked?.Invoke(conversation, convMessage.InitBy);
}
/// <summary>
/// 有用户被拉黑
/// </summary>
/// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnMembersBlocked(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
ReadOnlyCollection<string> blockedMemberIds = convMessage.M.ToList().AsReadOnly();
Client.OnMembersBlocked?.Invoke(conversation, blockedMemberIds, convMessage.InitBy);
}
/// <summary>
/// 有用户被移除黑名单
/// </summary>
/// <param name="convMessage"></param>
/// <returns></returns>
private async Task OnMembersUnblocked(ConvCommand convMessage) {
LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid);
ReadOnlyCollection<string> unblockedMemberIds = convMessage.M.ToList().AsReadOnly();
Client.OnMembersUnblocked?.Invoke(conversation, unblockedMemberIds, convMessage.InitBy);
}
/// <summary>
/// 对话属性被修改
/// </summary>
/// <param name="conv"></param>
/// <returns></returns>
private async Task OnPropertiesUpdated(ConvCommand conv) {
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid); LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid);
Dictionary<string, object> updatedAttr = JsonConvert.DeserializeObject<Dictionary<string, object>>(conv.AttrModified.Data, Dictionary<string, object> updatedAttr = JsonConvert.DeserializeObject<Dictionary<string, object>>(conv.AttrModified.Data,
new LCJsonConverter()); new LCJsonConverter());
// 更新内存数据 // 更新内存数据
conversation.MergeInfo(updatedAttr); conversation.MergeInfo(updatedAttr);
Client.OnConversationInfoUpdated?.Invoke(conversation, updatedAttr, conv.InitBy); Client.OnConversationInfoUpdated?.Invoke(conversation,
new ReadOnlyDictionary<string, object>(updatedAttr),
conv.InitBy);
} }
private async Task OnConversationMemberInfoChanged(ConvCommand conv) { /// <summary>
/// 用户角色被修改
/// </summary>
/// <param name="conv"></param>
/// <returns></returns>
private async Task OnMemberInfoChanged(ConvCommand conv) {
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid); LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid);
ConvMemberInfo memberInfo = conv.Info; ConvMemberInfo memberInfo = conv.Info;
Client.OnMemberInfoUpdated?.Invoke(conversation, memberInfo.Pid, memberInfo.Role, conv.InitBy); Client.OnMemberInfoUpdated?.Invoke(conversation, memberInfo.Pid, memberInfo.Role, conv.InitBy);
} }
#endregion
} }
} }

View File

@ -7,10 +7,14 @@ namespace LeanCloud.Realtime.Internal.Controller {
} }
#region 消息处理
internal override async Task OnNotification(GenericCommand notification) { internal override async Task OnNotification(GenericCommand notification) {
// 清空缓存,断开连接,等待重新连接 // 清空缓存,断开连接,等待重新连接
Connection.Router.Reset(); Connection.Router.Reset();
await Connection.Close(); await Connection.Close();
} }
#endregion
} }
} }

View File

@ -12,6 +12,14 @@ namespace LeanCloud.Realtime.Internal.Controller {
} }
#region 内部接口
/// <summary>
/// 发送消息
/// </summary>
/// <param name="convId"></param>
/// <param name="message"></param>
/// <returns></returns>
internal async Task<LCIMMessage> Send(string convId, internal async Task<LCIMMessage> Send(string convId,
LCIMMessage message) { LCIMMessage message) {
DirectCommand direct = new DirectCommand { DirectCommand direct = new DirectCommand {
@ -35,6 +43,12 @@ namespace LeanCloud.Realtime.Internal.Controller {
return message; return message;
} }
/// <summary>
/// 撤回消息
/// </summary>
/// <param name="convId"></param>
/// <param name="message"></param>
/// <returns></returns>
internal async Task RecallMessage(string convId, internal async Task RecallMessage(string convId,
LCIMMessage message) { LCIMMessage message) {
PatchCommand patch = new PatchCommand(); PatchCommand patch = new PatchCommand();
@ -49,6 +63,13 @@ namespace LeanCloud.Realtime.Internal.Controller {
await Client.Connection.SendRequest(request); await Client.Connection.SendRequest(request);
} }
/// <summary>
/// 修改消息
/// </summary>
/// <param name="convId"></param>
/// <param name="oldMessage"></param>
/// <param name="newMessage"></param>
/// <returns></returns>
internal async Task UpdateMessage(string convId, internal async Task UpdateMessage(string convId,
LCIMMessage oldMessage, LCIMMessage oldMessage,
LCIMMessage newMessage) { LCIMMessage newMessage) {
@ -76,6 +97,16 @@ namespace LeanCloud.Realtime.Internal.Controller {
GenericCommand response = await Client.Connection.SendRequest(request); GenericCommand response = await Client.Connection.SendRequest(request);
} }
/// <summary>
/// 查询消息
/// </summary>
/// <param name="convId"></param>
/// <param name="start"></param>
/// <param name="end"></param>
/// <param name="direction"></param>
/// <param name="limit"></param>
/// <param name="messageType"></param>
/// <returns></returns>
internal async Task<List<LCIMMessage>> QueryMessages(string convId, internal async Task<List<LCIMMessage>> QueryMessages(string convId,
LCIMMessageQueryEndpoint start = null, LCIMMessageQueryEndpoint start = null,
LCIMMessageQueryEndpoint end = null, LCIMMessageQueryEndpoint end = null,
@ -109,6 +140,10 @@ namespace LeanCloud.Realtime.Internal.Controller {
return null; return null;
} }
#endregion
#region 消息处理
internal override async Task OnNotification(GenericCommand notification) { internal override async Task OnNotification(GenericCommand notification) {
DirectCommand direct = notification.DirectMessage; DirectCommand direct = notification.DirectMessage;
LCIMMessage message = null; LCIMMessage message = null;
@ -150,5 +185,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
LCIMConversation conversation = await Client.GetOrQueryConversation(direct.Cid); LCIMConversation conversation = await Client.GetOrQueryConversation(direct.Cid);
Client.OnMessage?.Invoke(conversation, message); Client.OnMessage?.Invoke(conversation, message);
} }
#endregion
} }
} }

View File

@ -7,10 +7,17 @@ namespace LeanCloud.Realtime.Internal.Controller {
private string token; private string token;
private DateTimeOffset expiredAt; private DateTimeOffset expiredAt;
internal LCIMSessionController(LCIMClient client) : base(client) { internal LCIMSessionController(LCIMClient client)
: base(client) {
} }
#region 内部接口
/// <summary>
/// 打开会话
/// </summary>
/// <returns></returns>
internal async Task Open() { internal async Task Open() {
SessionCommand session = NewSessionCommand(); SessionCommand session = NewSessionCommand();
GenericCommand request = Client.NewCommand(CommandType.Session, OpType.Open); GenericCommand request = Client.NewCommand(CommandType.Session, OpType.Open);
@ -19,11 +26,19 @@ namespace LeanCloud.Realtime.Internal.Controller {
UpdateSession(response.SessionMessage); UpdateSession(response.SessionMessage);
} }
/// <summary>
/// 关闭会话
/// </summary>
/// <returns></returns>
internal async Task Close() { internal async Task Close() {
GenericCommand request = Client.NewCommand(CommandType.Session, OpType.Close); GenericCommand request = Client.NewCommand(CommandType.Session, OpType.Close);
await Client.Connection.SendRequest(request); await Client.Connection.SendRequest(request);
} }
/// <summary>
/// 获取可用 token
/// </summary>
/// <returns></returns>
internal async Task<string> GetToken() { internal async Task<string> GetToken() {
if (IsExpired) { if (IsExpired) {
await Refresh(); await Refresh();
@ -31,6 +46,8 @@ namespace LeanCloud.Realtime.Internal.Controller {
return token; return token;
} }
#endregion
private async Task Refresh() { private async Task Refresh() {
SessionCommand session = NewSessionCommand(); SessionCommand session = NewSessionCommand();
GenericCommand request = Client.NewCommand(CommandType.Session, OpType.Refresh); GenericCommand request = Client.NewCommand(CommandType.Session, OpType.Refresh);
@ -56,6 +73,14 @@ namespace LeanCloud.Realtime.Internal.Controller {
expiredAt = DateTimeOffset.Now + TimeSpan.FromSeconds(ttl); expiredAt = DateTimeOffset.Now + TimeSpan.FromSeconds(ttl);
} }
private bool IsExpired {
get {
return DateTimeOffset.Now > expiredAt;
}
}
#region 消息处理
internal override async Task OnNotification(GenericCommand notification) { internal override async Task OnNotification(GenericCommand notification) {
switch (notification.Op) { switch (notification.Op) {
case OpType.Closed: case OpType.Closed:
@ -66,12 +91,11 @@ namespace LeanCloud.Realtime.Internal.Controller {
} }
} }
private bool IsExpired { /// <summary>
get { /// 被关闭
return DateTimeOffset.Now > expiredAt; /// </summary>
} /// <param name="session"></param>
} /// <returns></returns>
private async Task OnClosed(SessionCommand session) { private async Task OnClosed(SessionCommand session) {
int code = session.Code; int code = session.Code;
string reason = session.Reason; string reason = session.Reason;
@ -79,5 +103,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
await Connection.Close(); await Connection.Close();
Client.OnClose?.Invoke(code, reason, detail); Client.OnClose?.Invoke(code, reason, detail);
} }
#endregion
} }
} }

View File

@ -1,6 +1,7 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using Newtonsoft.Json; using Newtonsoft.Json;
using LeanCloud.Realtime.Protocol; using LeanCloud.Realtime.Protocol;
using LeanCloud.Storage.Internal; using LeanCloud.Storage.Internal;
@ -8,17 +9,20 @@ using LeanCloud.Storage.Internal;
namespace LeanCloud.Realtime.Internal.Controller { namespace LeanCloud.Realtime.Internal.Controller {
internal class LCIMUnreadController : LCIMController { internal class LCIMUnreadController : LCIMController {
internal LCIMUnreadController(LCIMClient client) : base(client) { internal LCIMUnreadController(LCIMClient client) : base(client) {
} }
#region 消息处理
internal override async Task OnNotification(GenericCommand notification) { internal override async Task OnNotification(GenericCommand notification) {
UnreadCommand unread = notification.UnreadMessage; UnreadCommand unread = notification.UnreadMessage;
IEnumerable<string> convIds = unread.Convs IEnumerable<string> convIds = unread.Convs
.Select(conv => conv.Cid); .Select(conv => conv.Cid);
Dictionary<string, LCIMConversation> conversations = (await Client.GetConversationList(convIds)) Dictionary<string, LCIMConversation> conversationDict = (await Client.GetConversationList(convIds))
.ToDictionary(item => item.Id); .ToDictionary(item => item.Id);
List<LCIMConversation> conversationList = unread.Convs.Select(conv => { ReadOnlyCollection<LCIMConversation> conversations = unread.Convs.Select(conv => {
LCIMConversation conversation = conversations[conv.Cid]; LCIMConversation conversation = conversationDict[conv.Cid];
conversation.Unread = conv.Unread; conversation.Unread = conv.Unread;
// 解析最后一条消息 // 解析最后一条消息
Dictionary<string, object> msgData = JsonConvert.DeserializeObject<Dictionary<string, object>>(conv.Data, Dictionary<string, object> msgData = JsonConvert.DeserializeObject<Dictionary<string, object>>(conv.Data,
@ -53,8 +57,10 @@ namespace LeanCloud.Realtime.Internal.Controller {
message.SentTimestamp = conv.Timestamp; message.SentTimestamp = conv.Timestamp;
conversation.LastMessage = message; conversation.LastMessage = message;
return conversation; return conversation;
}).ToList(); }).ToList().AsReadOnly();
Client.OnUnreadMessagesCountUpdated?.Invoke(conversationList); Client.OnUnreadMessagesCountUpdated?.Invoke(conversations);
} }
#endregion
} }
} }

View File

@ -116,7 +116,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
ErrorCommand error = command.ErrorMessage; ErrorCommand error = command.ErrorMessage;
int code = error.Code; int code = error.Code;
string detail = error.Detail; string detail = error.Detail;
// TODO 包装成异常抛出 // 包装成异常抛出
LCException exception = new LCException(code, detail); LCException exception = new LCException(code, detail);
tcs.SetException(exception); tcs.SetException(exception);
} else { } else {

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq; using System.Linq;
using System.Collections.ObjectModel;
using LeanCloud.Realtime.Internal.WebSocket; using LeanCloud.Realtime.Internal.WebSocket;
using LeanCloud.Realtime.Protocol; using LeanCloud.Realtime.Protocol;
using LeanCloud.Realtime.Internal.Controller; using LeanCloud.Realtime.Internal.Controller;
@ -78,7 +79,7 @@ namespace LeanCloud.Realtime {
/// <summary> /// <summary>
/// 该对话信息被更新 /// 该对话信息被更新
/// </summary> /// </summary>
public Action<LCIMConversation, Dictionary<string, object>, string> OnConversationInfoUpdated; public Action<LCIMConversation, ReadOnlyDictionary<string, object>, string> OnConversationInfoUpdated;
/// <summary> /// <summary>
/// 当前用户被添加至某个对话 /// 当前用户被添加至某个对话
@ -97,42 +98,42 @@ namespace LeanCloud.Realtime {
/// <summary> /// <summary>
/// 有用户被添加至某个对话 /// 有用户被添加至某个对话
/// </summary> /// </summary>
public Action<LCIMConversation, List<string>, string> OnMembersJoined { public Action<LCIMConversation, ReadOnlyCollection<string>, string> OnMembersJoined {
get; set; get; set;
} }
/// <summary> /// <summary>
/// 有成员被从某个对话中移除 /// 有成员被从某个对话中移除
/// </summary> /// </summary>
public Action<LCIMConversation, List<string>, string> OnMembersLeft { public Action<LCIMConversation, ReadOnlyCollection<string>, string> OnMembersLeft {
get; set; get; set;
} }
/// <summary> /// <summary>
/// 有成员被加入某个对话的黑名单 /// 有成员被加入某个对话的黑名单
/// </summary> /// </summary>
public Action<LCIMConversation, List<string>, string> OnMembersBlocked { public Action<LCIMConversation, ReadOnlyCollection<string>, string> OnMembersBlocked {
get; set; get; set;
} }
/// <summary> /// <summary>
/// 有成员被移出某个对话的黑名单 /// 有成员被移出某个对话的黑名单
/// </summary> /// </summary>
public Action<LCIMConversation, List<string>, string> OnMembersUnblocked { public Action<LCIMConversation, ReadOnlyCollection<string>, string> OnMembersUnblocked {
get; set; get; set;
} }
/// <summary> /// <summary>
/// 有成员在某个对话中被禁言 /// 有成员在某个对话中被禁言
/// </summary> /// </summary>
public Action<LCIMConversation, List<string>, string> OnMembersMuted { public Action<LCIMConversation, ReadOnlyCollection<string>, string> OnMembersMuted {
get; set; get; set;
} }
/// <summary> /// <summary>
/// 有成员被移出某个对话的黑名单 /// 有成员被移出某个对话的黑名单
/// </summary> /// </summary>
public Action<LCIMConversation, List<string>, string> OnMembersUnmuted { public Action<LCIMConversation, ReadOnlyCollection<string>, string> OnMembersUnmuted {
get; set; get; set;
} }
@ -165,7 +166,7 @@ namespace LeanCloud.Realtime {
/// <summary> /// <summary>
/// 未读消息数目更新 /// 未读消息数目更新
/// </summary> /// </summary>
public Action<List<LCIMConversation>> OnUnreadMessagesCountUpdated { public Action<ReadOnlyCollection<LCIMConversation>> OnUnreadMessagesCountUpdated {
get; set; get; set;
} }
@ -318,7 +319,7 @@ namespace LeanCloud.Realtime {
LCIMConversationQuery query = GetQuery() LCIMConversationQuery query = GetQuery()
.WhereEqualTo("objectId", id) .WhereEqualTo("objectId", id)
.Limit(1); .Limit(1);
List<LCIMConversation> results = await ConversationController.Find(query); ReadOnlyCollection<LCIMConversation> results = await ConversationController.Find(query);
if (results == null || results.Count < 1) { if (results == null || results.Count < 1) {
return null; return null;
} }
@ -330,7 +331,7 @@ namespace LeanCloud.Realtime {
/// </summary> /// </summary>
/// <param name="ids"></param> /// <param name="ids"></param>
/// <returns></returns> /// <returns></returns>
public async Task<List<LCIMConversation>> GetConversationList(IEnumerable<string> ids) { public async Task<ReadOnlyCollection<LCIMConversation>> GetConversationList(IEnumerable<string> ids) {
if (ids == null || ids.Count() == 0) { if (ids == null || ids.Count() == 0) {
throw new ArgumentNullException(nameof(ids)); throw new ArgumentNullException(nameof(ids));
} }
@ -341,13 +342,19 @@ namespace LeanCloud.Realtime {
IEnumerable<string> convIds = ids.Where(item => { IEnumerable<string> convIds = ids.Where(item => {
return !tempConvIds.Contains(item); return !tempConvIds.Contains(item);
}); });
List<LCIMConversation> conversationList = new List<LCIMConversation>();
if (tempConvIds.Count() > 0) {
List<LCIMTemporaryConversation> temporaryConversations = await ConversationController.GetTemporaryConversations(tempConvIds); List<LCIMTemporaryConversation> temporaryConversations = await ConversationController.GetTemporaryConversations(tempConvIds);
conversationList.AddRange(temporaryConversations);
}
if (convIds.Count() > 0) {
LCIMConversationQuery query = GetQuery() LCIMConversationQuery query = GetQuery()
.WhereContainedIn("objectId", convIds) .WhereContainedIn("objectId", convIds)
.Limit(999); .Limit(convIds.Count());
List<LCIMConversation> conversations = await ConversationController.Find(query); ReadOnlyCollection<LCIMConversation> conversations = await ConversationController.Find(query);
conversations.AddRange(temporaryConversations); conversationList.AddRange(conversations);
return conversations; }
return conversationList.AsReadOnly();
} }
/// <summary> /// <summary>

View File

@ -1,8 +1,8 @@
using System.Collections.Generic; using System.Collections.ObjectModel;
namespace LeanCloud.Realtime { namespace LeanCloud.Realtime {
public class LCIMPageResult { public class LCIMPageResult {
public List<string> Results { public ReadOnlyCollection<string> Results {
get; internal set; get; internal set;
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using LeanCloud; using LeanCloud;
@ -31,7 +32,7 @@ namespace RealtimeConsole {
SingleThreadSynchronizationContext.Run(async () => { SingleThreadSynchronizationContext.Run(async () => {
Console.WriteLine($"start at {Thread.CurrentThread.ManagedThreadId}"); Console.WriteLine($"start at {Thread.CurrentThread.ManagedThreadId}");
await Run("cc2"); await Run("cc4");
//await ChatRoom(); //await ChatRoom();
//await TemporaryConversation(); //await TemporaryConversation();
//await CreateConversation(); //await CreateConversation();
@ -55,12 +56,36 @@ namespace RealtimeConsole {
//Unread().Wait(); //Unread().Wait();
//DemoAsync().Wait();
//SingleThreadSynchronizationContext.Run(async () => {
// await DemoAsync();
//});
Console.ReadKey(true); Console.ReadKey(true);
} }
static async Task DemoAsync() {
Dictionary<int, int> d = new Dictionary<int, int>();
for (int i = 0; i < 10000; i++) {
int id = Thread.CurrentThread.ManagedThreadId;
int count;
d[id] = d.TryGetValue(id, out count) ? count + 1 : 1;
await Task.Yield();
}
foreach (KeyValuePair<int, int> kv in d) {
Console.WriteLine(kv);
}
}
static async Task Run(string id) { static async Task Run(string id) {
LCIMClient client = new LCIMClient(id); LCIMClient client = new LCIMClient(id);
await client.Open(); await client.Open();
client.OnUnreadMessagesCountUpdated = (conversations) => {
foreach (LCIMConversation conv in conversations) {
Console.WriteLine($"unread: {conv.Id}");
}
};
client.OnMessage = (conversation, message) => { client.OnMessage = (conversation, message) => {
Console.WriteLine($"recv: {conversation.Id}, {message.Id} at {Thread.CurrentThread.ManagedThreadId}"); Console.WriteLine($"recv: {conversation.Id}, {message.Id} at {Thread.CurrentThread.ManagedThreadId}");
}; };
@ -77,12 +102,12 @@ namespace RealtimeConsole {
static async Task QueryMyConversation() { static async Task QueryMyConversation() {
LCIMClient cc1 = new LCIMClient("cc1"); LCIMClient cc1 = new LCIMClient("cc1");
await cc1.Open(); await cc1.Open();
List<LCIMConversation> conversationList = await cc1.GetQuery() ReadOnlyCollection<LCIMConversation> conversationList = await cc1.GetQuery()
.WhereEqualTo("objectId", "5e7c283790aef5aa846b5683") .WhereEqualTo("objectId", "5e7c283790aef5aa846b5683")
.Find(); .Find();
conversationList.ForEach(conv => { foreach (LCIMConversation conv in conversationList) {
Console.WriteLine($"convId: {conv.Id}"); Console.WriteLine($"convId: {conv.Id}");
}); }
} }
static async Task Unread() { static async Task Unread() {