Skip to content

Commit 5d45e53

Browse files
committed
implement last read marker
fixes #54
1 parent 028b7c8 commit 5d45e53

File tree

11 files changed

+202
-40
lines changed

11 files changed

+202
-40
lines changed

Signal-Windows/Controls/Conversation.xaml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,23 @@
33
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
55
xmlns:local="using:Signal_Windows.Controls"
6+
xmlns:models="using:Signal_Windows.Models"
67
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
78
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
xmlns:xaml="using:Windows.UI.Xaml"
810
mc:Ignorable="d"
911
d:DesignHeight="300"
1012
d:DesignWidth="400">
1113

14+
<Control.Resources>
15+
<DataTemplate x:Key="NormalMessageTemplate" x:DataType="models:SignalMessage">
16+
<local:Message></local:Message>
17+
</DataTemplate>
18+
<DataTemplate x:Key="UnreadMarkerTemplate">
19+
<local:UnreadMarker />
20+
</DataTemplate>
21+
<local:MessageTemplateSelector x:Key="MessageDataTemplateSelector" NormalMessage="{StaticResource NormalMessageTemplate}" UnreadMarker="{StaticResource UnreadMarkerTemplate}" />
22+
</Control.Resources>
1223
<Grid>
1324
<Grid.RowDefinitions>
1425
<RowDefinition Height="50" />
@@ -23,17 +34,12 @@
2334
</StackPanel>
2435
</Border>
2536
<ScrollViewer Grid.Row="1" Name="SelectedMessagesScrollViewer" VerticalScrollBarVisibility="Visible" Padding="0 0 14 0">
26-
<ItemsControl Name="SelectedMessagesList" ItemsSource="{x:Bind Messages}">
37+
<ItemsControl Name="SelectedMessagesList" ItemsSource="{x:Bind Messages}" ItemTemplateSelector="{StaticResource MessageDataTemplateSelector}">
2738
<ItemsControl.ItemsPanel>
2839
<ItemsPanelTemplate>
2940
<StackPanel Orientation="Vertical" />
3041
</ItemsPanelTemplate>
3142
</ItemsControl.ItemsPanel>
32-
<ItemsControl.ItemTemplate>
33-
<DataTemplate>
34-
<local:Message></local:Message>
35-
</DataTemplate>
36-
</ItemsControl.ItemTemplate>
3743
</ItemsControl>
3844
</ScrollViewer>
3945
<TextBox Grid.Row="2" Name="InputTextBox" VerticalAlignment="Bottom" KeyDown="TextBox_KeyDown"></TextBox>

Signal-Windows/Controls/Conversation.xaml.cs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.ComponentModel;
88
using System.Diagnostics;
99
using System.Threading.Tasks;
10+
using Windows.Foundation;
1011
using Windows.UI.Xaml;
1112
using Windows.UI.Xaml.Controls;
1213
using Windows.UI.Xaml.Input;
@@ -22,7 +23,9 @@ public sealed partial class Conversation : UserControl, INotifyPropertyChanged
2223

2324
private Dictionary<ulong, Message> OutgoingCache = new Dictionary<ulong, Message>();
2425

25-
public RangeObservableCollection<SignalMessage> Messages { get; set; } = new RangeObservableCollection<SignalMessage>();
26+
public RangeObservableCollection<object> Messages { get; set; } = new RangeObservableCollection<object>();
27+
private SignalUnreadMarker UnreadMarker = new SignalUnreadMarker();
28+
private bool UnreadMarkerAdded = false;
2629

2730
private string _ThreadDisplayName;
2831

@@ -113,11 +116,21 @@ private void UpdateHeader(SignalConversation thread)
113116
public void ScrollToBottom()
114117
{
115118
SelectedMessagesScrollViewer.UpdateLayout();
116-
SelectedMessagesScrollViewer.ChangeView(0.0f, double.MaxValue, 1.0f, true);
119+
if (UnreadMarkerAdded)
120+
{
121+
var transform = UnreadMarker.View.TransformToVisual((UIElement)SelectedMessagesScrollViewer.Content);
122+
var position = transform.TransformPoint(new Point(0, 0));
123+
SelectedMessagesScrollViewer.ChangeView(null, position.Y, null, true);
124+
}
125+
else
126+
{
127+
SelectedMessagesScrollViewer.ChangeView(null, double.MaxValue, null, true);
128+
}
117129
}
118130

