Skip to content

Commit d208656

Browse files
committed
Merge branch 'master' into redesign
2 parents 18c9dd9 + aca680a commit d208656

18 files changed

+685
-275
lines changed

Signal-Windows.sln

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.26206.0
4+
VisualStudioVersion = 15.0.26730.3
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Signal-Windows", "Signal-Windows\Signal-Windows.csproj", "{41736A64-5B66-44AF-879A-501192A46920}"
77
EndProject
88
Global
99
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
1011
Debug|ARM = Debug|ARM
1112
Debug|x64 = Debug|x64
1213
Debug|x86 = Debug|x86
14+
Release|Any CPU = Release|Any CPU
1315
Release|ARM = Release|ARM
1416
Release|x64 = Release|x64
1517
Release|x86 = Release|x86
1618
EndGlobalSection
1719
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20+
{41736A64-5B66-44AF-879A-501192A46920}.Debug|Any CPU.ActiveCfg = Debug|x86
1821
{41736A64-5B66-44AF-879A-501192A46920}.Debug|ARM.ActiveCfg = Debug|ARM
1922
{41736A64-5B66-44AF-879A-501192A46920}.Debug|ARM.Build.0 = Debug|ARM
2023
{41736A64-5B66-44AF-879A-501192A46920}.Debug|ARM.Deploy.0 = Debug|ARM
@@ -24,6 +27,7 @@ Global
2427
{41736A64-5B66-44AF-879A-501192A46920}.Debug|x86.ActiveCfg = Debug|x86
2528
{41736A64-5B66-44AF-879A-501192A46920}.Debug|x86.Build.0 = Debug|x86
2629
{41736A64-5B66-44AF-879A-501192A46920}.Debug|x86.Deploy.0 = Debug|x86
30+
{41736A64-5B66-44AF-879A-501192A46920}.Release|Any CPU.ActiveCfg = Release|x86
2731
{41736A64-5B66-44AF-879A-501192A46920}.Release|ARM.ActiveCfg = Release|ARM
2832
{41736A64-5B66-44AF-879A-501192A46920}.Release|ARM.Build.0 = Release|ARM
2933
{41736A64-5B66-44AF-879A-501192A46920}.Release|ARM.Deploy.0 = Release|ARM
@@ -37,4 +41,7 @@ Global
3741
GlobalSection(SolutionProperties) = preSolution
3842
HideSolutionNode = FALSE
3943
EndGlobalSection
44+
GlobalSection(ExtensibilityGlobals) = postSolution
45+
SolutionGuid = {6C980B4F-4E4C-422E-A06F-1FB4A091E952}
46+
EndGlobalSection
4047
EndGlobal

Signal-Windows/Controls/Conversation.xaml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,19 @@
3636
<TextBlock Name="Username" IsTextSelectionEnabled="True" HorizontalAlignment="Center" Text="{x:Bind ThreadUsername, Mode=OneWay}" Visibility="{x:Bind ThreadUsernameVisibility, Mode=OneWay}" />
3737
</StackPanel>
3838
</Border>
39-
<ScrollViewer Grid.Row="1" Name="SelectedMessagesScrollViewer" VerticalScrollBarVisibility="Visible" Padding="0 0 14 0">
40-
<ItemsControl Name="SelectedMessagesList" ItemsSource="{x:Bind Messages}" ItemTemplateSelector="{StaticResource MessageDataTemplateSelector}">
41-
<ItemsControl.ItemsPanel>
42-
<ItemsPanelTemplate>
43-
<StackPanel Orientation="Vertical" />
44-
</ItemsPanelTemplate>
45-
</ItemsControl.ItemsPanel>
46-
</ItemsControl>
47-
</ScrollViewer>
39+
<ListBox Grid.Row="1" Name="ConversationItemsControl" VirtualizingStackPanel.VirtualizationMode="Recycling" Background="White" ScrollViewer.VerticalScrollBarVisibility="Visible" Padding="0 0 15 0"> <!--ItemTemplateSelector="{StaticResource MessageDataTemplateSelector}"-->
40+
<ListBox.ItemContainerStyle>
41+
<Style TargetType="ListBoxItem">
42+
<Setter Property="Template">
43+
<Setter.Value>
44+
<ControlTemplate TargetType="ListBoxItem">
45+
<local:Message x:Name="ListBoxItemContent" />
46+
</ControlTemplate>
47+
</Setter.Value>
48+
</Setter>
49+
</Style>
50+
</ListBox.ItemContainerStyle>
51+
</ListBox>
4852
<Grid Grid.Row="2" BorderBrush="{ThemeResource TextBoxBorderThemeBrush}" BorderThickness="0,1,0,0">
4953
<Grid.ColumnDefinitions>
5054
<ColumnDefinition Width="*"/>

