1
0
mirror of synced 2024-11-21 12:23:50 +00:00

Implemented indicator for new messages

This commit is contained in:
Mark van Renswoude 2022-01-03 17:20:30 +01:00
parent c75ea0cc62
commit 79776fd813
8 changed files with 154 additions and 20 deletions

View File

@ -34,7 +34,7 @@ namespace PettingZoo.Test.Tapeti
objectValue.Should().HaveElement("RecursiveValue").Which.Type.Should().Be(JTokenType.Null);
// Via type mapping
// TODO
// TODO test type mappings
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace PettingZoo.UI.Tab.Subscriber
{
public class SameMessageVisibilityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return ReferenceEquals(values[0], values[1])
? Visibility.Visible
: Visibility.Collapsed;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

View File

@ -11,6 +11,9 @@
d:DesignWidth="800"
d:DataContext="{d:DesignInstance res:DesignTimeSubscriberViewModel, IsDesignTimeCreatable=True}"
Background="White">
<UserControl.Resources>
<res:SameMessageVisibilityConverter x:Key="SameMessageVisibilityConverter" />
</UserControl.Resources>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
@ -30,11 +33,37 @@
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="150"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" MinWidth="150" SharedSizeGroup="DateTime"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="{Binding ReceivedTimestamp, StringFormat=g}" Style="{StaticResource Timestamp}"></TextBlock>
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding RoutingKey}" Style="{StaticResource RoutingKey}"></TextBlock>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- TODO insert as non-focusable item instead, so it's not part of the selection (and perhaps also fixes the bug mentioned in SubscriberViewModel) -->
<Grid Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="DateTime" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.Visibility>
<MultiBinding Converter="{StaticResource SameMessageVisibilityConverter}">
<Binding RelativeSource="{RelativeSource Self}" Path="DataContext" />
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ListBox}}" Path="DataContext.NewMessage" />
</MultiBinding>
</Grid.Visibility>
<Separator Grid.Column="0" Margin="0,0,8,0" />
<TextBlock Grid.Column="1" Text="{x:Static res:SubscriberViewStrings.LabelNewMessages}" HorizontalAlignment="Center" Background="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Foreground="{x:Static SystemColors.GrayTextBrush}" />
<Separator Grid.Column="2" Margin="8,0,0,0" />
</Grid>
<TextBlock Grid.Column="0" Grid.Row="1" Text="{Binding ReceivedTimestamp, StringFormat=g}" Style="{StaticResource Timestamp}" />
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding RoutingKey}" Style="{StaticResource RoutingKey}" />
<Grid.ContextMenu>
<ContextMenu>
@ -66,6 +95,8 @@
<Border Grid.Column="0" Grid.Row="1" Style="{StaticResource SidePanel}">
<DockPanel>
<Label DockPanel.Dock="Top" Style="{StaticResource HeaderLabel}" Content="{x:Static res:SubscriberViewStrings.PanelTitleBody}"/>
<!-- TODO use AvalonEdit with syntax highlighting depending on content type -->
<TextBox
Text="{Binding SelectedMessageBody, Mode=OneWay}"
BorderThickness="0"

View File

