Kontaktliste wird bei neuer Nachricht aktualisiert

Text ist markierbar
This commit is contained in:
LynJet
2022-05-27 11:50:37 +02:00
parent 63d2ea05c2
commit 7d25cac6ca
12 changed files with 192 additions and 41 deletions

View File

@@ -71,7 +71,9 @@
<Compile Include="Converter\StringToBoolConverter.cs" />
<Compile Include="Converter\UserProfilePictureVisibilityConverter.cs" />
<Compile Include="Core\BindableTextBlock.cs" />
<Compile Include="Core\FlowDocumentExtensions.cs" />
<Compile Include="Core\OwnChatCache.cs" />
<Compile Include="Core\OwnChatRichTextBox.cs" />
<Compile Include="Data\LookupResult.cs" />
<Compile Include="Data\OwnChatApi.cs" />
<Compile Include="Extensions\IDictionaryTExtensions.cs" />

View File

@@ -18,7 +18,7 @@ namespace ChatController.ChatKlassen
public int TimeStringMaxWidth => IsSeparator ? int.MaxValue : 350;
public int MessageMaxWidth => IsSeparator ? int.MaxValue : 500;
public int MessageMaxWidth => IsSeparator ? int.MaxValue : 450;
public string SeparatorTimeString => SendTime.ToString("dd. MMMM yyyy");

View File