119131
public async Task Load(SignalConversation thread)
120132
{
133+
UnreadMarkerAdded = false;
121134
InputTextBox.IsEnabled = false;
122135
DisposeCurrentThread();
123136
UpdateHeader(thread);
@@ -127,8 +140,21 @@ public async Task Load(SignalConversation thread)
127140
return SignalDBContext.GetMessagesLocked(thread);
128141
});
129142
var after1 = Util.CurrentTimeMillis();
130-
Messages.AddRange(messages);
143+
foreach (var message in messages)
144+
{
145+
Messages.AddSilently(message);
146+
if (thread.LastSeenMessageId == message.Id && thread.LastMessageId != message.Id)
147+
{
148+
UnreadMarkerAdded = true;
149+
Messages.AddSilently(UnreadMarker);
150+
}
151+
}
152+
Messages.ForceCollectionChanged();
131153
UpdateLayout();
154+
if (UnreadMarkerAdded)
155+
{
156+
UnreadMarker.View.SetText(thread.UnreadCount + " UNREAD MESSAGE" + (thread.UnreadCount > 1 ? "S" : ""));
157+
}
132158
foreach (var message in messages)
133159
{
134160
if (message.Direction != SignalMessageDirection.Incoming)
@@ -179,5 +205,38 @@ private async void TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
179205
{
180206
await GetMainPageVm().TextBox_KeyDown(sender, e);
181207
}
208+
209+
public void RemoveUnreadMarker()
210+
{
211+
if (UnreadMarkerAdded)
212+
{
213+
Messages.Remove(UnreadMarker);
214+
}
215+
}
216+
}
217+
218+
public class SignalUnreadMarker
219+
{
220+
public UnreadMarker View { get; set; }
221+
}
222+
223+
public class MessageTemplateSelector : DataTemplateSelector
224+
{
225+
public DataTemplate NormalMessage { get; set; }
226+
public DataTemplate UnreadMarker { get; set; }
227+
228+
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
229+
{
230+
FrameworkElement element = container as FrameworkElement;
231+
if (item is SignalMessage)
232+
{
233+
return NormalMessage;
234+
}
235+
if (item is SignalUnreadMarker)
236+
{
237+
return UnreadMarker;
238+
}
239+
return null;
240+
}
182241
}
183242
}

Signal-Windows/Controls/ConversationListElement.xaml.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ public string LastMessage
7070
}
7171
set
7272
{
73-
Debug.WriteLine("setting lastmessage to " + value);
7473
_LastMessage = value;
7574
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LastMessage)));
7675
}
@@ -87,7 +86,7 @@ private void ThreadListItem_DataContextChanged(FrameworkElement sender, DataCont
8786
}
8887
}
8988

90-
public void Update(SignalConversation thread)
89+
public void UpdateConversationDisplay(SignalConversation thread)
9190
{
9291
Model.ThreadDisplayName = thread.ThreadDisplayName;
9392
Model.LastActiveTimestamp = thread.LastActiveTimestamp;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<UserControl
2+
x:Class="Signal_Windows.Controls.UnreadMarker"
3+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:local="using:Signal_Windows.Controls"
6+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
8+
mc:Ignorable="d"
9+
d:DesignHeight="300"
10+
d:DesignWidth="400">
11+
12+
<Border HorizontalAlignment="Center" BorderBrush="#00000000" BorderThickness="1,1,1,1" CornerRadius="8,8,8,8" Background="Beige" Padding="50 5 50 5">
13+
<TextBlock Name="UnreadText" />
14+
</Border>
15+
</UserControl>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Runtime.InteropServices.WindowsRuntime;
6+
using Windows.Foundation;
7+
using Windows.Foundation.Collections;
8+
using Windows.UI.Xaml;
9+
using Windows.UI.Xaml.Controls;
10+
using Windows.UI.Xaml.Controls.Primitives;
11+
using Windows.UI.Xaml.Data;
12+
using Windows.UI.Xaml.Input;
13+
using Windows.UI.Xaml.Media;
14+
using Windows.UI.Xaml.Navigation;
15+
16+
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
17+
18+
namespace Signal_Windows.Controls
19+
{
20+
public sealed partial class UnreadMarker : UserControl
21+
{
22+
public UnreadMarker()
23+
{
24+
this.InitializeComponent();
25+
DataContextChanged += UnreadMarker_DataContextChanged;
26+
}
27+
28+
public SignalUnreadMarker Model
29+
{
30+
get
31+
{
32+
return this.DataContext as SignalUnreadMarker;
33+
}
34+
}
35+
36+
private void UnreadMarker_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
37+
{
38+
Model.View = this;
39+
}
40+
41+
public void SetText(string text)
42+
{
43+
UnreadText.Text = text;
44+
}
45+
}
46+
}

Signal-Windows/Models/SignalConversation.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ public class SignalConversation
1414
public uint UnreadCount { get; set; }
1515
public bool CanReceive { get; set; }
1616
public uint ExpiresInSeconds { get; set; }
17+
public ulong? LastMessageId { get; set; }
1718
public SignalMessage LastMessage { get; set; }
19+
public ulong? LastSeenMessageId { get; set; }
1820
public SignalMessage LastSeenMessage { get; set; }
1921
[NotMapped] public ConversationListElement View;
2022
}

