field.SetValue(null, this.tabinfo);
// 標準のタブを追加
- this.tabinfo.AddTab("Recent", MyCommon.TabUsageType.Home, null);
- this.tabinfo.AddTab("Reply", MyCommon.TabUsageType.Mentions, null);
- this.tabinfo.AddTab("DM", MyCommon.TabUsageType.DirectMessage, null);
- this.tabinfo.AddTab("Favorites", MyCommon.TabUsageType.Favorites, null);
+ this.tabinfo.AddTab(new HomeTabModel("Recent"));
+ this.tabinfo.AddTab(new MentionsTabModel("Reply"));
+ this.tabinfo.AddTab(new DirectMessagesTabModel("DM"));
+ this.tabinfo.AddTab(new FavoritesTabModel("Favorites"));
}
[Fact]
public void AddTab_Test()
{
- var list = new ListElement { };
- var ret = this.tabinfo.AddTab("MyTab", MyCommon.TabUsageType.Lists, list);
+ var tab = new FilterTabModel("MyTab");
+ var ret = this.tabinfo.AddTab(tab);
Assert.True(ret);
-
- var lastTab = this.tabinfo.Tabs.Values.Last();
- Assert.Equal("MyTab", lastTab.TabName);
- Assert.Equal(MyCommon.TabUsageType.Lists, lastTab.TabType);
- Assert.Same(list, lastTab.ListInfo);
+ Assert.Same(tab, this.tabinfo.Tabs.Values.Last());
}
[Fact]
public void AddTab_DuplicateTest()
{
- var ret = this.tabinfo.AddTab("Recent", MyCommon.TabUsageType.UserDefined, null);
+ var ret = this.tabinfo.AddTab(new FilterTabModel("Recent"));
Assert.False(ret);
}
[Fact]
public void MakeTabName_RetryTest()
{
- this.tabinfo.AddTab("NewTab", MyCommon.TabUsageType.UserDefined, null);
- this.tabinfo.AddTab("NewTab2", MyCommon.TabUsageType.UserDefined, null);
+ this.tabinfo.AddTab(new FilterTabModel("NewTab"));
+ this.tabinfo.AddTab(new FilterTabModel("NewTab2"));
var baseTabName = "NewTab";
Assert.Equal("NewTab3", this.tabinfo.MakeTabName(baseTabName, 5));
[Fact]
public void MakeTabName_RetryErrorTest()
{
- this.tabinfo.AddTab("NewTab", MyCommon.TabUsageType.UserDefined, null);
- this.tabinfo.AddTab("NewTab2", MyCommon.TabUsageType.UserDefined, null);
- this.tabinfo.AddTab("NewTab3", MyCommon.TabUsageType.UserDefined, null);
- this.tabinfo.AddTab("NewTab4", MyCommon.TabUsageType.UserDefined, null);
- this.tabinfo.AddTab("NewTab5", MyCommon.TabUsageType.UserDefined, null);
+ this.tabinfo.AddTab(new FilterTabModel("NewTab"));
+ this.tabinfo.AddTab(new FilterTabModel("NewTab2"));
+ this.tabinfo.AddTab(new FilterTabModel("NewTab3"));
+ this.tabinfo.AddTab(new FilterTabModel("NewTab4"));
+ this.tabinfo.AddTab(new FilterTabModel("NewTab5"));
var baseTabName = "NewTab";
Assert.Throws<TabException>(() => this.tabinfo.MakeTabName(baseTabName, 5));
{
this.tabinfo.MuteUserIds = new HashSet<long> { };
- var muteTab = new TabClass("Mute", MyCommon.TabUsageType.Mute);
+ var muteTab = new MuteTabModel();
muteTab.AddFilter(new PostFilterRule
{
FilterName = "foo",
{
this.tabinfo.MuteUserIds = new HashSet<long> { };
- var muteTab = new TabClass("Mute", MyCommon.TabUsageType.Mute);
+ var muteTab = new MuteTabModel();
muteTab.AddFilter(new PostFilterRule
{
FilterName = "foo",
[Fact]
public void SetReadAllTab_MarkAsReadTest()
{
- var tab1 = new TabClass("search1", MyCommon.TabUsageType.PublicSearch);
- var tab2 = new TabClass("search2", MyCommon.TabUsageType.PublicSearch);
+ var tab1 = new PublicSearchTabModel("search1");
+ var tab2 = new PublicSearchTabModel("search2");
this.tabinfo.AddTab(tab1);
this.tabinfo.AddTab(tab2);
// search1 に追加するツイート (StatusId: 100, 150, 200; すべて未読)
tab1.UnreadManage = true;
- tab1.AddPostToInnerStorage(new PostClass { StatusId = 100L, IsRead = false });
- tab1.AddPostToInnerStorage(new PostClass { StatusId = 150L, IsRead = false });
- tab1.AddPostToInnerStorage(new PostClass { StatusId = 200L, IsRead = false });
+ tab1.AddPostQueue(new PostClass { StatusId = 100L, IsRead = false });
+ tab1.AddPostQueue(new PostClass { StatusId = 150L, IsRead = false });
+ tab1.AddPostQueue(new PostClass { StatusId = 200L, IsRead = false });
// search2 に追加するツイート (StatusId: 150, 200, 250; すべて未読)
tab2.UnreadManage = true;
- tab2.AddPostToInnerStorage(new PostClass { StatusId = 150L, IsRead = false });
- tab2.AddPostToInnerStorage(new PostClass { StatusId = 200L, IsRead = false });
- tab2.AddPostToInnerStorage(new PostClass { StatusId = 250L, IsRead = false });
+ tab2.AddPostQueue(new PostClass { StatusId = 150L, IsRead = false });
+ tab2.AddPostQueue(new PostClass { StatusId = 200L, IsRead = false });
+ tab2.AddPostQueue(new PostClass { StatusId = 250L, IsRead = false });
this.tabinfo.DistributePosts();
this.tabinfo.SubmitUpdate();
[Fact]
public void SetReadAllTab_MarkAsUnreadTest()
{
- var tab1 = new TabClass("search1", MyCommon.TabUsageType.PublicSearch);
- var tab2 = new TabClass("search2", MyCommon.TabUsageType.PublicSearch);
+ var tab1 = new PublicSearchTabModel("search1");
+ var tab2 = new PublicSearchTabModel("search2");
this.tabinfo.AddTab(tab1);
this.tabinfo.AddTab(tab2);
// search1 に追加するツイート (StatusId: 100, 150, 200; すべて既読)
tab1.UnreadManage = true;
- tab1.AddPostToInnerStorage(new PostClass { StatusId = 100L, IsRead = true });
- tab1.AddPostToInnerStorage(new PostClass { StatusId = 150L, IsRead = true });
- tab1.AddPostToInnerStorage(new PostClass { StatusId = 200L, IsRead = true });
+ tab1.AddPostQueue(new PostClass { StatusId = 100L, IsRead = true });
+ tab1.AddPostQueue(new PostClass { StatusId = 150L, IsRead = true });
+ tab1.AddPostQueue(new PostClass { StatusId = 200L, IsRead = true });
// search2 に追加するツイート (StatusId: 150, 200, 250; すべて既読)
tab2.UnreadManage = true;
- tab2.AddPostToInnerStorage(new PostClass { StatusId = 150L, IsRead = true });
- tab2.AddPostToInnerStorage(new PostClass { StatusId = 200L, IsRead = true });
- tab2.AddPostToInnerStorage(new PostClass { StatusId = 250L, IsRead = true });
+ tab2.AddPostQueue(new PostClass { StatusId = 150L, IsRead = true });
+ tab2.AddPostQueue(new PostClass { StatusId = 200L, IsRead = true });
+ tab2.AddPostQueue(new PostClass { StatusId = 250L, IsRead = true });
this.tabinfo.DistributePosts();
this.tabinfo.SubmitUpdate();
this.tabinfo.AddPost(new PostClass { StatusId = 200L, IsRead = false });
// StatusId: 150 だけ FilterTab の振り分けルールにヒットする (PostClass.FilterHit が true になる)
- this.tabinfo.AddTab("FilterTab", MyCommon.TabUsageType.UserDefined, null);
- var filterTab = this.tabinfo.Tabs["FilterTab"];
+ var filterTab = new FilterTabModel("FilterTab");
filterTab.AddFilter(TestPostFilterRule.Create(x =>
x.StatusId == 150L ? MyCommon.HITRESULT.Copy : MyCommon.HITRESULT.None));
+ this.tabinfo.AddTab(filterTab);
this.tabinfo.DistributePosts();
this.tabinfo.SubmitUpdate();
this.tabinfo.AddPost(new PostClass { StatusId = 200L, IsReply = true, IsRead = false });
// DM
- dmTab.AddPostToInnerStorage(new PostClass { StatusId = 300L, IsDm = true, IsRead = false });
+ dmTab.AddPostQueue(new PostClass { StatusId = 300L, IsDm = true, IsRead = false });
this.tabinfo.DistributePosts();
{
var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
- var myTab1 = new TabClass("MyTab1", MyCommon.TabUsageType.UserDefined);
+ var myTab1 = new FilterTabModel("MyTab1");
this.tabinfo.AddTab(myTab1);
var filter = new PostFilterRule
this.tabinfo.SubmitUpdate();
// この時点での振り分け状態
- Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.BackupIds, AnyOrderComparer<long>.Instance);
- Assert.Equal(new[] { 100L }, myTab1.BackupIds);
+ Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 100L }, myTab1.StatusIds);
// フィルタを変更する
filter.FilterName = "bbb";
// [statusId: 200] は Recent から MyTab1 にコピーされる
// 変更後の振り分け状態
- Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.BackupIds, AnyOrderComparer<long>.Instance);
- Assert.Equal(new[] { 200L }, myTab1.BackupIds);
+ Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 200L }, myTab1.StatusIds);
}
[Fact]
{
var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
- var myTab1 = new TabClass("MyTab1", MyCommon.TabUsageType.UserDefined);
+ var myTab1 = new FilterTabModel("MyTab1");
this.tabinfo.AddTab(myTab1);
var filter = new PostFilterRule
this.tabinfo.SubmitUpdate();
// この時点での振り分け状態
- Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.BackupIds, AnyOrderComparer<long>.Instance);
- Assert.Equal(new[] { 100L }, myTab1.BackupIds);
+ Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 100L }, myTab1.StatusIds);
// フィルタを変更する
filter.FilterName = "bbb";
// [statusId: 200] は Recent から MyTab1 にコピーされ、マークが付与される
// 変更後の振り分け状態
- Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.BackupIds, AnyOrderComparer<long>.Instance);
- Assert.Equal(new[] { 200L }, myTab1.BackupIds);
+ Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 200L }, myTab1.StatusIds);
// [statusId: 200] は IsMark が true の状態になる
Assert.True(this.tabinfo[200L].IsMark);
{
var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
- var myTab1 = new TabClass("MyTab1", MyCommon.TabUsageType.UserDefined);
+ var myTab1 = new FilterTabModel("MyTab1");
this.tabinfo.AddTab(myTab1);
var filter = new PostFilterRule
this.tabinfo.SubmitUpdate();
// この時点での振り分け状態
- Assert.Equal(new[] { 200L, 300L }, homeTab.BackupIds, AnyOrderComparer<long>.Instance);
- Assert.Equal(new[] { 100L }, myTab1.BackupIds);
+ Assert.Equal(new[] { 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 100L }, myTab1.StatusIds);
// フィルタを変更する
filter.FilterName = "bbb";
// [statusId: 200] は Recent から MyTab1 に移動される
// 変更後の振り分け状態
- Assert.Equal(new[] { 100L, 300L }, homeTab.BackupIds, AnyOrderComparer<long>.Instance);
- Assert.Equal(new[] { 200L }, myTab1.BackupIds);
+ Assert.Equal(new[] { 100L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 200L }, myTab1.StatusIds);
}
[Fact]
{
var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
- var myTab1 = new TabClass("MyTab1", MyCommon.TabUsageType.UserDefined);
- var myTab2 = new TabClass("MyTab2", MyCommon.TabUsageType.UserDefined);
+ var myTab1 = new FilterTabModel("MyTab1");
+ var myTab2 = new FilterTabModel("MyTab2");
this.tabinfo.AddTab(myTab1);
this.tabinfo.AddTab(myTab2);
this.tabinfo.SubmitUpdate();
// この時点での振り分け状態
- Assert.Equal(new[] { 300L }, homeTab.BackupIds);
- Assert.Equal(new[] { 100L }, myTab1.BackupIds);
- Assert.Equal(new[] { 200L }, myTab2.BackupIds);
+ Assert.Equal(new[] { 300L }, homeTab.StatusIds);
+ Assert.Equal(new[] { 100L }, myTab1.StatusIds);
+ Assert.Equal(new[] { 200L }, myTab2.StatusIds);
// MyTab1 のフィルタを変更する
filter1.FilterName = "bbb";
// [statusId: 300] は Recent から MyTab2 に移動される
// 変更後の振り分け状態
- Assert.Equal(new[] { 100L }, homeTab.BackupIds);
- Assert.Equal(new[] { 200L }, myTab1.BackupIds);
- Assert.Equal(new[] { 300L }, myTab2.BackupIds);
+ Assert.Equal(new[] { 100L }, homeTab.StatusIds);
+ Assert.Equal(new[] { 200L }, myTab1.StatusIds);
+ Assert.Equal(new[] { 300L }, myTab2.StatusIds);
}
[Fact]
public void FilterAll_ExcludeReplyFilterTest()
{
- var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
- var replyTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Mentions);
+ var homeTab = this.tabinfo.GetTabByType<HomeTabModel>();
+ var replyTab = this.tabinfo.GetTabByType<MentionsTabModel>();
var filter = new PostFilterRule
{
this.tabinfo.SubmitUpdate();
// この時点での振り分け状態
- Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.BackupIds, AnyOrderComparer<long>.Instance);
- Assert.Equal(new[] { 200L, 300L }, replyTab.BackupIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 200L, 300L }, replyTab.StatusIds, AnyOrderComparer<long>.Instance);
// [statusId: 100] は IsExcludeReply が true の状態になっている
Assert.True(this.tabinfo[100L].IsExcludeReply);
// [statusId: 200] は Reply から取り除かれ、IsExcludeReply が true になる
// 変更後の振り分け状態
- Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.BackupIds, AnyOrderComparer<long>.Instance);
- Assert.Equal(new[] { 100L, 300L }, replyTab.BackupIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
+ Assert.Equal(new[] { 100L, 300L }, replyTab.StatusIds, AnyOrderComparer<long>.Instance);
// [statusId: 100] は IsExcludeReply が false の状態になる
Assert.False(this.tabinfo[100L].IsExcludeReply);
namespace OpenTween.Models
{
- public class TabClassTest
+ public class TabModelTest
{
[Fact]
public void EnqueueRemovePost_Test()
{
- var tab = new TabClass
+ var tab = new PublicSearchTabModel("search")
{
- 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.AddPostQueue(new PostClass { StatusId = 100L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 110L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 120L, IsRead = false });
tab.AddSubmit();
Assert.Equal(2, tab.AllCount);
Assert.Equal(2, tab.UnreadCount);
- Assert.Equal(new[] { 110L, 120L }, tab.BackupIds);
+ Assert.Equal(new[] { 110L, 120L }, tab.StatusIds);
Assert.Equal(new[] { 100L }, removedIds.AsEnumerable());
}
[Fact]
public void EnqueueRemovePost_SetIsDeletedTest()
{
- var tab = new TabClass
+ var tab = new PublicSearchTabModel("search")
{
- TabType = MyCommon.TabUsageType.PublicSearch,
UnreadManage = true,
};
var post = new PostClass { StatusId = 100L, IsRead = false };
- tab.AddPostToInnerStorage(post);
+ tab.AddPostQueue(post);
tab.AddSubmit();
Assert.Equal(1, tab.AllCount);
[Fact]
public void EnqueueRemovePost_UnknownIdTest()
{
- var tab = new TabClass
+ var tab = new PublicSearchTabModel("search")
{
- TabType = MyCommon.TabUsageType.PublicSearch,
UnreadManage = true,
};
- tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 100L, IsRead = false });
tab.AddSubmit();
Assert.Equal(1, tab.AllCount);
[Fact]
public void NextUnreadId_Test()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.UnreadManage = true;
// 未読なし
Assert.Equal(-1L, tab.NextUnreadId);
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 100L,
IsRead = false, // 未読
Assert.Equal(100L, tab.NextUnreadId);
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 50L,
IsRead = true, // 既読
[Fact]
public void NextUnreadId_DisabledTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
// 未読表示無効
tab.UnreadManage = false;
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 100L,
IsRead = false, // 未読
[Fact]
public void NextUnreadId_SortByIdAscTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.UnreadManage = true;
tab.SetSortMode(ComparerMode.Id, SortOrder.Ascending);
// 画面には上から 100 → 200 → 300 の順に並ぶ
- tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, IsRead = false });
- tab.AddPostToInnerStorage(new PostClass { StatusId = 200L, IsRead = false });
- tab.AddPostToInnerStorage(new PostClass { StatusId = 300L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 100L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 200L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 300L, IsRead = false });
tab.AddSubmit();
// 昇順/降順に関わらず、ID の小さい順に未読の ID を返す
[Fact]
public void NextUnreadId_SortByIdDescTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.UnreadManage = true;
tab.SetSortMode(ComparerMode.Id, SortOrder.Descending);
// 画面には上から 300 → 200 → 100 の順に並ぶ
- tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, IsRead = false });
- tab.AddPostToInnerStorage(new PostClass { StatusId = 200L, IsRead = false });
- tab.AddPostToInnerStorage(new PostClass { StatusId = 300L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 100L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 200L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 300L, IsRead = false });
tab.AddSubmit();
// 昇順/降順に関わらず、ID の小さい順に未読の ID を返す
[Fact]
public void NextUnreadId_SortByScreenNameAscTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.UnreadManage = true;
tab.SetSortMode(ComparerMode.Name, SortOrder.Ascending);
// 画面には上から 200 → 100 → 300 の順に並ぶ
- tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, ScreenName = "bbb", IsRead = false });
- tab.AddPostToInnerStorage(new PostClass { StatusId = 200L, ScreenName = "aaa", IsRead = false });
- tab.AddPostToInnerStorage(new PostClass { StatusId = 300L, ScreenName = "ccc", IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 100L, ScreenName = "bbb", IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 200L, ScreenName = "aaa", IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 300L, ScreenName = "ccc", IsRead = false });
tab.AddSubmit();
// 昇順/降順に関わらず、ScreenName の辞書順で小さい順に未読の ID を返す
[Fact]
public void NextUnreadId_SortByScreenNameDescTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.UnreadManage = true;
tab.SetSortMode(ComparerMode.Name, SortOrder.Descending);
// 画面には上から 300 → 100 → 200 の順に並ぶ
- tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, ScreenName = "bbb", IsRead = false });
- tab.AddPostToInnerStorage(new PostClass { StatusId = 200L, ScreenName = "aaa", IsRead = false });
- tab.AddPostToInnerStorage(new PostClass { StatusId = 300L, ScreenName = "ccc", IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 100L, ScreenName = "bbb", IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 200L, ScreenName = "aaa", IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 300L, ScreenName = "ccc", IsRead = false });
tab.AddSubmit();
// 昇順/降順に関わらず、ScreenName の辞書順で小さい順に未読の ID を返す
[Fact]
public void UnreadCount_Test()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.UnreadManage = true;
// 未読なし
Assert.Equal(0, tab.UnreadCount);
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 100L,
IsRead = false, // 未読
Assert.Equal(1, tab.UnreadCount);
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 50L,
IsRead = true, // 既読
[Fact]
public void UnreadCount_DisabledTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
// 未読表示無効
tab.UnreadManage = false;
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 100L,
IsRead = false, // 未読
[Fact]
public void NextUnreadIndex_Test()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.SetSortMode(ComparerMode.Id, SortOrder.Ascending);
tab.UnreadManage = true;
// 未読なし
Assert.Equal(-1, tab.NextUnreadIndex);
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 50L,
IsRead = true, // 既読
});
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 100L,
IsRead = false, // 未読
});
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 150L,
IsRead = false, // 未読
[Fact]
public void NextUnreadIndex_DisabledTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.SetSortMode(ComparerMode.Id, SortOrder.Ascending);
// 未読表示無効
tab.UnreadManage = false;
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 100L,
IsRead = false, // 未読
[Fact]
public void GetUnreadIds_Test()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.UnreadManage = true;
Assert.Empty(tab.GetUnreadIds());
- tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, IsRead = false });
- tab.AddPostToInnerStorage(new PostClass { StatusId = 200L, IsRead = true });
+ tab.AddPostQueue(new PostClass { StatusId = 100L, IsRead = false });
+ tab.AddPostQueue(new PostClass { StatusId = 200L, IsRead = true });
tab.AddSubmit();
Assert.Equal(new[] { 100L }, tab.GetUnreadIds());
[Fact]
public void SetReadState_MarkAsReadTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.UnreadManage = true;
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 100L,
IsRead = false, // 未読
[Fact]
public void SetReadState_MarkAsUnreadTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.UserTimeline };
+ var tab = new PublicSearchTabModel("search");
tab.UnreadManage = true;
- tab.AddPostToInnerStorage(new PostClass
+ tab.AddPostQueue(new PostClass
{
StatusId = 100L,
IsRead = true, // 既読
[Fact]
public void FilterArraySetter_Test()
{
- var tab = new TabClass();
+ var tab = new FilterTabModel("MyTab");
var filter = new PostFilterRule();
tab.FilterArray = new[] { filter };
[Fact]
public void AddFilter_Test()
{
- var tab = new TabClass();
+ var tab = new FilterTabModel("MyTab");
var filter = new PostFilterRule();
tab.AddFilter(filter);
[Fact]
public void RemoveFilter_Test()
{
- var tab = new TabClass();
+ var tab = new FilterTabModel("MyTab");
var filter = new PostFilterRule();
tab.FilterArray = new[] { filter };
[Fact]
public void OnFilterModified_Test()
{
- var tab = new TabClass();
+ var tab = new FilterTabModel("MyTab");
var filter = new PostFilterRule();
tab.FilterArray = new[] { filter };
[Fact]
public void OnFilterModified_DetachedTest()
{
- var tab = new TabClass();
+ var tab = new FilterTabModel("MyTab");
var filter = new PostFilterRule();
tab.FilterArray = new[] { filter };
[Fact]
public void SearchPostsAll_Test()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.PublicSearch };
+ var tab = new PublicSearchTabModel("search");
- tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, TextFromApi = "abcd", ScreenName = "", Nickname = "" }); // 0
- tab.AddPostToInnerStorage(new PostClass { StatusId = 110L, TextFromApi = "efgh", ScreenName = "", Nickname = "" }); // 1
- tab.AddPostToInnerStorage(new PostClass { StatusId = 120L, TextFromApi = "ijkl", ScreenName = "", Nickname = "" }); // 2
- tab.AddPostToInnerStorage(new PostClass { StatusId = 130L, TextFromApi = "abc", ScreenName = "", Nickname = "" }); // 3
- tab.AddPostToInnerStorage(new PostClass { StatusId = 140L, TextFromApi = "def", ScreenName = "", Nickname = "" }); // 4
+ tab.AddPostQueue(new PostClass { StatusId = 100L, TextFromApi = "abcd", ScreenName = "", Nickname = "" }); // 0
+ tab.AddPostQueue(new PostClass { StatusId = 110L, TextFromApi = "efgh", ScreenName = "", Nickname = "" }); // 1
+ tab.AddPostQueue(new PostClass { StatusId = 120L, TextFromApi = "ijkl", ScreenName = "", Nickname = "" }); // 2
+ tab.AddPostQueue(new PostClass { StatusId = 130L, TextFromApi = "abc", ScreenName = "", Nickname = "" }); // 3
+ tab.AddPostQueue(new PostClass { StatusId = 140L, TextFromApi = "def", ScreenName = "", Nickname = "" }); // 4
tab.SetSortMode(ComparerMode.Id, SortOrder.Ascending);
tab.AddSubmit();
[Fact]
public void SearchPostsAll_ReverseOrderTest()
{
- var tab = new TabClass { TabType = MyCommon.TabUsageType.PublicSearch };
+ var tab = new PublicSearchTabModel("search");
- tab.AddPostToInnerStorage(new PostClass { StatusId = 100L, TextFromApi = "abcd", ScreenName = "", Nickname = "" }); // 0
- tab.AddPostToInnerStorage(new PostClass { StatusId = 110L, TextFromApi = "efgh", ScreenName = "", Nickname = "" }); // 1
- tab.AddPostToInnerStorage(new PostClass { StatusId = 120L, TextFromApi = "ijkl", ScreenName = "", Nickname = "" }); // 2
- tab.AddPostToInnerStorage(new PostClass { StatusId = 130L, TextFromApi = "abc", ScreenName = "", Nickname = "" }); // 3
- tab.AddPostToInnerStorage(new PostClass { StatusId = 140L, TextFromApi = "def", ScreenName = "", Nickname = "" }); // 4
+ tab.AddPostQueue(new PostClass { StatusId = 100L, TextFromApi = "abcd", ScreenName = "", Nickname = "" }); // 0
+ tab.AddPostQueue(new PostClass { StatusId = 110L, TextFromApi = "efgh", ScreenName = "", Nickname = "" }); // 1
+ tab.AddPostQueue(new PostClass { StatusId = 120L, TextFromApi = "ijkl", ScreenName = "", Nickname = "" }); // 2
+ tab.AddPostQueue(new PostClass { StatusId = 130L, TextFromApi = "abc", ScreenName = "", Nickname = "" }); // 3
+ tab.AddPostQueue(new PostClass { StatusId = 140L, TextFromApi = "def", ScreenName = "", Nickname = "" }); // 4
tab.SetSortMode(ComparerMode.Id, SortOrder.Ascending);
tab.AddSubmit();
<Compile Include="RegexAsyncTest.cs" />
<Compile Include="ShortcutCommandTest.cs" />
<Compile Include="ShortUrlTest.cs" />
- <Compile Include="Models\TabClassTest.cs" />
+ <Compile Include="Models\TabModelTest.cs" />
<Compile Include="Models\TabInformationTest.cs" />
<Compile Include="TabsDialogTest.cs" />
<Compile Include="TestUtils.cs" />
this.tabinfo = Activator.CreateInstance(typeof(TabInformations), true) as TabInformations;
// タブを追加
- this.tabinfo.AddTab("Recent", MyCommon.TabUsageType.Home, null);
- this.tabinfo.AddTab("Reply", MyCommon.TabUsageType.Mentions, null);
- this.tabinfo.AddTab("DM", MyCommon.TabUsageType.DirectMessage, null);
- this.tabinfo.AddTab("Favorites", MyCommon.TabUsageType.Favorites, null);
- this.tabinfo.AddTab("MyTab1", MyCommon.TabUsageType.UserDefined, null);
+ this.tabinfo.AddTab(new HomeTabModel("Recent"));
+ this.tabinfo.AddTab(new MentionsTabModel("Reply"));
+ this.tabinfo.AddTab(new DirectMessagesTabModel("DM"));
+ this.tabinfo.AddTab(new FavoritesTabModel("Favorites"));
+ this.tabinfo.AddTab(new FilterTabModel("MyTab1"));
// 一応 TabInformation.GetInstance() でも取得できるようにする
var field = typeof(TabInformations).GetField("_instance",
{
if (ListTabs.Items.Count == 0) return;
- var tab = _sts.Tabs[tabName];
-
ListFilters.Items.Clear();
+
+ var tab = _sts.Tabs[tabName] as FilterTabModel;
+ if (tab == null)
+ return;
+
ListFilters.Items.AddRange(tab.GetFilters());
if (ListFilters.Items.Count > 0)
if (rslt == DialogResult.Cancel) return;
var indices = ListFilters.SelectedIndices.Cast<int>().Reverse().ToArray(); // 後ろの要素から削除
- var tab = _sts.Tabs[ListTabs.SelectedItem.ToString()];
+ var tab = (FilterTabModel)_sts.Tabs[ListTabs.SelectedItem.ToString()];
using (ControlTransaction.Update(ListFilters))
{
return;
}
- var tab = this._sts.Tabs[(string)this.ListTabs.SelectedItem];
+ var tab = (FilterTabModel)this._sts.Tabs[(string)this.ListTabs.SelectedItem];
int i = ListFilters.SelectedIndex;
PostFilterRule ft;
list = listAvail.SelectedList;
}
}
- if (!_sts.AddTab(tabName, tabType, list) || !((TweenMain)this.Owner).AddNewTab(tabName, false, tabType, list))
+
+ TabModel tab;
+ switch (tabType)
+ {
+ case MyCommon.TabUsageType.UserDefined:
+ tab = new FilterTabModel(tabName);
+ break;
+ case MyCommon.TabUsageType.PublicSearch:
+ tab = new PublicSearchTabModel(tabName);
+ break;
+ case MyCommon.TabUsageType.Lists:
+ tab = new ListTimelineTabModel(tabName, list);
+ break;
+ default:
+ return;
+ }
+
+ if (!_sts.AddTab(tab) || !((TweenMain)this.Owner).AddNewTab(tab, startup: false))
{
string tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
MessageBox.Show(tmp, Properties.Resources.AddTabMenuItem_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
var lastSelIdx = indices[0] + diff;
- var tab = _sts.Tabs[ListTabs.Items[tabIdx].ToString()];
+ var tab = (FilterTabModel)_sts.Tabs[ListTabs.Items[tabIdx].ToString()];
try
{
{
if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
{
- TabClass[] selectedTabs;
+ TabModel[] selectedTabs;
using (TabsDialog dialog = new TabsDialog(_sts))
{
dialog.MultiSelect = true;
foreach (int idx in ListFilters.SelectedIndices)
{
- filters.Add(_sts.Tabs[tabname].FilterArray[idx].Clone());
+ var tab = (FilterTabModel)_sts.Tabs[tabname];
+ filters.Add(tab.FilterArray[idx].Clone());
}
- foreach (var tb in selectedTabs)
+ foreach (var tb in selectedTabs.Cast<FilterTabModel>())
{
if (tb.TabName == tabname) continue;
{
if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
{
- TabClass[] selectedTabs;
+ TabModel[] selectedTabs;
using (var dialog = new TabsDialog(_sts))
{
dialog.MultiSelect = true;
foreach (int idx in ListFilters.SelectedIndices)
{
- filters.Add(_sts.Tabs[tabname].FilterArray[idx].Clone());
+ var tab = (FilterTabModel)_sts.Tabs[tabname];
+ filters.Add(tab.FilterArray[idx].Clone());
}
if (selectedTabs.Length == 1 && selectedTabs[0].TabName == tabname) return;
- foreach (var tb in selectedTabs)
+ foreach (var tb in selectedTabs.Cast<FilterTabModel>())
{
if (tb.TabName == tabname) continue;
{
if (ListFilters.GetSelected(idx))
{
- _sts.Tabs[ListTabs.SelectedItem.ToString()].RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
+ var tab = (FilterTabModel)_sts.Tabs[ListTabs.SelectedItem.ToString()];
+ tab.RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
ListFilters.Items.RemoveAt(idx);
}
}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class DirectMessagesTabModel : InternalStorageTabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.DirectMessage;
+
+ public DirectMessagesTabModel() : this(MyCommon.DEFAULTTAB.DM)
+ {
+ }
+
+ public DirectMessagesTabModel(string tabName) : base(tabName)
+ {
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class FavoritesTabModel : TabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.Favorites;
+
+ public FavoritesTabModel() : this(MyCommon.DEFAULTTAB.FAV)
+ {
+ }
+
+ public FavoritesTabModel(string tabName) : base(tabName)
+ {
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class FilterTabModel : TabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.UserDefined;
+
+ public bool FilterModified { get; set; }
+
+ private List<PostFilterRule> _filters = new List<PostFilterRule>();
+ private object lockObjFilters = new object();
+
+ public FilterTabModel(string tabName) : base(tabName)
+ {
+ }
+
+ //フィルタに合致したら追加
+ public MyCommon.HITRESULT AddFiltered(PostClass post, bool immediately = false)
+ {
+ if (this.IsInnerStorageTabType)
+ return MyCommon.HITRESULT.None;
+
+ var rslt = MyCommon.HITRESULT.None;
+
+ //全フィルタ評価(優先順位あり)
+ lock (this.lockObjFilters)
+ {
+ foreach (var ft in _filters)
+ {
+ try
+ {
+ switch (ft.ExecFilter(post)) //フィルタクラスでヒット判定
+ {
+ case MyCommon.HITRESULT.None:
+ break;
+ case MyCommon.HITRESULT.Copy:
+ if (rslt != MyCommon.HITRESULT.CopyAndMark) rslt = MyCommon.HITRESULT.Copy;
+ break;
+ case MyCommon.HITRESULT.CopyAndMark:
+ rslt = MyCommon.HITRESULT.CopyAndMark;
+ break;
+ case MyCommon.HITRESULT.Move:
+ rslt = MyCommon.HITRESULT.Move;
+ break;
+ case MyCommon.HITRESULT.Exclude:
+ rslt = MyCommon.HITRESULT.Exclude;
+ goto exit_for;
+ }
+ }
+ catch (NullReferenceException)
+ {
+ // ExecFilterでNullRef出る場合あり。暫定対応
+ MyCommon.TraceOut("ExecFilterでNullRef: " + ft.ToString());
+ rslt = MyCommon.HITRESULT.None;
+ }
+ }
+ exit_for:
+ ;
+ }
+
+ if (this.TabType != MyCommon.TabUsageType.Mute &&
+ rslt != MyCommon.HITRESULT.None && rslt != MyCommon.HITRESULT.Exclude)
+ {
+ if (immediately)
+ this.AddPostImmediately(post.StatusId, post.IsRead);
+ else
+ this.AddPostQueue(post);
+ }
+
+ return rslt; //マーク付けは呼び出し元で行うこと
+ }
+
+
+ public PostFilterRule[] GetFilters()
+ {
+ lock (this.lockObjFilters)
+ {
+ return _filters.ToArray();
+ }
+ }
+
+ public void RemoveFilter(PostFilterRule filter)
+ {
+ lock (this.lockObjFilters)
+ {
+ _filters.Remove(filter);
+ filter.PropertyChanged -= this.OnFilterModified;
+ this.FilterModified = true;
+ }
+ }
+
+ public bool AddFilter(PostFilterRule filter)
+ {
+ lock (this.lockObjFilters)
+ {
+ if (_filters.Contains(filter)) return false;
+ filter.PropertyChanged += this.OnFilterModified;
+ _filters.Add(filter);
+ this.FilterModified = true;
+ return true;
+ }
+ }
+
+ private void OnFilterModified(object sender, PropertyChangedEventArgs e)
+ {
+ this.FilterModified = true;
+ }
+
+ public PostFilterRule[] FilterArray
+ {
+ get
+ {
+ lock (this.lockObjFilters)
+ {
+ return _filters.ToArray();
+ }
+ }
+ set
+ {
+ lock (this.lockObjFilters)
+ {
+ foreach (var oldFilter in this._filters)
+ {
+ oldFilter.PropertyChanged -= this.OnFilterModified;
+ }
+
+ this._filters.Clear();
+ this.FilterModified = true;
+
+ foreach (var newFilter in value)
+ {
+ _filters.Add(newFilter);
+ newFilter.PropertyChanged += this.OnFilterModified;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class HomeTabModel : TabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.Home;
+
+ public HomeTabModel() : this(MyCommon.DEFAULTTAB.RECENT)
+ {
+ }
+
+ public HomeTabModel(string tabName) : base(tabName)
+ {
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public abstract class InternalStorageTabModel : TabModel
+ {
+ protected readonly ConcurrentDictionary<long, PostClass> internalPosts = new ConcurrentDictionary<long, PostClass>();
+
+ public override ConcurrentDictionary<long, PostClass> Posts
+ => this.internalPosts;
+
+ public InternalStorageTabModel(string tabName) : base(tabName)
+ {
+ }
+
+ public override void AddPostQueue(PostClass post)
+ {
+ if (TabInformations.GetInstance().IsMuted(post, isHomeTimeline: false))
+ return;
+
+ base.AddPostQueue(post);
+
+ if (!this.internalPosts.TryAdd(post.StatusId, post))
+ return;
+ }
+
+ public override void EnqueueRemovePost(long statusId, bool setIsDeleted)
+ {
+ base.EnqueueRemovePost(statusId, setIsDeleted);
+
+ if (setIsDeleted)
+ {
+ PostClass post;
+ if (this.internalPosts.TryGetValue(statusId, out post))
+ post.IsDeleted = true;
+ }
+ }
+
+ public override bool RemovePostImmediately(long statusId)
+ {
+ if (!base.RemovePostImmediately(statusId))
+ return false;
+
+ PostClass removedPost;
+ this.internalPosts.TryRemove(statusId, out removedPost);
+
+ return true;
+ }
+
+ public override void ClearIDs()
+ {
+ base.ClearIDs();
+ this.internalPosts.Clear();
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class ListTimelineTabModel : InternalStorageTabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.Lists;
+
+ public ListElement ListInfo { get; set; }
+
+ public ListTimelineTabModel(string tabName, ListElement list)
+ : base(tabName)
+ {
+ this.ListInfo = list;
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2016 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class LocalSearchTabModel : InternalStorageTabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.SearchResults;
+
+ public LocalSearchTabModel(string tabName) : base(tabName)
+ {
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class MentionsTabModel : FilterTabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.Mentions;
+
+ public MentionsTabModel() : this(MyCommon.DEFAULTTAB.REPLY)
+ {
+ }
+
+ public MentionsTabModel(string tabName) : base(tabName)
+ {
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2016 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class MuteTabModel : FilterTabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.Mute;
+
+ public MuteTabModel() : this(MyCommon.DEFAULTTAB.MUTE)
+ {
+ }
+
+ public MuteTabModel(string tabName) : base(tabName)
+ {
+ }
+
+ public override void AddPostQueue(PostClass post)
+ {
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class PublicSearchTabModel : InternalStorageTabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.PublicSearch;
+
+ public string SearchWords
+ {
+ get { return this._searchWords; }
+ set
+ {
+ this._searchWords = value;
+ this.ResetFetchIds();
+ }
+ }
+
+ public string SearchLang
+ {
+ get { return this._searchLang; }
+ set
+ {
+ this._searchLang = value;
+ this.ResetFetchIds();
+ }
+ }
+
+ private string _searchWords = "";
+ private string _searchLang = "";
+
+ public PublicSearchTabModel(string tabName) : base(tabName)
+ {
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class RelatedPostsTabModel : TabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.Related;
+
+ public PostClass TargetPost { get; }
+
+ public RelatedPostsTabModel(string tabName, PostClass targetPost)
+ : base(tabName)
+ {
+ this.TargetPost = targetPost;
+ }
+ }
+}
+++ /dev/null
-// OpenTween - Client of Twitter
-// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
-// (c) 2008-2011 Moz (@syo68k)
-// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
-// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
-// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
-// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
-// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
-// All rights reserved.
-//
-// This file is part of OpenTween.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
-// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
-// Boston, MA 02110-1301, USA.
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace OpenTween.Models
-{
- public sealed class TabClass
- {
- 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;
-
- private readonly object _lockObj = new object();
-
- public string User { get; set; }
-
- #region "検索"
- //Search query
- private string _searchLang = "";
- private string _searchWords = "";
-
- public string SearchLang
- {
- get
- {
- return _searchLang;
- }
- set
- {
- _searchLang = value;
- this.ResetFetchIds();
- }
- }
- public string SearchWords
- {
- get
- {
- return _searchWords;
- }
- set
- {
- _searchWords = value.Trim();
- this.ResetFetchIds();
- }
- }
-
- private Dictionary<string, string> _beforeQuery = new Dictionary<string, string>();
-
- public bool IsSearchQueryChanged
- {
- get
- {
- var qry = new Dictionary<string, string>();
- if (!string.IsNullOrEmpty(_searchWords))
- {
- qry.Add("q", _searchWords);
- if (!string.IsNullOrEmpty(_searchLang)) qry.Add("lang", _searchLang);
- }
- if (qry.Count != _beforeQuery.Count)
- {
- _beforeQuery = qry;
- return true;
- }
-
- foreach (var kvp in qry)
- {
- string value;
- if (!_beforeQuery.TryGetValue(kvp.Key, out value) || value != kvp.Value)
- {
- _beforeQuery = qry;
- return true;
- }
- }
- return false;
- }
- }
- #endregion
-
- #region "リスト"
- private ListElement _listInfo;
- public ListElement ListInfo
- {
- get
- {
- return _listInfo;
- }
- set
- {
- _listInfo = value;
- }
- }
- #endregion
-
- public PostClass RelationTargetPost { get; set; }
-
- public long OldestId = long.MaxValue;
-
- public long SinceId { get; set; }
-
- public ConcurrentDictionary<long, PostClass> Posts { get; private set; }
-
- private ConcurrentDictionary<long, PostClass> _innerPosts;
-
- private struct TemporaryId
- {
- public long Id;
- public bool Read;
-
- public TemporaryId(long argId, bool argRead)
- {
- Id = argId;
- Read = argRead;
- }
- }
-
- public TabClass()
- {
- _innerPosts = new ConcurrentDictionary<long, PostClass>();
- Posts = _innerPosts;
- SoundFile = "";
- TabName = "";
- _filters = new List<PostFilterRule>();
- Protected = false;
- Notify = true;
- SoundFile = "";
- UnreadManage = true;
- _ids = new IndexedSortedSet<long>();
- _tabType = MyCommon.TabUsageType.Undefined;
- _listInfo = null;
- }
-
- public TabClass(string name, MyCommon.TabUsageType type) : this(name, type, list: null)
- {
- }
-
- public TabClass(string TabName, MyCommon.TabUsageType TabType, ListElement list) : this()
- {
- this.TabName = TabName;
- this.TabType = TabType;
- this.ListInfo = list;
- }
-
- /// <summary>
- /// タブ更新時に使用する SinceId, OldestId をリセットする
- /// </summary>
- public void ResetFetchIds()
- {
- this.SinceId = 0L;
- this.OldestId = long.MaxValue;
- }
-
- /// <summary>
- /// ソート対象のフィールドとソート順を設定し、ソートを実行します
- /// </summary>
- public void SetSortMode(ComparerMode mode, SortOrder sortOrder)
- {
- this.SortMode = mode;
- this.SortOrder = sortOrder;
-
- this.ApplySortMode();
- }
-
- private void ApplySortMode()
- {
- var sign = this.SortOrder == SortOrder.Ascending ? 1 : -1;
-
- Comparison<long> comparison;
- if (this.SortMode == ComparerMode.Id)
- {
- comparison = (x, y) => sign * x.CompareTo(y);
- }
- else
- {
- Comparison<PostClass> postComparison;
- switch (this.SortMode)
- {
- default:
- case ComparerMode.Data:
- postComparison = (x, y) => Comparer<string>.Default.Compare(x?.TextFromApi, y?.TextFromApi);
- break;
- case ComparerMode.Name:
- postComparison = (x, y) => Comparer<string>.Default.Compare(x?.ScreenName, y?.ScreenName);
- break;
- case ComparerMode.Nickname:
- postComparison = (x, y) => Comparer<string>.Default.Compare(x?.Nickname, y?.Nickname);
- break;
- case ComparerMode.Source:
- postComparison = (x, y) => Comparer<string>.Default.Compare(x?.Source, y?.Source);
- break;
- }
-
- comparison = (x, y) =>
- {
- PostClass xPost, yPost;
- this.Posts.TryGetValue(x, out xPost);
- this.Posts.TryGetValue(y, out yPost);
-
- var compare = sign * postComparison(xPost, yPost);
- if (compare != 0)
- return compare;
-
- // 同値であれば status_id で比較する
- return sign * x.CompareTo(y);
- };
- }
-
- var comparer = Comparer<long>.Create(comparison);
-
- this._ids = new IndexedSortedSet<long>(this._ids, comparer);
- this.unreadIds = new SortedSet<long>(this.unreadIds, comparer);
- }
-
- public ComparerMode SortMode { get; private set; }
- public SortOrder SortOrder { get; private set; }
-
- public void AddPostQueue(long statusId, bool read)
- {
- this.addQueue.Enqueue(new TemporaryId(statusId, read));
- }
-
- //無条件に追加
- public void AddPostImmediately(long ID, bool Read)
- {
- if (this._ids.Contains(ID)) return;
-
- this._ids.Add(ID);
-
- if (!Read)
- this.unreadIds.Add(ID);
- }
-
- //フィルタに合致したら追加
- public MyCommon.HITRESULT AddFiltered(PostClass post, bool immediately = false)
- {
- if (this.IsInnerStorageTabType) return MyCommon.HITRESULT.None;
-
- var rslt = MyCommon.HITRESULT.None;
- //全フィルタ評価(優先順位あり)
- lock (this._lockObj)
- {
- foreach (var ft in _filters)
- {
- try
- {
- switch (ft.ExecFilter(post)) //フィルタクラスでヒット判定
- {
- case MyCommon.HITRESULT.None:
- break;
- case MyCommon.HITRESULT.Copy:
- if (rslt != MyCommon.HITRESULT.CopyAndMark) rslt = MyCommon.HITRESULT.Copy;
- break;
- case MyCommon.HITRESULT.CopyAndMark:
- rslt = MyCommon.HITRESULT.CopyAndMark;
- break;
- case MyCommon.HITRESULT.Move:
- rslt = MyCommon.HITRESULT.Move;
- break;
- case MyCommon.HITRESULT.Exclude:
- rslt = MyCommon.HITRESULT.Exclude;
- goto exit_for;
- }
- }
- catch (NullReferenceException)
- {
- // ExecFilterでNullRef出る場合あり。暫定対応
- MyCommon.TraceOut("ExecFilterでNullRef: " + ft.ToString());
- rslt = MyCommon.HITRESULT.None;
- }
- }
- exit_for:
- ;
- }
-
- if (this.TabType != MyCommon.TabUsageType.Mute &&
- rslt != MyCommon.HITRESULT.None && rslt != MyCommon.HITRESULT.Exclude)
- {
- if (immediately)
- this.AddPostImmediately(post.StatusId, post.IsRead);
- else
- this.AddPostQueue(post.StatusId, post.IsRead);
- }
-
- return rslt; //マーク付けは呼び出し元で行うこと
- }
-
- //検索結果の追加
- public void AddPostToInnerStorage(PostClass Post)
- {
- if (_innerPosts.ContainsKey(Post.StatusId))
- return;
-
- if (TabInformations.GetInstance().IsMuted(Post, isHomeTimeline: false))
- return;
-
- _innerPosts.TryAdd(Post.StatusId, Post);
- this.AddPostQueue(Post.StatusId, Post.IsRead);
- }
-
- public IList<long> AddSubmit()
- {
- var addedIds = new List<long>();
-
- TemporaryId tId;
- while (this.addQueue.TryDequeue(out tId))
- {
- this.AddPostImmediately(tId.Id, tId.Read);
- addedIds.Add(tId.Id);
- }
-
- return addedIds;
- }
-
- public void EnqueueRemovePost(long statusId, bool setIsDeleted)
- {
- this.removeQueue.Enqueue(statusId);
-
- 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(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; }
- public bool Protected { get; set; }
- public bool Notify { get; set; }
- public string SoundFile { get; set; }
-
- /// <summary>
- /// 次に表示する未読ツイートのIDを返します。
- /// ただし、未読がない場合または UnreadManage が false の場合は -1 を返します
- /// </summary>
- public long NextUnreadId
- {
- get
- {
- if (!this.UnreadManage || !SettingCommon.Instance.UnreadManage)
- return -1L;
-
- if (this.unreadIds.Count == 0)
- return -1L;
-
- // unreadIds はリストのインデックス番号順に並んでいるため、
- // 例えば ID 順の整列であれば昇順なら上から、降順なら下から順に返せば過去→現在の順になる
- return this.SortOrder == SortOrder.Ascending ? this.unreadIds.Min : this.unreadIds.Max;
- }
- }
-
- /// <summary>
- /// 次に表示する未読ツイートのインデックス番号を返します。
- /// ただし、未読がない場合または UnreadManage が false の場合は -1 を返します
- /// </summary>
- public int NextUnreadIndex
- {
- get
- {
- var unreadId = this.NextUnreadId;
- return unreadId != -1 ? this.IndexOf(unreadId) : -1;
- }
- }
-
- /// <summary>
- /// 未読ツイートの件数を返します。
- /// ただし、未読がない場合または UnreadManage が false の場合は 0 を返します
- /// </summary>
- public int UnreadCount
- {
- get
- {
- if (!this.UnreadManage || !SettingCommon.Instance.UnreadManage)
- return 0;
-
- return this.unreadIds.Count;
- }
- }
-
- public int AllCount
- {
- get
- {
- return this._ids.Count;
- }
- }
-
- /// <summary>
- /// 未読ツイートの ID を配列で返します
- /// </summary>
- public long[] GetUnreadIds()
- {
- lock (this._lockObj)
- {
- return this.unreadIds.ToArray();
- }
- }
-
- /// <summary>
- /// タブ内の既読状態を変更します
- /// </summary>
- /// <remarks>
- /// 全タブを横断して既読状態を変える TabInformation.SetReadAllTab() の内部で呼び出されるメソッドです
- /// </remarks>
- /// <param name="statusId">変更するツイートのID</param>
- /// <param name="read">既読状態</param>
- /// <returns>既読状態に変化があれば true、変化がなければ false</returns>
- internal bool SetReadState(long statusId, bool read)
- {
- if (!this._ids.Contains(statusId))
- throw new ArgumentOutOfRangeException(nameof(statusId));
-
- if (this.IsInnerStorageTabType)
- this.Posts[statusId].IsRead = read;
-
- if (read)
- return this.unreadIds.Remove(statusId);
- else
- return this.unreadIds.Add(statusId);
- }
-
- public PostFilterRule[] GetFilters()
- {
- lock (this._lockObj)
- {
- return _filters.ToArray();
- }
- }
-
- public void RemoveFilter(PostFilterRule filter)
- {
- lock (this._lockObj)
- {
- _filters.Remove(filter);
- filter.PropertyChanged -= this.OnFilterModified;
- this.FilterModified = true;
- }
- }
-
- public bool AddFilter(PostFilterRule filter)
- {
- lock (this._lockObj)
- {
- if (_filters.Contains(filter)) return false;
- filter.PropertyChanged += this.OnFilterModified;
- _filters.Add(filter);
- this.FilterModified = true;
- return true;
- }
- }
-
- private void OnFilterModified(object sender, PropertyChangedEventArgs e)
- {
- this.FilterModified = true;
- }
-
- public PostFilterRule[] FilterArray
- {
- get
- {
- lock (this._lockObj)
- {
- return _filters.ToArray();
- }
- }
- set
- {
- lock (this._lockObj)
- {
- foreach (var oldFilter in this._filters)
- {
- oldFilter.PropertyChanged -= this.OnFilterModified;
- }
-
- this._filters.Clear();
- this.FilterModified = true;
-
- foreach (var newFilter in value)
- {
- _filters.Add(newFilter);
- newFilter.PropertyChanged += this.OnFilterModified;
- }
- }
- }
- }
- public bool Contains(long ID)
- {
- return _ids.Contains(ID);
- }
-
- public void ClearIDs()
- {
- _ids.Clear();
- this.unreadIds.Clear();
- _innerPosts.Clear();
-
- Interlocked.Exchange(ref this.addQueue, new ConcurrentQueue<TemporaryId>());
- }
-
- public PostClass this[int Index]
- {
- get
- {
- var id = GetId(Index);
- if (id < 0) throw new ArgumentException("Index can't find. Index=" + Index.ToString() + "/TabName=" + TabName, nameof(Index));
- return Posts[id];
- }
- }
-
- public PostClass[] this[int StartIndex, int EndIndex]
- {
- get
- {
- var length = EndIndex - StartIndex + 1;
- var posts = new PostClass[length];
- for (int i = 0; i < length; i++)
- {
- posts[i] = Posts[GetId(StartIndex + i)];
- }
- return posts;
- }
- }
-
- public long[] GetId(ListView.SelectedIndexCollection IndexCollection)
- {
- if (IndexCollection.Count == 0) return null;
-
- var Ids = new long[IndexCollection.Count];
- for (int i = 0; i < Ids.Length; i++)
- {
- Ids[i] = GetId(IndexCollection[i]);
- }
- return Ids;
- }
-
- public long GetId(int Index)
- {
- return Index < _ids.Count ? _ids[Index] : -1;
- }
-
- public int[] IndexOf(long[] Ids)
- {
- if (Ids == null) return null;
- var idx = new int[Ids.Length];
- for (int i = 0; i < Ids.Length; i++)
- {
- idx[i] = IndexOf(Ids[i]);
- }
- return idx;
- }
-
- public int IndexOf(long ID)
- {
- return _ids.IndexOf(ID);
- }
-
- public IEnumerable<int> SearchPostsAll(Func<string, bool> stringComparer)
- => this.SearchPostsAll(stringComparer, reverse: false);
-
- public IEnumerable<int> SearchPostsAll(Func<string, bool> stringComparer, int startIndex)
- => this.SearchPostsAll(stringComparer, startIndex, reverse: false);
-
- public IEnumerable<int> SearchPostsAll(Func<string, bool> stringComparer, bool reverse)
- {
- var startIndex = reverse ? this.AllCount - 1 : 0;
-
- return this.SearchPostsAll(stringComparer, startIndex, reverse: false);
- }
-
- /// <summary>
- /// タブ内の発言を指定された条件で検索します
- /// </summary>
- /// <param name="stringComparer">発言内容、スクリーン名、名前と比較する条件。マッチしたら true を返す</param>
- /// <param name="startIndex">検索を開始する位置</param>
- /// <param name="reverse">インデックスの昇順に検索する場合は false、降順の場合は true</param>
- /// <returns></returns>
- public IEnumerable<int> SearchPostsAll(Func<string, bool> stringComparer, int startIndex, bool reverse)
- {
- if (this.AllCount == 0)
- yield break;
-
- var searchIndices = Enumerable.Empty<int>();
-
- if (!reverse)
- {
- // startindex ...末尾
- if (startIndex != this.AllCount - 1)
- searchIndices = MyCommon.CountUp(startIndex, this.AllCount - 1);
-
- // 先頭 ... (startIndex - 1)
- if (startIndex != 0)
- searchIndices = searchIndices.Concat(MyCommon.CountUp(0, startIndex - 1));
- }
- else
- {
- // startIndex ... 先頭
- if (startIndex != 0)
- searchIndices = MyCommon.CountDown(startIndex, 0);
-
- // 末尾 ... (startIndex - 1)
- if (startIndex != this.AllCount - 1)
- searchIndices = searchIndices.Concat(MyCommon.CountDown(this.AllCount - 1, startIndex - 1));
- }
-
- foreach (var index in searchIndices)
- {
- PostClass post;
- if (!this.Posts.TryGetValue(this.GetId(index), out post))
- continue;
-
- if (stringComparer(post.Nickname) || stringComparer(post.TextFromApi) || stringComparer(post.ScreenName))
- {
- yield return index;
- }
- }
- }
-
- public bool FilterModified { get; set; }
-
- public long[] BackupIds
- {
- get
- {
- return _ids.ToArray();
- }
- }
-
- public string TabName { get; set; }
-
- public MyCommon.TabUsageType TabType
- {
- get
- {
- return _tabType;
- }
- set
- {
- _tabType = value;
- if (this.IsInnerStorageTabType)
- {
- Posts = _innerPosts;
- }
- else
- {
- Posts = TabInformations.GetInstance().Posts;
- }
- }
- }
-
- public bool IsDefaultTabType
- {
- get
- {
- return _tabType.IsDefault();
- }
- }
-
- public bool IsDistributableTabType
- {
- get
- {
- return _tabType.IsDistributable();
- }
- }
-
- public bool IsInnerStorageTabType
- {
- get
- {
- return _tabType.IsInnerStorage();
- }
- }
- }
-}
public sealed class TabInformations
{
//個別タブの情報をDictionaryで保持
- private Dictionary<string, TabClass> _tabs = new Dictionary<string, TabClass>();
+ private Dictionary<string, TabModel> _tabs = new Dictionary<string, TabModel>();
private ConcurrentDictionary<long, PostClass> _statuses = new ConcurrentDictionary<long, PostClass>();
private Dictionary<long, PostClass> _retweets = new Dictionary<long, PostClass>();
private Dictionary<long, PostClass> _quotes = new Dictionary<long, PostClass>();
- private Stack<TabClass> _removedTab = new Stack<TabClass>();
+ private Stack<TabModel> _removedTab = new Stack<TabModel>();
public ISet<long> BlockIds = new HashSet<long>();
public ISet<long> MuteUserIds = new HashSet<long>();
{
if (value != null && value.Count > 0)
{
- foreach (var tb in this.GetTabsByType(MyCommon.TabUsageType.Lists))
+ foreach (var tb in this.GetTabsByType<ListTimelineTabModel>())
{
foreach (var list in value)
{
}
}
- public bool AddTab(string TabName, MyCommon.TabUsageType TabType, ListElement List)
- => this.AddTab(new TabClass(TabName, TabType, List));
-
- public bool AddTab(TabClass tab)
+ public bool AddTab(TabModel tab)
{
if (this._tabs.ContainsKey(tab.TabName))
return false;
for (int idx = 0; idx < tb.AllCount; ++idx)
{
var exist = false;
- var Id = tb.GetId(idx);
+ var Id = tb.GetStatusIdAt(idx);
if (Id < 0) continue;
foreach (var tab in _tabs.Values)
{
}
}
- public Stack<TabClass> RemovedTab
+ public Stack<TabModel> RemovedTab
{
get { return _removedTab; }
}
return _tabs.ContainsKey(TabText);
}
- public bool ContainsTab(TabClass ts)
+ public bool ContainsTab(TabModel ts)
{
return _tabs.ContainsValue(ts);
}
throw new TabException(message);
}
- public Dictionary<string, TabClass> Tabs
+ public Dictionary<string, TabModel> Tabs
{
get
{
}
}
- public Dictionary<string, TabClass>.KeyCollection KeysTab
+ public Dictionary<string, TabModel>.KeyCollection KeysTab
{
get
{
var replyTab = this.GetTabByType(MyCommon.TabUsageType.Mentions);
var favTab = this.GetTabByType(MyCommon.TabUsageType.Favorites);
- var distributableTabs = this._tabs.Values.Where(x => x.IsDistributableTabType)
+ var distributableTabs = this.GetTabsByType<FilterTabModel>()
.ToArray();
var adddedCount = 0;
// 移動されなかったらRecentに追加
if (!moved)
- homeTab.AddPostQueue(post.StatusId, post.IsRead);
+ homeTab.AddPostQueue(post);
// 除外ルール適用のないReplyならReplyタブに追加
if (post.IsReply && !excludedReply)
- replyTab.AddPostQueue(post.StatusId, post.IsRead);
+ replyTab.AddPostQueue(post);
// Fav済み発言だったらFavoritesタブに追加
if (post.IsFav)
- favTab.AddPostQueue(post.StatusId, post.IsRead);
+ favTab.AddPostQueue(post);
adddedCount++;
}
public bool IsMuted(PostClass post, bool isHomeTimeline)
{
- var muteTab = this.GetTabByType(MyCommon.TabUsageType.Mute);
+ var muteTab = this.GetTabByType<MuteTabModel>();
if (muteTab != null && muteTab.AddFiltered(post) == MyCommon.HITRESULT.Move)
return true;
var homeTab = GetTabByType(MyCommon.TabUsageType.Home);
var detachedIdsAll = Enumerable.Empty<long>();
- foreach (var tab in _tabs.Values.ToArray())
+ foreach (var tab in _tabs.Values.OfType<FilterTabModel>().ToArray())
{
- if (!tab.IsDistributableTabType)
- continue;
-
if (tab.TabType == MyCommon.TabUsageType.Mute)
continue;
tab.FilterModified = false;
// フィルタ実行前の時点でタブに含まれていたstatusIdを記憶する
- var orgIds = tab.BackupIds;
+ var orgIds = tab.StatusIds;
tab.ClearIDs();
foreach (var post in _statuses.Values)
}
// フィルタの更新によってタブから取り除かれたツイートのID
- var detachedIds = orgIds.Except(tab.BackupIds).ToArray();
+ var detachedIds = orgIds.Except(tab.StatusIds).ToArray();
detachedIdsAll = detachedIdsAll.Concat(detachedIds);
}
var tb = _tabs[TabName];
if (!tb.IsInnerStorageTabType)
{
- foreach (var Id in tb.BackupIds)
+ foreach (var Id in tb.StatusIds)
{
var Hit = false;
foreach (var tab in _tabs.Values)
}
}
- public TabClass GetTabByType(MyCommon.TabUsageType tabType)
+ public TabModel GetTabByType(MyCommon.TabUsageType tabType)
{
//Home,Mentions,DM,Favは1つに制限する
//その他のタイプを指定されたら、最初に合致したものを返す
}
}
- public TabClass[] GetTabsByType(MyCommon.TabUsageType tabType)
+ public T GetTabByType<T>() where T : TabModel
+ {
+ lock (this.LockObj)
+ return this._tabs.Values.OfType<T>().FirstOrDefault();
+ }
+
+ public TabModel[] GetTabsByType(MyCommon.TabUsageType tabType)
{
lock (LockObj)
{
}
}
- public TabClass[] GetTabsInnerStorageType()
+ public T[] GetTabsByType<T>() where T : TabModel
+ {
+ lock (this.LockObj)
+ return this._tabs.Values.OfType<T>().ToArray();
+ }
+
+ public TabModel[] GetTabsInnerStorageType()
{
lock (LockObj)
{
}
}
- public TabClass GetTabByName(string tabName)
+ public TabModel GetTabByName(string tabName)
{
lock (LockObj)
{
- TabClass tab;
+ TabModel tab;
return _tabs.TryGetValue(tabName, out tab)
? tab
: null;
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace OpenTween.Models
+{
+ public abstract class TabModel
+ {
+ public string TabName { get; set; }
+
+ public bool UnreadManage { get; set; } = true;
+ public bool Protected { get; set; }
+ public bool Notify { get; set; } = true;
+ public string SoundFile { get; set; } = "";
+
+ public ComparerMode SortMode { get; private set; }
+ public SortOrder SortOrder { get; private set; }
+
+ public long OldestId { get; set; } = long.MaxValue;
+ public long SinceId { get; set; }
+
+ public abstract MyCommon.TabUsageType TabType { get; }
+
+ public virtual ConcurrentDictionary<long, PostClass> Posts
+ => TabInformations.GetInstance().Posts;
+
+ public int AllCount => this._ids.Count;
+ public long[] StatusIds => this._ids.ToArray();
+
+ public bool IsDefaultTabType => this.TabType.IsDefault();
+ public bool IsDistributableTabType => this.TabType.IsDistributable();
+ public bool IsInnerStorageTabType => this.TabType.IsInnerStorage();
+
+ private IndexedSortedSet<long> _ids = new IndexedSortedSet<long>();
+ private ConcurrentQueue<TemporaryId> addQueue = new ConcurrentQueue<TemporaryId>();
+ private ConcurrentQueue<long> removeQueue = new ConcurrentQueue<long>();
+ private SortedSet<long> unreadIds = new SortedSet<long>();
+
+ private readonly object _lockObj = new object();
+
+ public TabModel(string tabName)
+ {
+ this.TabName = tabName;
+ }
+
+ private struct TemporaryId
+ {
+ public long StatusId { get; }
+ public bool Read { get; }
+
+ public TemporaryId(long statusId, bool read)
+ {
+ this.StatusId = statusId;
+ this.Read = read;
+ }
+ }
+
+ public virtual void AddPostQueue(PostClass post)
+ {
+ this.addQueue.Enqueue(new TemporaryId(post.StatusId, post.IsRead));
+ }
+
+ //無条件に追加
+ internal void AddPostImmediately(long statusId, bool read)
+ {
+ if (this._ids.Contains(statusId)) return;
+
+ this._ids.Add(statusId);
+
+ if (!read)
+ this.unreadIds.Add(statusId);
+ }
+
+ public IList<long> AddSubmit()
+ {
+ var addedIds = new List<long>();
+
+ TemporaryId tId;
+ while (this.addQueue.TryDequeue(out tId))
+ {
+ this.AddPostImmediately(tId.StatusId, tId.Read);
+ addedIds.Add(tId.StatusId);
+ }
+
+ return addedIds;
+ }
+
+ public virtual void EnqueueRemovePost(long statusId, bool setIsDeleted)
+ {
+ this.removeQueue.Enqueue(statusId);
+ }
+
+ public virtual bool RemovePostImmediately(long statusId)
+ {
+ if (!this._ids.Remove(statusId))
+ return false;
+
+ this.unreadIds.Remove(statusId);
+ 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 virtual void ClearIDs()
+ {
+ this._ids.Clear();
+ this.unreadIds.Clear();
+
+ Interlocked.Exchange(ref this.addQueue, new ConcurrentQueue<TemporaryId>());
+ }
+
+ /// <summary>
+ /// タブ更新時に使用する SinceId, OldestId をリセットする
+ /// </summary>
+ public void ResetFetchIds()
+ {
+ this.SinceId = 0L;
+ this.OldestId = long.MaxValue;
+ }
+
+ /// <summary>
+ /// ソート対象のフィールドとソート順を設定し、ソートを実行します
+ /// </summary>
+ public void SetSortMode(ComparerMode mode, SortOrder sortOrder)
+ {
+ this.SortMode = mode;
+ this.SortOrder = sortOrder;
+
+ this.ApplySortMode();
+ }
+
+ private void ApplySortMode()
+ {
+ var sign = this.SortOrder == SortOrder.Ascending ? 1 : -1;
+
+ Comparison<long> comparison;
+ if (this.SortMode == ComparerMode.Id)
+ {
+ comparison = (x, y) => sign * x.CompareTo(y);
+ }
+ else
+ {
+ Comparison<PostClass> postComparison;
+ switch (this.SortMode)
+ {
+ default:
+ case ComparerMode.Data:
+ postComparison = (x, y) => Comparer<string>.Default.Compare(x?.TextFromApi, y?.TextFromApi);
+ break;
+ case ComparerMode.Name:
+ postComparison = (x, y) => Comparer<string>.Default.Compare(x?.ScreenName, y?.ScreenName);
+ break;
+ case ComparerMode.Nickname:
+ postComparison = (x, y) => Comparer<string>.Default.Compare(x?.Nickname, y?.Nickname);
+ break;
+ case ComparerMode.Source:
+ postComparison = (x, y) => Comparer<string>.Default.Compare(x?.Source, y?.Source);
+ break;
+ }
+
+ comparison = (x, y) =>
+ {
+ PostClass xPost, yPost;
+ this.Posts.TryGetValue(x, out xPost);
+ this.Posts.TryGetValue(y, out yPost);
+
+ var compare = sign * postComparison(xPost, yPost);
+ if (compare != 0)
+ return compare;
+
+ // 同値であれば status_id で比較する
+ return sign * x.CompareTo(y);
+ };
+ }
+
+ var comparer = Comparer<long>.Create(comparison);
+
+ this._ids = new IndexedSortedSet<long>(this._ids, comparer);
+ this.unreadIds = new SortedSet<long>(this.unreadIds, comparer);
+ }
+
+ /// <summary>
+ /// 次に表示する未読ツイートのIDを返します。
+ /// ただし、未読がない場合または UnreadManage が false の場合は -1 を返します
+ /// </summary>
+ public long NextUnreadId
+ {
+ get
+ {
+ if (!this.UnreadManage || !SettingCommon.Instance.UnreadManage)
+ return -1L;
+
+ if (this.unreadIds.Count == 0)
+ return -1L;
+
+ // unreadIds はリストのインデックス番号順に並んでいるため、
+ // 例えば ID 順の整列であれば昇順なら上から、降順なら下から順に返せば過去→現在の順になる
+ return this.SortOrder == SortOrder.Ascending ? this.unreadIds.Min : this.unreadIds.Max;
+ }
+ }
+
+ /// <summary>
+ /// 次に表示する未読ツイートのインデックス番号を返します。
+ /// ただし、未読がない場合または UnreadManage が false の場合は -1 を返します
+ /// </summary>
+ public int NextUnreadIndex
+ {
+ get
+ {
+ var unreadId = this.NextUnreadId;
+ return unreadId != -1 ? this.IndexOf(unreadId) : -1;
+ }
+ }
+
+ /// <summary>
+ /// 未読ツイートの件数を返します。
+ /// ただし、未読がない場合または UnreadManage が false の場合は 0 を返します
+ /// </summary>
+ public int UnreadCount
+ {
+ get
+ {
+ if (!this.UnreadManage || !SettingCommon.Instance.UnreadManage)
+ return 0;
+
+ return this.unreadIds.Count;
+ }
+ }
+
+ /// <summary>
+ /// 未読ツイートの ID を配列で返します
+ /// </summary>
+ public long[] GetUnreadIds()
+ {
+ lock (this._lockObj)
+ return this.unreadIds.ToArray();
+ }
+
+ /// <summary>
+ /// タブ内の既読状態を変更します
+ /// </summary>
+ /// <remarks>
+ /// 全タブを横断して既読状態を変える TabInformation.SetReadAllTab() の内部で呼び出されるメソッドです
+ /// </remarks>
+ /// <param name="statusId">変更するツイートのID</param>
+ /// <param name="read">既読状態</param>
+ /// <returns>既読状態に変化があれば true、変化がなければ false</returns>
+ internal bool SetReadState(long statusId, bool read)
+ {
+ if (!this._ids.Contains(statusId))
+ throw new ArgumentOutOfRangeException(nameof(statusId));
+
+ if (this.IsInnerStorageTabType)
+ this.Posts[statusId].IsRead = read;
+
+ if (read)
+ return this.unreadIds.Remove(statusId);
+ else
+ return this.unreadIds.Add(statusId);
+ }
+
+ public bool Contains(long statusId)
+ => this._ids.Contains(statusId);
+
+ public PostClass this[int index]
+ {
+ get
+ {
+ PostClass post;
+ if (!this.Posts.TryGetValue(this.GetStatusIdAt(index), out post))
+ throw new ArgumentException("Post not exists", nameof(index));
+
+ return post;
+ }
+ }
+
+ public PostClass[] this[int startIndex, int endIndex]
+ {
+ get
+ {
+ var length = endIndex - startIndex + 1;
+ var posts = new PostClass[length];
+
+ var i = 0;
+ foreach (var idx in Enumerable.Range(startIndex, length))
+ {
+ var statusId = this.GetStatusIdAt(idx);
+ this.Posts.TryGetValue(statusId, out posts[i++]);
+ }
+
+ return posts;
+ }
+ }
+
+ public long[] GetStatusIdAt(IEnumerable<int> indexes)
+ => indexes.Select(x => this.GetStatusIdAt(x)).ToArray();
+
+ public long GetStatusIdAt(int index)
+ => this._ids[index];
+
+ public int[] IndexOf(long[] statusIds)
+ {
+ if (statusIds == null)
+ throw new ArgumentNullException(nameof(statusIds));
+
+ return statusIds.Select(x => this.IndexOf(x)).ToArray();
+ }
+
+ public int IndexOf(long statusId)
+ => this._ids.IndexOf(statusId);
+
+ public IEnumerable<int> SearchPostsAll(Func<string, bool> stringComparer)
+ => this.SearchPostsAll(stringComparer, reverse: false);
+
+ public IEnumerable<int> SearchPostsAll(Func<string, bool> stringComparer, int startIndex)
+ => this.SearchPostsAll(stringComparer, startIndex, reverse: false);
+
+ public IEnumerable<int> SearchPostsAll(Func<string, bool> stringComparer, bool reverse)
+ {
+ var startIndex = reverse ? this.AllCount - 1 : 0;
+
+ return this.SearchPostsAll(stringComparer, startIndex, reverse: false);
+ }
+
+ /// <summary>
+ /// タブ内の発言を指定された条件で検索します
+ /// </summary>
+ /// <param name="stringComparer">発言内容、スクリーン名、名前と比較する条件。マッチしたら true を返す</param>
+ /// <param name="startIndex">検索を開始する位置</param>
+ /// <param name="reverse">インデックスの昇順に検索する場合は false、降順の場合は true</param>
+ /// <returns></returns>
+ public IEnumerable<int> SearchPostsAll(Func<string, bool> stringComparer, int startIndex, bool reverse)
+ {
+ if (this.AllCount == 0)
+ yield break;
+
+ var searchIndices = Enumerable.Empty<int>();
+
+ if (!reverse)
+ {
+ // startindex ...末尾
+ if (startIndex != this.AllCount - 1)
+ searchIndices = MyCommon.CountUp(startIndex, this.AllCount - 1);
+
+ // 先頭 ... (startIndex - 1)
+ if (startIndex != 0)
+ searchIndices = searchIndices.Concat(MyCommon.CountUp(0, startIndex - 1));
+ }
+ else
+ {
+ // startIndex ... 先頭
+ if (startIndex != 0)
+ searchIndices = MyCommon.CountDown(startIndex, 0);
+
+ // 末尾 ... (startIndex - 1)
+ if (startIndex != this.AllCount - 1)
+ searchIndices = searchIndices.Concat(MyCommon.CountDown(this.AllCount - 1, startIndex - 1));
+ }
+
+ foreach (var index in searchIndices)
+ {
+ PostClass post;
+ if (!this.Posts.TryGetValue(this.GetStatusIdAt(index), out post))
+ continue;
+
+ if (stringComparer(post.Nickname) || stringComparer(post.TextFromApi) || stringComparer(post.ScreenName))
+ {
+ yield return index;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+// (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenTween.Models
+{
+ public class UserTimelineTabModel : InternalStorageTabModel
+ {
+ public override MyCommon.TabUsageType TabType
+ => MyCommon.TabUsageType.UserTimeline;
+
+ public string ScreenName { get; }
+
+ public UserTimelineTabModel(string tabName, string screenName)
+ : base(tabName)
+ {
+ this.ScreenName = screenName;
+ }
+ }
+}
List<PostClass> listPost = new List<PostClass>();
List<PostClass> otherPost = new List<PostClass>();
- foreach (TabClass tab in TabInformations.GetInstance().Tabs.Values)
+ foreach (var tab in TabInformations.GetInstance().GetTabsByType<ListTimelineTabModel>())
{
- if (tab.TabType == MyCommon.TabUsageType.Lists)
- {
- if (listItem.Id == tab.ListInfo.Id)
- listPost.AddRange(tab.Posts.Values);
- else
- otherPost.AddRange(tab.Posts.Values);
- }
+ if (listItem.Id == tab.ListInfo.Id)
+ listPost.AddRange(tab.Posts.Values);
+ else
+ otherPost.AddRange(tab.Posts.Values);
}
//リストが空の場合は推定不能
</Compile>
<Compile Include="IndexedSortedSet.cs" />
<Compile Include="MediaItem.cs" />
+ <Compile Include="Models\ComparerMode.cs" />
+ <Compile Include="Models\DirectMessagesTabModel.cs" />
+ <Compile Include="Models\FavoritesTabModel.cs" />
+ <Compile Include="Models\FilterTabModel.cs" />
+ <Compile Include="Models\HomeTabModel.cs" />
+ <Compile Include="Models\InternalStorageTabModel.cs" />
+ <Compile Include="Models\ListTimelineTabModel.cs" />
+ <Compile Include="Models\LocalSearchTabModel.cs" />
<Compile Include="Models\MediaInfo.cs" />
+ <Compile Include="Models\MentionsTabModel.cs" />
+ <Compile Include="Models\MuteTabModel.cs" />
<Compile Include="Models\PostClass.cs" />
- <Compile Include="Models\TabClass.cs" />
+ <Compile Include="Models\PublicSearchTabModel.cs" />
+ <Compile Include="Models\RelatedPostsTabModel.cs" />
+ <Compile Include="Models\TabModel.cs" />
<Compile Include="Models\TabInformations.cs" />
+ <Compile Include="Models\TabUsageTypeExt.cs" />
+ <Compile Include="Models\UserTimelineTabModel.cs" />
<Compile Include="MouseWheelMessageFilter.cs" />
<Compile Include="NotifyPropertyChangedBase.cs" />
<Compile Include="SendErrorReportForm.cs">
protected internal class TabListItem
{
- public TabClass Tab { get; set; }
+ public TabModel Tab { get; set; }
public string Label { get; set; }
public override string ToString()
this.OK_Button.Enabled = true;
}
- public TabClass SelectedTab
+ public TabModel SelectedTab
{
get
{
}
}
- public TabClass[] SelectedTabs
+ public TabModel[] SelectedTabs
{
get
{
SetTabAlignment();
//デフォルトタブの存在チェック、ない場合には追加
- if (_statuses.GetTabByType(MyCommon.TabUsageType.Home) == null)
- {
- TabClass tab;
- if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.RECENT, out tab))
- {
- _statuses.AddTab(MyCommon.DEFAULTTAB.RECENT, MyCommon.TabUsageType.Home, null);
- }
- else
- {
- tab.TabType = MyCommon.TabUsageType.Home;
- }
- }
- if (_statuses.GetTabByType(MyCommon.TabUsageType.Mentions) == null)
- {
- TabClass tab;
- if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.REPLY, out tab))
- {
- _statuses.AddTab(MyCommon.DEFAULTTAB.REPLY, MyCommon.TabUsageType.Mentions, null);
- }
- else
- {
- tab.TabType = MyCommon.TabUsageType.Mentions;
- }
- }
- if (_statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage) == null)
- {
- TabClass tab;
- if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.DM, out tab))
- {
- _statuses.AddTab(MyCommon.DEFAULTTAB.DM, MyCommon.TabUsageType.DirectMessage, null);
- }
- else
- {
- tab.TabType = MyCommon.TabUsageType.DirectMessage;
- }
- }
- if (_statuses.GetTabByType(MyCommon.TabUsageType.Favorites) == null)
- {
- TabClass tab;
- if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.FAV, out tab))
- {
- _statuses.AddTab(MyCommon.DEFAULTTAB.FAV, MyCommon.TabUsageType.Favorites, null);
- }
- else
- {
- tab.TabType = MyCommon.TabUsageType.Favorites;
- }
- }
- if (_statuses.GetTabByType(MyCommon.TabUsageType.Mute) == null)
- {
- TabClass tab;
- if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.MUTE, out tab))
- {
- _statuses.AddTab(MyCommon.DEFAULTTAB.MUTE, MyCommon.TabUsageType.Mute, null);
- }
- else
- {
- tab.TabType = MyCommon.TabUsageType.Mute;
- }
- }
+ if (this._statuses.GetTabByType<HomeTabModel>() == null)
+ this._statuses.AddTab(new HomeTabModel());
+
+ if (this._statuses.GetTabByType<MentionsTabModel>() == null)
+ this._statuses.AddTab(new MentionsTabModel());
+
+ if (this._statuses.GetTabByType<DirectMessagesTabModel>() == null)
+ this._statuses.AddTab(new DirectMessagesTabModel());
+
+ if (this._statuses.GetTabByType<FavoritesTabModel>() == null)
+ this._statuses.AddTab(new FavoritesTabModel());
+
+ if (this._statuses.GetTabByType<MuteTabModel>() == null)
+ this._statuses.AddTab(new MuteTabModel());
foreach (var tab in _statuses.Tabs.Values)
{
if (tab.TabType == MyCommon.TabUsageType.Mute)
continue;
- if (tab.TabType == MyCommon.TabUsageType.Undefined)
- {
- tab.TabType = MyCommon.TabUsageType.UserDefined;
- }
- if (!AddNewTab(tab.TabName, true, tab.TabType, tab.ListInfo))
+ if (!AddNewTab(tab, startup: true))
throw new TabException(Properties.Resources.TweenMain_LoadText1);
}
var tabsSetting = SettingTabs.Load().Tabs;
foreach (var tabSetting in tabsSetting)
{
- var tab = new TabClass(tabSetting.TabName, tabSetting.TabType, tabSetting.ListInfo)
- {
- UnreadManage = tabSetting.UnreadManage,
- Protected = tabSetting.Protected,
- Notify = tabSetting.Notify,
- SoundFile = tabSetting.SoundFile,
- FilterArray = tabSetting.FilterArray,
- FilterModified = false,
- User = tabSetting.User,
- SearchWords = tabSetting.SearchWords,
- SearchLang = tabSetting.SearchLang,
- };
+ TabModel tab;
+ switch (tabSetting.TabType)
+ {
+ case MyCommon.TabUsageType.Home:
+ tab = new HomeTabModel(tabSetting.TabName);
+ break;
+ case MyCommon.TabUsageType.Mentions:
+ tab = new MentionsTabModel(tabSetting.TabName);
+ break;
+ case MyCommon.TabUsageType.DirectMessage:
+ tab = new DirectMessagesTabModel(tabSetting.TabName);
+ break;
+ case MyCommon.TabUsageType.Favorites:
+ tab = new FavoritesTabModel(tabSetting.TabName);
+ break;
+ case MyCommon.TabUsageType.UserDefined:
+ tab = new FilterTabModel(tabSetting.TabName);
+ break;
+ case MyCommon.TabUsageType.UserTimeline:
+ tab = new UserTimelineTabModel(tabSetting.TabName, tabSetting.User);
+ break;
+ case MyCommon.TabUsageType.PublicSearch:
+ tab = new PublicSearchTabModel(tabSetting.TabName)
+ {
+ SearchWords = tabSetting.SearchWords,
+ SearchLang = tabSetting.SearchLang,
+ };
+ break;
+ case MyCommon.TabUsageType.Lists:
+ tab = new ListTimelineTabModel(tabSetting.TabName, tabSetting.ListInfo);
+ break;
+ case MyCommon.TabUsageType.Mute:
+ tab = new MuteTabModel(tabSetting.TabName);
+ break;
+ default:
+ continue;
+ }
+
+ tab.UnreadManage = tabSetting.UnreadManage;
+ tab.Protected = tabSetting.Protected;
+ tab.Notify = tabSetting.Notify;
+ tab.SoundFile = tabSetting.SoundFile;
+
+ if (tab.IsDistributableTabType)
+ {
+ var filterTab = (FilterTabModel)tab;
+ filterTab.FilterArray = tabSetting.FilterArray;
+ filterTab.FilterModified = false;
+ }
if (this._statuses.ContainsTab(tab.TabName))
tab.TabName = this._statuses.MakeTabName("MyTab");
}
if (_statuses.Tabs.Count == 0)
{
- _statuses.AddTab(MyCommon.DEFAULTTAB.RECENT, MyCommon.TabUsageType.Home, null);
- _statuses.AddTab(MyCommon.DEFAULTTAB.REPLY, MyCommon.TabUsageType.Mentions, null);
- _statuses.AddTab(MyCommon.DEFAULTTAB.DM, MyCommon.TabUsageType.DirectMessage, null);
- _statuses.AddTab(MyCommon.DEFAULTTAB.FAV, MyCommon.TabUsageType.Favorites, null);
+ _statuses.AddTab(new HomeTabModel());
+ _statuses.AddTab(new MentionsTabModel());
+ _statuses.AddTab(new DirectMessagesTabModel());
+ _statuses.AddTab(new FavoritesTabModel());
}
}
foreach (TabPage tab in ListTab.TabPages)
{
DetailsListView lst = (DetailsListView)tab.Tag;
- TabClass tabInfo = _statuses.Tabs[tab.Text];
+ TabModel tabInfo = _statuses.Tabs[tab.Text];
if (isDelete || lst.VirtualListSize != tabInfo.AllCount)
{
using (ControlTransaction.Update(lst))
/// <summary>
/// <see cref="ListView"/> のスクロール位置に関する情報を <see cref="ListViewScroll"/> として返します
/// </summary>
- private ListViewScroll SaveListViewScroll(DetailsListView listView, TabClass tab)
+ private ListViewScroll SaveListViewScroll(DetailsListView listView, TabModel tab)
{
var listScroll = new ListViewScroll
{
{
var topItem = listView.TopItem;
if (topItem != null)
- listScroll.TopItemStatusId = tab.GetId(topItem.Index);
+ listScroll.TopItemStatusId = tab.GetStatusIdAt(topItem.Index);
}
return listScroll;
return listsDict;
}
- private long[] GetSelectedStatusIds(DetailsListView listView, TabClass tab)
+ private long[] GetSelectedStatusIds(DetailsListView listView, TabModel tab)
{
var selectedIndices = listView.SelectedIndices;
if (selectedIndices.Count > 0 && selectedIndices.Count < 61)
- return tab.GetId(selectedIndices);
+ return tab.GetStatusIdAt(selectedIndices.Cast<int>());
else
return null;
}
- private long? GetFocusedStatusId(DetailsListView listView, TabClass tab)
+ private long? GetFocusedStatusId(DetailsListView listView, TabModel tab)
{
var focusedItem = listView.FocusedItem;
- return focusedItem != null ? tab.GetId(focusedItem.Index) : (long?)null;
+ return focusedItem != null ? tab.GetStatusIdAt(focusedItem.Index) : (long?)null;
}
- private long? GetSelectionMarkStatusId(DetailsListView listView, TabClass tab)
+ private long? GetSelectionMarkStatusId(DetailsListView listView, TabModel tab)
{
var selectionMarkIndex = listView.SelectionMark;
- return selectionMarkIndex != -1 ? tab.GetId(selectionMarkIndex) : (long?)null;
+ return selectionMarkIndex != -1 ? tab.GetStatusIdAt(selectionMarkIndex) : (long?)null;
}
/// <summary>
/// <see cref="SaveListViewScroll"/> によって保存されたスクロール位置を復元します
/// </summary>
- private void RestoreListViewScroll(DetailsListView listView, TabClass tab, ListViewScroll listScroll)
+ private void RestoreListViewScroll(DetailsListView listView, TabModel tab, ListViewScroll listScroll)
{
if (listView.VirtualListSize == 0)
return;
/// <summary>
/// <see cref="SaveListViewStatus"/> によって保存された選択状態を復元します
/// </summary>
- private void RestoreListViewSelection(DetailsListView listView, TabClass tab, ListViewSelection listSelection)
+ private void RestoreListViewSelection(DetailsListView listView, TabModel tab, ListViewSelection listSelection)
{
// status_id から ListView 上のインデックスに変換
int[] selectedIndices = null;
private Task GetPublicSearchAllAsync()
{
- var tabs = this._statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch);
+ var tabs = this._statuses.GetTabsByType<PublicSearchTabModel>();
return this.GetPublicSearchAsync(tabs, loadMore: false);
}
- private Task GetPublicSearchAsync(TabClass tab)
+ private Task GetPublicSearchAsync(PublicSearchTabModel tab)
{
return this.GetPublicSearchAsync(tab, loadMore: false);
}
- private Task GetPublicSearchAsync(TabClass tab, bool loadMore)
+ private Task GetPublicSearchAsync(PublicSearchTabModel tab, bool loadMore)
{
return this.GetPublicSearchAsync(new[] { tab }, loadMore);
}
- private async Task GetPublicSearchAsync(IEnumerable<TabClass> tabs, bool loadMore)
+ private async Task GetPublicSearchAsync(IEnumerable<PublicSearchTabModel> tabs, bool loadMore)
{
await this.workerSemaphore.WaitAsync();
}
}
- private async Task GetPublicSearchAsyncInternal(IProgress<string> p, CancellationToken ct, IEnumerable<TabClass> tabs, bool loadMore)
+ private async Task GetPublicSearchAsyncInternal(IProgress<string> p, CancellationToken ct, IEnumerable<PublicSearchTabModel> tabs, bool loadMore)
{
if (ct.IsCancellationRequested)
return;
private Task GetUserTimelineAllAsync()
{
- var tabs = this._statuses.GetTabsByType(MyCommon.TabUsageType.UserTimeline);
+ var tabs = this._statuses.GetTabsByType<UserTimelineTabModel>();
return this.GetUserTimelineAsync(tabs, loadMore: false);
}
- private Task GetUserTimelineAsync(TabClass tab)
+ private Task GetUserTimelineAsync(UserTimelineTabModel tab)
{
return this.GetUserTimelineAsync(tab, loadMore: false);
}
- private Task GetUserTimelineAsync(TabClass tab, bool loadMore)
+ private Task GetUserTimelineAsync(UserTimelineTabModel tab, bool loadMore)
{
return this.GetUserTimelineAsync(new[] { tab }, loadMore);
}
- private async Task GetUserTimelineAsync(IEnumerable<TabClass> tabs, bool loadMore)
+ private async Task GetUserTimelineAsync(IEnumerable<UserTimelineTabModel> tabs, bool loadMore)
{
await this.workerSemaphore.WaitAsync();
}
}
- private async Task GetUserTimelineAsyncInternal(IProgress<string> p, CancellationToken ct, IEnumerable<TabClass> tabs, bool loadMore)
+ private async Task GetUserTimelineAsyncInternal(IProgress<string> p, CancellationToken ct, IEnumerable<UserTimelineTabModel> tabs, bool loadMore)
{
if (ct.IsCancellationRequested)
return;
{
try
{
- if (string.IsNullOrEmpty(tab.User))
+ if (string.IsNullOrEmpty(tab.ScreenName))
continue;
- await this.tw.GetUserTimelineApi(read, tab.User, tab, loadMore)
+ await this.tw.GetUserTimelineApi(read, tab.ScreenName, tab, loadMore)
.ConfigureAwait(false);
}
catch (WebApiException ex)
private Task GetListTimelineAllAsync()
{
- var tabs = this._statuses.GetTabsByType(MyCommon.TabUsageType.Lists);
+ var tabs = this._statuses.GetTabsByType<ListTimelineTabModel>();
return this.GetListTimelineAsync(tabs, loadMore: false);
}
- private Task GetListTimelineAsync(TabClass tab)
+ private Task GetListTimelineAsync(ListTimelineTabModel tab)
{
return this.GetListTimelineAsync(tab, loadMore: false);
}
- private Task GetListTimelineAsync(TabClass tab, bool loadMore)
+ private Task GetListTimelineAsync(ListTimelineTabModel tab, bool loadMore)
{
return this.GetListTimelineAsync(new[] { tab }, loadMore);
}
- private async Task GetListTimelineAsync(IEnumerable<TabClass> tabs, bool loadMore)
+ private async Task GetListTimelineAsync(IEnumerable<ListTimelineTabModel> tabs, bool loadMore)
{
await this.workerSemaphore.WaitAsync();
}
}
- private async Task GetListTimelineAsyncInternal(IProgress<string> p, CancellationToken ct, IEnumerable<TabClass> tabs, bool loadMore)
+ private async Task GetListTimelineAsyncInternal(IProgress<string> p, CancellationToken ct, IEnumerable<ListTimelineTabModel> tabs, bool loadMore)
{
if (ct.IsCancellationRequested)
return;
this.RefreshTimeline();
}
- private async Task GetRelatedTweetsAsync(TabClass tab)
+ private async Task GetRelatedTweetsAsync(RelatedPostsTabModel tab)
{
await this.workerSemaphore.WaitAsync();
}
}
- private async Task GetRelatedTweetsAsyncInternal(IProgress<string> p, CancellationToken ct, TabClass tab)
+ private async Task GetRelatedTweetsAsyncInternal(IProgress<string> p, CancellationToken ct, RelatedPostsTabModel tab)
{
if (ct.IsCancellationRequested)
return;
// TODO: 非同期更新中にタブが閉じられている場合を厳密に考慮したい
var listView = (DetailsListView)tabPage.Tag;
- var index = tab.IndexOf(tab.RelationTargetPost.RetweetedId ?? tab.RelationTargetPost.StatusId);
+ var index = tab.IndexOf(tab.TargetPost.RetweetedId ?? tab.TargetPost.StatusId);
if (index != -1 && index < listView.Items.Count)
{
}
}
- private async Task FavAddAsync(long statusId, TabClass tab)
+ private async Task FavAddAsync(long statusId, TabModel tab)
{
await this.workerSemaphore.WaitAsync();
}
}
- private async Task FavAddAsyncInternal(IProgress<string> p, CancellationToken ct, long statusId, TabClass tab)
+ private async Task FavAddAsyncInternal(IProgress<string> p, CancellationToken ct, long statusId, TabModel tab)
{
if (ct.IsCancellationRequested)
return;
postTl.IsFav = true;
var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites);
- favTab.AddPostQueue(statusId, postTl.IsRead);
+ favTab.AddPostQueue(postTl);
}
// 検索,リスト,UserTimeline,Relatedの各タブに反映
}
}
- private async Task FavRemoveAsync(IReadOnlyList<long> statusIds, TabClass tab)
+ private async Task FavRemoveAsync(IReadOnlyList<long> statusIds, TabModel tab)
{
await this.workerSemaphore.WaitAsync();
}
}
- private async Task FavRemoveAsyncInternal(IProgress<string> p, CancellationToken ct, IReadOnlyList<long> statusIds, TabClass tab)
+ private async Task FavRemoveAsyncInternal(IProgress<string> p, CancellationToken ct, IReadOnlyList<long> statusIds, TabModel tab)
{
if (ct.IsCancellationRequested)
return;
private async Task FavoriteChange(bool FavAdd, bool multiFavoriteChangeDialogEnable = true)
{
- TabClass tab;
+ TabModel tab;
if (!this._statuses.Tabs.TryGetValue(this._curTab.Text, out tab))
return;
{
if (_curTab != null)
{
- TabClass tab;
+ TabModel tab;
if (!this._statuses.Tabs.TryGetValue(this._curTab.Text, out tab))
return;
//case MyCommon.TabUsageType.Profile:
//// TODO
case MyCommon.TabUsageType.PublicSearch:
- //// TODO
- if (string.IsNullOrEmpty(tab.SearchWords)) return;
- await this.GetPublicSearchAsync(tab);
+ var searchTab = (PublicSearchTabModel)tab;
+ if (string.IsNullOrEmpty(searchTab.SearchWords)) return;
+ await this.GetPublicSearchAsync(searchTab);
break;
case MyCommon.TabUsageType.UserTimeline:
- await this.GetUserTimelineAsync(tab);
+ await this.GetUserTimelineAsync((UserTimelineTabModel)tab);
break;
case MyCommon.TabUsageType.Lists:
- //// TODO
- if (tab.ListInfo == null || tab.ListInfo.Id == 0) return;
- await this.GetListTimelineAsync(tab);
+ var listTab = (ListTimelineTabModel)tab;
+ if (listTab.ListInfo == null || listTab.ListInfo.Id == 0) return;
+ await this.GetListTimelineAsync(listTab);
break;
default:
await this.GetHomeTimelineAsync();
//ページ指定をマイナス1に
if (_curTab != null)
{
- TabClass tab;
+ TabModel tab;
if (!this._statuses.Tabs.TryGetValue(this._curTab.Text, out tab))
return;
//// TODO
break;
case MyCommon.TabUsageType.PublicSearch:
- // TODO
- if (string.IsNullOrEmpty(tab.SearchWords)) return;
- await this.GetPublicSearchAsync(tab, loadMore: true);
+ var searchTab = (PublicSearchTabModel)tab;
+ if (string.IsNullOrEmpty(searchTab.SearchWords)) return;
+ await this.GetPublicSearchAsync(searchTab, loadMore: true);
break;
case MyCommon.TabUsageType.UserTimeline:
- await this.GetUserTimelineAsync(tab, loadMore: true);
+ await this.GetUserTimelineAsync((UserTimelineTabModel)tab, loadMore: true);
break;
case MyCommon.TabUsageType.Lists:
- //// TODO
- if (tab.ListInfo == null || tab.ListInfo.Id == 0) return;
- await this.GetListTimelineAsync(tab, loadMore: true);
+ var listTab = (ListTimelineTabModel)tab;
+ if (listTab.ListInfo == null || listTab.ListInfo.Id == 0) return;
+ await this.GetListTimelineAsync(listTab, loadMore: true);
break;
default:
await this.GetHomeTimelineAsync(loadMore: true);
foreach (TabPage tab in ListTab.TabPages)
{
DetailsListView lst = (DetailsListView)tab.Tag;
- TabClass tabInfo = _statuses.Tabs[tab.Text];
+ TabModel tabInfo = _statuses.Tabs[tab.Text];
using (ControlTransaction.Update(lst))
{
// 選択位置などを復元
public void AddNewTabForSearch(string searchWord)
{
//同一検索条件のタブが既に存在すれば、そのタブアクティブにして終了
- foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch))
+ foreach (var tb in _statuses.GetTabsByType<PublicSearchTabModel>())
{
if (tb.SearchWords == searchWord && string.IsNullOrEmpty(tb.SearchLang))
{
break;
}
//タブ追加
- _statuses.AddTab(tabName, MyCommon.TabUsageType.PublicSearch, null);
- AddNewTab(tabName, false, MyCommon.TabUsageType.PublicSearch);
+ var tab = new PublicSearchTabModel(tabName);
+ _statuses.AddTab(tab);
+ AddNewTab(tab, startup: false);
//追加したタブをアクティブに
ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
//検索条件の設定
public void AddNewTabForUserTimeline(string user)
{
//同一検索条件のタブが既に存在すれば、そのタブアクティブにして終了
- foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.UserTimeline))
+ foreach (var tb in _statuses.GetTabsByType<UserTimelineTabModel>())
{
- if (tb.User == user)
+ if (tb.ScreenName == user)
{
foreach (TabPage tp in ListTab.TabPages)
{
tabName += "_";
}
//タブ追加
- var tab = new TabClass(tabName, MyCommon.TabUsageType.UserTimeline);
+ var tab = new UserTimelineTabModel(tabName, user);
this._statuses.AddTab(tab);
- tab.User = user;
- AddNewTab(tabName, false, MyCommon.TabUsageType.UserTimeline);
+ this.AddNewTab(tab, startup: false);
//追加したタブをアクティブに
ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
SaveConfigsTabs();
this.GetUserTimelineAsync(tab);
}
- public bool AddNewTab(string tabName, bool startup, MyCommon.TabUsageType tabType, ListElement listInfo = null)
+ public bool AddNewTab(TabModel tab, bool startup)
{
//重複チェック
foreach (TabPage tb in ListTab.TabPages)
{
- if (tb.Text == tabName) return false;
+ if (tb.Text == tab.TabName) return false;
}
//新規タブ名チェック
- if (tabName == Properties.Resources.AddNewTabText1) return false;
+ if (tab.TabName == Properties.Resources.AddNewTabText1) return false;
//タブタイプ重複チェック
if (!startup)
{
- if (tabType == MyCommon.TabUsageType.DirectMessage ||
- tabType == MyCommon.TabUsageType.Favorites ||
- tabType == MyCommon.TabUsageType.Home ||
- tabType == MyCommon.TabUsageType.Mentions ||
- tabType == MyCommon.TabUsageType.Related)
+ if (tab.IsDefaultTabType || tab.TabType == MyCommon.TabUsageType.Related)
{
- if (_statuses.GetTabByType(tabType) != null) return false;
+ if (_statuses.GetTabByType(tab.TabType) != null) return false;
}
}
_tabPage.Controls.Add(_listCustom);
/// UserTimeline関連
- if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists)
+ var userTab = tab as UserTimelineTabModel;
+ var listTab = tab as ListTimelineTabModel;
+ var searchTab = tab as PublicSearchTabModel;
+
+ if (userTab != null || listTab != null)
{
var label = new Label();
label.Dock = DockStyle.Top;
label.Name = "labelUser";
label.TabIndex = 0;
- if (tabType == MyCommon.TabUsageType.Lists)
+
+ if (listTab != null)
{
- label.Text = listInfo.ToString();
+ label.Text = listTab.ListInfo.ToString();
}
- else
+ else if (userTab != null)
{
- label.Text = _statuses.Tabs[tabName].User + "'s Timeline";
+ label.Text = userTab.ScreenName + "'s Timeline";
}
label.TextAlign = ContentAlignment.MiddleLeft;
using (ComboBox tmpComboBox = new ComboBox())
_tabPage.Controls.Add(label);
}
/// 検索関連の準備
- else if (tabType == MyCommon.TabUsageType.PublicSearch)
+ else if (searchTab != null)
{
var pnl = new Panel();
btn.TabIndex = 3;
btn.Click += SearchButton_Click;
- TabClass tab;
- if (_statuses.Tabs.TryGetValue(tabName, out tab))
+ if (!string.IsNullOrEmpty(searchTab.SearchWords))
{
- if (!string.IsNullOrEmpty(tab.SearchWords))
- {
- cmb.Items.Add(tab.SearchWords);
- cmb.Text = tab.SearchWords;
- }
-
- cmbLang.Text = tab.SearchLang;
+ cmb.Items.Add(searchTab.SearchWords);
+ cmb.Text = searchTab.SearchWords;
}
+ cmbLang.Text = searchTab.SearchLang;
+
_tabPage.Controls.Add(pnl);
}
}
_tabPage.Name = "CTab" + cnt.ToString();
_tabPage.Size = new Size(380, 260);
_tabPage.TabIndex = 2 + cnt;
- _tabPage.Text = tabName;
+ _tabPage.Text = tab.TabName;
_tabPage.UseVisualStyleBackColor = true;
_tabPage.AccessibleRole = AccessibleRole.PageTab;
MessageBox.Show(this, ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
- var resultTab = new TabClass(tabName, MyCommon.TabUsageType.SearchResults);
- this.AddNewTab(tabName, false, MyCommon.TabUsageType.SearchResults);
+ var resultTab = new LocalSearchTabModel(tabName);
+ this.AddNewTab(resultTab, startup: false);
this._statuses.AddTab(resultTab);
var targetTab = this._statuses.Tabs[this._curTab.Text];
var foundPosts = foundIndices.Select(x => targetTab[x]);
foreach (var post in foundPosts)
{
- resultTab.AddPostToInnerStorage(post);
+ resultTab.AddPostQueue(post);
}
this._statuses.DistributePosts();
{
if (_curPost == null) return;
- TabClass curTabClass = _statuses.Tabs[_curTab.Text];
+ TabModel curTabClass = _statuses.Tabs[_curTab.Text];
if (curTabClass.TabType == MyCommon.TabUsageType.PublicSearch && _curPost.InReplyToStatusId == null && _curPost.TextFromApi.Contains("@"))
{
{
if (_curPost == null) return;
- TabClass curTabClass = _statuses.Tabs[_curTab.Text];
+ TabModel curTabClass = _statuses.Tabs[_curTab.Text];
//Dictionary<long, PostClass> curTabPosts = curTabClass.Posts;
if (parallel)
Protected = tab.Protected,
Notify = tab.Notify,
SoundFile = tab.SoundFile,
- FilterArray = tab.FilterArray,
- User = tab.User,
- SearchWords = tab.SearchWords,
- SearchLang = tab.SearchLang,
- ListInfo = tab.ListInfo,
};
+
+ var filterTab = tab as FilterTabModel;
+ if (filterTab != null)
+ tabSetting.FilterArray = filterTab.FilterArray;
+
+ var userTab = tab as UserTimelineTabModel;
+ if (userTab != null)
+ tabSetting.User = userTab.ScreenName;
+
+ var searchTab = tab as PublicSearchTabModel;
+ if (searchTab != null)
+ {
+ tabSetting.SearchWords = searchTab.SearchWords;
+ tabSetting.SearchLang = searchTab.SearchLang;
+ }
+
+ var listTab = tab as ListTimelineTabModel;
+ if (listTab != null)
+ tabSetting.ListInfo = listTab.ListInfo;
+
tabsSetting.Tabs.Add(tabSetting);
}
return;
}
- TabClass tb = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
+ TabModel tb = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
if (this._cfgCommon.ReplyIconState != MyCommon.REPLY_ICONSTATE.None && tb != null && tb.UnreadCount > 0)
{
if (blinkCnt > 0) return;
if (_statuses == null) return;
if (_statuses.Tabs == null) return;
- TabClass tb = _statuses.Tabs[_rclickTabName];
+ TabModel tb = _statuses.Tabs[_rclickTabName];
if (tb == null) return;
NotifyDispMenuItem.Checked = tb.Notify;
list = listAvail.SelectedList;
}
}
- if (!_statuses.AddTab(tabName, tabUsage, list) || !AddNewTab(tabName, false, tabUsage, list))
+
+ TabModel tab;
+ switch (tabUsage)
+ {
+ case MyCommon.TabUsageType.UserDefined:
+ tab = new FilterTabModel(tabName);
+ break;
+ case MyCommon.TabUsageType.PublicSearch:
+ tab = new PublicSearchTabModel(tabName);
+ break;
+ case MyCommon.TabUsageType.Lists:
+ tab = new ListTimelineTabModel(tabName, list);
+ break;
+ default:
+ return;
+ }
+
+ if (!_statuses.AddTab(tab) || !AddNewTab(tab, startup: false))
{
string tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
MessageBox.Show(tmp, Properties.Resources.AddTabMenuItem_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
if (tabUsage == MyCommon.TabUsageType.Lists)
{
ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
- var tab = this._statuses.Tabs[this._curTab.Text];
- this.GetListTimelineAsync(tab);
+ var listTab = (ListTimelineTabModel)this._statuses.Tabs[this._curTab.Text];
+ this.GetListTimelineAsync(listTab);
}
}
}
//タブ選択(or追加)
if (!SelectTab(out tabName)) return;
- var tab = this._statuses.Tabs[tabName];
+ var tab = (FilterTabModel)this._statuses.Tabs[tabName];
bool mv;
bool mk;
return;
var currentTab = this._statuses.Tabs[this._curTab.Text];
- var filterTab = this._statuses.Tabs[tabName];
+ var filterTab = (FilterTabModel)this._statuses.Tabs[tabName];
bool mv;
bool mk;
this.TopMost = this._cfgCommon.AlwaysTop;
if (!string.IsNullOrEmpty(tabName))
{
- if (!_statuses.AddTab(tabName, MyCommon.TabUsageType.UserDefined, null) || !AddNewTab(tabName, false, MyCommon.TabUsageType.UserDefined))
+ var tab = new FilterTabModel(tabName);
+ if (!_statuses.AddTab(tab) || !AddNewTab(tab, startup: false))
{
string tmp = string.Format(Properties.Resources.IDRuleMenuItem_ClickText2, tabName);
MessageBox.Show(tmp, Properties.Resources.IDRuleMenuItem_ClickText3, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
//ステータス欄にカウント表示
//タブ未読数/タブ発言数 全未読数/総発言数 (未読@+未読DM数)
if (_statuses == null) return "";
- TabClass tbRep = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
- TabClass tbDm = _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage);
+ TabModel tbRep = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
+ TabModel tbDm = _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage);
if (tbRep == null || tbDm == null) return "";
int urat = tbRep.UnreadCount + tbDm.UnreadCount;
int ur = 0;
}
else
{
- foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.PublicSearch))
+ foreach (TabModel tb in _statuses.GetTabsByType(MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.PublicSearch))
{
if (tb == null || !tb.Contains(_curPost.InReplyToStatusId.Value)) break;
PostClass repPost = _statuses[_curPost.InReplyToStatusId.Value];
Control pnl = ((Control)sender).Parent;
if (pnl == null) return;
string tbName = pnl.Parent.Text;
- TabClass tb = _statuses.Tabs[tbName];
+ var tb = (PublicSearchTabModel)_statuses.Tabs[tbName];
ComboBox cmb = (ComboBox)pnl.Controls["comboSearch"];
ComboBox cmbLang = (ComboBox)pnl.Controls["comboLang"];
cmb.Text = cmb.Text.Trim();
var listView = (DetailsListView)pnl.Parent.Tag;
+ var queryChanged = tb.SearchWords != cmb.Text || tb.SearchLang != cmbLang.Text;
+
tb.SearchWords = cmb.Text;
tb.SearchLang = cmbLang.Text;
if (string.IsNullOrEmpty(cmb.Text))
SaveConfigsTabs();
return;
}
- if (tb.IsSearchQueryChanged)
+ if (queryChanged)
{
int idx = cmb.Items.IndexOf(tb.SearchWords);
if (idx > -1) cmb.Items.RemoveAt(idx);
{
DetailsListView listView = null;
- TabClass tb = _statuses.RemovedTab.Pop();
+ TabModel tb = _statuses.RemovedTab.Pop();
if (tb.TabType == MyCommon.TabUsageType.Related)
{
var relatedTab = _statuses.GetTabByType(MyCommon.TabUsageType.Related);
renamed = TabName + i.ToString();
}
tb.TabName = renamed;
- AddNewTab(renamed, false, tb.TabType, tb.ListInfo);
- _statuses.Tabs.Add(renamed, tb); // 後に
+
+ _statuses.AddTab(tb);
+ AddNewTab(tb, startup: false);
var tabPage = ListTab.TabPages[ListTab.TabPages.Count - 1];
listView = (DetailsListView)tabPage.Tag;
renamed = tb.TabName + "(" + i.ToString() + ")";
}
tb.TabName = renamed;
- _statuses.Tabs.Add(renamed, tb); // 先に
- AddNewTab(renamed, false, tb.TabType, tb.ListInfo);
+
+ _statuses.AddTab(tb);
+ AddNewTab(tb, startup: false);
var tabPage = ListTab.TabPages[ListTab.TabPages.Count - 1];
listView = (DetailsListView)tabPage.Tag;
//タブ選択(or追加)
if (!SelectTab(out tabName)) return;
- var tab = this._statuses.Tabs[tabName];
+ var tab = (FilterTabModel)this._statuses.Tabs[tabName];
bool mv;
bool mk;
/// <exception cref="TabException">名前の重複が多すぎてタブを作成できない場合</exception>
private async Task OpenRelatedTab(PostClass post)
{
- var tabRelated = this._statuses.GetTabByType(MyCommon.TabUsageType.Related);
- string tabName;
-
- if (tabRelated == null)
+ var tabRelated = this._statuses.GetTabByType<RelatedPostsTabModel>();
+ if (tabRelated != null)
{
- tabName = this._statuses.MakeTabName("Related Tweets");
+ this.RemoveSpecifiedTab(tabRelated.TabName, confirm: false);
+ }
- tabRelated = new TabClass(tabName, MyCommon.TabUsageType.Related);
- tabRelated.UnreadManage = false;
- tabRelated.Notify = false;
+ var tabName = this._statuses.MakeTabName("Related Tweets");
- this.AddNewTab(tabName, false, MyCommon.TabUsageType.Related);
- this._statuses.AddTab(tabRelated);
- }
- else
- {
- tabName = tabRelated.TabName;
- }
+ tabRelated = new RelatedPostsTabModel(tabName, post);
+ tabRelated.UnreadManage = false;
+ tabRelated.Notify = false;
- tabRelated.RelationTargetPost = post;
- this.ClearTab(tabName, false);
+ this._statuses.AddTab(tabRelated);
+ this.AddNewTab(tabRelated, startup: false);
for (int i = 0; i < this.ListTab.TabPages.Count; i++)
{
}
}
- public async Task GetUserTimelineApi(bool read, string userName, TabClass tab, bool more)
+ public async Task GetUserTimelineApi(bool read, string userName, UserTimelineTabModel tab, bool more)
{
this.CheckAccountState();
TwitterStatus[] statuses;
if (string.IsNullOrEmpty(userName))
{
- var target = tab.User;
+ var target = tab.ScreenName;
if (string.IsNullOrEmpty(target)) return;
userName = target;
statuses = await this.Api.StatusesUserTimeline(userName, count)
return item;
}
- public async Task GetStatusApi(bool read, long id, TabClass tab)
+ public async Task GetStatusApi(bool read, long id, TabModel tab)
{
var post = await this.GetStatusApi(read, id)
.ConfigureAwait(false);
//非同期アイコン取得&StatusDictionaryに追加
if (tab != null && tab.IsInnerStorageTabType)
- tab.AddPostToInnerStorage(post);
+ tab.AddPostQueue(post);
else
TabInformations.GetInstance().AddPost(post);
}
}
}
- private long? CreatePostsFromJson(TwitterStatus[] items, MyCommon.WORKERTYPE gType, TabClass tab, bool read)
+ private long? CreatePostsFromJson(TwitterStatus[] items, MyCommon.WORKERTYPE gType, TabModel tab, bool read)
{
long? minimumId = null;
//非同期アイコン取得&StatusDictionaryに追加
if (tab != null && tab.IsInnerStorageTabType)
- tab.AddPostToInnerStorage(post);
+ tab.AddPostQueue(post);
else
TabInformations.GetInstance().AddPost(post);
}
return minimumId;
}
- private long? CreatePostsFromSearchJson(TwitterSearchResult items, TabClass tab, bool read, int count, bool more)
+ private long? CreatePostsFromSearchJson(TwitterSearchResult items, TabModel tab, bool read, int count, bool more)
{
long? minimumId = null;
//非同期アイコン取得&StatusDictionaryに追加
if (tab != null && tab.IsInnerStorageTabType)
- tab.AddPostToInnerStorage(post);
+ tab.AddPostQueue(post);
else
TabInformations.GetInstance().AddPost(post);
}
}
}
- public async Task GetListStatus(bool read, TabClass tab, bool more, bool startup)
+ public async Task GetListStatus(bool read, ListTimelineTabModel tab, bool more, bool startup)
{
var count = GetApiResultCount(MyCommon.WORKERTYPE.List, more, startup);
return nextPost;
}
- public async Task GetRelatedResult(bool read, TabClass tab)
+ public async Task GetRelatedResult(bool read, RelatedPostsTabModel tab)
{
+ var targetPost = tab.TargetPost;
var relPosts = new Dictionary<Int64, PostClass>();
- if (tab.RelationTargetPost.TextFromApi.Contains("@") && tab.RelationTargetPost.InReplyToStatusId == null)
+ if (targetPost.TextFromApi.Contains("@") && targetPost.InReplyToStatusId == null)
{
//検索結果対応
- var p = TabInformations.GetInstance()[tab.RelationTargetPost.StatusId];
+ var p = TabInformations.GetInstance()[targetPost.StatusId];
if (p != null && p.InReplyToStatusId != null)
{
- tab.RelationTargetPost = p;
+ targetPost = p;
}
else
{
- p = await this.GetStatusApi(read, tab.RelationTargetPost.StatusId)
+ p = await this.GetStatusApi(read, targetPost.StatusId)
.ConfigureAwait(false);
- tab.RelationTargetPost = p;
+ targetPost = p;
}
}
- relPosts.Add(tab.RelationTargetPost.StatusId, tab.RelationTargetPost);
+ relPosts.Add(targetPost.StatusId, targetPost);
Exception lastException = null;
// in_reply_to_status_id を使用してリプライチェインを辿る
- var nextPost = FindTopOfReplyChain(relPosts, tab.RelationTargetPost.StatusId);
+ var nextPost = FindTopOfReplyChain(relPosts, targetPost.StatusId);
var loopCount = 1;
while (nextPost.InReplyToStatusId != null && loopCount++ <= 20)
{
}
//MRTとかに対応のためツイート内にあるツイートを指すURLを取り込む
- var text = tab.RelationTargetPost.Text;
+ var text = targetPost.Text;
var ma = Twitter.StatusUrlRegex.Matches(text).Cast<Match>()
.Concat(Twitter.ThirdPartyStatusUrlRegex.Matches(text).Cast<Match>());
foreach (var _match in ma)
else
p.IsRead = read;
- tab.AddPostToInnerStorage(p);
+ tab.AddPostQueue(p);
});
if (lastException != null)
throw new WebApiException(lastException.Message, lastException);
}
- public async Task GetSearch(bool read, TabClass tab, bool more)
+ public async Task GetSearch(bool read, PublicSearchTabModel tab, bool more)
{
var count = GetApiResultCount(MyCommon.WORKERTYPE.PublicSearch, more, false);
post.IsDm = true;
var dmTab = TabInformations.GetInstance().GetTabByType(MyCommon.TabUsageType.DirectMessage);
- dmTab.AddPostToInnerStorage(post);
+ dmTab.AddPostQueue(post);
}
}