OSDN Git Service

TabClassにEnqueueRemovePost, RemoveSubmitメソッドを追加
authorKimura Youichi <kim.upsilon@bucyou.net>
Thu, 12 May 2016 12:27:00 +0000 (21:27 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Fri, 13 May 2016 20:00:46 +0000 (05:00 +0900)
タブ内の発言の削除キューは TabClass 内で管理されるようになり、Favorites タブからの
発言の削除に専用のメソッドを必要としなくなります。

OpenTween.Tests/TabClassTest.cs
OpenTween.Tests/TabInformationTest.cs
OpenTween/StatusDictionary.cs
OpenTween/Tween.cs

index cad1d00..1544742 100644 (file)
@@ -33,6 +33,96 @@ namespace OpenTween
     public class TabClassTest
     {
         [Fact]
+        public void EnqueueRemovePost_Test()
+        {
+            var tab = new TabClass
+            {
+                TabType = MyCommon.TabUsageType.PublicSearch,
+                UnreadManage = true,
+            };
+
+            tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, IsRead = false });
+            tab.AddPostToInnerStorage(new PostClass { StatusId = 110L, IsRead = false });
+            tab.AddPostToInnerStorage(new PostClass { StatusId = 120L, IsRead = false });
+
+            tab.AddSubmit();
+
+            Assert.Equal(3, tab.AllCount);
+            Assert.Equal(3, tab.UnreadCount);
+
+            tab.EnqueueRemovePost(100L, setIsDeleted: false);
+
+            // この時点では削除は行われない
+            Assert.Equal(3, tab.AllCount);
+            Assert.Equal(3, tab.UnreadCount);
+
+            var removedIds = tab.RemoveSubmit();
+
+            Assert.Equal(2, tab.AllCount);
+            Assert.Equal(2, tab.UnreadCount);
+            Assert.Equal(new[] { 110L, 120L }, tab.BackupIds);
+            Assert.Equal(new[] { 100L }, removedIds.AsEnumerable());
+        }
+
+        [Fact]
+        public void EnqueueRemovePost_SetIsDeletedTest()
+        {
+            var tab = new TabClass
+            {
+                TabType = MyCommon.TabUsageType.PublicSearch,
+                UnreadManage = true,
+            };
+
+            var post = new PostClass { StatusId = 100L, IsRead = false };
+            tab.AddPostToInnerStorage(post);
+            tab.AddSubmit();
+
+            Assert.Equal(1, tab.AllCount);
+            Assert.Equal(1, tab.UnreadCount);
+
+            tab.EnqueueRemovePost(100L, setIsDeleted: true);
+
+            // この時点ではタブからの削除は行われないが、PostClass.IsDeleted は true にセットされる
+            Assert.Equal(1, tab.AllCount);
+            Assert.Equal(1, tab.UnreadCount);
+            Assert.True(post.IsDeleted);
+
+            var removedIds = tab.RemoveSubmit();
+
+            Assert.Equal(0, tab.AllCount);
+            Assert.Equal(0, tab.UnreadCount);
+            Assert.Equal(new[] { 100L }, removedIds.AsEnumerable());
+        }
+
+        [Fact]
+        public void EnqueueRemovePost_UnknownIdTest()
+        {
+            var tab = new TabClass
+            {
+                TabType = MyCommon.TabUsageType.PublicSearch,
+                UnreadManage = true,
+            };
+
+            tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, IsRead = false });
+            tab.AddSubmit();
+
+            Assert.Equal(1, tab.AllCount);
+            Assert.Equal(1, tab.UnreadCount);
+
+            // StatusId = 999L は存在しない
+            tab.EnqueueRemovePost(999L, setIsDeleted: false);
+
+            Assert.Equal(1, tab.AllCount);
+            Assert.Equal(1, tab.UnreadCount);
+
+            var removedIds = tab.RemoveSubmit();
+
+            Assert.Equal(1, tab.AllCount);
+            Assert.Equal(1, tab.UnreadCount);
+            Assert.Empty(removedIds);
+        }
+
+        [Fact]
         public void NextUnreadId_Test()
         {
             var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
index 294f908..d4a3d2b 100644 (file)
@@ -370,6 +370,32 @@ namespace OpenTween
         }
 
         [Fact]
