async Task OnMessageArrived (Message msg) { try { await conversationLoadTaskCompletionSource.Task; //prevent adding a new conversation before all conversations are loaded await newMessagesSemaphore.WaitAsync (); await UpdateConversationsWith (msg); newMessagesSemaphore.Release (); } catch (Exception ex) { App.Logger.Report (ex); } }
public async Task<SendMessageResult> SendMessageAsync(Message message) { try { Dictionary<string, byte[]> keys = null; string text = message.Text; await messageRepository.AddMessageAsync(message); if (EncryptionEnabled) { var deviceIdAndPublicKeyMap = await deviceInfoProvider.GetUserDevicesAndPublicKeys((int) message.Recipient); if (deviceIdAndPublicKeyMap.Count > 0) { //don't forget current user's other devices var myDevices = await deviceInfoProvider.GetUserDevicesAndPublicKeys(Settings.MyId); foreach (var myDevice in myDevices) { if (myDevice.Key != Settings.UserDeviceId && myDevice.Key != Settings.MyId.ToString()) deviceIdAndPublicKeyMap[myDevice.Key] = myDevice.Value; } text = cryptoService.Encrypt(message.Text, deviceIdAndPublicKeyMap, out keys); } } var request = new SendMessageRequest { ReceiverUserId = message.Recipient, SenderName = Settings.NickName, MessageType = ServerClient.Entities.Ws.Requests.MessageType.Text, MessageToken = message.MessageToken, Thumbnail = message.Thumbnail, GroupId = message.GroupId, Message = text, Keys = keys, }; var response = await messagingService.SendMessage(request); if (response.Error == Errors.SendMessage_ProvideKeysForTheseDevices) { foreach (var item in response.MissedDevicesWithPublicKeysToReEncrypt) { await deviceInfoProvider.SavePublicKeyForDeviceId(item.DeviceId, item.UserId, Convert.ToBase64String(item.PublicKey)); } //try again return await SendMessageAsync(message); } if (response.Error == Errors.SendMessage_ReceiversNotFound) { return SendMessageResult.ReceiverUnknown; } if (response.Error == Errors.SendMessage_ReceiverAndSenderAreSame) { return SendMessageResult.ReceiverAndSenderAreSame; } OnMessageSent(message.MessageToken); return SendMessageResult.Ok; } catch (ConnectionException) { return SendMessageResult.ConnectionError; } catch (Exception ex) { App.Logger.Report (ex); return SendMessageResult.UnknownError; } }
private async void OnIncomingMessages(IEnumerable<IncomingMessage> messages) { if (messages == null) { return; } var incomingMessages = messages.Where(m => m.GroupId == Guid.Empty /*not supported yet*/).OrderBy(m => m.Time).ToList(); foreach (var msg in incomingMessages) { string decryptedText = msg.Text; try { if (msg.EncryptionKey != null && msg.EncryptionKey.Length > 0) { decryptedText = cryptoService.Decrypt(msg.Text, msg.EncryptionKey); } } catch (Exception) { decryptedText = DecryptionErrorMessage; } var dbMessage = new Message(msg.MessageToken, msg.EventId, msg.Time, msg.ToUserId, msg.FromUserId, decryptedText, msg.Thumbnail, MessageStatus.Delivered); await messageRepository.AddMessageAsync(dbMessage); MessageArrived(this, new MessageEventArgs { Message = dbMessage }); } SendMessageAck(incomingMessages.Select(m => m.EventId).ToList()); }
public async Task MarkMessageAsSeen(Message message) { if (Settings.MyId == message.Sender) { //multi-device message return; } await messagingService.MarkMessageAsSeen(new MarkMessageAsSeenRequest { MessagesAuthor = message.Sender, MessagesSeen = new List<Guid> {message.MessageToken} }); message.Status = MessageStatus.Seen; await messageRepository.UpdateMessageStatusAsync(message.MessageToken, message.Status); }
public async Task SendMessage(string text, byte[] image = null) { try { currentUserTypingController.HandleOutgoingMessage(); Settings.KinderPoints = Settings.KinderPoints + 1; await messageLoadTaskCompletionSource.Task; App.ConversationsViewModel.IsDirty = true; var message = new Message(Guid.NewGuid(), Guid.Empty, DateTime.UtcNow, recipientId, Settings.MyId, text, image, MessageStatus.Unsent); Messages.Add(MessageViewModelFactory.Create(message)); //chatting with fake contacts if (recipientId < 0) { dataManager.AddMessageAsync(message); return; } var sendMessageResult = await App.MessagesManager.SendMessageAsync(message); switch (sendMessageResult) { case SendMessageResult.Ok: break; case SendMessageResult.ConnectionError: App.MessageDialog.SendMessage("Internet connection is required", "No service"); break; case SendMessageResult.ReceiverUnknown: App.MessageDialog.SendMessage("Receiver was not found on the server", "Error"); break; case SendMessageResult.ReceiverAndSenderAreSame: App.MessageDialog.SendMessage("That's you!", "Error"); break; case SendMessageResult.UnknownError: App.MessageDialog.SendMessage("Oops... something went wrong", "Error"); break; default: throw new ArgumentOutOfRangeException(); } App.Logger.Track("SendMessage"); } catch (Exception ex) { App.Logger.Report (ex); App.MessageDialog.SendMessage("Message wasn't sent", "Oops.."); } }
async Task UpdateConversationsWith (Message incomingMsg) { Message existingConversation = conversations.FirstOrDefault (c => c.ConversationId == incomingMsg.ConversationId); if (existingConversation != null) ReplaceConversation (existingConversation, incomingMsg); else await AddConversation (incomingMsg); }
void CopyNamePhoto (Message src, Message dst) { dst.FriendPhoto = src.FriendPhoto; dst.FriendName = src.FriendName; }
async Task<Friend> GetFriend (Message msg) { long id = GetFriendId (msg); var friend = await DataManager.GetFriendAsync (id); if (friend == null) { friend = new Friend { FriendId = id, Name = string.Empty }; await App.FriendsViewModel.UpdateFriendInfoAsync (friend); } return friend; }
long GetFriendId (Message msg) { // This is equivalent to Settings.MyId == msg.Recipient ? msg.Sender : msg.Recipient; // but has a simmetry between Sender and msg.Recipient return Settings.MyId ^ (msg.Recipient ^ msg.Sender); }
async Task FillNameAndPhoto (Message msg) { var friend = await GetFriend (msg); CopyNamePhoto (friend, msg); }
async Task AddConversation (Message incomingMsg) { await FillNameAndPhoto (incomingMsg); conversations.Insert (0, incomingMsg); }
void ReplaceConversation (Message existingConversation, Message incomingMsg) { conversations.Remove (existingConversation); CopyNamePhoto (existingConversation, incomingMsg); conversations.Insert (0, incomingMsg); //new conversation on the top }
public async Task<bool> AddMessageAsync(Message message) { //using (await LockAsync()) { Message existingMsg = null; if (message.MessageToken != Guid.Empty) { //ignore duplicates (by Token) - it may happen existingMsg = await database.GetItemAsync<Message>(msg => msg.MessageToken == message.MessageToken); if (existingMsg != null && message.Id < 1) { message.Id = existingMsg.Id; } } await database.SaveItemAsync<Message>(message); return existingMsg == null; } }
void HandleStatusChanged(Message message, int index) { }