Signal-Windows/Controls/Conversation.xaml.cs

Lines changed: 68 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,12 @@ namespace Signal_Windows.Controls
2020
public sealed partial class Conversation : UserControl, INotifyPropertyChanged
2121
{
2222
public event PropertyChangedEventHandler PropertyChanged;
23-
24-
private Dictionary<long, Message> OutgoingCache = new Dictionary<long, Message>();
25-
26-
public RangeObservableCollection<object> Messages { get; set; } = new RangeObservableCollection<object>();
27-
private SignalUnreadMarker UnreadMarker = new SignalUnreadMarker();
28-
private bool UnreadMarkerAdded = false;
2923
private bool SendingMessage = false;
24+
private Dictionary<long, SignalMessageContainer> OutgoingCache = new Dictionary<long, SignalMessageContainer>();
25+
//private SignalUnreadMarker UnreadMarker = new SignalUnreadMarker();
26+
private SignalConversation SignalConversation;
27+
//private bool UnreadMarkerAdded = false;
28+
private VirtualizedCollection Collection;
3029

3130
private string _ThreadDisplayName;
3231

@@ -126,92 +125,86 @@ private void UpdateHeader(SignalConversation thread)
126125
}
127126
}
128127

129-
public void ScrollToBottom()
128+
public void Load(SignalConversation conversation)
130129
{
131-
SelectedMessagesScrollViewer.UpdateLayout();
132-
if (UnreadMarkerAdded)
133-
{
134-
var transform = UnreadMarker.View.TransformToVisual((UIElement)SelectedMessagesScrollViewer.Content);
135-
var position = transform.TransformPoint(new Point(0, 0));
136-
SelectedMessagesScrollViewer.ChangeView(null, position.Y, null, true);
137-
}
138-
else
139-
{
140-
SelectedMessagesScrollViewer.ChangeView(null, double.MaxValue, null, true);
141-
}
142-
}
143-
144-
public async Task Load(SignalConversation thread)
145-
{
146-
UnreadMarkerAdded = false;
130+
SignalConversation = conversation;
131+
//UnreadMarkerAdded = false;
147132
InputTextBox.IsEnabled = false;
148133
DisposeCurrentThread();
149-
UpdateHeader(thread);
150-
var before = Util.CurrentTimeMillis();
151-
var messages = await Task.Run(() =>
152-
{
153-
return SignalDBContext.GetMessagesLocked(thread);
154-
});
155-
var after1 = Util.CurrentTimeMillis();
156-
foreach (var message in messages)
157-
{
158-
Messages.AddSilently(message);
159-
if (thread.LastSeenMessageId == message.Id && thread.LastMessageId != message.Id)
160-
{
161-
UnreadMarkerAdded = true;
162-
Messages.AddSilently(UnreadMarker);
163-
}
164-
}
165-
Messages.ForceCollectionChanged();
134+
UpdateHeader(conversation);
135+
136+
/*
137+
* When selecting a small (~650 messages) conversation after a bigger (~1800 messages) one,
138+
* ScrollToBottom would scroll so far south that the entire screen was white. Seems like the
139+
* scrollbar is not properly notified that the collection changed. I tried things like throwing
140+
* CollectionChanged (reset) event, but to no avail. This hack works, though.
141+
*/
142+
ConversationItemsControl.ItemsSource = new List<object>();
166143
UpdateLayout();
167-
if (UnreadMarkerAdded)
168-
{
169-
UnreadMarker.View.SetText(thread.UnreadCount + " UNREAD MESSAGE" + (thread.UnreadCount > 1 ? "S" : ""));
170-
}
171-
foreach (var message in messages)
172-
{
173-
if (message.Direction != SignalMessageDirection.Incoming)
174-
{
175-
AddToOutgoingMessagesCache(message);
176-
}
177-
}
178-
var after2 = Util.CurrentTimeMillis();
179-
Debug.WriteLine("db query: " + (after1 - before));
180-
Debug.WriteLine("ui: " + (after2 - after1));
181-
InputTextBox.IsEnabled = thread.CanReceive;
144+
Collection = new VirtualizedCollection(conversation);
145+
ConversationItemsControl.ItemsSource = Collection;
146+
UpdateLayout();
147+
InputTextBox.IsEnabled = conversation.CanReceive;
148+
ScrollToBottom();
182149
}
183150

