/// <summary> /// Primary method for loading more messages when user scrolls to the top of a chat box, aka infinite scrolling. /// </summary> /// <returns> /// A paged list of messages. Client-side will append this new set of messages to the existing set it already has. /// </returns> public async Task GetMoreMessages(MemberChatParams memberChatParams) { var username = Context.User.GetUsername(); var sender = await _unitOfWork.UserRepository.GetUserByUsernameAsync(username); var recipient = await _unitOfWork.UserRepository.GetUserByUsernameAsync(memberChatParams.RecipientUsername); if (recipient == null) { throw new HubException("Not found user"); } var messages = await _unitOfWork.MessageRepository .GetScrolledMessageThread(Context.User.GetUsername(), memberChatParams.RecipientUsername, memberChatParams); await Clients.Caller.SendAsync("ReceivedMessageThread", messages); }
/// <summary> /// Performs various critical functionality for sending and receiving messages via Signal R. /// Creates a groupname based on the sender and recipient. Combo of usernames, in alphabetical order. /// Asynchronously send data to front end that are called in client-side methods /// The name of the client-side method must match the string passed through in the "SendAsync()" /// </summary> public override async Task OnConnectedAsync() { var httpContext = Context.GetHttpContext(); // pass in the other user name (via a query string) with the key of user to get it into this variable. var otherUser = httpContext.Request.Query["user"].ToString(); // initialize the memberChatParams that are needed to get messages from the repo for scrolled pagination. var memberChatParams = new MemberChatParams { PageNumber = 1, PageSize = 10, // SCROLLED PAGE SIZE RecipientUsername = otherUser }; // TODO: Consider adding a check here to see if they exist first. // the group that a pair of users belong to. var groupName = GetGroupName(Context.User.GetUsername(), otherUser); await Groups.AddToGroupAsync(Context.ConnectionId, groupName); var group = await AddToGroup(groupName); await Clients.Group(groupName).SendAsync("UpdatedGroup", group); // get messages using GetMessageThread method from repo. (original method, consider removing) // TODO: Revisit whether this method is necessary anymore. Functionality has been moved to GetScrolledMessageThread() var messages = await _unitOfWork.MessageRepository .GetMessageThread(Context.User.GetUsername(), otherUser); // get messages using GetScrolledMessageThread method from repo (for scrolled pagination) var messages2 = await _unitOfWork.MessageRepository .GetScrolledMessageThread(Context.User.GetUsername(), otherUser, memberChatParams); // check to see if changes in this step. If there are, then save them to the DB here, not within the message repo itself. if (_unitOfWork.HasChanges()) { await _unitOfWork.Complete(); } // send the response back to the caller await Clients.Caller.SendAsync("ReceiveMessageThread", messages2); }
/// <summary> /// Primary method to load a set of messages for a message thread. Used withi infinte scrolling /// </summary> /// <param name="currentUsername">The current user's username</param> /// <param name="recipientUsername">The other user's username</param> /// <param name="memberChatParams">Params with data for the PagedList settings</param> /// <returns> /// A PagedList of messages (used for scrolled apges) /// </returns> public async Task <IEnumerable <MessageDto> > GetScrolledMessageThread(string currentUsername, string recipientUsername, MemberChatParams memberChatParams) { // store the query. Filter messagse for these users. Include photos. Order descending by MessageSent date var query = _context.Messages .Include(u => u.Sender).ThenInclude(p => p.Photos) .Include(u => u.Recipient).ThenInclude(p => p.Photos) .Where(m => m.Recipient.UserName == currentUsername && m.RecipientDeleted == false && m.Sender.UserName == recipientUsername || m.Recipient.UserName == recipientUsername && m.Sender.UserName == currentUsername && m.SenderDeleted == false ) .OrderByDescending(m => m.MessageSent) .AsQueryable(); // from the list of messages, determine if the current user has unread messages. var unreadMessages = query.Where(m => m.DateRead == null && m.Recipient.UserName == currentUsername).ToList(); // then mark those unread messages as read if (unreadMessages.Any()) { foreach (var message in unreadMessages) { message.DateRead = DateTime.UtcNow; } // save to DB (slight deviation from Unit of Work framework. But need for now if we still want to return a list of MessageDtos) // alternative is to have this method return a list of type Message, instead of the MessageDto. await _context.SaveChangesAsync(); } return(await PagedList <MessageDto> .CreateScrolledAsync(query.ProjectTo <MessageDto>(_mapper.ConfigurationProvider).AsNoTracking(), memberChatParams.PageNumber, memberChatParams.PageSize)); }