internal void AddThread(YamsterThread thread, YamsterModelEventCollector eventCollector) { int index = this.threadsInternal.BinarySearch(thread, Comparer <YamsterThread> .Create((x, y) => Math.Sign(x.ThreadId - y.ThreadId))); int deletedIndex = this.deletedThreadsInternal.BinarySearch(thread, Comparer <YamsterThread> .Create((x, y) => Math.Sign(x.ThreadId - y.ThreadId))); if (index >= 0 || deletedIndex >= 0) { throw new InvalidOperationException("Program Bug: The message was already added to this thread"); } if (!thread.AllMessagesDeleted) { this.threadsInternal.Insert(~index, thread); if (thread.Read) { this.NotifyThreadReadChanged(newReadValue: true, eventCollector: eventCollector); } } else { this.deletedThreadsInternal.Insert(~deletedIndex, thread); } }
internal void RemoveThread(YamsterThread thread, YamsterModelEventCollector eventCollector) { int index = this.threadsInternal.BinarySearch(thread, Comparer <YamsterThread> .Create((x, y) => Math.Sign(x.ThreadId - y.ThreadId))); int deletedIndex = this.deletedThreadsInternal.BinarySearch(thread, Comparer <YamsterThread> .Create((x, y) => Math.Sign(x.ThreadId - y.ThreadId))); if (index < 0 && deletedIndex < 0) { Debug.Assert(false, "RemoveThread() called on thread that doesn't belong to this group"); return; } if (index >= 0) { this.threadsInternal.RemoveAt(index); if (thread.Read) { this.NotifyThreadReadChanged(newReadValue: false, eventCollector: eventCollector); } } else { this.deletedThreadsInternal.RemoveAt(deletedIndex); } }
internal void FixupUnresolvedObjectsForThread(YamsterThread thread, YamsterMessage latestMessage, YamsterModelEventCollector eventCollector) { Debug.Assert(latestMessage.Thread == thread); DbThreadState dbThreadState; if (unresolvedThreadStatesById.TryGetValue(thread.ThreadId, out dbThreadState)) { unresolvedThreadStatesById.Remove(thread.ThreadId); thread.SetDbThreadState(dbThreadState, eventCollector); } // Is this thread part of a conversation? long conversationId = latestMessage.DbMessage.ConversationId; if (conversationId != 0) { // Register the thread as the owner of this conversation this.threadsByConversationId[conversationId] = thread; // Is there an unresolved conversation object? DbConversation unresolvedConversation; if (this.unresolvedConversationsById.TryGetValue(conversationId, out unresolvedConversation)) { // Yes, so apply it now this.unresolvedConversationsById.Remove(conversationId); thread.UpdateConversation(unresolvedConversation, eventCollector); } } }
internal FreshenThreadRequest(YamsterThread thread, MessagePuller messagePuller) { this.Thread = thread; this.MessagePuller = messagePuller; this.State = FreshenThreadState.Queued; this.Error = null; }
void ProcessDbMessage(DbMessage record) { // Does the message exist yet? var message = this.GetMessageById(record.MessageId, nullIfMissing: true); bool messageIsNew = message == null; var eventCollector = new YamsterModelEventCollector(); if (messageIsNew) { message = new YamsterMessage(record.MessageId, this); this.messagesById.Add(record.MessageId, message); eventCollector.NotifyAfterAdd(message); message.SetDbMessage(record, eventCollector); // For now we assume that messages cannot move between threads var threadId = message.ThreadId; YamsterThread thread = GetThreadById(threadId, nullIfMissing: true); if (thread == null) { thread = new YamsterThread(threadId, message.Group, this); threadsById.Add(threadId, thread); eventCollector.NotifyAfterAdd(thread); message.Group.AddThread(thread, eventCollector); thread.AddMessage(message, eventCollector); FixupUnresolvedObjectsForThread(thread, message, eventCollector); } else { thread.AddMessage(message, eventCollector); } } else { message.SetDbMessage(record, eventCollector); } // Was there an unresolved message that we can process now? DbMessageState unresolvedMessageState; if (this.unresolvedMessageStatesById.TryGetValue(record.MessageId, out unresolvedMessageState)) { this.unresolvedMessageStatesById.Remove(record.MessageId); ProcessDbMessageState(unresolvedMessageState, eventCollector); } if (messageIsNew) { CheckForListenedMessage(message, eventCollector); } eventCollector.FireEvents(); }
/// <summary> /// FreshenThread() asks the MessagePuller to refresh the specified thread as soon /// as possible, ignoring its normal algorithm priorities. /// </summary> /// <remarks> /// Since this operation may require multiple REST service calls and is subject to /// Yammer rate limits, it may still take a while to process. The returned /// FreshenThreadRequest object can be used to track the progress. Only one /// FreshenThread() request can be active at a time; any previous requests are /// canceled by a new call to FreshenThread(). Note that no processing will occur /// unless MessagePuller.Enabled=true and MessagePuller.Process() is being called /// at regular intervals. /// </remarks> public FreshenThreadRequest FreshenThread(YamsterThread thread) { FreshenThreadRequest interruptedRequest = freshenThreadRequest; freshenThreadRequest = new FreshenThreadRequest(thread, this); if (interruptedRequest != null) { interruptedRequest.SetError(new Exception("The operation was interrupted by a more recent request")); } return(freshenThreadRequest); }
void UpdateViewWithThread(YamsterThread thread) { bool shouldBeInView = false; if (CompiledFunc != null) { var executionContext = new YqlExecutionContext(this.appContext); executionContext.Thread = thread; shouldBeInView = CompiledFunc(executionContext); } ViewedThread viewedThread = null; bool isInView = viewedThreadsById.TryGetValue(thread.ThreadId, out viewedThread); bool statisticsChanged = false; if (isInView) { if (!shouldBeInView) { this.RemoveViewedThread(viewedThread); NotifyViewChanged(YamsterViewChangeType.ModelLeaveView, thread); // TotalItemCount changed statisticsChanged = true; } else { if (thread.Read != viewedThread.Read) { this.readThreadCount += thread.Read ? +1 : -1; viewedThread.Read = thread.Read; statisticsChanged = true; } } } else { if (shouldBeInView) { AddViewedThread(new ViewedThread(thread)); NotifyViewChanged(YamsterViewChangeType.ModelEnterView, thread); // TotalItemCount changed statisticsChanged = true; } } if (statisticsChanged) { NotifyViewChanged(YamsterViewChangeType.StatisticsChanged, null); } }
public YamsterThread GetThreadById(long threadId, bool nullIfMissing = false) { YamsterThread thread = null; if (!this.threadsById.TryGetValue(threadId, out thread)) { if (!nullIfMissing) { throw new KeyNotFoundException("The thread ID " + threadId + " was not found"); } } return(thread); }
public YamsterThreadChangedEventArgs(YamsterThread thread, YamsterModelChangeType changeType) : base(changeType) { this.Thread = thread; }
public ViewedThread(YamsterThread thread) { this.Thread = thread; this.Read = thread.Read; }
public static YamsterNewMessage CreateReply(YamsterThread threadBeingRepliedTo) { return(CreateReply(threadBeingRepliedTo.ThreadStarterMessage)); }
internal void NotifyAddedToThread(YamsterThread thread) { this.thread = thread; }