public MessageListViewModel(string folderId, FolderType folderType, MailBoxViewModel mailBox, IProfileDataQueryFactory queryFactory, IMailService mailService, ViewModelActivator activator) { var canExecute = this.WhenAnyObservable(x => x.Cache.SelectionChanged) .Select(x => x.IndexCount() > 0) .Publish(); Activator = activator; Archive = ReactiveCommand.Create <IReadOnlyList <string> >(async messageIds => { PrepareMessageIds(ref messageIds); await mailService.MoveMessage(messageIds, FolderType.Archive); }, canExecute); Delete = ReactiveCommand.Create <IReadOnlyList <string> >(async messageIds => { PrepareMessageIds(ref messageIds); if (folderType != FolderType.DeletedItems) { await mailService.MoveMessage(messageIds, FolderType.DeletedItems); } }, canExecute); MarkAsRead = ReactiveCommand.Create <IReadOnlyList <string> >(async messageIds => { PrepareMessageIds(ref messageIds); await mailService.UpdateMessage(messageIds) .Set(m => m.IsRead, true) .ExecuteAsync(); }, canExecute); MarkAsUnread = ReactiveCommand.Create <IReadOnlyList <string> >(async messageIds => { PrepareMessageIds(ref messageIds); await mailService.UpdateMessage(messageIds) .Set(m => m.IsRead, false) .ExecuteAsync(); }, canExecute); SetFlag = ReactiveCommand.Create <IReadOnlyList <string> >(async messageIds => { PrepareMessageIds(ref messageIds); await mailService.UpdateMessage(messageIds) .Set(m => m.IsFlagged, true) .ExecuteAsync(); }, canExecute); ClearFlag = ReactiveCommand.Create <IReadOnlyList <string> >(async messageIds => { PrepareMessageIds(ref messageIds); await mailService.UpdateMessage(messageIds) .Set(m => m.IsFlagged, false) .ExecuteAsync(); }, canExecute); Move = ReactiveCommand.CreateFromTask <IReadOnlyList <string> >(async messageIds => { PrepareMessageIds(ref messageIds); var selectionResult = await mailBox.PromptUserToSelectFolder( messageIds.Count == 1 ? "Move a message" : $"Move {messageIds.Count} messages", "Select another folder to move to:", includeRoot: false, destinationFolder => CanMoveTo(folderId, destinationFolder)); if (!selectionResult.IsCancelled) { await mailService.MoveMessage(messageIds, selectionResult.SelectedFolder.Id); } }, canExecute); MoveToJunk = ReactiveCommand.CreateFromTask <IReadOnlyList <string> >(async messageIds => { PrepareMessageIds(ref messageIds); await mailService.MoveMessage(messageIds, FolderType.Junk); }, canExecute); this.WhenActivated(disposables => { canExecute.Connect() .DisposeWith(disposables); Archive.ThrownExceptions .Do(this.Log().Error) .Subscribe() .DisposeWith(disposables); Delete.ThrownExceptions .Do(this.Log().Error) .Subscribe() .DisposeWith(disposables); SetFlag.ThrownExceptions .Do(this.Log().Error) .Subscribe() .DisposeWith(disposables); ClearFlag.ThrownExceptions .Do(this.Log().Error) .Subscribe() .DisposeWith(disposables); MarkAsRead.ThrownExceptions .Do(this.Log().Error) .Subscribe() .DisposeWith(disposables); MarkAsUnread.ThrownExceptions .Do(this.Log().Error) .Subscribe() .DisposeWith(disposables); Move.ThrownExceptions .Do(this.Log().Error) .Subscribe() .DisposeWith(disposables); MoveToJunk.ThrownExceptions .Do(this.Log().Error) .Subscribe() .DisposeWith(disposables); Observable.CombineLatest( this.WhenAnyValue(x => x.Order), this.WhenAnyValue(x => x.Filter), (order, filter) => (Order: order, Filter: filter)) .DistinctUntilChanged() .Where(x => x.Order != MessageOrder.Sender) .Subscribe(x => { Cache?.Dispose(); Cache = new VirtualizingCache <MessageSummary, MessageSummaryViewModel, string>( new PersistentVirtualizingSource <MessageSummary, string>(queryFactory, GetItemSpecification(folderId, x.Order, x.Filter), GetIndexSpecification(folderId, x.Order, x.Filter)), mailService.MessageChanges .Select(changes => FilterChanges(changes.ForFolder(folderId), x.Filter)), state => new MessageSummaryViewModel(state, this, queryFactory)); }) .DisposeWith(disposables); this.WhenAnyObservable(x => x.Cache.SelectionChanged) .Select(ranges => ranges.Sum(r => r.Length)) .Do(x => SelectionCount = x) .Subscribe() .DisposeWith(disposables); Disposable.Create(() => { Filter = MessageFilter.None; Cache?.Dispose(); Cache = null; IsSelecting = false; SelectionCount = 0; }) .DisposeWith(disposables); }); }
public MailFolderViewModel(Node <MailFolder, string> node, MailBoxViewModel mailBox, IProfileDataQueryFactory queryFactory, IMailService mailService) { Id = node.Item.Id; ParentId = node.Item.ParentId; Name = node.Item.Name; Type = node.Item.Type; IsFavorite = node.Item.IsFavorite; Messages = new MessageListViewModel(node.Item.Id, node.Item.Type, mailBox, queryFactory, mailService, Activator); Synchronize = ReactiveCommand.CreateFromObservable(() => Observable .StartAsync((token) => mailService.SynchronizeMessagesAsync(node.Item.Id, token)) .TakeUntil(CancelSynchronization)); Synchronize.IsExecuting .ToPropertyEx(this, x => x.IsSynchronizing) .DisposeWith(_disposables); Synchronize.ThrownExceptions .Subscribe(ex => this.Log().Error(ex)) .DisposeWith(_disposables); CancelSynchronization = ReactiveCommand.Create(() => { }, Synchronize.IsExecuting); Move = ReactiveCommand.CreateFromTask(async() => { var result = await mailBox.PromptUserToSelectFolder( "Move a folder", "Select another folder to move to:", includeRoot: true, CanMoveTo); this.Log().Debug(result); }); node.Children.Connect() .Transform(n => new MailFolderViewModel(n, mailBox, queryFactory, mailService)) .Sort(SortExpressionComparer <MailFolderViewModel> .Ascending(f => f.Name)) .ObserveOn(RxApp.MainThreadScheduler) .Bind(out _childFolders) .DisposeMany() .Subscribe() .DisposeWith(_disposables); mailService.MessageChanges .Where(changes => changes.AffectsFolder(node.Item.Id)) .SelectMany(_ => CountMessages(queryFactory, node.Item.Id)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { UnreadCount = x.UnreadCount; TotalCount = x.TotalCount; }) .DisposeWith(_disposables); CountMessages(queryFactory, node.Item.Id) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { UnreadCount = x.UnreadCount; TotalCount = x.TotalCount; }) .DisposeWith(_disposables); }