Example #1
0
        private static async Task AddGroupConversationThread(GraphServiceClient graphClient)
        {
            var posts = new ConversationThreadPostsCollectionPage();

            posts.Add(new Post
            {
                Body = new ItemBody
                {
                    Content     = "Welcome to this group!",
                    ContentType = BodyType.Text,
                }
            });

            var ct = new ConversationThread
            {
                Topic = "The Microsoft Graph SDK!",
                Posts = posts
            };

            var unifiedGroups = await graphClient.Groups
                                .Request()
                                .Filter("groupTypes/any(grp: grp eq 'Unified')")
                                .GetAsync();

            var groupEvents = await graphClient
                              .Groups[unifiedGroups.FirstOrDefault().Id].Threads
                              .Request()
                              .AddAsync(ct);
        }
Example #2
0
        // The time and star secton on the right side.
        private async void ConversationInfoHeader_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            FrameworkElement   grid         = (FrameworkElement)sender;
            ConversationThread conversation = (ConversationThread)grid.DataContext;

            ProgressIndicator.IsIndeterminate = true;
            try
            {
                if (conversation != null)
                {
                    Account account = App.AccountManager.GetCurrentAccount();
                    if (account != null)
                    {
                        if (conversation.HasStar)
                        {
                            // Remove the star from any starred messages
                            await account.SetStarAsync(conversation.Messages, starred : false);
                        }
                        else
                        {
                            // Add a star to the latest message
                            await account.SetStarAsync(conversation.Messages.First(), starred : true);
                        }

                        // Refresh the UI
                        grid.DataContext = null;
                        grid.DataContext = conversation;
                    }
                }
            }
            finally
            {
                ProgressIndicator.IsIndeterminate = false;
            }
        }
Example #3
0
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            ConversationThread conversation = (ConversationThread)value;

            // TODO: Super Stars - No IMAP support - Search term “has:blue-star”? http://googlesystem.blogspot.com/2008/07/gmail-superstars.html

            return((conversation.HasStar) ? Yellow : null);
        }
Example #4
0
        public virtual async Task SelectConversationAsync(ConversationThread conversation)
        {
            ActiveConversation = conversation;
            await SetReadStatusAsync(conversation.Messages, true);

            // Sync full conversation body, from disk or network.
            foreach (MailMessage message in conversation.Messages)
            {
                ObjectWHeaders view = message.GetHtmlView();
                await LazyLoadBodyPartAsync(message, view);
            }
        }
Example #5
0
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            Account account = App.AccountManager.GetCurrentAccount();

            if (account != null)
            {
                Conversation = account.ActiveConversation;
                GetLabelsAsync();
            }

            base.OnNavigatedTo(e);
        }
Example #6
0
        private async void ConversationHeader_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            FrameworkElement   grid         = (FrameworkElement)sender;
            ConversationThread conversation = (ConversationThread)grid.DataContext;

            if (conversation != null)
            {
                Account account = App.AccountManager.GetCurrentAccount();
                if (account != null)
                {
                    await account.SelectConversationAsync(conversation);

                    NavigationService.Navigate(new Uri("/ConversationPage.xaml", UriKind.Relative));
                }
            }
        }
Example #7
0
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            Account account = App.AccountManager.GetCurrentAccount();

            if (account != null)
            {
                Conversation = account.ActiveConversation;
                if (Conversation == null)
                {
                    // This happens after opening an attachment and then hitting back.
                    // TODO: Why do we lose app state after opening an attachment?
                    NavigationService.GoBack();
                }
                DataContext = null; // Force refresh after editing labels
                DataContext = Conversation;
            }
            base.OnNavigatedTo(e);
        }
        /// <summary>
        /// Update the navigation property threads in groups
        /// <param name="body"></param>
        /// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
        /// </summary>
        public RequestInformation CreatePatchRequestInformation(ConversationThread body, Action <ConversationThreadItemRequestBuilderPatchRequestConfiguration> requestConfiguration = default)
        {
            _ = body ?? throw new ArgumentNullException(nameof(body));
            var requestInfo = new RequestInformation {
                HttpMethod     = Method.PATCH,
                UrlTemplate    = UrlTemplate,
                PathParameters = PathParameters,
            };

            requestInfo.SetContentFromParsable(RequestAdapter, "application/json", body);
            if (requestConfiguration != null)
            {
                var requestConfig = new ConversationThreadItemRequestBuilderPatchRequestConfiguration();
                requestConfiguration.Invoke(requestConfig);
                requestInfo.AddRequestOptions(requestConfig.Options);
                requestInfo.AddHeaders(requestConfig.Headers);
            }
            return(requestInfo);
        }
