OSDN Git Service

キー難読化
[opentween/open-tween.git] / Tween / Tween.vb
index 99f821f..5f5b918 100644 (file)
@@ -132,7 +132,7 @@ Public Class TweenMain
     Private _anchorPost As PostClass
     Private _anchorFlag As Boolean        'True:関連発言移動中(関連移動以外のオペレーションをするとFalseへ。Trueだとリスト背景色をアンカー発言選択中として描画)
 
-    Private _history As New List(Of String)   '発言履歴
+    Private _history As New List(Of PostingStatus)   '発言履歴
     Private _hisIdx As Integer                  '発言履歴カレントインデックス
 
     '発言投稿時のAPI引数(発言編集時に設定。手書きreplyでは設定されない)
@@ -206,6 +206,8 @@ Public Class TweenMain
     'Private _FirstRefreshFlags As Boolean = False
     'Private _FirstListsRefreshFlags As Boolean = False
 
+    Private _DoFavRetweetFlags As Boolean = False
+
     '''''''''''''''''''''''''''''''''''''''''''''''''''''
     Private _postBrowserStatusText As String = ""
 
@@ -275,6 +277,14 @@ Public Class TweenMain
         Public inReplyToName As String = ""
         Public imageService As String = ""      '画像投稿サービス名
         Public imagePath As String = ""
+        Public Sub New()
+
+        End Sub
+        Public Sub New(ByVal status As String, ByVal replyToId As Long, ByVal replyToName As String)
+            Me.status = status
+            Me.inReplyToId = replyToId
+            Me.inReplyToName = replyToName
+        End Sub
     End Class
 
     Private Class SpaceKeyCanceler
@@ -319,11 +329,6 @@ Public Class TweenMain
         fDialog.Dispose()
         UrlDialog.Dispose()
         _spaceKeyCanceler.Dispose()
-        If TIconDic IsNot Nothing AndAlso TIconDic.Keys.Count > 0 Then
-            For Each value As Image In TIconDic.Values
-                value.Dispose()
-            Next
-        End If
         If NIconAt IsNot Nothing Then NIconAt.Dispose()
         If NIconAtRed IsNot Nothing Then NIconAtRed.Dispose()
         If NIconAtSmoke IsNot Nothing Then NIconAtSmoke.Dispose()
@@ -362,6 +367,7 @@ Public Class TweenMain
             _bwFollower.Dispose()
         End If
         Me._apiGauge.Dispose()
+        If TIconDic IsNot Nothing Then DirectCast(TIconDic, IDisposable).Dispose()
     End Sub
 
     Private Sub LoadIcon(ByRef IconInstance As Icon, ByVal FileName As String)
@@ -521,7 +527,7 @@ Public Class TweenMain
         TabDialog.Owner = Me
         UrlDialog.Owner = Me
 
-        _history.Add("")
+        _history.Add(New PostingStatus)
         _hisIdx = 0
         _reply_to_id = 0
         _reply_to_name = ""
@@ -879,6 +885,10 @@ Public Class TweenMain
         ShortUrl.BitlyKey = SettingDialog.BitlyPwd
         HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl
         HttpTwitter.TwitterSearchUrl = _cfgCommon.TwitterSearchUrl
+        tw.TrackWord = _cfgCommon.TrackWord
+        TrackToolStripMenuItem.Checked = Not String.IsNullOrEmpty(tw.TrackWord)
+        tw.AllAtReply = _cfgCommon.AllAtReply
+        AllrepliesToolStripMenuItem.Checked = tw.AllAtReply
 
         Outputz.Key = SettingDialog.OutputzKey
         Outputz.Enabled = SettingDialog.OutputzEnabled
@@ -1005,7 +1015,7 @@ Public Class TweenMain
         End If
 
         'アイコンリスト作成
-        TIconDic = New Dictionary(Of String, Image)
+        TIconDic = New ImageDictionary(5000)
 
         tw.DetailIcon = TIconDic
 
@@ -1625,7 +1635,7 @@ Public Class TweenMain
             End Select
         End If
 
-        _history(_history.Count - 1) = StatusText.Text.Trim
+        _history(_history.Count - 1) = New PostingStatus(StatusText.Text.Trim, _reply_to_id, _reply_to_name)
 
         If SettingDialog.UrlConvertAuto Then
             StatusText.SelectionStart = StatusText.Text.Length
@@ -1790,7 +1800,7 @@ Public Class TweenMain
         _reply_to_id = 0
         _reply_to_name = ""
         StatusText.Text = ""
-        _history.Add("")
+        _history.Add(New PostingStatus)
         _hisIdx = _history.Count - 1
         If Not ToolStripFocusLockMenuItem.Checked Then
             DirectCast(ListTab.SelectedTab.Tag, Control).Focus()
@@ -2049,6 +2059,11 @@ Public Class TweenMain
                 End If
                 '振り分け
                 rslt.addCount = _statuses.DistributePosts()
+            Case WORKERTYPE.Related
+                bw.ReportProgress(50, MakeStatusMessage(args, False))
+                Dim tb As TabClass = _statuses.GetTabByName(args.tName)
+                ret = tw.GetRelatedResultsApi(read, tb)
+                rslt.addCount = _statuses.DistributePosts()
         End Select
         'キャンセル要求
         If bw.CancellationPending Then
@@ -2130,6 +2145,8 @@ Public Class TweenMain
                     smsg = "Search refreshing..."
                 Case WORKERTYPE.List
                     smsg = "List refreshing..."
+                Case WORKERTYPE.Related
+                    smsg = "Related refreshing..."
             End Select
         Else
             '完了メッセージ
@@ -2154,6 +2171,8 @@ Public Class TweenMain
                     smsg = "Search refreshed"
                 Case WORKERTYPE.List
                     smsg = "List refreshed"
+                Case WORKERTYPE.Related
+                    smsg = "Related refreshed"
             End Select
         End If
         Return smsg
@@ -2266,7 +2285,8 @@ Public Class TweenMain
            rslt.type = WORKERTYPE.Favorites OrElse _
            rslt.type = WORKERTYPE.Follower OrElse _
            rslt.type = WORKERTYPE.FavAdd OrElse _
-           rslt.type = WORKERTYPE.FavRemove Then
+           rslt.type = WORKERTYPE.FavRemove OrElse _
+           rslt.type = WORKERTYPE.Related Then
             RefreshTimeline() 'リスト反映
         End If
 
@@ -2431,18 +2451,11 @@ Public Class TweenMain
 
 
     Private Sub FavoriteRetweetMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FavoriteRetweetMenuItem.Click, FavoriteRetweetContextMenu.Click
-        If _curList.SelectedIndices.Count > 1 AndAlso
-        MessageBox.Show(My.Resources.FavoriteRetweetQuestionText1, "Fav&Retweet", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) <> DialogResult.Yes Then
-            Exit Sub
-        End If
-
-        FavoriteChange(True, False)
-        doReTweetOfficial(False, False)
+        FavoritesRetweetOriginal()
     End Sub
 
     Private Sub FavoriteRetweetUnofficialMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FavoriteRetweetUnofficialMenuItem.Click, FavoriteRetweetUnofficialContextMenu.Click
-        FavoriteChange(True)
-        doReTweetUnofficial()
+        FavoritesRetweetUnofficial()
     End Sub
 
     Private Sub FavoriteChange(ByVal FavAdd As Boolean, Optional ByVal multiFavoriteChangeDialogEnable As Boolean = True)
@@ -2452,11 +2465,15 @@ Public Class TweenMain
         '複数fav確認msg
         If _curList.SelectedIndices.Count > 250 AndAlso FavAdd Then
             MessageBox.Show(My.Resources.FavoriteLimitCountText)
+            _DoFavRetweetFlags = False
             Exit Sub
         ElseIf multiFavoriteChangeDialogEnable AndAlso _curList.SelectedIndices.Count > 1 Then
             If FavAdd Then
-                If MessageBox.Show(My.Resources.FavAddToolStripMenuItem_ClickText1, My.Resources.FavAddToolStripMenuItem_ClickText2, _
+                Dim QuestionText As String = My.Resources.FavAddToolStripMenuItem_ClickText1
+                If _DoFavRetweetFlags Then QuestionText = My.Resources.FavoriteRetweetQuestionText3
+                If MessageBox.Show(QuestionText, My.Resources.FavAddToolStripMenuItem_ClickText2, _
                                    MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Cancel Then
+                    _DoFavRetweetFlags = False
                     Exit Sub
                 End If
             Else
@@ -2591,19 +2608,16 @@ Public Class TweenMain
         If ListTab.SelectedTab Is Nothing Then Exit Sub
         If _statuses Is Nothing OrElse _statuses.Tabs Is Nothing OrElse Not _statuses.Tabs.ContainsKey(ListTab.SelectedTab.Text) Then Exit Sub
         If _curPost Is Nothing Then
-            ShowProfileMenuItem.Enabled = False
-            ListManageUserContextToolStripMenuItem2.Enabled = False
             ReplyStripMenuItem.Enabled = False
             ReplyAllStripMenuItem.Enabled = False
             DMStripMenuItem.Enabled = False
+            ShowProfileMenuItem.Enabled = False
+            ListManageUserContextToolStripMenuItem2.Enabled = False
             MoveToFavToolStripMenuItem.Enabled = False
-            StatusOpenMenuItem.Enabled = False
-            FavorareMenuItem.Enabled = False
             TabMenuItem.Enabled = False
             IDRuleMenuItem.Enabled = False
             ReadedStripMenuItem.Enabled = False
             UnreadStripMenuItem.Enabled = False
-            DeleteStripMenuItem.Enabled = False
         Else
             ShowProfileMenuItem.Enabled = True
             ListManageUserContextToolStripMenuItem2.Enabled = True
@@ -2611,35 +2625,34 @@ Public Class TweenMain
             ReplyAllStripMenuItem.Enabled = True
             DMStripMenuItem.Enabled = True
             MoveToFavToolStripMenuItem.Enabled = True
-            StatusOpenMenuItem.Enabled = True
-            FavorareMenuItem.Enabled = True
             TabMenuItem.Enabled = True
             IDRuleMenuItem.Enabled = True
             ReadedStripMenuItem.Enabled = True
             UnreadStripMenuItem.Enabled = True
-            DeleteStripMenuItem.Enabled = True
         End If
-        If _statuses.Tabs(ListTab.SelectedTab.Text).TabType = TabUsageType.DirectMessage OrElse _curPost Is Nothing Then
+        If _statuses.Tabs(ListTab.SelectedTab.Text).TabType = TabUsageType.DirectMessage OrElse _curPost Is Nothing OrElse _curPost.IsDm Then
             FavAddToolStripMenuItem.Enabled = False
             FavRemoveToolStripMenuItem.Enabled = False
             StatusOpenMenuItem.Enabled = False
             FavorareMenuItem.Enabled = False
-        Else
-            If IsNetworkAvailable() Then
-                FavAddToolStripMenuItem.Enabled = True
-                FavRemoveToolStripMenuItem.Enabled = True
-                StatusOpenMenuItem.Enabled = True
-                FavorareMenuItem.Enabled = True
-            End If
-        End If
-        If _curPost Is Nothing OrElse _curPost.IsDm Then
+            ShowRelatedStatusesMenuItem.Enabled = False
+
             ReTweetStripMenuItem.Enabled = False
             ReTweetOriginalStripMenuItem.Enabled = False
             QuoteStripMenuItem.Enabled = False
+            FavoriteRetweetContextMenu.Enabled = False
+            FavoriteRetweetUnofficialContextMenu.Enabled = False
             If _curPost IsNot Nothing AndAlso _curPost.IsDm Then DeleteStripMenuItem.Enabled = True
         Else
+            FavAddToolStripMenuItem.Enabled = True
+            FavRemoveToolStripMenuItem.Enabled = True
+            StatusOpenMenuItem.Enabled = True
+            FavorareMenuItem.Enabled = True
+            ShowRelatedStatusesMenuItem.Enabled = True  'PublicSearchの時問題出るかも
+
             If _curPost.IsMe Then
                 ReTweetOriginalStripMenuItem.Enabled = False
+                FavoriteRetweetContextMenu.Enabled = False
                 DeleteStripMenuItem.Enabled = True
             Else
                 DeleteStripMenuItem.Enabled = False
@@ -2647,10 +2660,14 @@ Public Class TweenMain
                     ReTweetOriginalStripMenuItem.Enabled = False
                     ReTweetStripMenuItem.Enabled = False
                     QuoteStripMenuItem.Enabled = False
+                    FavoriteRetweetContextMenu.Enabled = False
+                    FavoriteRetweetUnofficialContextMenu.Enabled = False
                 Else
                     ReTweetOriginalStripMenuItem.Enabled = True
                     ReTweetStripMenuItem.Enabled = True
                     QuoteStripMenuItem.Enabled = True
+                    FavoriteRetweetContextMenu.Enabled = True
+                    FavoriteRetweetUnofficialContextMenu.Enabled = True
                 End If
             End If
         End If
@@ -3197,7 +3214,8 @@ Public Class TweenMain
             If tabType = TabUsageType.DirectMessage OrElse _
                tabType = TabUsageType.Favorites OrElse _
                tabType = TabUsageType.Home OrElse _
-               tabType = TabUsageType.Mentions Then
+               tabType = TabUsageType.Mentions OrElse _
+               tabType = TabUsageType.Related Then
                 If _statuses.GetTabByType(tabType) IsNot Nothing Then Return False
             End If
         End If
@@ -3379,7 +3397,7 @@ Public Class TweenMain
         _colHd8.Width = 50
 
         If (_statuses.Tabs.ContainsKey(tabName) AndAlso _statuses.Tabs(tabName).TabType = TabUsageType.Mentions) _
-           OrElse (Not _statuses.IsDefaultTab(tabName) AndAlso tabType <> TabUsageType.PublicSearch AndAlso tabType <> TabUsageType.Lists) Then
+           OrElse (Not _statuses.IsDefaultTab(tabName) AndAlso tabType <> TabUsageType.PublicSearch AndAlso tabType <> TabUsageType.Lists AndAlso tabType <> TabUsageType.Related) Then
             TabDialog.AddTab(tabName)
         End If
 
@@ -3749,7 +3767,8 @@ Public Class TweenMain
     Private Function GetRestStatusCount(ByVal isAuto As Boolean, ByVal isAddFooter As Boolean) As Integer
         '文字数カウント
         Dim pLen As Integer = 140 - StatusText.Text.Length
-        If (isAuto AndAlso Not My.Computer.Keyboard.ShiftKeyDown) OrElse _
+        If (isAuto AndAlso Not My.Computer.Keyboard.CtrlKeyDown AndAlso SettingDialog.PostShiftEnter) OrElse _
+           (isAuto AndAlso Not My.Computer.Keyboard.ShiftKeyDown AndAlso Not SettingDialog.PostShiftEnter) OrElse _
            (Not isAuto AndAlso isAddFooter) Then
             If SettingDialog.UseRecommendStatus Then
                 pLen -= SettingDialog.RecommendStatusText.Length
@@ -3791,7 +3810,7 @@ Public Class TweenMain
             Catch ex As Exception
                 '不正な要求に対する間に合わせの応答
                 Dim sitem() As String = {"", "", "", "", "", "", "", ""}
-                e.Item = New ListViewItem(sitem, "")
+                e.Item = New ImageListViewItem(sitem, "")
             End Try
         End If
     End Sub
@@ -3822,13 +3841,13 @@ Public Class TweenMain
         If Post.IsMark Then mk += "♪"
         If Post.IsProtect Then mk += "Ю"
         If Post.InReplyToId > 0 Then mk += "⇒"
-        Dim itm As ListViewItem
+        Dim itm As ImageListViewItem
         If Post.RetweetedId = 0 Then
             Dim sitem() As String = {"", Post.Nickname, Post.Data, Post.PDate.ToString(SettingDialog.DateTimeFormat), Post.Name, "", mk, Post.Source}
-            itm = New ListViewItem(sitem, Post.ImageUrl)
+            itm = New ImageListViewItem(sitem, DirectCast(Me.TIconDic, ImageDictionary), Post.ImageUrl)
         Else
             Dim sitem() As String = {"", Post.Nickname, Post.Data, Post.PDate.ToString(SettingDialog.DateTimeFormat), Post.Name + Environment.NewLine + "(RT:" + Post.RetweetedBy + ")", "", mk, Post.Source}
-            itm = New ListViewItem(sitem, Post.ImageUrl)
+            itm = New ImageListViewItem(sitem, DirectCast(Me.TIconDic, ImageDictionary), Post.ImageUrl)
         End If
 
         Dim read As Boolean = Post.IsRead
@@ -4095,9 +4114,10 @@ Public Class TweenMain
     End Sub
 
     Private Sub DrawListViewItemIcon(ByVal e As DrawListViewSubItemEventArgs)
-        If Not String.IsNullOrEmpty(e.Item.ImageKey) AndAlso Me.TIconDic.ContainsKey(e.Item.ImageKey) Then
+        Dim item As ImageListViewItem = DirectCast(e.Item, ImageListViewItem)
+        If item.Image IsNot Nothing Then
             'e.Bounds.Leftが常に0を指すから自前で計算
-            Dim itemRect As Rectangle = e.Item.Bounds
+            Dim itemRect As Rectangle = item.Bounds
             itemRect.Width = e.Item.ListView.Columns(0).Width
 
             For Each clm As ColumnHeader In e.Item.ListView.Columns
@@ -4112,7 +4132,7 @@ Public Class TweenMain
             If iconRect.Width > 0 Then
                 e.Graphics.FillRectangle(Brushes.White, iconRect)
                 e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.High
-                e.Graphics.DrawImage(Me.TIconDic(e.Item.ImageKey), iconRect)
+                e.Graphics.DrawImage(item.Image, iconRect)
             End If
         End If
     End Sub
@@ -4505,8 +4525,18 @@ RETRY:
         If Not String.IsNullOrEmpty(_curPost.RetweetedBy) Then
             NameLabel.Text += " (RT:" + _curPost.RetweetedBy + ")"
         End If
+        If UserPicture.Image IsNot Nothing Then UserPicture.Image.Dispose()
         If Not String.IsNullOrEmpty(_curPost.ImageUrl) AndAlso TIconDic.ContainsKey(_curPost.ImageUrl) Then
             UserPicture.Image = TIconDic(_curPost.ImageUrl)
+
+            'Dim dummy As Image = DirectCast(TIconDic, ImageDictionary)(_curPost.ImageUrl, Sub(getImg)
+            '                                                                                  If img IsNot Nothing Then img.Dispose()
+            '                                                                                  If getImg Is Nothing Then Exit Sub
+            '                                                                                  img = DirectCast(getImg.Clone(), Image)
+            '                                                                                  Me.Invoke(Sub()
+            '                                                                                                Me.UserPicture.Image = img
+            '                                                                                            End Sub)
+            '                                                                              End Sub)
         Else
             UserPicture.Image = Nothing
         End If
@@ -4979,6 +5009,19 @@ RETRY:
             End If
         End If
 
+        If e.Alt AndAlso e.Control Then
+            ' CTRL+ALTキーが押されている場合
+            If e.KeyCode = Keys.S Then
+                e.Handled = True
+                e.SuppressKeyPress = True
+                FavoritesRetweetOriginal()
+            ElseIf e.KeyCode = Keys.R Then
+                e.Handled = True
+                e.SuppressKeyPress = True
+                FavoritesRetweetUnofficial()
+            End If
+        End If
+
     End Sub
 
     Private Sub ScrollDownPostBrowser(ByVal forward As Boolean)
@@ -5454,7 +5497,9 @@ RETRY:
             If e.KeyCode = Keys.A Then
                 StatusText.SelectAll()
             ElseIf e.KeyCode = Keys.Up OrElse e.KeyCode = Keys.Down Then
-                If StatusText.Text.Trim() <> "" Then _history(_hisIdx) = StatusText.Text
+                If StatusText.Text.Trim() <> "" Then
+                    _history(_hisIdx) = New PostingStatus(StatusText.Text, _reply_to_id, _reply_to_name)
+                End If
                 If e.KeyCode = Keys.Up Then
                     _hisIdx -= 1
                     If _hisIdx < 0 Then _hisIdx = 0
@@ -5462,7 +5507,9 @@ RETRY:
                     _hisIdx += 1
                     If _hisIdx > _history.Count - 1 Then _hisIdx = _history.Count - 1
                 End If
-                StatusText.Text = _history(_hisIdx)
+                StatusText.Text = _history(_hisIdx).status
+                _reply_to_id = _history(_hisIdx).inReplyToId
+                _reply_to_name = _history(_hisIdx).inReplyToName
                 StatusText.SelectionStart = StatusText.Text.Length
                 e.Handled = True
                 e.SuppressKeyPress = True
@@ -5696,6 +5743,20 @@ RETRY:
                 Thumbnail.ScrollThumbnail(True)
             End If
         End If
+
+        ' Alt + Control キー
+        If e.Alt AndAlso e.Control Then
+            If e.KeyCode = Keys.S Then
+                e.Handled = True
+                e.SuppressKeyPress = True
+                FavoritesRetweetOriginal()
+            ElseIf e.KeyCode = Keys.R Then
+                e.Handled = True
+                e.SuppressKeyPress = True
+                FavoritesRetweetUnofficial()
+            End If
+        End If
+
         Me.StatusText_TextChanged(Nothing, Nothing)
     End Sub
 
@@ -5824,6 +5885,8 @@ RETRY:
             _cfgCommon.FirstCountApi = SettingDialog.FirstCountApi
             _cfgCommon.SearchCountApi = SettingDialog.SearchCountApi
             _cfgCommon.FavoritesCountApi = SettingDialog.FavoritesCountApi
+            _cfgCommon.TrackWord = tw.TrackWord
+            _cfgCommon.AllAtReply = tw.AllAtReply
 
             _cfgCommon.Save()
         End SyncLock
@@ -5878,7 +5941,7 @@ RETRY:
     Private Sub SaveConfigsTabs()
         Dim tabSetting As New SettingTabs
         For i As Integer = 0 To ListTab.TabPages.Count - 1
-            tabSetting.Tabs.Add(_statuses.Tabs(ListTab.TabPages(i).Text))
+            If _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.Related Then tabSetting.Tabs.Add(_statuses.Tabs(ListTab.TabPages(i).Text))
         Next
         tabSetting.Save()
     End Sub
@@ -6109,6 +6172,18 @@ RETRY:
 
         End If
 
+        'CtrlKey + AltKey + 何か
+        If e.Modifiers = (Keys.Control Or Keys.Alt) Then
+            Select Case e.KeyCode
+                Case Keys.R
+                    e.IsInputKey = True
+                    FavoritesRetweetUnofficial()
+                Case Keys.S
+                    e.IsInputKey = True
+                    FavoritesRetweetOriginal()
+            End Select
+        End If
+
     End Sub
     Public Function TabRename(ByRef tabName As String) As Boolean
         'タブ名変更
@@ -6133,7 +6208,7 @@ RETRY:
             'タブ名のリスト作り直し(デフォルトタブ以外は再作成)
             For i As Integer = 0 To ListTab.TabCount - 1
                 If _statuses.Tabs(ListTab.TabPages(i).Text).TabType = TabUsageType.Mentions OrElse _
-                   (Not _statuses.IsDefaultTab(ListTab.TabPages(i).Text) AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.PublicSearch AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.Lists) Then
+                   (Not _statuses.IsDefaultTab(ListTab.TabPages(i).Text) AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.PublicSearch AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.Lists AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.Related) Then
                     TabDialog.RemoveTab(ListTab.TabPages(i).Text)
                 End If
                 If ListTab.TabPages(i).Text = tabName Then
@@ -6144,7 +6219,7 @@ RETRY:
 
             For i As Integer = 0 To ListTab.TabCount - 1
                 If _statuses.Tabs(ListTab.TabPages(i).Text).TabType = TabUsageType.Mentions OrElse _
-                   (Not _statuses.IsDefaultTab(ListTab.TabPages(i).Text) AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.PublicSearch AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.Lists) Then
+                   (Not _statuses.IsDefaultTab(ListTab.TabPages(i).Text) AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.PublicSearch AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.Lists AndAlso _statuses.Tabs(ListTab.TabPages(i).Text).TabType <> TabUsageType.Related) Then
                     If ListTab.TabPages(i).Text = tabName Then
                         ListTab.TabPages(i).Text = newTabText
                     End If
@@ -6499,15 +6574,34 @@ RETRY:
     End Sub
 
     Private Sub TimerRefreshIcon_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerRefreshIcon.Tick
+        '200ms
         If _colorize Then Colorize()
         If Not TimerRefreshIcon.Enabled Then Exit Sub
         Static iconCnt As Integer = 0
         Static blinkCnt As Integer = 0
         Static blink As Boolean = False
         Static idle As Boolean = False
+        Static usCheckCnt As Integer = 0
+
+        Static iconDlListTopItem As ListViewItem = Nothing
+        If DirectCast(ListTab.SelectedTab.Tag, ListView).TopItem Is iconDlListTopItem Then
+            DirectCast(Me.TIconDic, ImageDictionary).PauseGetImage = False
+        Else
+            DirectCast(Me.TIconDic, ImageDictionary).PauseGetImage = True
+        End If
+        iconDlListTopItem = DirectCast(ListTab.SelectedTab.Tag, ListView).TopItem
 
         iconCnt += 1
         blinkCnt += 1
+        usCheckCnt += 1
+
+        If usCheckCnt > 300 Then    '1min
+            usCheckCnt = 0
+            If Not Me.IsReceivedUserStream Then
+                TraceOut("ReconnectUserStream")
+                tw.ReconnectUserStream()
+            End If
+        End If
 
         Dim busy As Boolean = False
         For Each bw As BackgroundWorker In Me._bw
@@ -7099,13 +7193,19 @@ RETRY:
 
     Private Sub ClearTabMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ClearTabMenuItem.Click, ClearTbMenuItem.Click
         If String.IsNullOrEmpty(_rclickTabName) Then Exit Sub
-        Dim tmp As String = String.Format(My.Resources.ClearTabMenuItem_ClickText1, Environment.NewLine)
-        If MessageBox.Show(tmp, _rclickTabName + " " + My.Resources.ClearTabMenuItem_ClickText2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Cancel Then
-            Exit Sub
+        ClearTab(_rclickTabName, True)
+    End Sub
+
+    Private Sub ClearTab(ByVal tabName As String, ByVal showWarning As Boolean)
+        If showWarning Then
+            Dim tmp As String = String.Format(My.Resources.ClearTabMenuItem_ClickText1, Environment.NewLine)
+            If MessageBox.Show(tmp, tabName + " " + My.Resources.ClearTabMenuItem_ClickText2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Cancel Then
+                Exit Sub
+            End If
         End If
 
-        _statuses.ClearTabIds(_rclickTabName)
-        If ListTab.SelectedTab.Text = _rclickTabName Then
+        _statuses.ClearTabIds(tabName)
+        If ListTab.SelectedTab.Text = tabName Then
             _anchorPost = Nothing
             _anchorFlag = False
             _itemCache = Nothing
@@ -7115,7 +7215,7 @@ RETRY:
             _curPost = Nothing
         End If
         For Each tb As TabPage In ListTab.TabPages
-            If tb.Text = _rclickTabName Then
+            If tb.Text = tabName Then
                 tb.ImageIndex = -1
                 DirectCast(tb.Tag, DetailsListView).VirtualListSize = 0
                 Exit For
@@ -7151,7 +7251,7 @@ RETRY:
                 ttl.Append("Ver:").Append(myVer)
             Case DispTitleEnum.Post
                 If _history IsNot Nothing AndAlso _history.Count > 1 Then
-                    ttl.Append(_history(_history.Count - 2).Replace(vbCrLf, ""))
+                    ttl.Append(_history(_history.Count - 2).status.Replace(vbCrLf, ""))
                 End If
             Case DispTitleEnum.UnreadRepCount
                 ttl.AppendFormat(My.Resources.SetMainWindowTitleText1, _statuses.GetTabByType(TabUsageType.Mentions).UnreadCount + _statuses.GetTabByType(TabUsageType.DirectMessage).UnreadCount)
@@ -8192,6 +8292,16 @@ RETRY:
             End If
         End If
         _initial = False
+        AddHandler tw.NewPostFromStream, AddressOf tw_NewPostFromStream
+        AddHandler tw.UserStreamStarted, AddressOf tw_UserStreamStarted
+        AddHandler tw.UserStreamStopped, AddressOf tw_UserStreamStopped
+        AddHandler tw.UserStreamPaused, AddressOf tw_UserStreamPaused
+        AddHandler tw.PostDeleted, AddressOf tw_PostDeleted
+        PauseToolStripMenuItem.Text = "&Pause"
+        PauseToolStripMenuItem.Enabled = False
+        StopToolStripMenuItem.Text = "&Start"
+        StopToolStripMenuItem.Enabled = True
+        tw.StartUserStream()
         TimerTimeline.Enabled = True
     End Sub
 
@@ -8228,24 +8338,36 @@ RETRY:
         doReTweetUnofficial()
     End Sub
 
-    Private Sub doReTweetOfficial(ByVal isConfirm As Boolean, Optional ByVal multiReTweetDialogEnable As Boolean = True)
+    Private Sub doReTweetOfficial(ByVal isConfirm As Boolean)
         '公式RT
-        If _curPost IsNot Nothing AndAlso Not _curPost.IsDm AndAlso Not _curPost.IsMe Then
+        If _curPost IsNot Nothing Then
             If _curPost.IsProtect Then
                 MessageBox.Show("Protected.")
+                _DoFavRetweetFlags = False
                 Exit Sub
             End If
             If _curList.SelectedIndices.Count > 15 Then
                 MessageBox.Show(My.Resources.RetweetLimitText)
+                _DoFavRetweetFlags = False
                 Exit Sub
-            ElseIf multiReTweetDialogEnable AndAlso _curList.SelectedIndices.Count > 1 Then
-                Select Case MessageBox.Show(My.Resources.RetweetQuestion2, "Retweet", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
+            ElseIf _curList.SelectedIndices.Count > 1 Then
+                Dim QuestionText As String = My.Resources.RetweetQuestion2
+                If _DoFavRetweetFlags Then QuestionText = My.Resources.FavoriteRetweetQuestionText1
+                Select Case MessageBox.Show(QuestionText, "Retweet", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
                     Case Windows.Forms.DialogResult.Cancel, Windows.Forms.DialogResult.No
+                        _DoFavRetweetFlags = False
                         Exit Sub
                 End Select
             Else
+                If _curPost.IsDm OrElse _curPost.IsMe Then
+                    _DoFavRetweetFlags = False
+                    Exit Sub
+                End If
                 If Not SettingDialog.RetweetNoConfirm Then
-                    If isConfirm AndAlso MessageBox.Show(My.Resources.RetweetQuestion1, "Retweet", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Cancel Then
+                    Dim Questiontext As String = My.Resources.RetweetQuestion1
+                    If _DoFavRetweetFlags Then Questiontext = My.Resources.FavoritesRetweetQuestionText2
+                    If isConfirm AndAlso MessageBox.Show(Questiontext, "Retweet", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Cancel Then
+                        _DoFavRetweetFlags = False
                         Exit Sub
                     End If
                 End If
@@ -8267,6 +8389,27 @@ RETRY:
         doReTweetOfficial(True)
     End Sub
 
+    Private Sub FavoritesRetweetOriginal()
+        If _curPost Is Nothing Then Exit Sub
+        _DoFavRetweetFlags = True
+        doReTweetOfficial(True)
+        If _DoFavRetweetFlags Then
+            _DoFavRetweetFlags = False
+            FavoriteChange(True, False)
+        End If
+    End Sub
+
+    Private Sub FavoritesRetweetUnofficial()
+        If _curPost IsNot Nothing AndAlso Not _curPost.IsDm Then
+            _DoFavRetweetFlags = True
+            FavoriteChange(True)
+            If Not _curPost.IsProtect AndAlso _DoFavRetweetFlags Then
+                _DoFavRetweetFlags = False
+                doReTweetUnofficial()
+            End If
+        End If
+    End Sub
+
     Private Function CreateRetweetUnofficial(ByVal status As String) As String
 
         ' Twitterにより省略されているURLを含むaタグをキャプチャしてリンク先URLへ置き換える
@@ -8287,7 +8430,7 @@ RETRY:
         End If
 
         'その他のリンク(@IDなど)を置き換える
-        status = Regex.Replace(status, "@<a target=""_self"" href=""https?://twitter.com/(#!/)?(?<url>[^""]+)""[^>]*>(?<link>[^<]+)</a>", "${url}")
+        status = Regex.Replace(status, "@<a target=""_self"" href=""https?://twitter.com/(#!/)?(?<url>[^""]+)""[^>]*>(?<link>[^<]+)</a>", "@${url}")
         'ハッシュタグ
         status = Regex.Replace(status, "<a target=""_self"" href=""(?<url>[^""]+)""[^>]*>(?<link>[^<]+)</a>", "${link}")
         '<br>タグ除去
@@ -8834,7 +8977,7 @@ RETRY:
         End If
     End Sub
 
-    Private Sub ListManageUserContextToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListManageUserContextToolStripMenuItem.Click, ToolStripMenuItem9.Click, ListManageUserContextToolStripMenuItem2.Click, ListManageUserContextToolStripMenuItem3.Click
+    Private Sub ListManageUserContextToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListManageUserContextToolStripMenuItem.Click, ListManageMenuItem.Click, ListManageUserContextToolStripMenuItem2.Click, ListManageUserContextToolStripMenuItem3.Click
         Dim user As String
 
         Dim menuItem As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
@@ -8958,41 +9101,67 @@ RETRY:
     Private Sub MenuItemOperate_DropDownOpening(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItemOperate.DropDownOpening
         If ListTab.SelectedTab Is Nothing Then Exit Sub
         If _statuses Is Nothing OrElse _statuses.Tabs Is Nothing OrElse Not _statuses.Tabs.ContainsKey(ListTab.SelectedTab.Text) Then Exit Sub
-        If _statuses.Tabs(ListTab.SelectedTab.Text).TabType = TabUsageType.DirectMessage Then
+        If _curPost Is Nothing Then
+            Me.ReplyOpMenuItem.Enabled = False
+            Me.ReplyAllOpMenuItem.Enabled = False
+            Me.DmOpMenuItem.Enabled = False
+            Me.ShowProfMenuItem.Enabled = False
+            Me.ListManageMenuItem.Enabled = False
+            Me.OpenFavOpMenuItem.Enabled = False
+            Me.CreateTabRuleOpMenuItem.Enabled = False
+            Me.CreateIdRuleOpMenuItem.Enabled = False
+            Me.ReadOpMenuItem.Enabled = False
+            Me.UnreadOpMenuItem.Enabled = False
+        Else
+            Me.ReplyOpMenuItem.Enabled = True
+            Me.ReplyAllOpMenuItem.Enabled = True
+            Me.DmOpMenuItem.Enabled = True
+            Me.ShowProfMenuItem.Enabled = True
+            Me.ListManageMenuItem.Enabled = True
+            Me.OpenFavOpMenuItem.Enabled = True
+            Me.CreateTabRuleOpMenuItem.Enabled = True
+            Me.CreateIdRuleOpMenuItem.Enabled = True
+            Me.ReadOpMenuItem.Enabled = True
+            Me.UnreadOpMenuItem.Enabled = True
+        End If
+
+        If _statuses.Tabs(ListTab.SelectedTab.Text).TabType = TabUsageType.DirectMessage OrElse _curPost Is Nothing OrElse _curPost.IsDm Then
             Me.FavOpMenuItem.Enabled = False
             Me.UnFavOpMenuItem.Enabled = False
             Me.OpenStatusOpMenuItem.Enabled = False
             Me.OpenFavotterOpMenuItem.Enabled = False
-        Else
-            Me.FavOpMenuItem.Enabled = True
-            Me.UnFavOpMenuItem.Enabled = True
-            Me.OpenStatusOpMenuItem.Enabled = True
-            Me.OpenFavotterOpMenuItem.Enabled = True
-        End If
-        If _curPost Is Nothing OrElse _curPost.IsDm Then
+            Me.ShowRelatedStatusesMenuItem2.Enabled = False
             Me.RtOpMenuItem.Enabled = False
             Me.RtUnOpMenuItem.Enabled = False
             Me.QtOpMenuItem.Enabled = False
+            Me.FavoriteRetweetMenuItem.Enabled = False
+            Me.FavoriteRetweetUnofficialMenuItem.Enabled = False
             If _curPost IsNot Nothing AndAlso _curPost.IsDm Then Me.DelOpMenuItem.Enabled = True
         Else
-            If _curPost.IsProtect Then
+            Me.FavOpMenuItem.Enabled = True
+            Me.UnFavOpMenuItem.Enabled = True
+            Me.OpenStatusOpMenuItem.Enabled = True
+            Me.OpenFavotterOpMenuItem.Enabled = True
+            Me.ShowRelatedStatusesMenuItem2.Enabled = True  'PublicSearchの時問題出るかも
+
+            If _curPost.IsMe Then
                 Me.RtOpMenuItem.Enabled = False
-                Me.RtUnOpMenuItem.Enabled = False
-                Me.QtOpMenuItem.Enabled = False
-                If _curPost.IsMe Then
-                    Me.DelOpMenuItem.Enabled = True
-                Else
-                    Me.DelOpMenuItem.Enabled = False
-                End If
+                Me.FavoriteRetweetMenuItem.Enabled = False
+                Me.DelOpMenuItem.Enabled = True
             Else
-                Me.RtOpMenuItem.Enabled = True
-                Me.RtUnOpMenuItem.Enabled = True
-                Me.QtOpMenuItem.Enabled = True
-                If _curPost.IsMe Then
+                Me.DelOpMenuItem.Enabled = False
+                If _curPost.IsProtect Then
                     Me.RtOpMenuItem.Enabled = False
-                    Me.DelOpMenuItem.Enabled = True
+                    Me.RtUnOpMenuItem.Enabled = False
+                    Me.QtOpMenuItem.Enabled = False
+                    Me.FavoriteRetweetMenuItem.Enabled = False
+                    Me.FavoriteRetweetUnofficialMenuItem.Enabled = False
                 Else
-                    Me.DelOpMenuItem.Enabled = False
+                    Me.RtOpMenuItem.Enabled = True
+                    Me.RtUnOpMenuItem.Enabled = True
+                    Me.QtOpMenuItem.Enabled = True
+                    Me.FavoriteRetweetMenuItem.Enabled = True
+                    Me.FavoriteRetweetUnofficialMenuItem.Enabled = True
                 End If
             End If
         End If
@@ -9003,8 +9172,8 @@ RETRY:
             Me.RefreshPrevOpMenuItem.Enabled = False
         End If
         If _statuses.Tabs(ListTab.SelectedTab.Text).TabType = TabUsageType.PublicSearch _
-            OrElse _curPost Is Nothing _
-            OrElse Not _curPost.InReplyToId > 0 Then
+                            OrElse _curPost Is Nothing _
+                            OrElse Not _curPost.InReplyToId > 0 Then
             OpenRepSourceOpMenuItem.Enabled = False
         Else
             OpenRepSourceOpMenuItem.Enabled = True
@@ -9014,37 +9183,6 @@ RETRY:
         Else
             OpenRterHomeMenuItem.Enabled = True
         End If
-        If _curPost Is Nothing Then
-            Me.ReplyOpMenuItem.Enabled = False
-            Me.ReplyAllOpMenuItem.Enabled = False
-            Me.DmOpMenuItem.Enabled = False
-            Me.FavOpMenuItem.Enabled = False
-            Me.UnFavOpMenuItem.Enabled = False
-            Me.OpenFavOpMenuItem.Enabled = False
-            Me.OpenStatusOpMenuItem.Enabled = False
-            Me.OpenFavotterOpMenuItem.Enabled = False
-            Me.CreateTabRuleOpMenuItem.Enabled = False
-            Me.CreateIdRuleOpMenuItem.Enabled = False
-            Me.ReadOpMenuItem.Enabled = False
-            Me.UnreadOpMenuItem.Enabled = False
-            Me.ShowProfMenuItem.Enabled = False
-            Me.ToolStripMenuItem9.Enabled = False
-        Else
-            Me.ReplyOpMenuItem.Enabled = True
-            Me.ReplyAllOpMenuItem.Enabled = True
-            Me.DmOpMenuItem.Enabled = True
-            Me.FavOpMenuItem.Enabled = True
-            Me.UnFavOpMenuItem.Enabled = True
-            Me.OpenFavOpMenuItem.Enabled = True
-            Me.OpenStatusOpMenuItem.Enabled = True
-            Me.OpenFavotterOpMenuItem.Enabled = True
-            Me.CreateTabRuleOpMenuItem.Enabled = True
-            Me.CreateIdRuleOpMenuItem.Enabled = True
-            Me.ReadOpMenuItem.Enabled = True
-            Me.UnreadOpMenuItem.Enabled = True
-            Me.ShowProfMenuItem.Enabled = True
-            Me.ToolStripMenuItem9.Enabled = True
-        End If
     End Sub
 
     Private Sub MenuItemTab_DropDownOpening(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItemTab.DropDownOpening
@@ -9568,10 +9706,10 @@ RETRY:
     End Sub
 
     Private Sub MenuItemCommand_DropDownOpening(ByVal sender As Object, ByVal e As System.EventArgs) Handles MenuItemCommand.DropDownOpening
-        If _curPost Is Nothing Then
-            RtCountMenuItem.Enabled = False
-        Else
+        If _curPost IsNot Nothing AndAlso Not _curPost.IsDm Then
             RtCountMenuItem.Enabled = True
+        Else
+            RtCountMenuItem.Enabled = False
         End If
     End Sub
 
@@ -9587,4 +9725,202 @@ RETRY:
             MessageBox.Show(ex.Message)
         End Try
     End Sub
+
+    Private Sub ShowRelatedStatusesMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ShowRelatedStatusesMenuItem.Click, ShowRelatedStatusesMenuItem2.Click
+        If _curPost IsNot Nothing AndAlso Not _curPost.IsDm Then
+            'PublicSearchも除外した方がよい?
+            If _statuses.GetTabByType(TabUsageType.Related) Is Nothing Then
+                Const TabName As String = "Related Tweets"
+                Dim tName As String = TabName
+                If Not Me.AddNewTab(tName, False, TabUsageType.Related) Then
+                    For i As Integer = 2 To 100
+                        tName = TabName + i.ToString()
+                        If Me.AddNewTab(tName, False, TabUsageType.Related) Then
+                            _statuses.AddTab(tName, TabUsageType.Related, Nothing)
+                            Exit For
+                        End If
+                    Next
+                Else
+                    _statuses.AddTab(tName, TabUsageType.Related, Nothing)
+                End If
+            End If
+
+            Dim tb As TabClass = _statuses.GetTabByType(TabUsageType.Related)
+            tb.RelationTargetId = _curPost.Id
+            Me.ClearTab(tb.TabName, False)
+            For i As Integer = 0 To ListTab.TabPages.Count - 1
+                If tb.TabName = ListTab.TabPages(i).Text Then
+                    ListTab.SelectedIndex = i
+                    ListTabSelect(ListTab.TabPages(i))
+                    Exit For
+                End If
+            Next
+
+            GetTimeline(WORKERTYPE.Related, 1, 1, tb.TabName)
+        End If
+    End Sub
+
+    Private Sub CacheInfoMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CacheInfoMenuItem.Click
+        Dim buf As New StringBuilder
+        buf.AppendFormat("キャッシュメモリ容量         : {0}bytes({1}MB)" + vbCrLf, DirectCast(TIconDic, ImageDictionary).CacheMemoryLimit, DirectCast(TIconDic, ImageDictionary).CacheMemoryLimit / 1048576)
+        buf.AppendFormat("物理メモリ使用割合           : {0}%" + vbCrLf, DirectCast(TIconDic, ImageDictionary).PhysicalMemoryLimit)
+        buf.AppendFormat("キャッシュエントリ保持数     : {0}" + vbCrLf, DirectCast(TIconDic, ImageDictionary).CacheCount)
+        buf.AppendFormat("キャッシュエントリ破棄数     : {0}" + vbCrLf, DirectCast(TIconDic, ImageDictionary).CacheRemoveCount)
+        MessageBox.Show(buf.ToString, "アイコンキャッシュ使用状況")
+    End Sub
+
+    Private Sub tw_PostDeleted(ByVal id As Long)
+        Try
+            If InvokeRequired Then
+                Invoke(New Action(Of Long)(AddressOf tw_PostDeleted), id)
+                Exit Sub
+            End If
+        Catch ex As ObjectDisposedException
+            Exit Sub
+        End Try
+
+        _statuses.RemovePost(id)
+
+        Me.RefreshTimeline()
+    End Sub
+
+    Private Sub tw_NewPostFromStream()
+        If SettingDialog.ReadOldPosts Then
+            _statuses.SetRead() '新着時未読クリア
+        End If
+
+        Dim rsltAddCount As Integer = _statuses.DistributePosts()
+        SyncLock _syncObject
+            Dim tm As Date = Now
+            If _tlTimestamps.ContainsKey(tm) Then
+                _tlTimestamps(tm) += rsltAddCount
+            Else
+                _tlTimestamps.Add(Now, rsltAddCount)
+            End If
+            Dim oneHour As Date = Now.Subtract(New TimeSpan(1, 0, 0))
+            Dim keys As New List(Of Date)
+            _tlCount = 0
+            For Each key As Date In _tlTimestamps.Keys
+                If key.CompareTo(oneHour) < 0 Then
+                    keys.Add(key)
+                Else
+                    _tlCount += _tlTimestamps(key)
+                End If
+            Next
+            For Each key As Date In keys
+                _tlTimestamps.Remove(key)
+            Next
+            keys.Clear()
+
+            'Static before As DateTime = Now
+            'If before.Subtract(Now).Seconds > -5 Then Exit Sub
+            'before = Now
+        End SyncLock
+
+        Try
+            If InvokeRequired AndAlso Not IsDisposed Then
+                Invoke(New MethodInvoker(AddressOf RefreshTimeline))
+                Exit Sub
+            End If
+        Catch ex As ObjectDisposedException
+            Exit Sub
+        End Try
+    End Sub
+    Private Sub tw_UserStreamStarted()
+        If InvokeRequired Then
+            Invoke(New MethodInvoker(AddressOf tw_UserStreamStarted))
+            Exit Sub
+        End If
+
+        MenuItemUserStream.Text = "&UserStream ▶"
+        MenuItemUserStream.Enabled = True
+        PauseToolStripMenuItem.Text = "&Pause"
+        PauseToolStripMenuItem.Enabled = True
+        StopToolStripMenuItem.Text = "&Stop"
+        StopToolStripMenuItem.Enabled = True
+
+        StatusLabel.Text = "UserStream Started."
+    End Sub
+
+    Private Sub tw_UserStreamStopped()
+        If InvokeRequired Then
+            Invoke(New MethodInvoker(AddressOf tw_UserStreamStopped))
+            Exit Sub
+        End If
+
+        MenuItemUserStream.Text = "&UserStream ■"
+        MenuItemUserStream.Enabled = True
+        PauseToolStripMenuItem.Text = "&Pause"
+        PauseToolStripMenuItem.Enabled = False
+        StopToolStripMenuItem.Text = "&Start"
+        StopToolStripMenuItem.Enabled = True
+
+        StatusLabel.Text = "UserStream Stopped."
+    End Sub
+
+    Private Sub tw_UserStreamPaused()
+        If InvokeRequired Then
+            Invoke(New MethodInvoker(AddressOf tw_UserStreamPaused))
+            Exit Sub
+        End If
+
+        MenuItemUserStream.Text = "&UserStream ||"
+        MenuItemUserStream.Enabled = True
+        PauseToolStripMenuItem.Text = "&Resume"
+        PauseToolStripMenuItem.Enabled = True
+        StopToolStripMenuItem.Text = "&Stop"
+        StopToolStripMenuItem.Enabled = True
+
+        StatusLabel.Text = "UserStream Paused."
+    End Sub
+
+    Private ReadOnly Property IsReceivedUserStream As Boolean
+        Get
+            Static lastTime As DateTime
+            Dim changed As Boolean = (lastTime.CompareTo(tw.LastReceivedUserStream) < 0)
+            lastTime = tw.LastReceivedUserStream
+            Return changed
+        End Get
+    End Property
+
+    Private Sub PauseToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PauseToolStripMenuItem.Click
+        MenuItemUserStream.Enabled = False
+        tw.PauseUserStream()
+    End Sub
+
+    Private Sub StopToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopToolStripMenuItem.Click
+        MenuItemUserStream.Enabled = False
+        tw.StartUserStream()
+    End Sub
+
+    Private Sub TrackToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrackToolStripMenuItem.Click
+        Static inputTrack As String = ""
+        If TrackToolStripMenuItem.Checked Then
+            Using inputForm As New InputTabName
+                inputForm.TabName = inputTrack
+                inputForm.FormTitle = "Input track word"
+                inputForm.FormDescription = "Track word"
+                If inputForm.ShowDialog() <> Windows.Forms.DialogResult.OK Then
+                    TrackToolStripMenuItem.Checked = False
+                    Exit Sub
+                End If
+                inputTrack = inputForm.TabName.Trim()
+            End Using
+            If Not inputTrack.Equals(tw.TrackWord) Then
+                tw.TrackWord = inputTrack
+                Me._modifySettingCommon = True
+                TrackToolStripMenuItem.Checked = Not String.IsNullOrEmpty(inputTrack)
+                tw.ReconnectUserStream()
+            End If
+        Else
+            tw.TrackWord = ""
+            tw.ReconnectUserStream()
+        End If
+    End Sub
+
+    Private Sub AllrepliesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AllrepliesToolStripMenuItem.Click
+        tw.AllAtReply = AllrepliesToolStripMenuItem.Checked
+        Me._modifySettingCommon = True
+        tw.ReconnectUserStream()
+    End Sub
 End Class