@@ -94,9 +94,11 @@ namespace ChatController.ChatKlassen
IsChatMessageInputGridVisible = isChatMessageInputGridVisible;
if(accentColorBrushString == null)
Utils.DownloadUserProfilePicturesAsync(userId2Uri);
if (accentColorBrushString is null)
{
if(pUserIdManage != null)
if(!(pUserIdManage is null))
{
accentColorBrushString = "3B7799";
}
@@ -114,7 +116,7 @@ namespace ChatController.ChatKlassen
IsGroupChat = pUserCount > 2;
Utils.DownloadProfilePictureAsync(profilePicturePath, key, delegate(ImageSource imageSource)
Utils.DownloadGroupProfilePictureAsync(profilePicturePath, key, delegate(ImageSource imageSource)
{
Image = imageSource;
});

View File

@@ -68,7 +68,7 @@
<Setter Property="Template" Value="{StaticResource ContactListBoxTemplate}" />
</Style>
<!-- Kontaktliste -->
<!-- region Styling Kontaktliste -->
<Style x:Key="ContactListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorLevel=1, AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}" />
<Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorLevel=1, AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}" />
@@ -126,8 +126,9 @@
</Setter.Value>
</Setter>
</Style>
<!-- endregion Styling Kontaktliste -->
<!-- Gruppensuchtemplate -->
<!-- region Styling Gruppensuchtemplate -->
<ControlTemplate x:Key="SearchTextBoxTemplate" TargetType="{x:Type TextBox}">
<Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="2,2,2,2">
<Grid>
@@ -149,7 +150,7 @@
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- /Gruppensuchtemplate -->
<!-- endregion Styling Gruppensuchtemplate -->
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" />
@@ -177,7 +178,7 @@
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Gruppensuche und Gruppenliste aktualisieren -->
<!-- region Gruppensuche und Gruppenliste aktualisieren -->
<Grid Grid.Column="0" Grid.Row="0" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
@@ -195,9 +196,9 @@
<TextBox Grid.Column="0" x:Name="Suche" Height="22" HorizontalAlignment="Stretch" Margin="5" TabIndex="0" Template="{DynamicResource SearchTextBoxTemplate}" BorderThickness="0,0,0,0" TextChanged="Suche_OnTextChanged" />
</Grid>
<!-- /Gruppensuche und Gruppenliste aktualisieren -->
<!-- endregion Gruppensuche und Gruppenliste aktualisieren -->
<!-- Kontaktliste -->
<!-- region Kontaktliste -->
<Grid Grid.Column="0" Grid.Row="1" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
@@ -210,7 +211,7 @@
ItemContainerStyle="{StaticResource ContactListBoxItemStyle}" SelectionChanged="Clientlist_OnSelectionChanged" Style="{StaticResource ContactListStyle}">
</ListView>
</Grid>
<!-- /Kontaktliste -->
<!-- endregion Kontaktliste -->
</Grid>
<Grid Grid.Column="1" Grid.Row="0" x:Name="GridRechts">
@@ -335,7 +336,10 @@
<StackPanel DockPanel.Dock="Bottom" Orientation="Vertical">
<Image ToolTip="Dokument öffnen" Height="{Binding ThumbnailPlaceholderHeight, UpdateSourceTrigger=PropertyChanged}" Width="150" Source="{Binding Path=Thumbnail, UpdateSourceTrigger=PropertyChanged}" Stretch="Uniform" VerticalAlignment="Center" HorizontalAlignment="Center" />
<Image MaxWidth="300" Height="{Binding PicturePlaceholderHeight, UpdateSourceTrigger=PropertyChanged}" Source="{Binding Path=PictureSource, UpdateSourceTrigger=PropertyChanged}" x:Name="imgChatMessage" Stretch="UniformToFill" />
<core:BindableTextBlock VerticalAlignment="Center" InlineList="{Binding MessageInlines, UpdateSourceTrigger=PropertyChanged}" MinWidth="0" MaxWidth="{Binding MessageMaxWidth}" TextWrapping="Wrap" FontSize="14" />
<core:OwnChatRichTextBox VerticalAlignment="Center" InlineList="{Binding MessageInlines, UpdateSourceTrigger=PropertyChanged}"
MinWidth="0" MaxWidth="{Binding MessageMaxWidth}" FontSize="14" IsReadOnly="True"
HorizontalAlignment="{Binding HorizontalAlignmentValue}"
BorderThickness="0" Background="Transparent" IsDocumentEnabled="True" Margin="-5,0,0,0" />
</StackPanel>
<StackPanel DockPanel.Dock="Left" Margin="0,0,0,0">
<TextBlock Text="{Binding UserTimeStringLeft}" MaxWidth="{Binding TimeStringMaxWidth}" FontSize="11" HorizontalAlignment="Left" TextAlignment="Left" VerticalAlignment="Center" Foreground="{Binding Foreground}" />

View File

@@ -14,7 +14,6 @@ using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Threading;
using ChatController.Annotations;
using ChatController.ChatKlassen;
@@ -124,7 +123,7 @@ namespace ChatController
{
get
{
if(_CurrentContact == null)
if(_CurrentContact is null)
{
return Visibility.Collapsed;
}
@@ -155,7 +154,7 @@ namespace ChatController
_ChatMessages = new ObservableCollection<ChatMessage>();
ChatMessages = CollectionViewSource.GetDefaultView(_ChatMessages) as ListCollectionView;
if (ChatMessages != null)
if (!(ChatMessages is null))
{
ChatMessages.CustomSort = new ChatMessageComparer();
}
@@ -191,7 +190,7 @@ namespace ChatController
exception => {
this.Dispatch(
() => {
if(exception == null)
if(exception is null)
{
ThreadExceptionMessage = null;
}
@@ -340,6 +339,7 @@ namespace ChatController
pContact.HasUnreadMessages = false;
Clientlist.Items.Refresh();
OnPropertyChanged(nameof(ContactList));
}
var currentContact = pContact;
@@ -359,12 +359,15 @@ namespace ChatController
}
_ChatMessages.Clear();
OnPropertyChanged(nameof(_ChatMessages));
Chat.LoadChatMessagesForContactAsync(currentContact, GetFirstMessage(), chatMessages =>
{
this.Dispatch(() =>
{
_ChatMessages.Clear();
_ChatMessages.AddRangeIfElementsNotIn(chatMessages);
OnPropertyChanged(nameof(_ChatMessages));
WpfUtils.ScrollToBottomOfListBox(ChatListBox);
@@ -821,7 +824,9 @@ namespace ChatController
}
}
Clientlist.Items.Refresh();
//Clientlist.Items.Refresh();
OnPropertyChanged(nameof(ChatMessages));
OnPropertyChanged(nameof(ContactList));
});
});
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Documents;
using System.Windows.Media;
namespace ChatController.Core
{
public static class FlowDocumentExtensions
{
private static IEnumerable<TextElement> GetRunsAndParagraphs(FlowDocument doc)
{
for (var position = doc.ContentStart; !(position is null) && position.CompareTo(doc.ContentEnd) <= 0; position = position.GetNextContextPosition(LogicalDirection.Forward))
{
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)
{
switch (position.Parent)
{
case Run run:
yield return run;
break;
case Paragraph paragraph:
yield return paragraph;
break;
}
}
}
}
public static FormattedText GetFormattedText(this FlowDocument flowDocument)
{
if (flowDocument is null)
{
throw new ArgumentNullException(nameof(flowDocument));
}
var output = new FormattedText(GetText(flowDocument), CultureInfo.CurrentCulture, flowDocument.FlowDirection, new Typeface(flowDocument.FontFamily, flowDocument.FontStyle, flowDocument.FontWeight, flowDocument.FontStretch), flowDocument.FontSize, flowDocument.Foreground);
var offset = 0;
foreach (var textElement in GetRunsAndParagraphs(flowDocument))
{
if (textElement is Run run)
{
var count = run.Text.Length;
output.SetFontFamily(run.FontFamily, offset, count);
output.SetFontStyle(run.FontStyle, offset, count);
output.SetFontWeight(run.FontWeight, offset, count);
output.SetFontSize(run.FontSize, offset, count);
output.SetForegroundBrush(run.Foreground, offset, count);
output.SetFontStretch(run.FontStretch, offset, count);
output.SetTextDecorations(run.TextDecorations, offset, count);
offset += count;
}
else
{
offset += Environment.NewLine.Length;
}
}
return output;
}
private static string GetText(FlowDocument flowDocument)
{
var stringBuilder = new StringBuilder();
foreach (var textElement in GetRunsAndParagraphs(flowDocument))
{
stringBuilder.Append(!(textElement is Run run) ? Environment.NewLine : run.Text);
}
return stringBuilder.ToString();
}
}
}

View File

@@ -117,6 +117,14 @@ namespace ChatController.Core
return _UserProfilePictures.ContainsKey(userId) ? _UserProfilePictures[userId] : null;
}
}
public bool IsUserProfilePictureInCache(long userId)
{
lock(_Lock)
{
return _UserProfilePictures.ContainsKey(userId);
}
}
}
public class ProfilePictureObject

