@@ -20,12 +20,11 @@ namespace Signal_Windows.Controls
20
20
public sealed partial class Conversation : UserControl , INotifyPropertyChanged
21
21
{
22
22
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 ;
23
+ private Dictionary < long , SignalMessageContainer > OutgoingCache = new Dictionary < long , SignalMessageContainer > ( ) ;
24
+ //private SignalUnreadMarker UnreadMarker = new SignalUnreadMarker();
25
+ private SignalConversation SignalConversation ;
26
+ //private bool UnreadMarkerAdded = false;
27
+ private VirtualizedCollection Collection ;
29
28
30
29
private string _ThreadDisplayName ;
31
30
@@ -113,114 +112,98 @@ private void UpdateHeader(SignalConversation thread)
113
112
}
114
113
}
115
114
116
- public void ScrollToBottom ( )
115
+ public void Load ( SignalConversation conversation )
117
116
{
118
- SelectedMessagesScrollViewer . UpdateLayout ( ) ;
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
- }
129
- }
130
-
131
- public async Task Load ( SignalConversation thread )
132
- {
133
- UnreadMarkerAdded = false ;
117
+ SignalConversation = conversation ;
118
+ //UnreadMarkerAdded = false;
134
119
InputTextBox . IsEnabled = false ;
135
120
DisposeCurrentThread ( ) ;
136
- UpdateHeader ( thread ) ;
137
- var before = Util . CurrentTimeMillis ( ) ;
138
- var messages = await Task . Run ( ( ) =>
139
- {
140
- return SignalDBContext . GetMessagesLocked ( thread ) ;
141
- } ) ;
142
- var after1 = Util . CurrentTimeMillis ( ) ;
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 ( ) ;
121
+ UpdateHeader ( conversation ) ;
122
+ ConversationItemsControl . ItemsSource = new List < object > ( ) ; /* hack to avoid glitches */
153
123
UpdateLayout ( ) ;
154
- if ( UnreadMarkerAdded )
155
- {
156
- UnreadMarker . View . SetText ( thread . UnreadCount + " UNREAD MESSAGE" + ( thread . UnreadCount > 1 ? "S" : "" ) ) ;
157
- }
158
- foreach ( var message in messages )
159
- {
160
- if ( message . Direction != SignalMessageDirection . Incoming )
161
- {
162
- AddToOutgoingMessagesCache ( message ) ;
163
- }
164
- }
165
- var after2 = Util . CurrentTimeMillis ( ) ;
166
- Debug . WriteLine ( "db query: " + ( after1 - before ) ) ;
167
- Debug . WriteLine ( "ui: " + ( after2 - after1 ) ) ;
168
- InputTextBox . IsEnabled = thread . CanReceive ;
124
+ Collection = new VirtualizedCollection ( conversation ) ;
125
+ ConversationItemsControl . ItemsSource = Collection ;
126
+ UpdateLayout ( ) ;
127
+ InputTextBox . IsEnabled = conversation . CanReceive ;
128
+ ScrollToBottom ( ) ;
169
129
}
170
130
171
131
public void DisposeCurrentThread ( )
172
132
{
173
- Messages . Clear ( ) ;
174
133
OutgoingCache . Clear ( ) ;
175
134
}
176
135
136
+ public T FindElementByName < T > ( FrameworkElement element , string sChildName ) where T : FrameworkElement
137
+ {
138
+ T childElement = null ;
139
+ var nChildCount = VisualTreeHelper . GetChildrenCount ( element ) ;
140
+ for ( int i = 0 ; i < nChildCount ; i ++ )
141
+ {
142
+ FrameworkElement child = VisualTreeHelper . GetChild ( element , i ) as FrameworkElement ;
143
+
144
+ if ( child == null )
145
+ continue ;
146
+
147
+ if ( child is T && child . Name . Equals ( sChildName ) )
148
+ {
149
+ childElement = ( T ) child ;
150
+ break ;
151
+ }
152
+
153
+ childElement = FindElementByName < T > ( child , sChildName ) ;
154
+
155
+ if ( childElement != null )
156
+ break ;
157
+ }
158
+ return childElement ;
159
+ }
160
+
177
161
public void UpdateMessageBox ( SignalMessage updatedMessage )
178
162
{
179
163
if ( OutgoingCache . ContainsKey ( updatedMessage . Id ) )
180
164
{
181
165
var m = OutgoingCache [ updatedMessage . Id ] ;
182
- m . UpdateMessageBox ( updatedMessage ) ;
166
+ var item = ( ListBoxItem ) ConversationItemsControl . ContainerFromIndex ( m . Index ) ;
167
+ var message = FindElementByName < Message > ( item , "ListBoxItemContent" ) ;
168
+ bool retain = message . HandleUpdate ( updatedMessage ) ;
169
+ if ( ! retain )
170
+ {
171
+ OutgoingCache . Remove ( m . Index ) ;
172
+ }
183
173
}
184
174
}
185
175
186
- public void Append ( SignalMessage sm )
176
+ public void Append ( SignalMessageContainer sm , bool forceScroll )
187
177
{
188
- Messages . Add ( sm ) ;
189
- //TODO move scrolltobottom here
178
+ Collection . Add ( sm ) ;
179
+ if ( forceScroll || true ) //TODO
180
+ {
181
+ ScrollToBottom ( ) ;
182
+ }
190
183
}
191
184
192
- public void AddToOutgoingMessagesCache ( SignalMessage sm )
185
+ public void AddToOutgoingMessagesCache ( SignalMessageContainer m )
193
186
{
194
- if ( sm . View != null )
195
- {
196
- OutgoingCache [ sm . Id ] = sm . View ;
197
- }
198
- else
199
- {
200
- throw new Exception ( "Attempt to add null view to OutgoingCache" ) ;
201
- }
187
+ OutgoingCache [ m . Message . Id ] = m ;
202
188
}
203
189
204
190
private async void TextBox_KeyDown ( object sender , KeyRoutedEventArgs e )
205
191
{
206
192
await GetMainPageVm ( ) . TextBox_KeyDown ( sender , e ) ;
207
193
}
208
194
209
- public void RemoveUnreadMarker ( )
195
+ private void ScrollToBottom ( )
210
196
{
211
- if ( UnreadMarkerAdded )
212
- {
213
- Messages . Remove ( UnreadMarker ) ;
214
- UnreadMarkerAdded = false ;
215
- }
197
+ var lastMsg = ConversationItemsControl . Items [ ConversationItemsControl . Items . Count - 1 ] as SignalMessageContainer ;
198
+ Debug . WriteLine ( $ "scroll to { lastMsg } ") ;
199
+ ConversationItemsControl . ScrollIntoView ( lastMsg ) ;
216
200
}
217
201
}
218
202
219
203
public class SignalUnreadMarker
220
204
{
221
205
public UnreadMarker View { get ; set ; }
222
206
}
223
-
224
207
public class MessageTemplateSelector : DataTemplateSelector
225
208
{
226
209
public DataTemplate NormalMessage { get ; set ; }
@@ -230,19 +213,15 @@ public class MessageTemplateSelector : DataTemplateSelector
230
213
protected override DataTemplate SelectTemplateCore ( object item , DependencyObject container )
231
214
{
232
215
FrameworkElement element = container as FrameworkElement ;
233
- if ( item is SignalMessage )
216
+ if ( item is SignalMessageContainer )
234
217
{
235
- SignalMessage sm = ( SignalMessage ) item ;
218
+ SignalMessage sm = ( ( SignalMessageContainer ) item ) . Message ;
236
219
if ( sm . Type == SignalMessageType . IdentityKeyChange )
237
220
{
238
221
return IdentityKeyChangeMessage ;
239
222
}
240
223
return NormalMessage ;
241
224
}
242
- if ( item is SignalUnreadMarker )
243
- {
244
- return UnreadMarker ;
245
- }
246
225
return null ;
247
226
}
248
227
}
0 commit comments