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 };
}
[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);
//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>
: 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)
}
}
- 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);
}
}
newMentionOrDm = false;
isDeletePost = false;
- var totalPosts = 0;
+ var addedCountTotal = 0;
+ var removedIdsAll = new List<long>();
var notifyPostsList = new List<PostClass>();
var currentNotifyPriority = -1;
}
}
- 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;
}
}
// 移動されたらRecentから除去
if (moved)
- homeTab.Remove(post.StatusId);
+ homeTab.RemovePostImmediately(post.StatusId);
if (tab.TabType == MyCommon.TabUsageType.Mentions)
{
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;
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; }
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();
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)
continue;
}
- this._statuses.RemovePost(post.StatusId);
+ this._statuses.RemovePostFromAllTabs(post.StatusId, setIsDeleted: true);
}
if (lastException == null)
{
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();
}
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);
}
}
}