184151
public void DisposeCurrentThread()
185152
{
186-
Messages.Clear();
187153
OutgoingCache.Clear();
188154
}
189155

156+
public T FindElementByName<T>(FrameworkElement element, string sChildName) where T : FrameworkElement
157+
{
158+
T childElement = null;
159+
var nChildCount = VisualTreeHelper.GetChildrenCount(element);
160+
for (int i = 0; i < nChildCount; i++)
161+
{
162+
FrameworkElement child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;
163+
164+
if (child == null)
165+
continue;
166+
167+
if (child is T && child.Name.Equals(sChildName))
168+
{
169+
childElement = (T)child;
170+
break;
171+
}
172+
173+
childElement = FindElementByName<T>(child, sChildName);
174+
175+
if (childElement != null)
176+
break;
177+
}
178+
return childElement;
179+
}
180+
190181
public void UpdateMessageBox(SignalMessage updatedMessage)
191182
{
192183
if (OutgoingCache.ContainsKey(updatedMessage.Id))
193184
{
194185
var m = OutgoingCache[updatedMessage.Id];
195-
m.UpdateMessageBox(updatedMessage);
186+
var item = (ListBoxItem) ConversationItemsControl.ContainerFromIndex(m.Index);
187+
var message = FindElementByName<Message>(item, "ListBoxItemContent");
188+
bool retain = message.HandleUpdate(updatedMessage);
189+
if (!retain)
190+
{
191+
OutgoingCache.Remove(m.Index);
192+
}
196193
}
197194
}
198195

199-
public void Append(SignalMessage sm)
196+
public void Append(SignalMessageContainer sm, bool forceScroll)
200197
{
201-
Messages.Add(sm);
202-
//TODO move scrolltobottom here
198+
Collection.Add(sm);
199+
if (forceScroll || true) //TODO
200+
{
201+
ScrollToBottom();
202+
}
203203
}
204204

205-
public void AddToOutgoingMessagesCache(SignalMessage sm)
205+
public void AddToOutgoingMessagesCache(SignalMessageContainer m)
206206
{
207-
if (sm.View != null)
208-
{
209-
OutgoingCache[sm.Id] = sm.View;
210-
}
211-
else
212-
{
213-
throw new Exception("Attempt to add null view to OutgoingCache");
214-
}
207+
OutgoingCache[m.Message.Id] = m;
215208
}
216209

217210
private async void TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
@@ -228,13 +221,11 @@ private async void TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
228221
}
229222
}
230223

231-
public void RemoveUnreadMarker()
224+
private void ScrollToBottom()
232225
{
233-
if (UnreadMarkerAdded)
234-
{
235-
Messages.Remove(UnreadMarker);
236-
UnreadMarkerAdded = false;
237-
}
226+
var lastMsg = ConversationItemsControl.Items[ConversationItemsControl.Items.Count - 1] as SignalMessageContainer;
227+
Debug.WriteLine($"scroll to {lastMsg}");
228+
ConversationItemsControl.ScrollIntoView(lastMsg);
238229
}
239230

240231
private async void SendMessageButton_Click(object sender, RoutedEventArgs e)
@@ -253,7 +244,6 @@ public class SignalUnreadMarker
253244
{
254245
public UnreadMarker View { get; set; }
255246
}
256-
257247
public class MessageTemplateSelector : DataTemplateSelector
258248
{
259249
public DataTemplate NormalMessage { get; set; }
@@ -263,19 +253,15 @@ public class MessageTemplateSelector : DataTemplateSelector
263253
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
264254
{
265255
FrameworkElement element = container as FrameworkElement;
266-
if (item is SignalMessage)
256+
if (item is SignalMessageContainer)
267257
{
268-
SignalMessage sm = (SignalMessage)item;
258+
SignalMessage sm = ((SignalMessageContainer)item).Message;
269259
if (sm.Type == SignalMessageType.IdentityKeyChange)
270260
{
271261
return IdentityKeyChangeMessage;
272262
}
273263
return NormalMessage;
274264
}
275-
if (item is SignalUnreadMarker)
276-
{
277-
return UnreadMarker;
278-
}
279265
return null;
280266
}
281267
}

Signal-Windows/Controls/IdentityKeyChangeMessage.xaml.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,14 @@ public SignalMessage Model
3939

