1 ' Tween - Client of Twitter
2 ' Copyright (c) 2007-2010 kiri_feather (@kiri_feather) <kiri_feather@gmail.com>
3 ' (c) 2008-2010 Moz (@syo68k) <http://iddy.jp/profile/moz/>
4 ' (c) 2008-2010 takeshik (@takeshik) <http://www.takeshik.org/>
7 ' This file is part of Tween.
9 ' This program is free software; you can redistribute it and/or modify it
10 ' under the terms of the GNU General Public License as published by the Free
11 ' Software Foundation; either version 3 of the License, or (at your option)
14 ' This program is distributed in the hope that it will be useful, but
15 ' WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 ' or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 ' You should have received a copy of the GNU General Public License along
20 ' with this program. If not, see <http://www.gnu.org/licenses/>, or write to
21 ' the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
22 ' Boston, MA 02110-1301, USA.
24 Imports System.Collections.Generic
25 Imports System.Collections.ObjectModel
26 Imports Tween.TweenCustomControl
27 Imports System.Text.RegularExpressions
28 Imports System.Web.HttpUtility
30 Public NotInheritable Class PostClass
31 Private _Nick As String
32 Private _Data As String
33 Private _ImageUrl As String
34 Private _Name As String
35 Private _PDate As Date
37 Private _IsFav As Boolean
38 Private _OrgData As String
39 Private _IsRead As Boolean
40 Private _IsReply As Boolean
41 Private _IsProtect As Boolean
42 Private _IsOWL As Boolean
43 Private _IsMark As Boolean
44 Private _InReplyToUser As String
45 Private _InReplyToId As Long
46 Private _Source As String
47 Private _ReplyToList As New List(Of String)
48 Private _IsMe As Boolean
49 Private _ImageIndex As Integer
50 Private _IsDm As Boolean
51 Private _statuses As Statuses = Statuses.None
53 Private _FilterHit As Boolean
54 Private _RetweetedBy As String = ""
55 Private _RetweetedId As Long = 0
56 Private _searchTabName As String = ""
67 Public Sub New(ByVal Nickname As String, _
68 ByVal Data As String, _
69 ByVal OriginalData As String, _
70 ByVal ImageUrl As String, _
71 ByVal Name As String, _
72 ByVal PDate As Date, _
74 ByVal IsFav As Boolean, _
75 ByVal IsRead As Boolean, _
76 ByVal IsReply As Boolean, _
77 ByVal IsProtect As Boolean, _
78 ByVal IsOwl As Boolean, _
79 ByVal IsMark As Boolean, _
80 ByVal InReplyToUser As String, _
81 ByVal InReplyToId As Long, _
82 ByVal Source As String, _
83 ByVal ReplyToList As List(Of String), _
84 ByVal IsMe As Boolean, _
85 ByVal ImageIndex As Integer, _
86 ByVal IsDm As Boolean, _
88 ByVal FilterHit As Boolean, _
89 ByVal RetweetedBy As String, _
90 ByVal RetweetedId As Long)
98 _OrgData = OriginalData
101 _IsProtect = IsProtect
104 _InReplyToUser = InReplyToUser
105 _InReplyToId = InReplyToId
107 _ReplyToList = ReplyToList
109 _ImageIndex = ImageIndex
112 _FilterHit = FilterHit
113 _RetweetedBy = RetweetedBy
114 _RetweetedId = RetweetedId
120 Public Property Nickname() As String
124 Set(ByVal value As String)
128 Public Property Data() As String
132 Set(ByVal value As String)
136 Public Property ImageUrl() As String
140 Set(ByVal value As String)
144 Public Property Name() As String
148 Set(ByVal value As String)
152 Public Property PDate() As Date
156 Set(ByVal value As Date)
160 Public Property Id() As Long
164 Set(ByVal value As Long)
168 Public Property IsFav() As Boolean
170 If Me.RetweetedId > 0 AndAlso TabInformations.GetInstance.RetweetSource(Me.RetweetedId) IsNot Nothing Then
171 Return TabInformations.GetInstance.RetweetSource(Me.RetweetedId).IsFav
176 Set(ByVal value As Boolean)
178 If Me.RetweetedId > 0 AndAlso TabInformations.GetInstance.RetweetSource(Me.RetweetedId) IsNot Nothing Then
179 TabInformations.GetInstance.RetweetSource(Me.RetweetedId).IsFav = value
183 Public Property OriginalData() As String
187 Set(ByVal value As String)
191 Public Property IsRead() As Boolean
195 Set(ByVal value As Boolean)
197 _statuses = _statuses Or Statuses.Read
199 _statuses = _statuses And Not Statuses.Read
204 Public Property IsReply() As Boolean
208 Set(ByVal value As Boolean)
212 Public Property IsProtect() As Boolean
216 Set(ByVal value As Boolean)
218 _statuses = _statuses Or Statuses.Protect
220 _statuses = _statuses And Not Statuses.Protect
225 Public Property IsOwl() As Boolean
229 Set(ByVal value As Boolean)
233 Public Property IsMark() As Boolean
237 Set(ByVal value As Boolean)
239 _statuses = _statuses Or Statuses.Mark
241 _statuses = _statuses And Not Statuses.Mark
246 Public Property InReplyToUser() As String
248 Return _InReplyToUser
250 Set(ByVal value As String)
251 _InReplyToUser = value
254 Public Property InReplyToId() As Long
258 Set(ByVal value As Long)
262 Public Property Source() As String
266 Set(ByVal value As String)
270 Public Property ReplyToList() As List(Of String)
274 Set(ByVal value As List(Of String))
278 Public Property IsMe() As Boolean
282 Set(ByVal value As Boolean)
286 Public Property ImageIndex() As Integer
290 Set(ByVal value As Integer)
294 Public Property IsDm() As Boolean
298 Set(ByVal value As Boolean)
302 Public ReadOnly Property StatusIndex() As Integer
307 Public Property Uid() As Long
311 Set(ByVal value As Long)
315 Public Property FilterHit() As Boolean
319 Set(ByVal value As Boolean)
323 Public Property RetweetedBy() As String
327 Set(ByVal value As String)
331 Public Property RetweetedId() As Long
335 Set(ByVal value As Long)
339 Public Property RelTabName() As String
341 Return _searchTabName
343 Set(ByVal value As String)
344 _searchTabName = value
349 Public NotInheritable Class TabInformations
350 '個別タブの情報をDictionaryで保持
351 Private _sorter As IdComparerClass
352 Private _tabs As New Dictionary(Of String, TabClass)
353 Private _statuses As New Dictionary(Of Long, PostClass)
354 Private _addedIds As List(Of Long)
355 Private _retweets As New Dictionary(Of Long, PostClass)
356 Private _removedTab As TabClass = Nothing
359 'AddPost(複数回) -> DistributePosts -> SubmitUpdate
362 Private _addCount As Integer
363 Private _soundFile As String
364 Private _notifyPosts As List(Of PostClass)
365 Private ReadOnly LockObj As New Object
366 Private ReadOnly LockUnread As New Object
368 Private Shared _instance As TabInformations = New TabInformations
371 Private _lists As New List(Of ListElement)
374 _sorter = New IdComparerClass()
377 Public Shared Function GetInstance() As TabInformations
378 Return _instance 'singleton
381 Public Property SubscribableLists() As List(Of ListElement)
385 Set(ByVal value As List(Of ListElement))
386 If value IsNot Nothing AndAlso value.Count > 0 Then
387 For Each tb As TabClass In Me.GetTabsByType(TabUsageType.Lists)
388 For Each list As ListElement In value
389 If tb.ListInfo.Id = list.Id Then
400 Public Sub AddTab(ByVal TabName As String, ByVal TabType As TabUsageType, ByVal List As ListElement)
401 _tabs.Add(TabName, New TabClass(TabName, TabType, List))
402 _tabs(TabName).Sorter.Mode = _sorter.Mode
403 _tabs(TabName).Sorter.Order = _sorter.Order
406 'Public Sub AddTab(ByVal TabName As String, ByVal Tab As TabClass)
407 ' _tabs.Add(TabName, Tab)
410 Public Sub RemoveTab(ByVal TabName As String)
412 If IsDefaultTab(TabName) Then Exit Sub '念のため
413 If _tabs(TabName).TabType <> TabUsageType.PublicSearch AndAlso _tabs(TabName).TabType <> TabUsageType.Lists Then
414 Dim homeTab As TabClass = GetTabByType(TabUsageType.Home)
415 Dim dmName As String = GetTabByType(TabUsageType.DirectMessage).TabName
417 For idx As Integer = 0 To _tabs(TabName).AllCount - 1
418 Dim exist As Boolean = False
419 Dim Id As Long = _tabs(TabName).GetId(idx)
420 For Each key As String In _tabs.Keys
421 If Not key = TabName AndAlso key <> dmName Then
422 If _tabs(key).Contains(Id) Then
428 If Not exist Then homeTab.Add(Id, _statuses(Id).IsRead, False)
431 If _removedTab IsNot Nothing Then _removedTab = Nothing
432 _removedTab = _tabs(TabName)
433 _tabs.Remove(TabName)
437 Public Property RemovedTab() As TabClass
441 Set(ByVal value As TabClass)
446 Public Function ContainsTab(ByVal TabText As String) As Boolean
447 Return _tabs.ContainsKey(TabText)
450 Public Function ContainsTab(ByVal ts As TabClass) As Boolean
451 Return _tabs.ContainsValue(ts)
454 Public Property Tabs() As Dictionary(Of String, TabClass)
458 Set(ByVal value As Dictionary(Of String, TabClass))
463 Public ReadOnly Property KeysTab() As Collections.Generic.Dictionary(Of String, TabClass).KeyCollection
469 Public Sub SortPosts()
470 For Each key As String In _tabs.Keys
475 Public Property SortOrder() As SortOrder
479 Set(ByVal value As SortOrder)
480 _sorter.Order = value
481 For Each key As String In _tabs.Keys
482 _tabs(key).Sorter.Order = value
487 Public Property SortMode() As IdComparerClass.ComparerMode
491 Set(ByVal value As IdComparerClass.ComparerMode)
493 For Each key As String In _tabs.Keys
494 _tabs(key).Sorter.Mode = value
499 Public Sub ToggleSortOrder(ByVal SortMode As IdComparerClass.ComparerMode)
500 If _sorter.Mode = SortMode Then
501 If _sorter.Order = Windows.Forms.SortOrder.Ascending Then
502 _sorter.Order = Windows.Forms.SortOrder.Descending
504 _sorter.Order = Windows.Forms.SortOrder.Ascending
506 For Each key As String In _tabs.Keys
507 _tabs(key).Sorter.Order = _sorter.Order
510 _sorter.Mode = SortMode
511 _sorter.Order = Windows.Forms.SortOrder.Ascending
512 For Each key As String In _tabs.Keys
513 _tabs(key).Sorter.Mode = SortMode
514 _tabs(key).Sorter.Order = Windows.Forms.SortOrder.Ascending
520 Public ReadOnly Property RetweetSource(ByVal Id As Long) As PostClass
522 If _retweets.ContainsKey(Id) Then
530 Public Sub RemoveFavPost(ByVal Id As Long)
532 Dim post As PostClass = Nothing
533 Dim tab As TabClass = Me.GetTabByType(TabUsageType.Favorites)
534 Dim tn As String = tab.TabName
535 If _statuses.ContainsKey(Id) Then
538 Dim tType As TabUsageType = tab.TabType
539 If tab.Contains(Id) Then
540 If tab.UnreadManage AndAlso Not post.IsRead Then '未読管理
543 Me.SetNextUnreadId(Id, tab)
548 'FavタブからRetweet発言を削除する場合は、他の同一参照Retweetも削除
549 If tType = TabUsageType.Favorites AndAlso post.RetweetedId > 0 Then
550 For i As Integer = 0 To tab.AllCount - 1
551 Dim rPost As PostClass = Me.Item(tn, i)
552 If rPost.RetweetedId > 0 AndAlso rPost.RetweetedId = post.RetweetedId Then
553 If tab.UnreadManage AndAlso Not rPost.IsRead Then '未読管理
556 Me.SetNextUnreadId(rPost.Id, tab)
564 ''TabType=PublicSearchの場合(Postの保存先がTabClass内)
565 'If tab.Contains(Id) AndAlso _
566 ' (tab.TabType = TabUsageType.PublicSearch OrElse tab.TabType = TabUsageType.DirectMessage) Then
567 ' post = tab.Posts(Id)
568 ' If tab.UnreadManage AndAlso Not post.IsRead Then '未読管理
569 ' SyncLock LockUnread
570 ' tab.UnreadCount -= 1
571 ' Me.SetNextUnreadId(Id, tab)
579 Public Sub RemovePost(ByVal Id As Long)
581 Dim post As PostClass = Nothing
582 If _statuses.ContainsKey(Id) Then
585 For Each key As String In _tabs.Keys
586 Dim tab As TabClass = _tabs(key)
587 If tab.Contains(Id) Then
588 If tab.UnreadManage AndAlso Not post.IsRead Then '未読管理
591 Me.SetNextUnreadId(Id, tab)
599 For Each tb As TabClass In _tabs.Values
600 If (tb.TabType = TabUsageType.PublicSearch OrElse tb.TabType = TabUsageType.DirectMessage OrElse tb.TabType = TabUsageType.Lists) _
601 AndAlso tb.Contains(Id) Then
603 If tb.UnreadManage AndAlso Not post.IsRead Then
606 Me.SetNextUnreadId(Id, tb)
615 Public Function GetOldestUnreadId(ByVal TabName As String) As Integer
616 Dim tb As TabClass = _tabs(TabName)
617 If tb.OldestUnreadId > -1 AndAlso _
618 tb.Contains(tb.OldestUnreadId) AndAlso _
619 tb.UnreadCount > 0 Then
621 Dim isRead As Boolean
622 If tb.TabType <> TabUsageType.PublicSearch AndAlso tb.TabType <> TabUsageType.DirectMessage AndAlso tb.TabType <> TabUsageType.Lists Then
623 isRead = _statuses(tb.OldestUnreadId).IsRead
625 isRead = tb.Posts(tb.OldestUnreadId).IsRead
630 Me.SetNextUnreadId(-1, tb) '頭から探索
632 If tb.OldestUnreadId = -1 Then
635 Return tb.IndexOf(tb.OldestUnreadId)
638 Return tb.IndexOf(tb.OldestUnreadId) '最短経路
641 '一見未読なさそうだが、未読カウントはあるので探索
642 If tb.UnreadCount > 0 Then
644 Me.SetNextUnreadId(-1, tb)
646 If tb.OldestUnreadId = -1 Then
649 Return tb.IndexOf(tb.OldestUnreadId)
657 Private Sub SetNextUnreadId(ByVal CurrentId As Long, ByVal Tab As TabClass)
658 'CurrentID:今既読にしたID(OldestIDの可能性あり)
659 '最古未読が設定されていて、既読の場合(1発言以上存在)
661 Dim posts As Dictionary(Of Long, PostClass)
662 If Tab.TabType <> TabUsageType.PublicSearch AndAlso Tab.TabType <> TabUsageType.DirectMessage AndAlso Tab.TabType <> TabUsageType.Lists Then
667 If Tab.OldestUnreadId > -1 AndAlso _
668 posts.ContainsKey(Tab.OldestUnreadId) AndAlso _
669 posts.Item(Tab.OldestUnreadId).IsRead AndAlso _
670 _sorter.Mode = IdComparerClass.ComparerMode.Id Then '次の未読探索
671 If Tab.UnreadCount = 0 Then
673 Tab.OldestUnreadId = -1
674 ElseIf Tab.OldestUnreadId = CurrentId Then
675 '最古IDを既読にしたタイミング→次のIDから続けて探索
676 Dim idx As Integer = Tab.IndexOf(CurrentId)
679 FindUnreadId(idx, Tab)
682 FindUnreadId(-1, Tab)
686 FindUnreadId(-1, Tab)
690 FindUnreadId(-1, Tab)
692 Catch ex As Generic.KeyNotFoundException
694 FindUnreadId(-1, Tab)
698 Private Sub FindUnreadId(ByVal StartIdx As Integer, ByVal Tab As TabClass)
699 If Tab.AllCount = 0 Then
700 Tab.OldestUnreadId = -1
704 Dim toIdx As Integer = 0
705 Dim stp As Integer = 1
706 Tab.OldestUnreadId = -1
707 If _sorter.Order = Windows.Forms.SortOrder.Ascending Then
708 If StartIdx = -1 Then
712 If StartIdx > Tab.AllCount - 1 Then StartIdx = Tab.AllCount - 1 '念のため
714 toIdx = Tab.AllCount - 1
715 If toIdx < 0 Then toIdx = 0 '念のため
718 If StartIdx = -1 Then
719 StartIdx = Tab.AllCount - 1
723 If StartIdx < 0 Then StartIdx = 0 '念のため
727 If Tab.TabType <> TabUsageType.PublicSearch AndAlso Tab.TabType <> TabUsageType.DirectMessage AndAlso Tab.TabType <> TabUsageType.Lists Then
728 For i As Integer = StartIdx To toIdx Step stp
729 If Not _statuses(Tab.GetId(i)).IsRead Then
730 Tab.OldestUnreadId = Tab.GetId(i)
735 For i As Integer = StartIdx To toIdx Step stp
736 If Not Tab.Posts(Tab.GetId(i)).IsRead Then
737 Tab.OldestUnreadId = Tab.GetId(i)
744 Public Function DistributePosts() As Integer
747 'If _addedIds Is Nothing Then Return 0
748 'If _addedIds.Count = 0 Then Return 0
750 If _addedIds Is Nothing Then _addedIds = New List(Of Long)
751 If _notifyPosts Is Nothing Then _notifyPosts = New List(Of PostClass)
752 Me.Distribute() 'タブに仮振分
753 Dim retCnt As Integer = _addedIds.Count
756 _addedIds = Nothing '後始末
761 Public Function SubmitUpdate(ByRef soundFile As String, ByRef notifyPosts As PostClass()) As Integer
764 If _notifyPosts Is Nothing Then
766 notifyPosts = Nothing
770 For Each tb As TabClass In _tabs.Values
771 If tb.TabType = TabUsageType.PublicSearch OrElse tb.TabType = TabUsageType.DirectMessage OrElse tb.TabType = TabUsageType.Lists Then
772 _addCount += tb.GetTemporaryCount
774 tb.AddSubmit() '振分確定(各タブに反映)
778 soundFile = _soundFile
780 notifyPosts = _notifyPosts.ToArray()
782 _notifyPosts = Nothing
783 Dim retCnt As Integer = _addCount
785 Return retCnt '件数(EndUpdateの戻り値と同じ)
789 Private Sub Distribute()
790 '各タブのフィルターと照合。合致したらタブにID追加
791 '通知メッセージ用に、表示必要な発言リストと再生サウンドを返す
792 'notifyPosts = New List(Of PostClass)
793 Dim homeTab As TabClass = GetTabByType(TabUsageType.Home)
794 Dim replyTab As TabClass = GetTabByType(TabUsageType.Mentions)
795 Dim dmTab As TabClass = GetTabByType(TabUsageType.DirectMessage)
796 Dim favTab As TabClass = GetTabByType(TabUsageType.Favorites)
797 For Each id As Long In _addedIds
798 Dim post As PostClass = _statuses(id)
799 Dim add As Boolean = False '通知リスト追加フラグ
800 Dim mv As Boolean = False '移動フラグ(Recent追加有無)
801 For Each tn As String In _tabs.Keys
802 Dim rslt As HITRESULT = HITRESULT.None
803 rslt = _tabs(tn).AddFiltered(post)
804 If rslt <> HITRESULT.None Then
805 If rslt = HITRESULT.CopyAndMark Then post.IsMark = True 'マークあり
806 If rslt = HITRESULT.Move Then
810 If _tabs(tn).Notify Then add = True '通知あり
811 If Not _tabs(tn).SoundFile = "" AndAlso _soundFile = "" Then
812 _soundFile = _tabs(tn).SoundFile 'wavファイル(未設定の場合のみ)
814 post.FilterHit = True
816 post.FilterHit = False
819 If Not mv Then '移動されなかったらRecentに追加
820 homeTab.Add(post.Id, post.IsRead, True)
821 If Not homeTab.SoundFile = "" AndAlso _soundFile = "" Then _soundFile = homeTab.SoundFile
822 If homeTab.Notify Then add = True
824 If post.IsReply Then 'ReplyだったらReplyタブに追加
825 replyTab.Add(post.Id, post.IsRead, True)
826 If Not replyTab.SoundFile = "" Then _soundFile = replyTab.SoundFile
827 If replyTab.Notify Then add = True
829 If post.IsFav Then 'Fav済み発言だったらFavoritesタブに追加
830 If favTab.Contains(post.Id) Then
835 favTab.Add(post.Id, post.IsRead, True)
836 If Not favTab.SoundFile = "" AndAlso _soundFile = "" Then _soundFile = favTab.SoundFile
837 If favTab.Notify Then add = True
840 If add Then _notifyPosts.Add(post)
842 For Each tb As TabClass In _tabs.Values
843 If tb.TabType = TabUsageType.PublicSearch OrElse tb.TabType = TabUsageType.DirectMessage OrElse tb.TabType = TabUsageType.Lists Then
845 If tb.GetTemporaryCount > 0 Then
846 For Each post As PostClass In tb.GetTemporaryPosts
847 Dim exist As Boolean = False
848 For Each npost As PostClass In _notifyPosts
849 If npost.Id = post.Id Then
854 If Not exist Then _notifyPosts.Add(post)
856 If tb.SoundFile <> "" Then
857 If tb.TabType = TabUsageType.DirectMessage OrElse _soundFile = "" Then
858 _soundFile = tb.SoundFile
867 Public Sub AddPost(ByVal Item As PostClass)
869 If Item.RelTabName = "" Then
870 If Not Item.IsDm Then
871 If _statuses.ContainsKey(Item.Id) Then
873 _statuses.Item(Item.Id).IsFav = True
875 Exit Sub '追加済みなら何もしない
878 _statuses.Add(Item.Id, Item)
880 If Item.RetweetedId > 0 Then
883 If Item.IsFav AndAlso _retweets.ContainsKey(Item.Id) Then
884 Exit Sub 'Fav済みのRetweet元発言は追加しない
886 If _addedIds Is Nothing Then _addedIds = New List(Of Long) 'タブ追加用IDコレクション準備
887 _addedIds.Add(Item.Id)
890 Dim tb As TabClass = Me.GetTabByType(TabUsageType.DirectMessage)
891 If tb.Contains(Item.Id) Then Exit Sub
892 tb.AddPostToInnerStorage(Item)
897 If Me.Tabs.ContainsKey(Item.RelTabName) Then
898 tb = Me.Tabs(Item.RelTabName)
902 If tb Is Nothing Then Exit Sub
903 If tb.Contains(Item.Id) Then Exit Sub
904 'tb.Add(Item.Id, Item.IsRead, True)
905 tb.AddPostToInnerStorage(Item)
910 Private Sub AddRetweet(ByVal item As PostClass)
911 If _retweets.ContainsKey(item.RetweetedId) Then Exit Sub
929 item.InReplyToUser, _
944 Public Sub SetRead(ByVal Read As Boolean, ByVal TabName As String, ByVal Index As Integer)
945 'Read:True=既読へ False=未読へ
946 Dim tb As TabClass = _tabs(TabName)
948 If tb.UnreadManage = False Then Exit Sub '未読管理していなければ終了
950 Dim Id As Long = tb.GetId(Index)
951 Dim post As PostClass
952 If tb.TabType <> TabUsageType.PublicSearch AndAlso tb.TabType <> TabUsageType.DirectMessage AndAlso tb.TabType <> TabUsageType.Lists Then
957 If post.IsRead = Read Then Exit Sub '状態変更なければ終了
959 post.IsRead = Read '指定の状態に変更
964 Me.SetNextUnreadId(Id, tb) '次の未読セット
965 '他タブの最古未読IDはタブ切り替え時に。
966 If tb.TabType = TabUsageType.PublicSearch OrElse tb.TabType = TabUsageType.DirectMessage OrElse tb.TabType = TabUsageType.Lists Then Exit Sub
967 For Each key As String In _tabs.Keys
968 If key <> TabName AndAlso _
969 _tabs(key).UnreadManage AndAlso _
970 _tabs(key).Contains(Id) AndAlso _
971 (_tabs(key).TabType <> TabUsageType.PublicSearch AndAlso _tabs(key).TabType <> TabUsageType.DirectMessage AndAlso _tabs(key).TabType <> TabUsageType.Lists) Then
972 _tabs(key).UnreadCount -= 1
973 If _tabs(key).OldestUnreadId = Id Then _tabs(key).OldestUnreadId = -1
978 If tb.OldestUnreadId > Id OrElse tb.OldestUnreadId = -1 Then tb.OldestUnreadId = Id
979 If tb.TabType = TabUsageType.PublicSearch OrElse tb.TabType = TabUsageType.DirectMessage OrElse tb.TabType = TabUsageType.Lists Then Exit Sub
980 For Each key As String In _tabs.Keys
981 If Not key = TabName AndAlso _
982 _tabs(key).UnreadManage AndAlso _
983 _tabs(key).Contains(Id) AndAlso _
984 (_tabs(key).TabType <> TabUsageType.PublicSearch AndAlso _tabs(key).TabType <> TabUsageType.DirectMessage AndAlso _tabs(key).TabType <> TabUsageType.Lists) Then
985 _tabs(key).UnreadCount += 1
986 If _tabs(key).OldestUnreadId > Id Then _tabs(key).OldestUnreadId = Id
994 Dim tb As TabClass = GetTabByType(TabUsageType.Home)
995 If tb.UnreadManage = False Then Exit Sub
997 For i As Integer = 0 To tb.AllCount - 1
998 Dim id As Long = tb.GetId(i)
999 If Not _statuses(id).IsReply AndAlso _
1000 Not _statuses(id).IsRead AndAlso _
1001 Not _statuses(id).FilterHit Then
1002 _statuses(id).IsRead = True
1003 Me.SetNextUnreadId(id, tb) '次の未読セット
1004 For Each key As String In _tabs.Keys
1005 If _tabs(key).UnreadManage AndAlso _
1006 _tabs(key).Contains(id) Then
1007 _tabs(key).UnreadCount -= 1
1008 If _tabs(key).OldestUnreadId = id Then _tabs(key).OldestUnreadId = -1
1015 Public ReadOnly Property Item(ByVal ID As Long) As PostClass
1017 If _statuses.ContainsKey(ID) Then Return _statuses(ID)
1018 For Each tb As TabClass In _tabs.Values
1019 If (tb.TabType = TabUsageType.PublicSearch OrElse tb.TabType = TabUsageType.DirectMessage OrElse tb.TabType = TabUsageType.Lists) AndAlso _
1020 tb.Contains(ID) Then
1028 Public ReadOnly Property Item(ByVal TabName As String, ByVal Index As Integer) As PostClass
1030 'If Not _tabs.ContainsKey(TabName) Then Return Nothing
1031 If _tabs(TabName).TabType = TabUsageType.PublicSearch OrElse _tabs(TabName).TabType = TabUsageType.DirectMessage OrElse _tabs(TabName).TabType = TabUsageType.Lists Then
1032 Return _tabs(TabName).Posts(_tabs(TabName).GetId(Index))
1034 Return _statuses(_tabs(TabName).GetId(Index))
1039 Public ReadOnly Property Item(ByVal TabName As String, ByVal StartIndex As Integer, ByVal EndIndex As Integer) As PostClass()
1041 Dim length As Integer = EndIndex - StartIndex + 1
1042 Dim posts() As PostClass = New PostClass(length - 1) {}
1043 If _tabs(TabName).TabType = TabUsageType.PublicSearch OrElse _tabs(TabName).TabType = TabUsageType.DirectMessage OrElse _tabs(TabName).TabType = TabUsageType.Lists Then
1044 For i As Integer = 0 To length - 1
1045 posts(i) = _tabs(TabName).Posts(_tabs(TabName).GetId(StartIndex + i))
1048 For i As Integer = 0 To length - 1
1049 posts(i) = _statuses(_tabs(TabName).GetId(StartIndex + i))
1056 'Public ReadOnly Property ItemCount() As Integer
1059 ' Return _statuses.Count 'DM,公式検索は除く
1064 Public Function ContainsKey(ByVal Id As Long) As Boolean
1067 Return _statuses.ContainsKey(Id)
1071 Public Function ContainsKey(ByVal Id As Long, ByVal TabName As String) As Boolean
1074 Return _tabs(TabName).Contains(Id)
1078 Public Sub SetUnreadManage(ByVal Manage As Boolean)
1080 For Each key As String In _tabs.Keys
1081 Dim tb As TabClass = _tabs(key)
1082 If tb.UnreadManage Then
1084 Dim cnt As Integer = 0
1085 Dim oldest As Long = Long.MaxValue
1086 Dim posts As Dictionary(Of Long, PostClass)
1087 If tb.TabType <> TabUsageType.PublicSearch AndAlso tb.TabType <> TabUsageType.DirectMessage AndAlso tb.TabType <> TabUsageType.Lists Then
1092 For Each id As Long In tb.BackupIds
1093 If Not posts(id).IsRead Then
1095 If oldest > id Then oldest = id
1098 If oldest = Long.MaxValue Then oldest = -1
1099 tb.OldestUnreadId = oldest
1100 tb.UnreadCount = cnt
1105 For Each key As String In _tabs.Keys
1106 Dim tb As TabClass = _tabs(key)
1107 If tb.UnreadManage AndAlso tb.UnreadCount > 0 Then
1110 tb.OldestUnreadId = -1
1117 Public Sub RenameTab(ByVal Original As String, ByVal NewName As String)
1118 Dim tb As TabClass = _tabs(Original)
1119 _tabs.Remove(Original)
1120 tb.TabName = NewName
1121 _tabs.Add(NewName, tb)
1124 Public Sub FilterAll()
1126 Dim tbr As TabClass = GetTabByType(TabUsageType.Home)
1127 Dim replyTab As TabClass = GetTabByType(TabUsageType.Mentions)
1128 For Each key As String In _tabs.Keys
1129 Dim tb As TabClass = _tabs(key)
1130 If tb.FilterModified Then
1131 tb.FilterModified = False
1132 Dim orgIds() As Long = tb.BackupIds()
1134 ''''''''''''''フィルター前のIDsを退避。どのタブにも含まれないidはrecentへ追加
1135 ''''''''''''''moveフィルターにヒットした際、recentに該当あればrecentから削除
1136 For Each id As Long In _statuses.Keys
1137 Dim post As PostClass = _statuses.Item(id)
1138 If post.IsDm Then Continue For
1139 Dim rslt As HITRESULT = HITRESULT.None
1140 rslt = tb.AddFiltered(post)
1142 Case HITRESULT.CopyAndMark
1143 post.IsMark = True 'マークあり
1144 post.FilterHit = True
1146 tbr.Remove(post.Id, post.IsRead)
1148 post.FilterHit = True
1151 post.FilterHit = True
1153 If key = replyTab.TabName AndAlso post.IsReply Then replyTab.Add(post.Id, post.IsRead, True)
1154 If post.IsFav Then GetTabByType(TabUsageType.Favorites).Add(post.Id, post.IsRead, True)
1155 post.FilterHit = False
1158 tb.AddSubmit() '振分確定
1159 For Each id As Long In orgIds
1160 Dim hit As Boolean = False
1161 For Each tkey As String In _tabs.Keys
1162 If _tabs(tkey).Contains(id) Then
1167 If Not hit Then tbr.Add(id, _statuses(id).IsRead, False)
1175 Public Function GetId(ByVal TabName As String, ByVal IndexCollection As ListView.SelectedIndexCollection) As Long()
1176 If IndexCollection.Count = 0 Then Return Nothing
1178 Dim tb As TabClass = _tabs(TabName)
1179 Dim Ids(IndexCollection.Count - 1) As Long
1180 For i As Integer = 0 To Ids.Length - 1
1181 Ids(i) = tb.GetId(IndexCollection(i))
1186 Public Function GetId(ByVal TabName As String, ByVal Index As Integer) As Long
1187 Return _tabs(TabName).GetId(Index)
1190 Public Function IndexOf(ByVal TabName As String, ByVal Ids() As Long) As Integer()
1191 If Ids Is Nothing Then Return Nothing
1192 Dim idx(Ids.Length - 1) As Integer
1193 Dim tb As TabClass = _tabs(TabName)
1194 For i As Integer = 0 To Ids.Length - 1
1195 idx(i) = tb.IndexOf(Ids(i))
1200 Public Function IndexOf(ByVal TabName As String, ByVal Id As Long) As Integer
1201 Return _tabs(TabName).IndexOf(Id)
1204 Public Sub ClearTabIds(ByVal TabName As String)
1207 If _tabs(TabName).TabType <> TabUsageType.PublicSearch AndAlso _tabs(TabName).TabType <> TabUsageType.DirectMessage AndAlso _tabs(TabName).TabType <> TabUsageType.Lists Then
1208 For Each Id As Long In _tabs(TabName).BackupIds
1209 Dim Hit As Boolean = False
1210 For Each tb As TabClass In _tabs.Values
1211 If tb.Contains(Id) Then
1216 If Not Hit Then _statuses.Remove(Id)
1221 _tabs(TabName).ClearIDs()
1225 Public Sub SetTabUnreadManage(ByVal TabName As String, ByVal Manage As Boolean)
1226 Dim tb As TabClass = _tabs(TabName)
1229 Dim cnt As Integer = 0
1230 Dim oldest As Long = Long.MaxValue
1231 Dim posts As Dictionary(Of Long, PostClass)
1232 If tb.TabType <> TabUsageType.PublicSearch AndAlso tb.TabType <> TabUsageType.DirectMessage AndAlso tb.TabType <> TabUsageType.Lists Then
1237 For Each id As Long In tb.BackupIds
1238 If Not posts(id).IsRead Then
1240 If oldest > id Then oldest = id
1243 If oldest = Long.MaxValue Then oldest = -1
1244 tb.OldestUnreadId = oldest
1245 tb.UnreadCount = cnt
1247 tb.OldestUnreadId = -1
1251 tb.UnreadManage = Manage
1254 'Public Sub RefreshOwl(ByVal follower As List(Of String))
1256 ' If follower.Count > 1 Then
1257 ' For Each id As Long In _statuses.Keys
1258 ' _statuses(id).IsOwl = Not follower.Contains(_statuses(id).Name.ToLower())
1261 ' For Each id As Long In _statuses.Keys
1262 ' _statuses(id).IsOwl = False
1268 Public Sub RefreshOwl(ByVal follower As List(Of Long))
1270 If follower.Count > 0 Then
1271 For Each post As PostClass In _statuses.Values
1272 'If post.Uid = 0 OrElse post.IsDm Then Continue For
1276 post.IsOwl = Not follower.Contains(post.Uid)
1280 For Each id As Long In _statuses.Keys
1281 _statuses(id).IsOwl = False
1287 Public Function GetTabByType(ByVal tabType As TabUsageType) As TabClass
1288 'Home,Mentions,DM,Favは1つに制限する
1289 'その他のタイプを指定されたら、最初に合致したものを返す
1292 For Each tb As TabClass In _tabs.Values
1293 If tb IsNot Nothing AndAlso tb.TabType = tabType Then Return tb
1299 Public Function GetTabsByType(ByVal tabType As TabUsageType) As List(Of TabClass)
1303 Dim tbs As New List(Of TabClass)
1304 For Each tb As TabClass In _tabs.Values
1305 If tb.TabType = tabType Then tbs.Add(tb)
1311 Public Function GetTabByName(ByVal tabName As String) As TabClass
1313 If _tabs.ContainsKey(tabName) Then Return _tabs(tabName)
1319 Public Function IsDefaultTab(ByVal tabName As String) As Boolean
1320 If tabName IsNot Nothing AndAlso _
1321 _tabs.ContainsKey(tabName) AndAlso _
1322 (_tabs(tabName).TabType = TabUsageType.Home OrElse _
1323 _tabs(tabName).TabType = TabUsageType.Mentions OrElse _
1324 _tabs(tabName).TabType = TabUsageType.DirectMessage OrElse _
1325 _tabs(tabName).TabType = TabUsageType.Favorites) Then
1332 Public Function GetUniqueTabName() As String
1333 Dim tabNameTemp As String = "MyTab" + (_tabs.Count + 1).ToString
1334 For i As Integer = 2 To 100
1335 If _tabs.ContainsKey(tabNameTemp) Then
1336 tabNameTemp = "MyTab" + (_tabs.Count + i).ToString
1344 Public ReadOnly Property Posts() As Dictionary(Of Long, PostClass)
1352 Public NotInheritable Class TabClass
1353 Private _unreadManage As Boolean = False
1354 Private _notify As Boolean = False
1355 Private _soundFile As String = ""
1356 Private _filters As List(Of FiltersClass)
1357 Private _oldestUnreadItem As Long = -1 'ID
1358 Private _unreadCount As Integer = 0
1359 Private _ids As List(Of Long)
1360 Private _filterMod As Boolean = False
1361 Private _tmpIds As New List(Of TemporaryId)
1362 Private _tabName As String = ""
1363 Private _tabType As TabUsageType = TabUsageType.Undefined
1364 Private _posts As New Dictionary(Of Long, PostClass)
1365 Private _sorter As New IdComparerClass
1366 Private _oldestId As Long = -1 '古いポスト取得用
1370 Private _searchLang As String = ""
1371 Private _searchWords As String = ""
1373 Public Property SearchLang() As String
1377 Set(ByVal value As String)
1381 Public Property SearchWords() As String
1385 Set(ByVal value As String)
1386 _searchWords = value.Trim
1389 Public ReadOnly Property SearchPage() As Integer
1391 Return ((_ids.Count \ 40) + 1)
1394 Private _beforeQuery As New Dictionary(Of String, String)
1395 Public Sub SaveQuery(ByVal more As Boolean)
1396 Dim qry As New Dictionary(Of String, String)
1397 If String.IsNullOrEmpty(_searchWords) Then
1401 qry.Add("q", _searchWords)
1402 If Not String.IsNullOrEmpty(_searchLang) Then qry.Add("lang", _searchLang)
1406 Public Function IsQueryChanged() As Boolean
1407 Dim qry As New Dictionary(Of String, String)
1408 If Not String.IsNullOrEmpty(_searchWords) Then
1409 qry.Add("q", _searchWords)
1410 If Not String.IsNullOrEmpty(_searchLang) Then qry.Add("lang", _searchLang)
1412 If qry.Count <> _beforeQuery.Count Then Return True
1414 For Each kvp As KeyValuePair(Of String, String) In qry
1415 If Not _beforeQuery.ContainsKey(kvp.Key) OrElse _beforeQuery(kvp.Key) <> kvp.Value Then
1423 Private _listInfo As ListElement
1424 Public Property ListInfo() As ListElement
1428 Set(ByVal value As ListElement)
1434 Public Property OldestId() As Long
1438 Set(ByVal value As Long)
1443 <Xml.Serialization.XmlIgnore()> _
1444 Public Property Posts() As Dictionary(Of Long, PostClass)
1448 Set(ByVal value As Dictionary(Of Long, PostClass))
1453 'Public Function SearchedPost(ByVal Id As Long) As PostClass
1454 ' If Not _posts.ContainsKey(Id) Then Return Nothing
1458 Public Function GetTemporaryPosts() As PostClass()
1459 Dim tempPosts As New List(Of PostClass)
1460 If _tmpIds.Count = 0 Then Return tempPosts.ToArray
1461 For Each tempId As TemporaryId In _tmpIds
1462 tempPosts.Add(_posts(tempId.Id))
1464 Return tempPosts.ToArray
1467 Public Function GetTemporaryCount() As Integer
1468 Return _tmpIds.Count
1471 Private Structure TemporaryId
1473 Public Read As Boolean
1475 Public Sub New(ByVal argId As Long, ByVal argRead As Boolean)
1482 _filters = New List(Of FiltersClass)
1485 _unreadManage = True
1486 _ids = New List(Of Long)
1487 _oldestUnreadItem = -1
1488 _tabType = TabUsageType.Undefined
1492 Public Sub New(ByVal TabName As String, ByVal TabType As TabUsageType, ByVal list As ListElement)
1494 _filters = New List(Of FiltersClass)
1497 _unreadManage = True
1498 _ids = New List(Of Long)
1499 _oldestUnreadItem = -1
1502 If TabType = TabUsageType.PublicSearch OrElse TabType = TabUsageType.DirectMessage OrElse TabType = TabUsageType.Lists Then
1503 _sorter.posts = _posts
1505 _sorter.posts = TabInformations.GetInstance.Posts
1510 _ids.Sort(_sorter.CmpMethod)
1513 Public ReadOnly Property Sorter() As IdComparerClass
1520 Private Sub Add(ByVal ID As Long, ByVal Read As Boolean)
1521 If Me._ids.Contains(ID) Then Exit Sub
1525 If Not Read AndAlso Me._unreadManage Then
1526 Me._unreadCount += 1
1527 If Me._oldestUnreadItem = -1 Then
1528 Me._oldestUnreadItem = ID
1530 If ID < Me._oldestUnreadItem Then Me._oldestUnreadItem = ID
1535 Public Sub Add(ByVal ID As Long, ByVal Read As Boolean, ByVal Temporary As Boolean)
1536 If Not Temporary Then
1539 _tmpIds.Add(New TemporaryId(ID, Read))
1544 Public Function AddFiltered(ByVal post As PostClass) As HITRESULT
1546 ' rwLock.AcquireReaderLock(System.Threading.Timeout.Infinite) '読み取りロック取得
1547 If Me.TabType = TabUsageType.PublicSearch OrElse Me.TabType = TabUsageType.DirectMessage OrElse Me.TabType = TabUsageType.Lists Then Return HITRESULT.None
1549 Dim rslt As HITRESULT = HITRESULT.None
1551 For Each ft As FiltersClass In _filters
1552 Select Case ft.IsHit(post) 'フィルタクラスでヒット判定
1555 If rslt <> HITRESULT.CopyAndMark Then rslt = HITRESULT.Copy
1556 Case HITRESULT.CopyAndMark
1557 rslt = HITRESULT.CopyAndMark
1559 rslt = HITRESULT.Move
1560 Case HITRESULT.Exclude
1561 rslt = HITRESULT.None
1566 If rslt <> HITRESULT.None Then
1567 _tmpIds.Add(New TemporaryId(post.Id, post.IsRead))
1571 Return rslt 'マーク付けは呼び出し元で行うこと
1574 ' rwLock.ReleaseReaderLock()
1579 Public Sub AddPostToInnerStorage(ByVal Post As PostClass)
1580 If _posts.ContainsKey(Post.Id) Then Exit Sub
1581 _posts.Add(Post.Id, Post)
1582 _tmpIds.Add(New TemporaryId(Post.Id, Post.IsRead))
1585 Public Sub AddSubmit()
1586 If _tmpIds.Count = 0 Then Exit Sub
1587 For Each tId As TemporaryId In _tmpIds
1588 Me.Add(tId.Id, tId.Read)
1593 Public Sub Remove(ByVal Id As Long)
1594 If Not Me._ids.Contains(Id) Then Exit Sub
1596 If Me.TabType = TabUsageType.PublicSearch OrElse Me.TabType = TabUsageType.DirectMessage OrElse Me.TabType = TabUsageType.Lists Then _posts.Remove(Id)
1599 Public Sub Remove(ByVal Id As Long, ByVal Read As Boolean)
1600 If Not Me._ids.Contains(Id) Then Exit Sub
1602 If Not Read AndAlso Me._unreadManage Then
1603 Me._unreadCount -= 1
1604 Me._oldestUnreadItem = -1
1608 If Me.TabType = TabUsageType.PublicSearch OrElse Me.TabType = TabUsageType.DirectMessage OrElse Me.TabType = TabUsageType.Lists Then _posts.Remove(Id)
1611 Public Property UnreadManage() As Boolean
1613 Return _unreadManage
1615 Set(ByVal value As Boolean)
1616 Me._unreadManage = value
1618 Me._oldestUnreadItem = -1
1624 Public Property Notify() As Boolean
1628 Set(ByVal value As Boolean)
1633 Public Property SoundFile() As String
1637 Set(ByVal value As String)
1642 <Xml.Serialization.XmlIgnore()> _
1643 Public Property OldestUnreadId() As Long
1645 Return _oldestUnreadItem
1647 Set(ByVal value As Long)
1648 _oldestUnreadItem = value
1652 <Xml.Serialization.XmlIgnore()> _
1653 Public Property UnreadCount() As Integer
1657 Set(ByVal value As Integer)
1658 _unreadCount = value
1662 Public ReadOnly Property AllCount() As Integer
1664 Return Me._ids.Count
1668 Public Function GetFilters() As FiltersClass()
1669 Return _filters.ToArray()
1672 Public Sub RemoveFilter(ByVal filter As FiltersClass)
1673 _filters.Remove(filter)
1677 Public Function AddFilter(ByVal filter As FiltersClass) As Boolean
1678 If _filters.Contains(filter) Then Return False
1679 _filters.Add(filter)
1684 Public Sub EditFilter(ByVal original As FiltersClass, ByVal modified As FiltersClass)
1685 original.BodyFilter = modified.BodyFilter
1686 original.NameFilter = modified.NameFilter
1687 original.SearchBoth = modified.SearchBoth
1688 original.SearchUrl = modified.SearchUrl
1689 original.UseRegex = modified.UseRegex
1690 original.CaseSensitive = modified.CaseSensitive
1691 original.IsRt = modified.IsRt
1692 original.Source = modified.Source
1693 original.ExBodyFilter = modified.ExBodyFilter
1694 original.ExNameFilter = modified.ExNameFilter
1695 original.ExSearchBoth = modified.ExSearchBoth
1696 original.ExSearchUrl = modified.ExSearchUrl
1697 original.ExUseRegex = modified.ExUseRegex
1698 original.ExCaseSensitive = modified.ExCaseSensitive
1699 original.IsExRt = modified.IsExRt
1700 original.ExSource = modified.ExSource
1701 original.MoveFrom = modified.MoveFrom
1702 original.SetMark = modified.SetMark
1706 <Xml.Serialization.XmlIgnore()> _
1707 Public Property Filters() As List(Of FiltersClass)
1711 Set(ByVal value As List(Of FiltersClass))
1716 Public Property FilterArray() As FiltersClass()
1718 Return _filters.ToArray
1720 Set(ByVal value As FiltersClass())
1721 For Each filters As FiltersClass In value
1722 _filters.Add(filters)
1727 Public Function Contains(ByVal ID As Long) As Boolean
1728 Return _ids.Contains(ID)
1731 Public Sub ClearIDs()
1735 _oldestUnreadItem = -1
1736 If _posts IsNot Nothing Then
1741 Public Function GetId(ByVal Index As Integer) As Long
1745 Public Function IndexOf(ByVal ID As Long) As Integer
1746 Return _ids.IndexOf(ID)
1749 <Xml.Serialization.XmlIgnore()> _
1750 Public Property FilterModified() As Boolean
1754 Set(ByVal value As Boolean)
1759 Public Function BackupIds() As Long()
1760 Return _ids.ToArray()
1763 Public Property TabName() As String
1767 Set(ByVal value As String)
1772 Public Property TabType() As TabUsageType
1776 Set(ByVal value As TabUsageType)
1778 If _tabType = TabUsageType.PublicSearch OrElse _tabType = TabUsageType.DirectMessage OrElse _tabType = TabUsageType.Lists Then
1779 _sorter.posts = _posts
1781 _sorter.posts = TabInformations.GetInstance.Posts
1789 Public NotInheritable Class FiltersClass
1790 Implements System.IEquatable(Of FiltersClass)
1791 Private _name As String = ""
1792 Private _body As New List(Of String)
1793 Private _searchBoth As Boolean = True
1794 Private _searchUrl As Boolean = False
1795 Private _caseSensitive As Boolean = False
1796 Private _useRegex As Boolean = False
1797 Private _isRt As Boolean = False
1798 Private _source As String = ""
1799 Private _exname As String = ""
1800 Private _exbody As New List(Of String)
1801 Private _exsearchBoth As Boolean = True
1802 Private _exsearchUrl As Boolean = False
1803 Private _exuseRegex As Boolean = False
1804 Private _excaseSensitive As Boolean = False
1805 Private _isExRt As Boolean = False
1806 Private _exSource As String = ""
1807 Private _moveFrom As Boolean = False
1808 Private _setMark As Boolean = True
1810 'Public Sub New(ByVal NameFilter As String, _
1811 ' ByVal BodyFilter As List(Of String), _
1812 ' ByVal SearchBoth As Boolean, _
1813 ' ByVal SearchUrl As Boolean, _
1814 ' ByVal CaseSensitive As Boolean, _
1815 ' ByVal UseRegex As Boolean, _
1816 ' ByVal ParentTab As String, _
1817 ' ByVal ExNameFilter As String, _
1818 ' ByVal ExBodyFilter As List(Of String), _
1819 ' ByVal ExSearchBoth As Boolean, _
1820 ' ByVal ExSearchUrl As Boolean, _
1821 ' ByVal ExUseRegex As Boolean, _
1822 ' ByVal ExCaseSensitive As Boolean, _
1823 ' ByVal MoveFrom As Boolean, _
1824 ' ByVal SetMark As Boolean)
1825 ' _name = NameFilter
1826 ' _body = BodyFilter
1827 ' _searchBoth = SearchBoth
1828 ' _searchUrl = SearchUrl
1829 ' _caseSensitive = CaseSensitive
1830 ' _useRegex = UseRegex
1831 ' _exname = ExNameFilter
1832 ' _exbody = ExBodyFilter
1833 ' _exsearchBoth = ExSearchBoth
1834 ' _exsearchUrl = ExSearchUrl
1835 ' _exuseRegex = ExUseRegex
1836 ' _excaseSensitive = ExCaseSensitive
1837 ' _moveFrom = MoveFrom
1838 ' _setMark = SetMark
1842 ' Dim rgx As New Regex(_name)
1843 ' Catch ex As Exception
1844 ' Throw New Exception(My.Resources.ButtonOK_ClickText3 + ex.Message)
1847 ' For Each bs As String In _body
1849 ' Dim rgx As New Regex(bs)
1850 ' Catch ex As Exception
1851 ' Throw New Exception(My.Resources.ButtonOK_ClickText3 + ex.Message)
1856 ' If _exuseRegex Then
1858 ' Dim rgx As New Regex(_exname)
1859 ' Catch ex As Exception
1860 ' Throw New Exception(My.Resources.ButtonOK_ClickText3 + ex.Message)
1863 ' For Each bs As String In _exbody
1865 ' Dim rgx As New Regex(bs)
1866 ' Catch ex As Exception
1867 ' Throw New Exception(My.Resources.ButtonOK_ClickText3 + ex.Message)
1879 Private Function MakeSummary() As String
1880 Dim fs As New System.Text.StringBuilder()
1881 If _name <> "" OrElse _body.Count > 0 OrElse _isRt OrElse _source <> "" Then
1884 fs.AppendFormat(My.Resources.SetFiltersText1, _name)
1886 fs.Append(My.Resources.SetFiltersText2)
1889 If _body.Count > 0 Then
1890 fs.Append(My.Resources.SetFiltersText3)
1891 For Each bf As String In _body
1896 fs.Append(My.Resources.SetFiltersText4)
1900 fs.Append(My.Resources.SetFiltersText5)
1902 fs.Append(My.Resources.SetFiltersText6)
1905 fs.Append(My.Resources.SetFiltersText7)
1908 fs.Append(My.Resources.SetFiltersText8)
1910 If _caseSensitive Then
1911 fs.Append(My.Resources.SetFiltersText13)
1916 If _source <> "" Then
1917 fs.AppendFormat("Src…{0}/", _source)
1920 ' fs.Append(My.Resources.SetFiltersText9)
1921 'ElseIf _setMark Then
1922 ' fs.Append(My.Resources.SetFiltersText10)
1924 ' fs.Append(My.Resources.SetFiltersText11)
1929 If _exname <> "" OrElse _exbody.Count > 0 OrElse _isExRt OrElse _exSource <> "" Then
1931 fs.Append(My.Resources.SetFiltersText12)
1932 If _exsearchBoth Then
1933 If _exname <> "" Then
1934 fs.AppendFormat(My.Resources.SetFiltersText1, _exname)
1936 fs.Append(My.Resources.SetFiltersText2)
1939 If _exbody.Count > 0 Then
1940 fs.Append(My.Resources.SetFiltersText3)
1941 For Each bf As String In _exbody
1946 fs.Append(My.Resources.SetFiltersText4)
1949 If _exsearchBoth Then
1950 fs.Append(My.Resources.SetFiltersText5)
1952 fs.Append(My.Resources.SetFiltersText6)
1955 fs.Append(My.Resources.SetFiltersText7)
1957 If _exsearchUrl Then
1958 fs.Append(My.Resources.SetFiltersText8)
1960 If _excaseSensitive Then
1961 fs.Append(My.Resources.SetFiltersText13)
1966 If _exSource <> "" Then
1967 fs.AppendFormat("Src…{0}/", _exSource)
1975 fs.Append(My.Resources.SetFiltersText9)
1977 fs.Append(My.Resources.SetFiltersText11)
1979 If Not _moveFrom AndAlso _setMark Then
1980 fs.Append(My.Resources.SetFiltersText10)
1981 ElseIf Not _moveFrom Then
1987 Return fs.ToString()
1990 Public Property NameFilter() As String
1994 Set(ByVal value As String)
1999 Public Property ExNameFilter() As String
2003 Set(ByVal value As String)
2008 <Xml.Serialization.XmlIgnore()> _
2009 Public Property BodyFilter() As List(Of String)
2013 Set(ByVal value As List(Of String))
2018 Public Property BodyFilterArray() As String()
2020 Return _body.ToArray
2022 Set(ByVal value As String())
2023 _body = New List(Of String)
2024 For Each filter As String In value
2030 <Xml.Serialization.XmlIgnore()> _
2031 Public Property ExBodyFilter() As List(Of String)
2035 Set(ByVal value As List(Of String))
2040 Public Property ExBodyFilterArray() As String()
2042 Return _exbody.ToArray
2044 Set(ByVal value As String())
2045 _exbody = New List(Of String)
2046 For Each filter As String In value
2052 Public Property SearchBoth() As Boolean
2056 Set(ByVal value As Boolean)
2061 Public Property ExSearchBoth() As Boolean
2063 Return _exsearchBoth
2065 Set(ByVal value As Boolean)
2066 _exsearchBoth = value
2070 Public Property MoveFrom() As Boolean
2074 Set(ByVal value As Boolean)
2079 Public Property SetMark() As Boolean
2083 Set(ByVal value As Boolean)
2088 Public Property SearchUrl() As Boolean
2092 Set(ByVal value As Boolean)
2097 Public Property ExSearchUrl() As Boolean
2101 Set(ByVal value As Boolean)
2102 _exsearchUrl = value
2106 Public Property CaseSensitive() As Boolean
2108 Return _caseSensitive
2110 Set(ByVal value As Boolean)
2111 _caseSensitive = value
2115 Public Property ExCaseSensitive() As Boolean
2117 Return _excaseSensitive
2119 Set(ByVal value As Boolean)
2120 _excaseSensitive = value
2124 Public Property UseRegex() As Boolean
2128 Set(ByVal value As Boolean)
2133 Public Property ExUseRegex() As Boolean
2137 Set(ByVal value As Boolean)
2142 Public Property IsRt() As Boolean
2146 Set(ByVal value As Boolean)
2151 Public Property IsExRt() As Boolean
2155 Set(ByVal value As Boolean)
2160 Public Property Source() As String
2164 Set(ByVal value As String)
2169 Public Property ExSource() As String
2173 Set(ByVal value As String)
2178 Public Overrides Function ToString() As String
2179 Return MakeSummary()
2182 Public Function IsHit(ByVal post As PostClass) As HITRESULT
2183 Dim bHit As Boolean = True
2186 tBody = post.OriginalData
2191 Dim compOpt As System.StringComparison
2192 Dim rgOpt As System.Text.RegularExpressions.RegexOptions
2193 If _caseSensitive Then
2194 compOpt = StringComparison.Ordinal
2195 rgOpt = RegexOptions.None
2197 compOpt = StringComparison.OrdinalIgnoreCase
2198 rgOpt = RegexOptions.IgnoreCase
2201 If _name = "" OrElse _
2202 post.Name.Equals(_name, compOpt) OrElse _
2203 post.RetweetedBy.Equals(_name, compOpt) OrElse _
2204 (_useRegex AndAlso (Regex.IsMatch(post.Name, _name, rgOpt) OrElse _
2205 Regex.IsMatch(post.RetweetedBy, _name, rgOpt))) Then
2206 For Each fs As String In _body
2208 If Not Regex.IsMatch(tBody, fs, rgOpt) Then bHit = False
2210 If _caseSensitive Then
2211 If Not tBody.Contains(fs) Then bHit = False
2213 If Not tBody.ToLower().Contains(fs.ToLower()) Then bHit = False
2216 If Not bHit Then Exit For
2222 For Each fs As String In _body
2224 If Not (Regex.IsMatch(post.Name, fs, rgOpt) OrElse _
2225 Regex.IsMatch(post.RetweetedBy, fs, rgOpt) OrElse _
2226 Regex.IsMatch(tBody, fs, rgOpt)) Then bHit = False
2228 If _caseSensitive Then
2229 If Not (post.Name.Contains(fs) OrElse _
2230 post.RetweetedBy.Contains(fs) OrElse _
2231 tBody.Contains(fs)) Then bHit = False
2233 If Not (post.Name.ToLower().Contains(fs.ToLower()) OrElse _
2234 post.RetweetedBy.ToLower().Contains(fs.ToLower()) OrElse _
2235 tBody.ToLower().Contains(fs.ToLower())) Then bHit = False
2238 If Not bHit Then Exit For
2242 If post.RetweetedId = 0 Then bHit = False
2244 If Not String.IsNullOrEmpty(_source) Then
2246 If Not Regex.IsMatch(post.Source, _source, rgOpt) Then bHit = False
2248 If Not post.Source.Equals(_source, compOpt) Then bHit = False
2253 If _exsearchUrl Then
2254 tBody = post.OriginalData
2259 Dim exFlag As Boolean = False
2260 'If _name = "" AndAlso _body.Count = 0 Then
2264 If _exname <> "" OrElse _exbody.Count > 0 Then
2265 If _excaseSensitive Then
2266 compOpt = StringComparison.Ordinal
2267 rgOpt = RegexOptions.None
2269 compOpt = StringComparison.OrdinalIgnoreCase
2270 rgOpt = RegexOptions.IgnoreCase
2272 If _exsearchBoth Then
2273 If _exname = "" OrElse _
2274 post.Name.Equals(_exname, compOpt) OrElse _
2275 post.RetweetedBy.Equals(_exname, compOpt) OrElse _
2276 (_exuseRegex AndAlso _
2277 (Regex.IsMatch(post.Name, _exname, rgOpt) OrElse _
2278 Regex.IsMatch(post.RetweetedBy, _exname, rgOpt))) Then
2279 If _exbody.Count > 0 Then
2280 For Each fs As String In _exbody
2282 If Regex.IsMatch(tBody, fs, rgOpt) Then exFlag = True
2284 If _excaseSensitive Then
2285 If tBody.Contains(fs) Then exFlag = True
2287 If tBody.ToLower().Contains(fs.ToLower()) Then exFlag = True
2290 If exFlag Then Exit For
2297 For Each fs As String In _exbody
2299 If Regex.IsMatch(post.Name, fs, rgOpt) OrElse _
2300 Regex.IsMatch(post.RetweetedBy, fs, rgOpt) OrElse _
2301 Regex.IsMatch(tBody, fs, rgOpt) Then exFlag = True
2303 If _excaseSensitive Then
2304 If post.Name.Contains(fs) OrElse _
2305 post.RetweetedBy.Contains(fs) OrElse _
2306 tBody.Contains(fs) Then exFlag = True
2308 If post.Name.ToLower().Contains(fs.ToLower()) OrElse _
2309 post.RetweetedBy.ToLower().Contains(fs.ToLower()) OrElse _
2310 tBody.ToLower().Contains(fs.ToLower()) Then exFlag = True
2313 If exFlag Then Exit For
2318 If post.RetweetedId > 0 Then exFlag = True
2320 If Not String.IsNullOrEmpty(_exSource) Then
2322 If Regex.IsMatch(post.Source, _exSource, rgOpt) Then exFlag = True
2324 If post.Source.Equals(_exSource, compOpt) Then exFlag = True
2328 If _name = "" AndAlso _body.Count = 0 AndAlso Not _isRt AndAlso _source = "" Then
2333 'If _setMark Then Return HITRESULT.CopyAndMark
2335 Return HITRESULT.Move
2338 Return HITRESULT.CopyAndMark
2340 Return HITRESULT.Copy
2342 'Return HITRESULT.Copy
2344 Return HITRESULT.Exclude
2348 Return HITRESULT.Exclude
2350 Return HITRESULT.None
2354 Return HITRESULT.None
2358 Public Overloads Function Equals(ByVal other As FiltersClass) As Boolean _
2359 Implements System.IEquatable(Of Tween.FiltersClass).Equals
2361 If Me.BodyFilter.Count <> other.BodyFilter.Count Then Return False
2362 If Me.ExBodyFilter.Count <> other.ExBodyFilter.Count Then Return False
2363 For i As Integer = 0 To Me.BodyFilter.Count - 1
2364 If Me.BodyFilter(i) <> other.BodyFilter(i) Then Return False
2366 For i As Integer = 0 To Me.ExBodyFilter.Count - 1
2367 If Me.ExBodyFilter(i) <> other.ExBodyFilter(i) Then Return False
2370 Return (Me.MoveFrom = other.MoveFrom) And _
2371 (Me.SetMark = other.SetMark) And _
2372 (Me.NameFilter = other.NameFilter) And _
2373 (Me.SearchBoth = other.SearchBoth) And _
2374 (Me.SearchUrl = other.SearchUrl) And _
2375 (Me.UseRegex = other.UseRegex) And _
2376 (Me.ExNameFilter = other.ExNameFilter) And _
2377 (Me.ExSearchBoth = other.ExSearchBoth) And _
2378 (Me.ExSearchUrl = other.ExSearchUrl) And _
2379 (Me.ExUseRegex = other.ExUseRegex) And _
2380 (Me.IsRt = other.IsRt) And _
2381 (Me.Source = other.Source) And _
2382 (Me.IsExRt = other.IsExRt) And _
2383 (Me.ExSource = other.ExSource)
2386 Public Overrides Function Equals(ByVal obj As Object) As Boolean
2387 If (obj Is Nothing) OrElse Not (Me.GetType() Is obj.GetType()) Then Return False
2388 Return Me.Equals(CType(obj, FiltersClass))
2391 Public Overrides Function GetHashCode() As Integer
2392 Return Me.MoveFrom.GetHashCode Xor _
2393 Me.SetMark.GetHashCode Xor _
2394 Me.BodyFilter.GetHashCode Xor _
2395 Me.NameFilter.GetHashCode Xor _
2396 Me.SearchBoth.GetHashCode Xor _
2397 Me.SearchUrl.GetHashCode Xor _
2398 Me.UseRegex.GetHashCode Xor _
2399 Me.ExBodyFilter.GetHashCode Xor _
2400 Me.ExNameFilter.GetHashCode Xor _
2401 Me.ExSearchBoth.GetHashCode Xor _
2402 Me.ExSearchUrl.GetHashCode Xor _
2403 Me.ExUseRegex.GetHashCode Xor _
2404 Me.IsRt.GetHashCode Xor _
2405 Me.Source.GetHashCode Xor _
2406 Me.IsExRt.GetHashCode Xor _
2407 Me.ExSource.GetHashCode
2412 Public NotInheritable Class IdComparerClass
2413 Implements IComparer(Of Long)
2418 Public Enum ComparerMode
2426 Private _order As SortOrder
2427 Private _mode As ComparerMode
2428 Private _statuses As Dictionary(Of Long, PostClass)
2429 Private _CmpMethod As Comparison(Of Long)
2432 ''' 昇順か降順か Setの際は同時に比較関数の切り替えを行う
2434 Public Property Order() As SortOrder
2438 Set(ByVal Value As SortOrder)
2440 SetCmpMethod(_mode, _order)
2445 ''' 並び替えの方法 Setの際は同時に比較関数の切り替えを行う
2447 Public Property Mode() As ComparerMode
2451 Set(ByVal Value As ComparerMode)
2453 SetCmpMethod(_mode, _order)
2458 ''' ListViewItemComparerクラスのコンストラクタ(引数付は未使用)
2460 ''' <param name="col">並び替える列番号</param>
2461 ''' <param name="ord">昇順か降順か</param>
2462 ''' <param name="cmod">並び替えの方法</param>
2463 'Public Sub New(ByVal ord As SortOrder, ByVal SortMode As ComparerMode)
2466 ' SetCmpMethod(_mode, _order)
2469 'Public Sub New(ByVal posts As Dictionary(Of Long, PostClass))
2470 ' _order = SortOrder.Ascending
2471 ' _mode = ComparerMode.Id
2473 ' SetCmpMethod(_mode, _order)
2477 _order = SortOrder.Ascending
2478 _mode = ComparerMode.Id
2479 SetCmpMethod(_mode, _order)
2482 Public WriteOnly Property posts() As Dictionary(Of Long, PostClass)
2483 Set(ByVal value As Dictionary(Of Long, PostClass))
2488 ' 指定したソートモードとソートオーダーに従い使用する比較関数のアドレスを返す
2489 Public Overloads ReadOnly Property CmpMethod(ByVal _sortmode As ComparerMode, ByVal _sortorder As SortOrder) As Comparison(Of Long)
2491 Dim _method As Comparison(Of Long) = Nothing
2492 If _sortorder = SortOrder.Ascending Then
2494 Select Case _sortmode
2495 Case ComparerMode.Data
2496 _method = AddressOf Compare_ModeData_Ascending
2497 Case ComparerMode.Id
2498 _method = AddressOf Compare_ModeId_Ascending
2499 Case ComparerMode.Name
2500 _method = AddressOf Compare_ModeName_Ascending
2501 Case ComparerMode.Nickname
2502 _method = AddressOf Compare_ModeNickName_Ascending
2503 Case ComparerMode.Source
2504 _method = AddressOf Compare_ModeSource_Ascending
2508 Select Case _sortmode
2509 Case ComparerMode.Data
2510 _method = AddressOf Compare_ModeData_Descending
2511 Case ComparerMode.Id
2512 _method = AddressOf Compare_ModeId_Descending
2513 Case ComparerMode.Name
2514 _method = AddressOf Compare_ModeName_Descending
2515 Case ComparerMode.Nickname
2516 _method = AddressOf Compare_ModeNickName_Descending
2517 Case ComparerMode.Source
2518 _method = AddressOf Compare_ModeSource_Descending
2525 ' ソートモードとソートオーダーに従い使用する比較関数のアドレスを返す
2526 ' (overload 現在の使用中の比較関数のアドレスを返す)
2527 Public Overloads ReadOnly Property CmpMethod() As Comparison(Of Long)
2533 ' ソートモードとソートオーダーに従い比較関数のアドレスを切り替え
2534 Private Sub SetCmpMethod(ByVal mode As ComparerMode, ByVal order As SortOrder)
2535 _CmpMethod = Me.CmpMethod(mode, order)
2538 'xがyより小さいときはマイナスの数、大きいときはプラスの数、
2539 '同じときは0を返す (こちらは未使用 一応比較関数群呼び出しの形のまま残しておく)
2540 Public Function Compare(ByVal x As Long, ByVal y As Long) _
2541 As Integer Implements IComparer(Of Long).Compare
2542 Return _CmpMethod(x, y)
2545 ' 比較用関数群 いずれもステータスIDの順序を考慮する
2546 ' 注:ID比較でCTypeを使用しているが、abs(x-y)がInteger(Int32)に収まらないことはあり得ないのでこれでよい
2548 Public Function Compare_ModeData_Ascending(ByVal x As Long, ByVal y As Long) As Integer
2549 Dim result As Integer = String.Compare(_statuses.Item(x).Data, _statuses.Item(y).Data)
2550 If result = 0 Then result = x.CompareTo(y)
2555 Public Function Compare_ModeData_Descending(ByVal x As Long, ByVal y As Long) As Integer
2556 Dim result As Integer = String.Compare(_statuses.Item(y).Data, _statuses.Item(x).Data)
2557 If result = 0 Then result = y.CompareTo(x)
2562 Public Function Compare_ModeId_Ascending(ByVal x As Long, ByVal y As Long) As Integer
2563 Return x.CompareTo(y)
2567 Public Function Compare_ModeId_Descending(ByVal x As Long, ByVal y As Long) As Integer
2568 Return y.CompareTo(x)
2572 Public Function Compare_ModeName_Ascending(ByVal x As Long, ByVal y As Long) As Integer
2573 Dim result As Integer = String.Compare(_statuses.Item(x).Name, _statuses.Item(y).Name)
2574 If result = 0 Then result = x.CompareTo(y)
2579 Public Function Compare_ModeName_Descending(ByVal x As Long, ByVal y As Long) As Integer
2580 Dim result As Integer = String.Compare(_statuses.Item(y).Name, _statuses.Item(x).Name)
2581 If result = 0 Then result = y.CompareTo(x)
2586 Public Function Compare_ModeNickName_Ascending(ByVal x As Long, ByVal y As Long) As Integer
2587 Dim result As Integer = String.Compare(_statuses.Item(x).Nickname, _statuses.Item(y).Nickname)
2588 If result = 0 Then result = x.CompareTo(y)
2593 Public Function Compare_ModeNickName_Descending(ByVal x As Long, ByVal y As Long) As Integer
2594 Dim result As Integer = String.Compare(_statuses.Item(y).Nickname, _statuses.Item(x).Nickname)
2595 If result = 0 Then result = y.CompareTo(x)
2600 Public Function Compare_ModeSource_Ascending(ByVal x As Long, ByVal y As Long) As Integer
2601 Dim result As Integer = String.Compare(_statuses.Item(x).Source, _statuses.Item(y).Source)
2602 If result = 0 Then result = x.CompareTo(y)
2607 Public Function Compare_ModeSource_Descending(ByVal x As Long, ByVal y As Long) As Integer
2608 Dim result As Integer = String.Compare(_statuses.Item(y).Source, _statuses.Item(x).Source)
2609 If result = 0 Then result = y.CompareTo(x)