View File

@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace ChatController.Core
{
public class OwnChatRichTextBox : RichTextBox
{
public ObservableCollection<Inline> InlineList
{
get => (ObservableCollection<Inline>)GetValue(InlineListProperty);
set => SetValue(InlineListProperty, value);
}
public static readonly DependencyProperty InlineListProperty = DependencyProperty.Register("InlineList", typeof(ObservableCollection<Inline>), typeof(OwnChatRichTextBox), new UIPropertyMetadata(null, OnPropertyChanged));
public static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is null)
{
return;
}
((OwnChatRichTextBox)sender).Document = GetCustomDocument(e.NewValue as ObservableCollection<Inline>);
if(sender is OwnChatRichTextBox ownChatRichTextBox)
{
ownChatRichTextBox.Document = GetCustomDocument(e.NewValue as ObservableCollection<Inline>);
ownChatRichTextBox.Width = ownChatRichTextBox.Document.GetFormattedText().WidthIncludingTrailingWhitespace + 20;
}
}
private static FlowDocument GetCustomDocument(IEnumerable<Inline> inlines)
{
var flowDocument = new FlowDocument();
var paragraph = new Paragraph
{
Margin = new Thickness(0) // remove indent between paragraphs
};
paragraph.Inlines.AddRange(inlines);
flowDocument.Blocks.Add(paragraph);
return flowDocument;
}
}
}