+        public void SubmitUpdate_RemoveSubmit_Test()
+        {
+            var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
+
+            this.tabinfo.AddPost(new PostClass { StatusId = 100L });
+            this.tabinfo.DistributePosts();
+            this.tabinfo.SubmitUpdate();
+
+            Assert.Equal(1, homeTab.AllCount);
+
+            this.tabinfo.RemovePostFromAllTabs(100L, setIsDeleted: true);
+
+            // この時点ではまだ削除されない
+            Assert.Equal(1, homeTab.AllCount);
+
+            string soundFile;
+            PostClass[] notifyPosts;
+            bool newMentionOrDm, isDeletePost;
+            this.tabinfo.SubmitUpdate(out soundFile, out notifyPosts, out newMentionOrDm, out isDeletePost);
+
+            Assert.True(isDeletePost);
+            Assert.Equal(0, homeTab.AllCount);
+            Assert.False(this.tabinfo.Posts.ContainsKey(100L));
+        }
+
+        [Fact]
         public void SubmitUpdate_NotifyPriorityTest()
         {
             var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
index 4b1db36..8a20d7d 100644 (file)
@@ -557,7 +557,6 @@ namespace OpenTween
         //AddPost(複数回) -> DistributePosts          -> SubmitUpdate
 
         private ConcurrentQueue<long> addQueue = new ConcurrentQueue<long>();
-        private ConcurrentQueue<long> deleteQueue = new ConcurrentQueue<long>();
 
         /// <summary>通知サウンドを再生する優先順位</summary>
         private Dictionary<MyCommon.TabUsageType, int> notifyPriorityByTabType = new Dictionary<MyCommon.TabUsageType, int>
@@ -789,50 +788,6 @@ namespace OpenTween
                 : null;
         }
 
-        public void RemoveFavPost(long Id)
-        {
-            lock (LockObj)
-            {
-                PostClass post;
-                var tab = this.GetTabByType(MyCommon.TabUsageType.Favorites);
-
-                if (_statuses.TryGetValue(Id, out post))
-                {
-                    //指定タブから該当ID削除
-                    var tType = tab.TabType;
-                    if (tab.Contains(Id))
-                        tab.Remove(Id);
-
-                    //FavタブからRetweet発言を削除する場合は、他の同一参照Retweetも削除
-                    if (tType == MyCommon.TabUsageType.Favorites && post.RetweetedId != null)
-                    {
-                        for (int i = 0; i < tab.AllCount; i++)
-                        {
-                            PostClass rPost = null;
-                            try
-                            {
-                                rPost = tab[i];
-                            }
-                            catch (ArgumentOutOfRangeException)
-                            {
-                                break;
-                            }
-                            if (rPost.RetweetedId != null && rPost.RetweetedId == post.RetweetedId)
-                            {
-                                tab.Remove(rPost.StatusId);
-                            }
-                        }
-                    }
-                }
-                //TabType=PublicSearchの場合(Postの保存先がTabClass内)
-                //if (tab.Contains(StatusId) &&
-                //   (tab.TabType = MyCommon.TabUsageType.PublicSearch || tab.TabType = MyCommon.TabUsageType.DirectMessage))
-                //{
-                //    tab.Remove(StatusId);
-                //}
-            }
-        }
-
         public void ScrubGeoReserve(long id, long upToStatusId)
         {
             lock (LockObj)
@@ -867,48 +822,11 @@ namespace OpenTween
             }
         }
 