@ -1,14 +1,16 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Threading;
using PettingZoo.Core.Connection;
using PettingZoo.Core.Rendering;
using PettingZoo.WPF.ViewModel;
// TODO visual hint of where the last read message was when activating the tab again
// TODO if the "New message" line is visible when this tab is undocked, the line in the ListBox does not shrink. Haven't been able to figure out yet how to solve it
namespace PettingZoo.UI.Tab.Subscriber
{
@ -18,7 +20,7 @@ namespace PettingZoo.UI.Tab.Subscriber
private readonly ITabFactory tabFactory;
private readonly IConnection connection;
private readonly ISubscriber subscriber;
private readonly TaskScheduler uiScheduler;
private readonly Dispatcher dispatcher;
private ReceivedMessageInfo? selectedMessage;
private readonly DelegateCommand clearCommand;
private readonly TabToolbarCommand[] toolbarCommands;
@ -27,6 +29,8 @@ namespace PettingZoo.UI.Tab.Subscriber
private readonly DelegateCommand createPublisherCommand;
private bool tabActive;
private ReceivedMessageInfo? newMessage;
private Timer? newMessageTimer;
private int unreadCount;
@ -47,6 +51,14 @@ namespace PettingZoo.UI.Tab.Subscriber
}
}
public ReceivedMessageInfo? NewMessage
{
get => newMessage;
set => SetField(ref newMessage, value);
}
public string SelectedMessageBody =>
SelectedMessage != null
? MessageBodyRenderer.Render(SelectedMessage.Body, SelectedMessage.Properties.ContentType)
@ -70,8 +82,8 @@ namespace PettingZoo.UI.Tab.Subscriber
this.tabFactory = tabFactory;
this.connection = connection;
this.subscriber = subscriber;
uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
dispatcher = Dispatcher.CurrentDispatcher;
Messages = new ObservableCollection<ReceivedMessageInfo>();
clearCommand = new DelegateCommand(ClearExecute, ClearCanExecute);
@ -116,12 +128,14 @@ namespace PettingZoo.UI.Tab.Subscriber
private void SubscriberMessageReceived(object? sender, MessageReceivedEventArgs args)
{
RunFromUiScheduler(() =>
dispatcher.BeginInvoke(() =>
{
if (!tabActive)
{
unreadCount++;
RaisePropertyChanged(nameof(Title));
NewMessage ??= args.MessageInfo;
}
Messages.Add(args.MessageInfo);
@ -140,22 +154,39 @@ namespace PettingZoo.UI.Tab.Subscriber
}
private void RunFromUiScheduler(Action action)
{
_ = Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
}
public void Activate()
{
tabActive = true;
unreadCount = 0;
RaisePropertyChanged(nameof(Title));
if (NewMessage == null)
return;
newMessageTimer?.Dispose();
newMessageTimer = new Timer(
_ =>
{
dispatcher.BeginInvoke(() =>
{
NewMessage = null;
});
},
null,
TimeSpan.FromSeconds(5),
Timeout.InfiniteTimeSpan);
}
public void Deactivate()
{
if (newMessageTimer != null)
{
newMessageTimer.Dispose();
newMessageTimer = null;
}
NewMessage = null;
tabActive = false;
}
}
@ -165,6 +196,20 @@ namespace PettingZoo.UI.Tab.Subscriber
{
public DesignTimeSubscriberViewModel() : base(null!, null!, null!, new DesignTimeSubscriber())
{
for (var i = 1; i <= 5; i++)
Messages.Add(new ReceivedMessageInfo(
"designtime",
$"designtime.message.{i}",
Encoding.UTF8.GetBytes(@"Design-time message"),
new MessageProperties(null)
{
ContentType = "text/fake",
ReplyTo = "/dev/null"
},
DateTime.Now));
SelectedMessage = Messages[2];
NewMessage = Messages[2];
}

View File

@ -96,6 +96,15 @@ namespace PettingZoo.UI.Tab.Subscriber {
}
}
/// <summary>
/// Looks up a localized string similar to New messages.
/// </summary>
public static string LabelNewMessages {
get {
return ResourceManager.GetString("LabelNewMessages", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Body.
/// </summary>

View File

@ -112,10 +112,10 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CommandClear" xml:space="preserve">
<value>Clear</value>
@ -129,6 +129,9 @@
<data name="DeliveryModePersistent" xml:space="preserve">
<value>Persistent</value>
</data>
<data name="LabelNewMessages" xml:space="preserve">
<value>New messages</value>
</data>
<data name="PanelTitleBody" xml:space="preserve">
<value>Body</value>
</data>

View File

@ -8,7 +8,7 @@ using PettingZoo.WPF.ViewModel;
namespace PettingZoo.UI.Tab.Undocked
{
public class UndockedTabHostViewModel : BaseViewModel
public class UndockedTabHostViewModel : BaseViewModel, ITabActivate
{
private readonly ITabHost tabHost;
private readonly ITab tab;
@ -51,6 +51,17 @@ namespace PettingZoo.UI.Tab.Undocked
{
tabHost.UndockedTabClosed(tab);
}
public void Activate()
{
(tab as ITabActivate)?.Activate();
}
public void Deactivate()
{
(tab as ITabActivate)?.Deactivate();
}
}

View File

@ -1,5 +1,7 @@
using System.Windows;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
namespace PettingZoo.UI.Tab.Undocked
{
@ -30,6 +32,16 @@ namespace PettingZoo.UI.Tab.Undocked
{
viewModel.WindowClosed();
};
Activated += (_, _) =>
{
viewModel.Activate();
};
Deactivated += (_, _) =>
{
viewModel.Deactivate();
};
}
private void Toolbar_Loaded(object sender, RoutedEventArgs e)