View File

@@ -117,7 +117,7 @@ namespace ChatController.HauptKlassen
// Führt zu doppelter neuester Nachricht, wenn man vorher eine verschickt hat!
public void LoadChatMessagesForContactAsync(Contact contact, ChatMessage previousMessage, Action<List<ChatMessage>> callback)
{
if(contact != null)
if(!(contact is null))
{
LoadMessagesFromServerAsync(contact.GroupId, delegate
{
@@ -146,7 +146,7 @@ namespace ChatController.HauptKlassen
{
_UserMessages = JsonConvert.DeserializeObject<UserMessages>(response.Content);
if (_UserMessages.Response.HasMorePages)
if (_UserMessages?.Response?.HasMorePages ?? false)
{
_NextPage = _UserMessages.Response.NextPage;
_HasNextPage = true;
@@ -177,7 +177,7 @@ namespace ChatController.HauptKlassen
{
try
{
if(page == null || !page.Contains("="))
if(page is null || !page.Contains("="))
{
callback?.Invoke();
return;
@@ -195,18 +195,15 @@ namespace ChatController.HauptKlassen
client.ExecuteAsync(request, response =>
{
// TODO: Entfernen
Debug.WriteLine(response.Content);
_AdditionalUserMessages = null;
_AdditionalUserMessages = JsonConvert.DeserializeObject<UserMessages>(response.Content);
if (_AdditionalUserMessages.Response.HasMorePages)
if (_AdditionalUserMessages?.Response?.HasMorePages ?? false)
{
_NextPage = _AdditionalUserMessages.Response.NextPage;
}
_HasNextPage = _AdditionalUserMessages.Response.HasMorePages;
_HasNextPage = _AdditionalUserMessages?.Response?.HasMorePages ?? false;
callback?.Invoke();
});
@@ -1076,8 +1073,6 @@ namespace ChatController.HauptKlassen
var key = $"group-{groupInput.Oid}";
contacts.Add(new Contact(
groupInput.Name,
groupInput.LastMessage,

View File

@@ -90,18 +90,6 @@ namespace ChatController
DataContext = this;
LeseDateiFallsVorhanden();
#if DEBUG
//_Kundennummer = "4368658436";
//_ChatCode = "ZMCKb-BckTt";
//_Benutzername = "muellerp";
//Password = "F5aTk9Co47JFJCWB2Z7Y";
//_Kundennummer = "9988776655";
//_ChatCode = "K2UPV-qrirb";
//_Benutzername = "lyndon";
//Password = "lyndon2travemünde";
#endif
}
private void AnmeldenButton_OnClick(object sender, RoutedEventArgs e)

View File

@@ -30,13 +30,13 @@ namespace ChatController.Utilities
public static DateTime DefaultDate = new DateTime(1, 1, 1);
public static void DownloadProfilePictureAsync(string pathToProfilePicture, string key, Action<ImageSource> callback)
public static void DownloadGroupProfilePictureAsync(string pathToProfilePicture, string key, Action<ImageSource> callback)
{
var cache = OwnChatCache.GetInstance();
var cachedProfileImage = cache.GetCachedProfilePicture(key, pathToProfilePicture);
if (cachedProfileImage != null)
if (!(cachedProfileImage is null))
{
callback?.Invoke(cachedProfileImage);
return;
@@ -49,6 +49,24 @@ namespace ChatController.Utilities
});
}
public static void DownloadUserProfilePicturesAsync(Dictionary<long, string> userIds2Uris)
{
var cache = OwnChatCache.GetInstance();
foreach(var userId2Uri in userIds2Uris)
{
if(cache.IsUserProfilePictureInCache(userId2Uri.Key))
{
continue;
}
DownloadImage(userId2Uri.Value, imageSource =>
{
cache.AddUserProfilePictureToCache(imageSource, userId2Uri.Key, userId2Uri.Value);
});
}
}
private static void DownloadImage(string uri, Action<ImageSource> callback)
{
var client = new RestClient(uri);