Example #9
0
        static void AddConsumers(ConversationThread conversation, ChartTable chart, OutputTimelineOptions options)
        {
            foreach (var consumer in conversation.Consumers.OrderBy(x => x.Message.StartTime))
            {
                var sb = new StringBuilder(60);
                if (conversation.Depth > 1)
                {
                    sb.Append(' ', (conversation.Depth - 1) * 2);
                }
                if (conversation.Depth > 0)
                {
                    sb.Append("\x2514 ");
                }

                sb.Append("Consume ");
                sb.Append(options.MessageType(consumer.Message));

                chart.Add(sb.ToString(), consumer.Message.StartTime, consumer.Message.ElapsedTime, consumer.Message.Address);
            }
        }
Example #10
0
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Attachment         attachment = (Attachment)value;
            Account            account    = App.AccountManager.GetCurrentAccount();
            ConversationThread thread     = account.ActiveConversation;
            // Gind the message by matching the file name
            // TODO: This could be wrong because the same conversation thread may have
            // multiple messages with the same attachment name.
            MailMessage message = thread.Messages.Where(
                msg => msg.Attachments.FirstOrDefault(
                    att => att.Filename == attachment.Filename) != null).First();

            // TODO: Size
            if (attachment.Scope == Scope.HeadersAndBody ||
                account.MailStorage.HasMessagePart(message.GetThreadId(), message.GetMessageId(), attachment.BodyId))
            {
                return(attachment.Filename + " (open)");
            }
            else
            {
                return(attachment.Filename + " (download)");
            }
        }
Example #11
0
        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            // The query parameter is used to tell us if we're in a reply mode.
            string[] parts = e.Uri.ToString().Split('?');
            if (parts.Length > 1 && !string.IsNullOrEmpty(parts[1]))
            {
                string             query       = parts[1];
                Account            account     = App.AccountManager.GetCurrentAccount();
                ConversationThread mailThread  = account.ActiveConversation;
                MailMessage        lastMessage = mailThread.Messages.First(); // They're in reverse order.

                if (query.Equals("Forward"))
                {
                    // No addresses
                    // TODO: Prefix subject
                    SubjectField.Text = lastMessage.Subject;
                }
                else if (query.Equals("ReplyAll"))
                {
                    // Include all addresses
                    if (lastMessage.ReplyTo.Count > 0)
                    {
                        ToField.Text = string.Join(", ", lastMessage.ReplyTo);
                    }
                    else
                    {
                        ToField.Text = string.Join(", ", new[] { lastMessage.From }.Concat(
                                                       lastMessage.To.Where(mailAddress =>
                                                                            // Filter yourself out of the to line, unless you explicitly sent the e-mail.
                                                                            !mailAddress.Address.Equals(account.Info.Address, StringComparison.OrdinalIgnoreCase)
                                                                            )));
                    }
                    // TODO: CC

                    // TODO: Prefix subject
                    SubjectField.Text = lastMessage.Subject;

                    // For threading
                    _additionalHeaders.Add(new KeyValuePair <string, string>("In-Reply-To", lastMessage.MessageID));
                    _additionalHeaders.Add(new KeyValuePair <string, string>("References", lastMessage.MessageID));
                }
                else if (query.Equals("Reply"))
                {
                    // Include only the sender/reply-to
                    if (lastMessage.ReplyTo.Count > 0)
                    {
                        ToField.Text = string.Join(", ", lastMessage.ReplyTo);
                    }
                    else
                    {
                        ToField.Text = lastMessage.From.ToString();
                    }

                    // TODO: Prefix subject
                    SubjectField.Text = lastMessage.Subject;

                    // For threading
                    _additionalHeaders.Add(new KeyValuePair <string, string>("In-Reply-To", lastMessage.MessageID));
                    _additionalHeaders.Add(new KeyValuePair <string, string>("References", lastMessage.MessageID));
                }

                ObjectWHeaders view = lastMessage.GetTextView();
                await account.LazyLoadBodyPartAsync(lastMessage, view);

                BodyField.Text = "\r\n\r\nOn "
                                 + lastMessage.Date.ToString("ddd, MMM d, yyyy a\\t h:mm tt") + ", " + lastMessage.From + " wrote:\r\n\r\n> "
                                 + view.Body.Replace("\r\n", "\r\n> ");
            }

            // TODO: Signature

            base.OnNavigatedTo(e);
        }
