From 02e4f31e8558a841d6e24a0835024dce48fa9519 Mon Sep 17 00:00:00 2001 From: Lyndon Jetten Date: Thu, 6 Jun 2024 10:07:34 +0200 Subject: [PATCH] Bug gefixt, der durch das TimeStamp-Objekt zustande kam. --- ChatController/ChatController.csproj | 1 + ChatController/ChatMainControl.xaml.cs | 2 +- ChatController/HauptKlassen/Chat.cs | 49 ++++++--- .../LoginKlassen/ChatGruppenDaten.cs | 99 ++++++++++++++++++- .../LoginKlassen/TimeStampConverter.cs | 57 +++++++++++ ChatController/LoginKlassen/UserMessages.cs | 69 ++++++++++--- ChatController/Utilities/Utils.cs | 54 +++++----- 7 files changed, 276 insertions(+), 55 deletions(-) create mode 100644 ChatController/LoginKlassen/TimeStampConverter.cs diff --git a/ChatController/ChatController.csproj b/ChatController/ChatController.csproj index 42bd7b1..cd6dd03 100644 --- a/ChatController/ChatController.csproj +++ b/ChatController/ChatController.csproj @@ -93,6 +93,7 @@ + diff --git a/ChatController/ChatMainControl.xaml.cs b/ChatController/ChatMainControl.xaml.cs index 12aecf4..e86b914 100644 --- a/ChatController/ChatMainControl.xaml.cs +++ b/ChatController/ChatMainControl.xaml.cs @@ -990,7 +990,7 @@ namespace ChatController private void ListenForMessagesForCurrentContact(Contact pCurrentContact) { - if(!ShouldInterruptContactsThread && !(CurrentContact is null)) + if(!ShouldInterruptContactsThread && CurrentContact != null) { CheckForNewMessagesForContact(pCurrentContact); } diff --git a/ChatController/HauptKlassen/Chat.cs b/ChatController/HauptKlassen/Chat.cs index 2a5522b..ad4cceb 100644 --- a/ChatController/HauptKlassen/Chat.cs +++ b/ChatController/HauptKlassen/Chat.cs @@ -4,7 +4,6 @@ using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; -using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; @@ -41,6 +40,8 @@ namespace ChatController.HauptKlassen // Ist quasi das ViewModel public class Chat : INotifyPropertyChanged { + private static DateTime _DefaultTime = new DateTime(1970, 1, 1); + public Action ExceptionCallback { get; set; } public Action ThreadExceptionCallback { get; set; } @@ -117,7 +118,7 @@ namespace ChatController.HauptKlassen { LoadMessagesFromServerAsync(contact.GroupId, delegate { - callback?.Invoke(AddMessagesFromServerResponse(_UserMessages?.Response.Messages ?? new Messages[0], previousMessage)); + callback?.Invoke(AddMessagesFromServerResponse(_UserMessages?.Response?.Messages ?? new OwnChatMessage[0], previousMessage)); }); return; @@ -158,7 +159,7 @@ namespace ChatController.HauptKlassen { LoadMoreMessagesFromServerAsync(contact.GroupId, _NextPage, () => { - callback?.Invoke(AddMessagesFromServerResponse(_AdditionalUserMessages?.Response.Messages ?? new Messages[0], previousMessage)); + callback?.Invoke(AddMessagesFromServerResponse(_AdditionalUserMessages?.Response?.Messages ?? new OwnChatMessage[0], previousMessage)); }); } @@ -200,12 +201,19 @@ namespace ChatController.HauptKlassen public void CheckIfNewMessagesExistAsync(long groupId, Action callback) { + #if DEBUG + if(_UserMessages.Response is null) + { + throw new Exception("Too many requests."); + } + #endif + var span = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var timespan = Convert.ToInt64(span.TotalSeconds); if(!(_UserMessages is null) && _UserMessages.Response.Messages.Length > 0) { - timespan = _UserMessages.Response.Messages.First().Created_At; + timespan = _UserMessages.Response.Messages.First().CreatedAt; } GetNumberOfNewMessagesAsync(groupId, timespan, numberOfNewMessages => @@ -297,6 +305,11 @@ namespace ChatController.HauptKlassen { LoadGroupsAsync(rawData => { + if(rawData.Response is null) + { + return; + } + var contacts = GenerateContactsFromServerResponse(rawData.Response.Groups.ToArray(), true); callback?.Invoke(contacts.OrderByDescending(c => c.TimeStamp)); @@ -329,7 +342,7 @@ namespace ChatController.HauptKlassen { var endurl = ChatDaten.ServerUrl + Constants.SendMessageUrl; - using (var multiPartContent = new MultipartFormDataContent()) + using(var multiPartContent = new MultipartFormDataContent()) { multiPartContent.Add(new StringContent(groupId.ToString()), "groupid"); multiPartContent.Add(new StringContent(message), "text"); @@ -484,7 +497,7 @@ namespace ChatController.HauptKlassen else { // Dokument - var chatMessage = new ChatMessage(groupId, 0, ChatDaten.LoggedInUser.Response.User.UserName, Path.GetFileName(fileName), sendtime, true, 0, fileName, null, null, message.Smaller_Image, null, ChatMessageType.Document, ChatDaten.LoggedInUser.Response.User.Oid); + var chatMessage = new ChatMessage(groupId, 0, ChatDaten.LoggedInUser.Response.User.UserName, Path.GetFileName(fileName), sendtime, true, 0, fileName, null, null, message.SmallerImage, null, ChatMessageType.Document, ChatDaten.LoggedInUser.Response.User.Oid); result.Add(chatMessage); } @@ -857,9 +870,10 @@ namespace ChatController.HauptKlassen var latestMessage = groupInput.LastMessage; - if(!(latestMessage?.Text is null)) + if(latestMessage?.Text != null)// && latestMessage?.Timestamp != null) { var timeStamp = DateTime.Parse(latestMessage.Timestamp.Date); + var clientZone = TimeZoneInfo.Local; formattedTime = TimeZoneInfo.ConvertTimeFromUtc(timeStamp, clientZone); @@ -898,7 +912,10 @@ namespace ChatController.HauptKlassen continue; } - var unixTimeStamp = DateTime.Parse(latestMessage.Timestamp.Date).GetUnixTimeStamp(); + var time = DateTime.Parse(latestMessage.Timestamp.Date); + + //var unixTimeStamp = latestMessage.Timestamp.Value.GetUnixTimeStamp(); + var unixTimeStamp = time.GetUnixTimeStamp(); if(LastTimeStamp < unixTimeStamp) { @@ -928,29 +945,31 @@ namespace ChatController.HauptKlassen return contacts; } - public List AddMessagesFromServerResponse(Messages[] pMessages, ChatMessage previousMessage) + public List AddMessagesFromServerResponse(OwnChatMessage[] pMessages, ChatMessage previousMessage) { var result = new List(); - foreach(var message in pMessages ?? new Messages[0]) + foreach(var message in pMessages ?? new OwnChatMessage[0]) { - var time = DateTime.Parse(message.Timestamp.Date); + var time = DateTime.Parse(message.Timestamp.Date); + var clientZone = TimeZoneInfo.Local; var formattedTime = TimeZoneInfo.ConvertTimeFromUtc(time, clientZone); + var isLoggedInUsersMessage = !(ChatDaten.Userid is null) && message.UserId == ChatDaten.Userid.Value; - var messageText = message.Text ?? (string.IsNullOrEmpty(message.File) ? string.Empty : message.Original_Filename); + var messageText = message.Text ?? (string.IsNullOrEmpty(message.File) ? string.Empty : message.OriginalFilename); if(!string.IsNullOrEmpty(message.File)) { var message2Add = Constants.ImageFileExtensions.Contains(Path.GetExtension(message.File).ToUpperInvariant()) ? //SmallerImage ist null - new ChatMessage(message.GroupId, message.Id, message.User_Name, messageText, formattedTime, isLoggedInUsersMessage, message.FileSize, message.Smaller_Image, message.File, message.Original_Filename, null, null, ChatMessageType.Image, message.UserId) : - new ChatMessage(message.GroupId, message.Id, message.User_Name, messageText, formattedTime, isLoggedInUsersMessage, 0, message.File, null, null, message.Smaller_Image, null, ChatMessageType.Document, message.UserId); + new ChatMessage(message.GroupId, message.Id, message.UserName, messageText, formattedTime, isLoggedInUsersMessage, message.FileSize, message.SmallerImage, message.File, message.OriginalFilename, null, null, ChatMessageType.Image, message.UserId) : + new ChatMessage(message.GroupId, message.Id, message.UserName, messageText, formattedTime, isLoggedInUsersMessage, 0, message.File, null, null, message.SmallerImage, null, ChatMessageType.Document, message.UserId); result.AddIfNotIn(message2Add); } else { - var chatMessage = new ChatMessage(message.GroupId, message.Id, message.User_Name, message.Text, formattedTime, isLoggedInUsersMessage, message.FileSize, null, null, null, null, null, ChatMessageType.Message, message.UserId); + var chatMessage = new ChatMessage(message.GroupId, message.Id, message.UserName, message.Text, formattedTime, isLoggedInUsersMessage, message.FileSize, null, null, null, null, null, ChatMessageType.Message, message.UserId); result.AddIfNotIn(chatMessage); } diff --git a/ChatController/LoginKlassen/ChatGruppenDaten.cs b/ChatController/LoginKlassen/ChatGruppenDaten.cs index 7cef755..49cb099 100644 --- a/ChatController/LoginKlassen/ChatGruppenDaten.cs +++ b/ChatController/LoginKlassen/ChatGruppenDaten.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel; using System.IO; using Newtonsoft.Json; @@ -10,35 +11,70 @@ namespace ChatController.LoginKlassen /// public class ChatGruppenDaten { + [JsonProperty("response")] public ChatGruppenDatenResponse Response { get; set; } } public class GroupInput { + [JsonProperty("oid")] public int Oid { get; set; } + + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("avatar")] public string Avatar { get; set; } - public string Mobile { get; set; } - public GroupLatestMessage LastMessage { get; set; } - public GroupUsers[] Users { get; set; } - public bool OnlyEmployees { get; set; } [JsonProperty("accent_color")] public string AccentColor { get; set; } + [JsonProperty("mobile")] + public string Mobile { get; set; } + + [JsonProperty("lastmessage")] + public GroupLatestMessage LastMessage { get; set; } + + [JsonProperty("users")] + public GroupUsers[] Users { get; set; } + + [JsonProperty("onlyemployees")] + public bool OnlyEmployees { get; set; } + + [JsonProperty("notificationtype")] + public string NotificationType { get; set; } + + [JsonProperty("is_read_only")] + public bool IsReadOnly { get; set; } + [DefaultValue(true)] [JsonProperty("i_can_write", DefaultValueHandling = DefaultValueHandling.Populate)] public bool CanWrite { get; set; } [JsonProperty("i_can_see_participants")] public bool CanSeeParticipants { get; set; } + + [JsonProperty("i_can_mute")] + public bool CanMute { get; set; } + + [JsonProperty("i_can_delete")] + public bool CanDelete { get; set; } + + [JsonProperty("i_can_delete_others")] + public bool CanDeleteOthers { get; set; } + + [DefaultValue(0)] + [JsonProperty("unreadmessagecount")] + public int UnreadMessagesCount { get; set; } } public class GroupLatestMessage { + [JsonProperty("id")] public long Id { get; set; } private string _Text; + [JsonProperty("text")] public string Text { get @@ -61,27 +97,72 @@ namespace ChatController.LoginKlassen set => _Text = value; } + [JsonProperty("file")] public string File { get; set; } + + [JsonProperty("file_protected")] + public string FileProtected { get; set; } + + [JsonProperty("original_filename")] public string OriginalFileName { get; set; } + + [JsonProperty("smaller_image")] public string SmallerImage { get; set; } + + [JsonProperty("file_size")] + public long FileSize { get; set; } + + [JsonConverter(typeof(TimeStampConverter))] + [JsonProperty("timestamp")] public LastMessageTimeStamp Timestamp { get; set; } + + [JsonProperty("created_at")] public long CreatedAt { get; set; } + + [JsonProperty("deleted_at")] + public long? DeletedAt { get; set; } + + [JsonProperty("userid")] public long UserId { get; set; } + + [JsonProperty("userid_manage")] public string UserIdManage { get; set; } + + [JsonProperty("user_name")] public string UserName { get; set; } + + [JsonProperty("user_picture")] public string UserPicture { get; set; } + + [JsonProperty("groupid")] public string GroupId { get; set; } } public class GroupUsers { + [JsonProperty("oid")] public long Oid { get; set; } + + [JsonProperty("userid_manage")] public string Userid_Manage { get; set; } + + [JsonProperty("firstname")] public string Firstname { get; set; } + + [JsonProperty("lastname")] public string Lastname { get; set; } + + [JsonProperty("mobile")] public string Mobile { get; set; } + + [JsonProperty("picture")] public string Picture { get; set; } + + [JsonProperty("is_employee")] public bool Is_Employee { get; set; } + + [JsonProperty("accent_color")] + public string AccentColor { get; set; } } public class LastMessageTimeStamp @@ -89,10 +170,18 @@ namespace ChatController.LoginKlassen public string Date { get; set; } public int TimeZoneType { get; set; } public string TimeZone { get; set; } + + public LastMessageTimeStamp(string date, int timeZoneType, string timeZone) + { + Date = date; + TimeZoneType = timeZoneType; + TimeZone = timeZone; + } } public class ChatGruppenDatenResponse { + [JsonProperty("groups")] public List Groups { get; set; } } } diff --git a/ChatController/LoginKlassen/TimeStampConverter.cs b/ChatController/LoginKlassen/TimeStampConverter.cs new file mode 100644 index 0000000..327c27a --- /dev/null +++ b/ChatController/LoginKlassen/TimeStampConverter.cs @@ -0,0 +1,57 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace ChatController.LoginKlassen +{ + public class TimeStampConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException("Nicht implementiert, da nicht benötigt."); + } + + public override object ReadJson(JsonReader reader, Type objectType, object messageJson, JsonSerializer serializer) + { + switch(reader.TokenType) + { + case JsonToken.Null: + return null; + case JsonToken.StartObject: + { + var jsonObject = JObject.Load(reader); + var date = jsonObject["date"]?.ToString(); + var timeZoneType = jsonObject["timezone_type"]?.ToObject(); + var timeZone = jsonObject["timezone"]?.ToString(); + + if(date is null || timeZoneType is null || timeZone is null) + { + return null; + } + + return new LastMessageTimeStamp(date, timeZoneType.Value, timeZone); + } + case JsonToken.Date: + { + if(reader.Value is null) + { + return null; + } + + return DateTime.TryParse(reader.Value.ToString(), out var timestamp) ? new LastMessageTimeStamp(timestamp.ToString("dd.MM.yyyy HH:mm:ss.ffffff"), 3, "UTC") : null; + } + default: + return null; + } + } + + public override bool CanRead => true; + + public override bool CanWrite => false; + + public override bool CanConvert(Type objectType) + { + return typeof(LastMessageTimeStamp).IsAssignableFrom(objectType); + } + } +} diff --git a/ChatController/LoginKlassen/UserMessages.cs b/ChatController/LoginKlassen/UserMessages.cs index c07e329..72711cb 100644 --- a/ChatController/LoginKlassen/UserMessages.cs +++ b/ChatController/LoginKlassen/UserMessages.cs @@ -1,40 +1,87 @@ -using Newtonsoft.Json; +using System; +using Newtonsoft.Json; namespace ChatController.LoginKlassen { public class UserMessages { + [JsonProperty("response")] public UserMessageInput Response { get; set; } + + [JsonProperty("message")] public string Message { get; set; } + + [JsonProperty("errors")] public string Errors { get; set; } + + [JsonProperty("success")] public bool Success { get; set; } } public class UserMessageInput { + [JsonProperty("currentPage")] public string CurrentPage { get; set; } + + [JsonProperty("hasMorePages")] public bool HasMorePages { get; set; } + + [JsonProperty("nextPage")] public string NextPage { get; set; } + + [JsonProperty("perPage")] public int PerPage { get; set; } + + [JsonProperty("previousPage")] public string PreviousPage { get; set; } - public Messages[] Messages { get; set; } + + [JsonProperty("messages")] + public OwnChatMessage[] Messages { get; set; } } - public class Messages + public class OwnChatMessage { + [JsonProperty("id")] public long Id { get; set; } + + [JsonProperty("text")] public string Text { get; set; } + + [JsonProperty("file")] public string File { get; set; } - public string Original_Filename { get; set; } - public string Smaller_Image { get; set; } - public LastMessageTimeStamp Timestamp { get; set; } - public long Created_At { get; set; } - public long UserId { get; set; } - public string User_Name { get; set; } - public string User_Picture { get; set; } - public long GroupId { get; set; } + + [JsonProperty("original_filename")] + public string OriginalFilename { get; set; } + + [JsonProperty("smaller_image")] + public string SmallerImage { get; set; } [JsonProperty("file_size")] public long FileSize { get; set; } + + [JsonConverter(typeof(TimeStampConverter))] + [JsonProperty("timestamp")] + public LastMessageTimeStamp Timestamp { get; set; } + + [JsonProperty("created_at")] + public long CreatedAt { get; set; } + + [JsonProperty("deleted_at")] + public long? DeletedAt { get; set; } + + [JsonProperty("userid")] + public long UserId { get; set; } + + [JsonProperty("userid_manage")] + public string UserIdManage { get; set; } + + [JsonProperty("user_name")] + public string UserName { get; set; } + + [JsonProperty("user_picture")] + public string UserPicture { get; set; } + + [JsonProperty("groupid")] + public long GroupId { get; set; } } } diff --git a/ChatController/Utilities/Utils.cs b/ChatController/Utilities/Utils.cs index e31d8cb..01f2e89 100644 --- a/ChatController/Utilities/Utils.cs +++ b/ChatController/Utilities/Utils.cs @@ -44,6 +44,7 @@ namespace ChatController.Utilities private static void DownloadImage(string uri, Action callback) { var client = new RestClient(uri); + var request = new RestRequest { ResponseWriter = stream => @@ -473,42 +474,49 @@ namespace ChatController.Utilities request.Headers[Constants.Token] = AuthToken; request.Headers[Constants.CustomerId] = Tenant; - using(var response = request.GetResponse()) + try { - var responseStream = response.GetResponseStream(); - - if(responseStream is null) + using(var response = request.GetResponse()) { - return null; - } + var responseStream = response.GetResponseStream(); - var rotation = Rotation.Rotate0; - - using(var image = Image.FromStream(responseStream)) - { - if(image.PropertyIdList.Contains(0x112)) + if(responseStream is null) { - rotation = GetRotationFromExifTag(image.GetPropertyItem(0x112).Value[0]); + return null; } - var bitmap = new BitmapImage(); + var rotation = Rotation.Rotate0; - var localStream = new MemoryStream(); + using(var image = Image.FromStream(responseStream)) + { + if(image.PropertyIdList.Contains(0x112)) + { + rotation = GetRotationFromExifTag(image.GetPropertyItem(0x112).Value[0]); + } - image.Save(localStream, image.RawFormat); + var bitmap = new BitmapImage(); - localStream.Position = 0; + var localStream = new MemoryStream(); - bitmap.BeginInit(); - bitmap.StreamSource = localStream; - bitmap.Rotation = rotation; - bitmap.EndInit(); - bitmap.Freeze(); + image.Save(localStream, image.RawFormat); - cache.AddAvatar(uri, bitmap, userId, groupId); - return cache.GetAvatar(uri, userId, groupId); + localStream.Position = 0; + + bitmap.BeginInit(); + bitmap.StreamSource = localStream; + bitmap.Rotation = rotation; + bitmap.EndInit(); + bitmap.Freeze(); + + cache.AddAvatar(uri, bitmap, userId, groupId); + return cache.GetAvatar(uri, userId, groupId); + } } } + catch(Exception exception) + { + return null; + } } } }