-        public void RemovePostReserve(long id)
-        {
-            lock (LockObj)
-            {
-                this.deleteQueue.Enqueue(id);
-                this.DeletePost(id);   //UI選択行がずれるため、RemovePostは使用しない
-            }
-        }
-
-        public void RemovePost(long Id)
-        {
-            lock (LockObj)
-            {
-                //各タブから該当ID削除
-                foreach (var tab in _tabs.Values)
-                {
-                    if (tab.Contains(Id))
-                        tab.Remove(Id);
-                }
-
-                PostClass removedPost;
-                _statuses.TryRemove(Id, out removedPost);
-            }
-        }
-
-        private void DeletePost(long Id)
+        public void RemovePostFromAllTabs(long statusId, bool setIsDeleted)
         {
-            lock (LockObj)
+            foreach (var tab in this.Tabs.Values)
             {
-                PostClass post;
-                if (_statuses.TryGetValue(Id, out post))
-                {
-                    post.IsDeleted = true;
-                }
-                foreach (var tb in this.GetTabsInnerStorageType())
-                {
-                    if (tb.Contains(Id))
-                    {
-                        post = tb.Posts[Id];
-                        post.IsDeleted = true;
-                    }
-                }
+                tab.EnqueueRemovePost(statusId, setIsDeleted);
             }
         }
 
@@ -933,7 +851,8 @@ namespace OpenTween
                 newMentionOrDm = false;
                 isDeletePost = false;
 
-                var totalPosts = 0;
+                var addedCountTotal = 0;
+                var removedIdsAll = new List<long>();
                 var notifyPostsList = new List<PostClass>();
 
                 var currentNotifyPriority = -1;
@@ -980,19 +899,24 @@ namespace OpenTween
                         }
                     }
 
-                    totalPosts += addedIds.Count;
+                    addedCountTotal += addedIds.Count;
+
+                    var removedIds = tab.RemoveSubmit();
+                    removedIdsAll.AddRange(removedIds);
                 }
 
                 notifyPosts = notifyPostsList.Distinct().ToArray();
 
-                long deletedStatusId;
-                while (this.deleteQueue.TryDequeue(out deletedStatusId))
-                {
-                    this.RemovePost(deletedStatusId);
+                if (removedIdsAll.Count > 0)
                     isDeletePost = true;
+
+                foreach (var removedId in removedIdsAll.Distinct())
+                {
+                    PostClass removedPost;
+                    this._statuses.TryRemove(removedId, out removedPost);
                 }
 
-                return totalPosts;
+                return addedCountTotal;
             }
         }
 
@@ -1326,7 +1250,7 @@ namespace OpenTween
 
                         // 移動されたらRecentから除去
                         if (moved)
-                            homeTab.Remove(post.StatusId);
+                            homeTab.RemovePostImmediately(post.StatusId);
 
                         if (tab.TabType == MyCommon.TabUsageType.Mentions)
                         {
@@ -1483,6 +1407,7 @@ namespace OpenTween
         private List<PostFilterRule> _filters;
         private IndexedSortedSet<long> _ids;
         private ConcurrentQueue<TemporaryId> addQueue = new ConcurrentQueue<TemporaryId>();
+        private ConcurrentQueue<long> removeQueue = new ConcurrentQueue<long>();
         private SortedSet<long> unreadIds = new SortedSet<long>();
         private MyCommon.TabUsageType _tabType = MyCommon.TabUsageType.Undefined;
 
@@ -1790,19 +1715,46 @@ namespace OpenTween
             return addedIds;
         }
 
-        public void Remove(long Id)
+        public void EnqueueRemovePost(long statusId, bool setIsDeleted)
         {
-            if (!this._ids.Contains(Id))
-                return;
+            this.removeQueue.Enqueue(statusId);
 
-            this._ids.Remove(Id);
-            this.unreadIds.Remove(Id);
+            if (setIsDeleted && this.IsInnerStorageTabType)
+            {
+                PostClass post;
+                if (this._innerPosts.TryGetValue(statusId, out post))
+                    post.IsDeleted = true;
+            }
+        }
+
+        public bool RemovePostImmediately(long statusId)
+        {
+            if (!this._ids.Remove(statusId))
+                return false;
+
+            this.unreadIds.Remove(statusId);
 
             if (this.IsInnerStorageTabType)
             {
                 PostClass removedPost;
-                this._innerPosts.TryRemove(Id, out removedPost);
+                this._innerPosts.TryRemove(statusId, out removedPost);
             }
+
+            return true;
+        }
+
+        public IReadOnlyList<long> RemoveSubmit()
+        {
+            var removedIds = new List<long>();
+
+            long statusId;
+            while (this.removeQueue.TryDequeue(out statusId))
+            {
+                if (this.RemovePostImmediately(statusId))
+                    removedIds.Add(statusId);
+            }
+
+            return removedIds;
         }
 
         public bool UnreadManage { get; set; }