Example #12
0
        /// <summary>
        /// Output a timeline of messages published, sent, and consumed by the test harness.
        /// </summary>
        /// <param name="harness"></param>
        /// <param name="textWriter"></param>
        /// <param name="configure">Configure the timeout output options</param>
        /// <exception cref="ArgumentNullException"></exception>
        public static async Task OutputTimeline(this BusTestHarness harness, TextWriter textWriter, Action <OutputTimelineOptions> configure = default)
        {
            if (harness == null)
            {
                throw new ArgumentNullException(nameof(harness));
            }
            if (textWriter == null)
            {
                throw new ArgumentNullException(nameof(textWriter));
            }

            var options = new OutputTimelineOptions();

            configure?.Invoke(options);

            options.Apply(harness);

            await harness.InactivityTask.ConfigureAwait(false);

            var produced = new List <Message>();

            await foreach (var message in harness.Published.SelectAsync(_ => true).ConfigureAwait(false))
            {
                produced.Add(new Message(message));
            }

            await foreach (var message in harness.Sent.SelectAsync(_ => true).ConfigureAwait(false))
            {
                produced.Add(new Message(message));
            }

            var consumed = new List <Message>();

            await foreach (var message in harness.Consumed.SelectAsync(_ => true).ConfigureAwait(false))
            {
                consumed.Add(new Message(message));
            }

            Dictionary <Guid?, ConversationThread> conversations = produced.GroupBy(m => m.ConversationId).Select(x =>
            {
                List <Message> messages = x.OrderBy(m => m.StartTime).ToList();

                var initiator = messages.FirstOrDefault(m => m.ParentMessageId == default) ?? messages.First();

                var initiatorThread = new ConversationThread(initiator, 1);

                var stack = new Stack <ConversationThread>();
                stack.Push(initiatorThread);

                while (stack.Any())
                {
                    var thread = stack.Pop();

                    List <Message> consumes = consumed.Where(message => message.MessageId == thread.Message.MessageId).ToList();
                    thread.Consumers.AddRange(consumes.Select(message => new ConversationConsumer(message)));

                    IEnumerable <Message> threadMessages = x.Where(m => m.ParentMessageId == thread.Message.MessageId);
                    foreach (var message in threadMessages)
                    {
                        var nextThread = new ConversationThread(message, thread.Depth + 1);
                        thread.Nodes.Add(nextThread);
                        stack.Push(nextThread);
                    }
                }

                return(initiatorThread);
            }).ToDictionary(x => x.Message.ConversationId);

            var chart = new ChartTable();

            foreach (var conversation in conversations.Values.OrderBy(x => x.Message.StartTime))
            {
                var whitespace       = new string(' ', (conversation.Depth - 1) * 2);
                var conversationLine = $"{whitespace}{conversation.Message.EventType} {options.MessageType(conversation.Message)}";

                chart.Add(conversationLine, conversation.Message.StartTime, conversation.Message.ElapsedTime, conversation.Message.Address);

                AddConsumers(conversation, chart, options);

                var stack = new Stack <ConversationThread>(conversation.Nodes.OrderByDescending(x => x.Message.StartTime));
                while (stack.Any())
                {
                    var current = stack.Pop();

                    whitespace = new string(' ', (current.Depth - 1) * 2);
                    var line = $"{whitespace}{current.Message.EventType} {options.MessageType(current.Message)}";

                    chart.Add(line, current.Message.StartTime, current.Message.ElapsedTime, current.Message.Address);

                    AddConsumers(current, chart, options);

                    foreach (var node in current.Nodes.OrderByDescending(x => x.Message.StartTime))
                    {
                        stack.Push(node);
                    }
                }
            }

            options.GetTable(chart)
            .SetColumn(1, "Duration", typeof(int))
            .SetRightNumberAlignment()
            .OutputTo(textWriter)
            .Write();
        }
Example #13
0
        private static async Task AddGroupConversationThread(GraphServiceClient graphClient)
        {
            var posts = new ConversationThreadPostsCollectionPage();
            posts.Add(new Post
            {
                Body = new ItemBody
                {
                    Content = "Welcome to this group!",
                    ContentType = BodyType.Text,
                }
            });

            var ct = new ConversationThread
            {
                Topic = "The Microsoft Graph SDK!",
                Posts = posts
            };

            var unifiedGroups = await graphClient.Groups
                .Request()
                .Filter("groupTypes/any(grp: grp eq 'Unified')")
                .GetAsync();

            var groupEvents = await graphClient
                .Groups[unifiedGroups.FirstOrDefault().Id].Threads
                .Request()
                .AddAsync(ct);
        }