public FeedGroupPageViewModel(HohoemaApp hohoemaApp, PageManager pageManager, Views.Service.ContentSelectDialogService contentSelectDialogService) : base(hohoemaApp, pageManager) { ContentSelectDialogService = contentSelectDialogService; IsDeleted = new ReactiveProperty <bool>(); FeedGroupName = new ReactiveProperty <string>(); MylistFeedSources = new ObservableCollection <FeedItemSourceListItem>(); TagFeedSources = new ObservableCollection <FeedItemSourceListItem>(); UserFeedSources = new ObservableCollection <FeedItemSourceListItem>(); HasMylistFeedSource = MylistFeedSources.ObserveProperty(x => x.Count) .Select(x => x > 0) .ToReadOnlyReactiveProperty(); HasTagFeedSource = TagFeedSources.ObserveProperty(x => x.Count) .Select(x => x > 0) .ToReadOnlyReactiveProperty(); HasUserFeedSource = UserFeedSources.ObserveProperty(x => x.Count) .Select(x => x > 0) .ToReadOnlyReactiveProperty(); MylistFavItems = new ObservableCollection <FollowItemInfo>(); TagFavItems = new ObservableCollection <FollowItemInfo>(); UserFavItems = new ObservableCollection <FollowItemInfo>(); SelectFromFavItems = new ReactiveProperty <bool>(true); SelectedFavInfo = new ReactiveProperty <FollowItemInfo>(); FavItemType = new ReactiveProperty <FollowItemType>(); FeedSourceId = new ReactiveProperty <string>(); FeedSourceItemName = new ReactiveProperty <string>(); ExistFeedSource = new ReactiveProperty <bool>(); IsPublicFeedSource = new ReactiveProperty <bool>(); CanUseFeedSource = Observable.CombineLatest( ExistFeedSource, IsPublicFeedSource ) .Select(x => x.All(y => y)) .ToReactiveProperty(); FavItemType.Subscribe(x => { FeedSourceId.Value = ""; ExistFeedSource.Value = false; FeedSourceItemName.Value = ""; // お気に入りアイテムがある場合は、「お気に入りから選択」をデフォルトに switch (x) { case FollowItemType.Tag: SelectFromFavItems.Value = TagFavItems.Count > 0; break; case FollowItemType.Mylist: SelectFromFavItems.Value = MylistFavItems.Count > 0; break; case FollowItemType.User: SelectFromFavItems.Value = UserFavItems.Count > 0; break; default: break; } }); FeedSourceId.ToUnit() .Subscribe(_ => { ExistFeedSource.Value = false; FeedSourceItemName.Value = ""; }); Observable.Merge( SelectFromFavItems.ToUnit(), SelectedFavInfo.ToUnit(), FavItemType.ToUnit(), FeedSourceId.ToUnit().Throttle(TimeSpan.FromSeconds(1)) ) .Subscribe(async x => { if (SelectFromFavItems.Value) { ExistFeedSource.Value = SelectedFavInfo.Value != null; IsPublicFeedSource.Value = true; FeedSourceItemName.Value = ""; return; } ExistFeedSource.Value = false; if (FavItemType.Value == FollowItemType.Tag) { ExistFeedSource.Value = !string.IsNullOrWhiteSpace(FeedSourceId.Value); IsPublicFeedSource.Value = true; FeedSourceItemName.Value = FeedSourceId.Value; } else { if (string.IsNullOrWhiteSpace(FeedSourceId.Value)) { ExistFeedSource.Value = false; } else { if (FavItemType.Value == FollowItemType.Mylist) { try { var mylistRes = await HohoemaApp.ContentFinder.GetMylistGroupDetail(FeedSourceId.Value); var mylist = mylistRes?.MylistGroup; if (mylist != null) { ExistFeedSource.Value = true; IsPublicFeedSource.Value = mylist.IsPublic; FeedSourceItemName.Value = Mntone.Nico2.StringExtention.DecodeUTF8(mylist.Name); } } catch { ExistFeedSource.Value = false; } } else if (FavItemType.Value == FollowItemType.User) { try { var user = await HohoemaApp.ContentFinder.GetUserDetail(FeedSourceId.Value); if (user != null) { ExistFeedSource.Value = true; IsPublicFeedSource.Value = !user.IsOwnerVideoPrivate; FeedSourceItemName.Value = user.Nickname; } } catch { ExistFeedSource.Value = false; } } if (!ExistFeedSource.Value) { IsPublicFeedSource.Value = false; FeedSourceItemName.Value = ""; } } } }); AddFeedCommand = Observable.CombineLatest( ExistFeedSource, IsPublicFeedSource ) .Select(x => x.All(y => y == true)) .ToReactiveCommand(); AddFeedCommand.Subscribe(_ => { string name = ""; string id = ""; if (SelectFromFavItems.Value) { var favInfo = SelectedFavInfo.Value; name = favInfo.Name; id = favInfo.Id; if (favInfo.FollowItemType != FavItemType.Value) { throw new Exception(); } } else { // idからMylistGroupを引く // 公開されていない場合にはエラー id = FeedSourceId.Value; name = FeedSourceItemName.Value; FeedSourceItemName.Value = ""; FeedSourceId.Value = ""; } var favManager = HohoemaApp.FollowManager; var feedManager = HohoemaApp.FeedManager; IFeedSource feedSource; switch (FavItemType.Value) { case FollowItemType.Tag: feedSource = FeedGroup.AddTagFeedSource(id); if (feedSource != null) { var favInfo = favManager.Tag.FollowInfoItems.SingleOrDefault(x => x.Id == id); if (favInfo != null) { TagFavItems.Remove(favInfo); } TagFeedSources.Add(new FeedItemSourceListItem(feedSource, this)); } break; case FollowItemType.Mylist: feedSource = FeedGroup.AddMylistFeedSource(name, id); if (feedSource != null) { var favInfo = favManager.Mylist.FollowInfoItems.SingleOrDefault(x => x.Id == id); if (favInfo != null) { MylistFavItems.Remove(favInfo); } MylistFeedSources.Add(new FeedItemSourceListItem(feedSource, this)); } break; case FollowItemType.User: feedSource = FeedGroup.AddUserFeedSource(name, id); if (feedSource != null) { var favInfo = favManager.User.FollowInfoItems.SingleOrDefault(x => x.Id == id); if (favInfo != null) { UserFavItems.Remove(favInfo); } UserFeedSources.Add(new FeedItemSourceListItem(feedSource, this)); } break; default: break; } HohoemaApp.FeedManager.SaveOne(FeedGroup); }); RenameApplyCommand = FeedGroupName .Where(x => HohoemaApp.FeedManager != null && x != null) .Select(x => HohoemaApp.FeedManager.CanAddLabel(x)) .ToReactiveCommand(); RenameApplyCommand.Subscribe(async _ => { if (await FeedGroup.Rename(FeedGroupName.Value)) { UpdateTitle(FeedGroup.Label); } FeedGroupName.ForceNotify(); }); }
public MylistPageViewModel( HohoemaApp hohoemaApp , PageManager pageManager , Views.Service.MylistRegistrationDialogService mylistDialogService , Views.Service.ContentSelectDialogService contentSelectDialogService ) : base(hohoemaApp, pageManager, mylistDialogService, isRequireSignIn: true) { _ContentSelectDialogService = contentSelectDialogService; PlayableList = new ReactiveProperty <IPlayableList>(); MylistOrigin = new ReactiveProperty <Models.PlaylistOrigin>(); IsFavoriteMylist = new ReactiveProperty <bool>(mode: ReactivePropertyMode.DistinctUntilChanged) .AddTo(_CompositeDisposable); CanChangeFavoriteMylistState = new ReactiveProperty <bool>() .AddTo(_CompositeDisposable); IsFavoriteMylist .Where(x => PlayableList.Value.Id != null) .Subscribe(async x => { if (PlayableList.Value.Origin != PlaylistOrigin.OtherUser) { return; } if (_NowProcessFavorite) { return; } _NowProcessFavorite = true; CanChangeFavoriteMylistState.Value = false; if (x) { if (await FavoriteMylist()) { Debug.WriteLine(_MylistTitle + "のマイリストをお気に入り登録しました."); } else { // お気に入り登録に失敗した場合は状態を差し戻し Debug.WriteLine(_MylistTitle + "のマイリストをお気に入り登録に失敗"); IsFavoriteMylist.Value = false; } } else { if (await UnfavoriteMylist()) { Debug.WriteLine(_MylistTitle + "のマイリストをお気に入り解除しました."); } else { // お気に入り解除に失敗した場合は状態を差し戻し Debug.WriteLine(_MylistTitle + "のマイリストをお気に入り解除に失敗"); IsFavoriteMylist.Value = true; } } CanChangeFavoriteMylistState.Value = IsFavoriteMylist.Value == true || HohoemaApp.FollowManager.CanMoreAddFollow(FollowItemType.Mylist); _NowProcessFavorite = false; }) .AddTo(_CompositeDisposable); UnregistrationMylistCommand = SelectedItems.ObserveProperty(x => x.Count) .Where(_ => this.CanEditMylist) .Select(x => x > 0) .ToReactiveCommand(false); UnregistrationMylistCommand.Subscribe(async _ => { var mylistGroup = HohoemaApp.UserMylistManager.GetMylistGroup(PlayableList.Value.Id); var items = SelectedItems.ToArray(); var action = AsyncInfo.Run <uint>(async(cancelToken, progress) => { uint progressCount = 0; int successCount = 0; int failedCount = 0; Debug.WriteLine($"マイリストに追加解除を開始..."); foreach (var video in items) { var unregistrationResult = await mylistGroup.Unregistration( video.RawVideoId , withRefresh: false /* あとでまとめてリフレッシュするのでここでは OFF */); if (unregistrationResult == ContentManageResult.Success) { successCount++; } else { failedCount++; } progressCount++; progress.Report(progressCount); Debug.WriteLine($"{video.Title}[{video.RawVideoId}]:{unregistrationResult.ToString()}"); } // 登録解除結果を得るためリフレッシュ await mylistGroup.Refresh(); // ユーザーに結果を通知 var titleText = $"「{mylistGroup.Name}」から {successCount}件 の動画が登録解除されました"; var toastService = App.Current.Container.Resolve <ToastNotificationService>(); var resultText = $""; if (failedCount > 0) { resultText += $"\n登録解除に失敗した {failedCount}件 は選択されたままです"; } toastService.ShowText(titleText, resultText); // 登録解除に失敗したアイテムだけを残すように // マイリストから除外された動画を選択アイテムリストから削除 foreach (var item in SelectedItems.ToArray()) { if (false == mylistGroup.CheckRegistratedVideoId(item.RawVideoId)) { SelectedItems.Remove(item); IncrementalLoadingItems.Remove(item); } } Debug.WriteLine($"マイリストに追加解除完了---------------"); }); await PageManager.StartNoUIWork("マイリストに追加解除", items.Length, () => action); }); CopyMylistCommand = SelectedItems.ObserveProperty(x => x.Count) .Where(_ => this.CanEditMylist) .Select(x => x > 0) .ToReactiveCommand(false); CopyMylistCommand.Subscribe(async _ => { var mylistGroup = HohoemaApp.UserMylistManager.GetMylistGroup(PlayableList.Value.Id); // ターゲットのマイリストを選択する var targetMylist = await MylistDialogService .ShowSelectSingleMylistDialog( SelectedItems.Count , hideMylistGroupId: mylistGroup.GroupId ); if (targetMylist == null) { return; } // すでにターゲットのマイリストに登録されている動画を除外してコピーする var items = SelectedItems .Where(x => !targetMylist.CheckRegistratedVideoId(x.RawVideoId)) .ToList(); var action = AsyncInfo.Run <uint>(async(cancelToken, progress) => { Debug.WriteLine($"マイリストのコピーを開始..."); var result = await mylistGroup.CopyMylistTo( targetMylist , items.Select(video => video.RawVideoId).ToArray() ); Debug.WriteLine($"copy mylist {items.Count} item from {mylistGroup.Name} to {targetMylist.Name} : {result.ToString()}"); // ユーザーに結果を通知 var toastService = App.Current.Container.Resolve <ToastNotificationService>(); string titleText; string contentText; if (result == ContentManageResult.Success) { titleText = $"「{targetMylist.Name}」に {SelectedItems.Count}件 コピーしました"; contentText = $" {SelectedItems.Count}件 の動画をコピーしました"; progress.Report((uint)items.Count); } else { titleText = $"マイリストコピーに失敗"; contentText = $"時間を置いてからやり直してみてください"; } toastService.ShowText(titleText, contentText); // 成功した場合は選択状態を解除 if (result == ContentManageResult.Success) { ClearSelection(); } Debug.WriteLine($"マイリストのコピー完了..."); }); await PageManager.StartNoUIWork("マイリストのコピー", items.Count, () => action); }); MoveMylistCommand = SelectedItems.ObserveProperty(x => x.Count) .Where(_ => this.CanEditMylist) .Select(x => x > 0) .ToReactiveCommand(false); MoveMylistCommand.Subscribe(async _ => { var mylistGroup = HohoemaApp.UserMylistManager.GetMylistGroup(PlayableList.Value.Id); // ターゲットのマイリストを選択する var targetMylist = await MylistDialogService .ShowSelectSingleMylistDialog( SelectedItems.Count , hideMylistGroupId: mylistGroup.GroupId ); if (targetMylist == null) { return; } // すでにターゲットのマイリストに登録されている動画を除外してコピーする var items = SelectedItems .Where(x => !targetMylist.CheckRegistratedVideoId(x.RawVideoId)) .ToList(); Debug.WriteLine($"マイリストの移動を開始..."); var result = await mylistGroup.MoveMylistTo( targetMylist , items.Select(video => video.RawVideoId).ToArray() ); Debug.WriteLine($"move mylist {items.Count} item from {mylistGroup.Name} to {targetMylist.Name} : {result.ToString()}"); // ユーザーに結果を通知 var toastService = App.Current.Container.Resolve <ToastNotificationService>(); string titleText; string contentText; if (result == ContentManageResult.Success) { titleText = $"「{targetMylist.Name}」に {SelectedItems.Count}件 移動しました"; contentText = $" {SelectedItems.Count}件 の動画を移動しました"; } else { titleText = $"マイリスト移動に失敗"; contentText = $"時間を置いてからやり直してみてください"; } toastService.ShowText(titleText, contentText); // 成功した場合は選択状態を解除 if (result == ContentManageResult.Success) { // 移動元のマイリストからは削除されているはず foreach (var item in SelectedItems) { if (!mylistGroup.CheckRegistratedVideoId(item.RawVideoId)) { IncrementalLoadingItems.Remove(item); } else { throw new Exception(); } } ClearSelection(); } Debug.WriteLine($"マイリストの移動完了..."); }); }
public UserInfoPageViewModel( HohoemaApp hohoemaApp , PageManager pageManager , Views.Service.ContentSelectDialogService contentSelectDialogService ) : base(hohoemaApp, pageManager) { _ContentSelectDialogService = contentSelectDialogService; HasOwnerVideo = true; MylistGroups = new ObservableCollection <MylistGroupListItem>(); VideoInfoItems = new ObservableCollection <VideoInfoControlViewModel>(); IsFavorite = new ReactiveProperty <bool>() .AddTo(_CompositeDisposable); CanChangeFavoriteState = new ReactiveProperty <bool>() .AddTo(_CompositeDisposable); IsFavorite .Where(x => UserId != null) .Subscribe(async x => { if (_NowProcessFavorite) { return; } _NowProcessFavorite = true; CanChangeFavoriteState.Value = false; if (x) { if (await FavoriteUser()) { Debug.WriteLine(UserName + "をお気に入り登録しました."); } else { // お気に入り登録に失敗した場合は状態を差し戻し Debug.WriteLine(UserName + "をお気に入り登録に失敗"); IsFavorite.Value = false; } } else { if (await UnfavoriteUser()) { Debug.WriteLine(UserName + "をお気に入り解除しました."); } else { // お気に入り解除に失敗した場合は状態を差し戻し Debug.WriteLine(UserName + "お気に入り解除に失敗"); IsFavorite.Value = true; } } CanChangeFavoriteState.Value = IsFavorite.Value == true || HohoemaApp.FollowManager.CanMoreAddFollow(FollowItemType.User); _NowProcessFavorite = false; }) .AddTo(_CompositeDisposable); OpenUserVideoPageCommand = VideoInfoItems.ObserveProperty(x => x.Count) .Select(x => x > 0) .ToReactiveCommand() .AddTo(_CompositeDisposable); OpenUserVideoPageCommand.Subscribe(x => { PageManager.OpenPage(HohoemaPageType.UserVideo, UserId); }) .AddTo(_CompositeDisposable); IsNGVideoOwner = new ReactiveProperty <bool>(false); AddNGVideoOwnerCommand = new ReactiveCommand(); AddNGVideoOwnerCommand.Subscribe(_ => { HohoemaApp.UserSettings.NGSettings.AddNGVideoOwnerId(UserId, UserName); IsNGVideoOwner.Value = true; HohoemaApp.UserSettings.NGSettings.Save().ConfigureAwait(false); Debug.WriteLine(UserName + "をNG動画投稿者として登録しました。"); }); RemoveNGVideoOwnerCommand = new ReactiveCommand(); RemoveNGVideoOwnerCommand.Subscribe(_ => { HohoemaApp.UserSettings.NGSettings.RemoveNGVideoOwnerId(UserId); IsNGVideoOwner.Value = false; HohoemaApp.UserSettings.NGSettings.Save().ConfigureAwait(false); Debug.WriteLine(UserName + "をNG動画投稿者の指定を解除しました。"); }); }