index 5173f2d..34b76d6 100644 (file)
@@ -3035,7 +3035,12 @@ namespace OpenTween
             if (ct.IsCancellationRequested)
                 return;
 
-            this.RemovePostFromFavTab(successIds.ToArray());
+            var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites);
+            foreach (var statusId in successIds)
+            {
+                // ツイートが削除された訳ではないので IsDeleted はセットしない
+                favTab.EnqueueRemovePost(statusId, setIsDeleted: false);
+            }
 
             this.RefreshTimeline();
 
@@ -3368,68 +3373,6 @@ namespace OpenTween
             this.StatusLabel.Text = Properties.Resources.UpdateMuteUserIds_Finish;
         }
 
-        private void RemovePostFromFavTab(Int64[] ids)
-        {
-            var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites);
-            string favTabName = favTab.TabName;
-            int fidx = 0;
-            if (_curTab.Text.Equals(favTabName))
-            {
-                fidx = _curList.FocusedItem?.Index ?? _curList.TopItem?.Index ?? 0;
-            }
-
-            foreach (long i in ids)
-            {
-                try
-                {
-                    _statuses.RemoveFavPost(i);
-                }
-                catch (Exception)
-                {
-                    continue;
-                }
-            }
-            if (_curTab != null && _curTab.Text.Equals(favTabName))
-            {
-                this.PurgeListViewItemCache();
-                _curPost = null;
-                //_curItemIndex = -1;
-            }
-            foreach (TabPage tp in ListTab.TabPages)
-            {
-                if (tp.Text == favTabName)
-                {
-                    ((DetailsListView)tp.Tag).VirtualListSize = favTab.AllCount;
-                    break;
-                }
-            }
-            if (_curTab.Text.Equals(favTabName))
-            {
-                do
-                {
-                    _curList.SelectedIndices.Clear();
-                }
-                while (_curList.SelectedIndices.Count > 0);
-
-                if (favTab.AllCount > 0)
-                {
-                    if (favTab.AllCount - 1 > fidx && fidx > -1)
-                    {
-                        _curList.SelectedIndices.Add(fidx);
-                    }
-                    else
-                    {
-                        _curList.SelectedIndices.Add(favTab.AllCount - 1);
-                    }
-                    if (_curList.SelectedIndices.Count > 0)
-                    {
-                        _curList.EnsureVisible(_curList.SelectedIndices[0]);
-                        _curList.FocusedItem = _curList.Items[_curList.SelectedIndices[0]];
-                    }
-                }
-            }
-        }
-
         private void NotifyIcon1_MouseClick(object sender, MouseEventArgs e)
         {
             if (e.Button == MouseButtons.Left)
@@ -3917,7 +3860,7 @@ namespace OpenTween
                         continue;
                     }
 
-                    this._statuses.RemovePost(post.StatusId);
+                    this._statuses.RemovePostFromAllTabs(post.StatusId, setIsDeleted: true);
                 }
 
                 if (lastException == null)
@@ -12841,7 +12784,7 @@ namespace OpenTween
                 {
                     Invoke((Action) (async () =>
                            {
-                               _statuses.RemovePostReserve(e.StatusId);
+                               this._statuses.RemovePostFromAllTabs(e.StatusId, setIsDeleted: true);
                                if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(e.StatusId))
                                {
                                    this.PurgeListViewItemCache();
@@ -12991,7 +12934,8 @@ namespace OpenTween
                 }
                 if (ev.Event == "unfavorite" && ev.Username.ToLowerInvariant().Equals(tw.Username.ToLowerInvariant()))
                 {
-                    RemovePostFromFavTab(new long[] {ev.Id});
+                    var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites);
+                    favTab.EnqueueRemovePost(ev.Id, setIsDeleted: false);
                 }
             }
         }