Signal-Windows/Signal-Windows.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@
113113
<Compile Include="Controls\Conversation.xaml.cs">
114114
<DependentUpon>Conversation.xaml</DependentUpon>
115115
</Compile>
116+
<Compile Include="Controls\UnreadMarker.xaml.cs">
117+
<DependentUpon>UnreadMarker.xaml</DependentUpon>
118+
</Compile>
116119
<Compile Include="Controls\Welcome.xaml.cs">
117120
<DependentUpon>Welcome.xaml</DependentUpon>
118121
</Compile>
@@ -199,6 +202,10 @@
199202
<SubType>Designer</SubType>
200203
<Generator>MSBuild:Compile</Generator>
201204
</Page>
205+
<Page Include="Controls\UnreadMarker.xaml">
206+
<SubType>Designer</SubType>
207+
<Generator>MSBuild:Compile</Generator>
208+
</Page>
202209
<Page Include="Controls\Welcome.xaml">
203210
<SubType>Designer</SubType>
204211
<Generator>MSBuild:Compile</Generator>

Signal-Windows/Signal/IncomingMessages.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ private void HandleMessage(SignalServiceEnvelope envelope)
136136
var readMessages = content.SynchronizeMessage.getRead().ForceGetValue();
137137
foreach (var readMessage in readMessages)
138138
{
139-
SignalDBContext.ClearUnreadLocked(readMessage.getSender(), this);
139+
//TODO
140140
}
141141
}
142142
} //TODO callmessages

Signal-Windows/Storage/DB.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ public static void UpdateExpiresInLocked(SignalConversation thread, uint exp)
839839
}
840840
}
841841

842-
public static void UpdateConversationLocked(string threadId, uint unread)
842+
public static void UpdateConversationLocked(string threadId, uint unread, ulong? lastSeenMessageId)
843843
{
844844
lock (DBLock)
845845
{
@@ -854,42 +854,50 @@ public static void UpdateConversationLocked(string threadId, uint unread)
854854
.Where(g => g.ThreadId == threadId)
855855
.Single();
856856
group.UnreadCount = unread;
857+
if (lastSeenMessageId != null)
858+
{
859+
group.LastSeenMessageId = lastSeenMessageId;
860+
}
857861
}
858862
else
859863
{
860864
contact.UnreadCount = unread;
865+
if (lastSeenMessageId != null)
866+
{
867+
contact.LastSeenMessageId = lastSeenMessageId;
868+
}
861869
}
862870
ctx.SaveChanges();
863871
}
864872
}
865873
}
866874

867-
public static void ClearUnreadLocked(string threadId, MainPageViewModel mpvm)
875+
public static SignalConversation ClearUnreadLocked(string threadId)
868876
{
869877
lock (DBLock)
870878
{
879+
SignalConversation conversation;
871880
using (var ctx = new SignalDBContext())
872881
{
873-
var contact = ctx.Contacts
882+
conversation = ctx.Contacts
874883
.Where(c => c.ThreadId == threadId)
875884
.SingleOrDefault();
876-
if (contact == null)
885+
if (conversation == null)
877886
{
878-
var group = ctx.Groups
887+
conversation = ctx.Groups
879888
.Where(g => g.ThreadId == threadId)
880889
.Single();
881-
group.UnreadCount = 0;
890+
conversation.UnreadCount = 0;
891+
conversation.LastSeenMessageId = conversation.LastMessageId;
882892
}
883893
else
884894
{
885-
contact.UnreadCount = 0;
895+
conversation.UnreadCount = 0;
896+
conversation.LastSeenMessageId = conversation.LastMessageId;
886897
}
887898
ctx.SaveChanges();
888899
}
889-
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
890-
{
891-
mpvm.UIResetRead(threadId);
892-
}).AsTask().Wait();
900+
return conversation;
893901
}
894902
}
895903

Signal-Windows/Utils.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,5 +163,18 @@ public void AddRange(IEnumerable<T> list)
163163
_suppressNotification = false;
164164
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
165165
}
166+
167+
public void AddSilently(T t)
168+
{
169+
bool old = _suppressNotification;
170+
_suppressNotification = true;
171+
Add(t);
172+
_suppressNotification = old;
173+
}
174+
175+
public void ForceCollectionChanged()
176+
{
177+
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
178+
}
166179
}
167180
}

0 commit comments

Comments
 (0)