4040
private void IdentityKeyChangeMessage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
4141
{
42-
MessageTextBlock.Text = Model.Content.Content;
42+
if (Model != null)
43+
{
44+
MessageTextBlock.Text = Model.Content.Content;
45+
}
46+
else
47+
{
48+
MessageTextBlock.Text = "null";
49+
}
4350
}
4451
}
4552
}

Signal-Windows/Controls/Message.xaml

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,21 @@
1414
<BitmapImage x:Key="Check" UriSource="ms-appx:///Assets//check.png" />
1515
<BitmapImage x:Key="DoubleCheck" UriSource="ms-appx:///Assets//double-check.png" />
1616
</UserControl.Resources>
17-
<Border BorderBrush="#00000000" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4" Background="{x:Bind Background}" Padding="10 5 10 5" Margin="4">
17+
<Border Name="MessageBoxBorder" BorderBrush="#00000000" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4" Padding="10 5 10 5" Margin="4">
1818
<ItemsControl>
19-
<TextBlock Visibility="{x:Bind HeaderVisibility}" Name="MessageContentHeader" Foreground="{x:Bind ContactNameColor}" Text="{x:Bind ContactName}" FontWeight="Bold" />
20-
<TextBlock Name="MessageContentTextBlock" TextWrapping="Wrap" MaxWidth="300" IsTextSelectionEnabled="True" FontSize="14" Foreground="{x:Bind TextColor}" Text="{x:Bind Model.Content.Content}"></TextBlock>
21-
<ItemsControl Name="MessageAttachments" ItemsSource="{x:Bind Model.Attachments}">
22-
<ItemsControl.ItemTemplate>
23-
<DataTemplate x:DataType="models:SignalAttachment">
24-
<StackPanel>
25-
<TextBlock Name="AttachmentFilenameTextBlock" Text="{x:Bind SentFileName}"></TextBlock>
26-
<Image Name="AttachmentImage"></Image>
27-
<Button Name="AttachmentSaveButton" Click="AttachmentSaveButton_Click">Save</Button>
28-
</StackPanel>
29-
</DataTemplate>
30-
</ItemsControl.ItemTemplate>
31-
</ItemsControl>
19+
<TextBlock Name="MessageAuthor" FontWeight="Bold" />
20+
<TextBlock Name="MessageContentTextBlock" TextWrapping="Wrap" MaxWidth="300" IsTextSelectionEnabled="True" FontSize="14" Foreground="Black" />
3221
<Grid Name="FooterPanel">
3322
<Grid.ColumnDefinitions>
3423
<ColumnDefinition Width="Auto"/>
3524
<ColumnDefinition />
3625
<ColumnDefinition />
3726
<ColumnDefinition />
3827
</Grid.ColumnDefinitions>
39-
<TextBlock Grid.Column="0" Margin="0 0 5 0" Foreground="Red" FontWeight="SemiBold" Visibility="{x:Bind ResendVisibility, Mode=OneWay}" Tapped="ResendTextBlock_Tapped">Send again</TextBlock>
40-
<TextBlock Grid.Column="1" Foreground="{x:Bind TimestampColor}" Text="{x:Bind FancyTimestamp}" Margin="0 0 5 0" />
41-
<Image Grid.Column="2" Source="{StaticResource Check}" Visibility="{x:Bind CheckVisibility, Mode=OneWay}" Width="16" Height="16" />
42-
<Image Grid.Column="3" Source="{StaticResource DoubleCheck}" Visibility="{x:Bind DoubleCheckVisibility, Mode=OneWay}" Width="16" Height="16" />
28+
<TextBlock Grid.Column="0" Name="ResendTextBlock" Margin="0 0 5 0" Foreground="Red" FontWeight="SemiBold" Tapped="ResendTextBlock_Tapped" Visibility="Collapsed">Send again</TextBlock>
29+
<TextBlock Name="FancyTimestampBlock" Grid.Column="1" Margin="0 0 5 0" />
30+
<Image Grid.Column="2" Name="CheckImage" Source="{StaticResource Check}" Width="16" Height="16" Visibility="Collapsed"/>
31+
<Image Grid.Column="3" Name="DoubleCheckImage" Source="{StaticResource DoubleCheck}" Width="16" Height="16" Visibility="Collapsed"/>
4332
</Grid>
4433
</ItemsControl>
4534
</Border>

0 commit comments

Comments
 (0)