OSDN Git Service

Win32ApiクラスをNativeMethodsクラスに名前変更 (CA1060)
[opentween/open-tween.git] / OpenTween / Tween.cs
index d71d35e..56b20f2 100644 (file)
@@ -53,8 +53,6 @@ namespace OpenTween
 {
     public partial class TweenMain : OTBaseForm
     {
-        private readonly HttpClient http;
-
         //各種設定
         private Size _mySize;           //画面サイズ
         private Point _myLoc;           //画面位置
@@ -362,8 +360,6 @@ namespace OpenTween
                 this.IconCache.Dispose();
             }
 
-            this.http.Dispose();
-
             // 終了時にRemoveHandlerしておかないとメモリリークする
             // http://msdn.microsoft.com/ja-jp/library/microsoft.win32.systemevents.powermodechanged.aspx
             Microsoft.Win32.SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
@@ -664,7 +660,7 @@ namespace OpenTween
             ////設定読み出し
             LoadConfig();
 
-            ThumbnailGenerator.InitializeGenerator(this.http);
+            ThumbnailGenerator.InitializeGenerator();
 
             var imgazyobizinet = ThumbnailGenerator.ImgAzyobuziNetInstance;
             imgazyobizinet.Enabled = this._cfgCommon.EnableImgAzyobuziNet;
@@ -918,8 +914,10 @@ namespace OpenTween
 
             _initial = true;
 
+            Networking.Initialize();
+
             //アイコンリスト作成
-            this.IconCache = new ImageCache(this.http);
+            this.IconCache = new ImageCache();
 
             bool saveRequired = false;
             bool firstRun = false;
@@ -996,12 +994,10 @@ namespace OpenTween
             }
 
             //Twitter用通信クラス初期化
-            HttpConnection.InitializeConnection(SettingDialog.DefaultTimeOut,
-                                                SettingDialog.SelectedProxyType,
-                                                SettingDialog.ProxyAddress,
-                                                SettingDialog.ProxyPort,
-                                                SettingDialog.ProxyUser,
-                                                SettingDialog.ProxyPassword);
+            Networking.DefaultTimeout = TimeSpan.FromSeconds(this.SettingDialog.DefaultTimeOut);
+            Networking.SetWebProxy(this.SettingDialog.SelectedProxyType,
+                this.SettingDialog.ProxyAddress, this.SettingDialog.ProxyPort,
+                this.SettingDialog.ProxyUser, this.SettingDialog.ProxyPassword);
 
             tw.RestrictFavCheck = SettingDialog.RestrictFavCheck;
             tw.ReadOwnPost = SettingDialog.ReadOwnPost;
@@ -1015,7 +1011,7 @@ namespace OpenTween
             AllrepliesToolStripMenuItem.Checked = tw.AllAtReply;
 
             //画像投稿サービス
-            ImageSelector.Initialize(tw, _cfgCommon.UseImageServiceName, _cfgCommon.UseImageService);
+            ImageSelector.Initialize(tw, SettingDialog.TwitterConfiguration, _cfgCommon.UseImageServiceName, _cfgCommon.UseImageService);
 
             //ウィンドウ設定
             this.ClientSize = _cfgLocal.FormSize;
@@ -1498,8 +1494,8 @@ namespace OpenTween
                                 //アイコン描画不具合あり?
                             }
                             this.SelectListItem(lst,
-                                                _statuses.IndexOf(tab.Text, selId[tab.Text]),
-                                                _statuses.IndexOf(tab.Text, focusedId[tab.Text]));
+                                                tabInfo.IndexOf(selId[tab.Text]),
+                                                tabInfo.IndexOf(focusedId[tab.Text]));
                         }
                     }
                     if (tabInfo.UnreadCount > 0)
@@ -1648,10 +1644,11 @@ namespace OpenTween
             if (MyCommon._endingFlag) return;
             foreach (TabPage tab in ListTab.TabPages)
             {
-                DetailsListView lst = (DetailsListView)tab.Tag;
+                var lst = (DetailsListView)tab.Tag;
+                var tabInfo = _statuses.Tabs[tab.Text];
                 if (lst.SelectedIndices.Count > 0 && lst.SelectedIndices.Count < 61)
                 {
-                    selId.Add(tab.Text, _statuses.GetId(tab.Text, lst.SelectedIndices));
+                    selId.Add(tab.Text, tabInfo.GetId(lst.SelectedIndices));
                 }
                 else
                 {
@@ -1660,9 +1657,9 @@ namespace OpenTween
 
                 var fIds = new long[2];  // 0 = focus, 1 = selection mark
                 var item = lst.FocusedItem;
-                fIds[0] = (item != null) ? _statuses.GetId(tab.Text, item.Index) : -2;
+                fIds[0] = (item != null) ? tabInfo.GetId(item.Index) : -2;
                 var mIdx = lst.SelectionMark;
-                fIds[1] = (mIdx > -1) ? _statuses.GetId(tab.Text, mIdx) : -2;
+                fIds[1] = (mIdx > -1) ? tabInfo.GetId(mIdx) : -2;
                 focusedId.Add(tab.Text, fIds);
             }
 
@@ -1704,7 +1701,7 @@ namespace OpenTween
                     !SettingDialog.LimitBalloon
                     )
                 ) &&
-                !Win32Api.IsScreenSaverRunning())
+                !NativeMethods.IsScreenSaverRunning())
             {
                 return true;
             }
@@ -1921,7 +1918,7 @@ namespace OpenTween
             //mentions新着時に画面ブリンク
             if (!_initial && SettingDialog.BlinkNewMentions && newMentions && Form.ActiveForm == null)
             {
-                Win32Api.FlashMyWindow(this.Handle, Win32Api.FlashSpecification.FlashTray, 3);
+                NativeMethods.FlashMyWindow(this.Handle, NativeMethods.FlashSpecification.FlashTray, 3);
             }
         }
 
@@ -1953,9 +1950,10 @@ namespace OpenTween
 
         private void ChangeCacheStyleRead(bool Read, int Index)
         {
+            var tabInfo = _statuses.Tabs[_curTab.Text];
             //Read:true=既読 false=未読
             //未読管理していなかったら既読として扱う
-            if (!_statuses.Tabs[_curTab.Text].UnreadManage ||
+            if (!tabInfo.UnreadManage ||
                !SettingDialog.UnreadManage) Read = true;
 
             //対象の特定
@@ -1967,7 +1965,7 @@ namespace OpenTween
             if (itm == null || post == null)
             {
                 itm = ((DetailsListView)_curTab.Tag).Items[Index];
-                post = _statuses[_curTab.Text, Index];
+                post = tabInfo[Index];
             }
 
             ChangeItemStyleRead(Read, itm, post, ((DetailsListView)_curTab.Tag));
@@ -2518,19 +2516,14 @@ namespace OpenTween
                     else
                     {
                         var service = ImageSelector.GetService(args.status.imageService);
-                        if (args.status.imagePath.Length > 1 &&
-                            args.status.imageService.Equals("Twitter"))
+                        try
                         {
-                            //複数画像投稿
-                            ret = ((TwitterPhoto)service).Upload(ref args.status.imagePath,
-                                                                 ref args.status.status,
-                                                                 args.status.inReplyToId);
+                            service.PostStatusAsync(args.status.status, args.status.inReplyToId, args.status.imagePath)
+                                .Wait();
                         }
-                        else
+                        catch (AggregateException ex)
                         {
-                            ret = service.Upload(ref args.status.imagePath[0],
-                                                 ref args.status.status,
-                                                 args.status.inReplyToId);
+                            ret = ex.InnerException.Message;
                         }
                     }
                     bw.ReportProgress(300);
@@ -3068,9 +3061,10 @@ namespace OpenTween
                     //_waitFollower = false
                     if (SettingDialog.TwitterConfiguration.PhotoSizeLimit != 0)
                     {
-                        var service = ImageSelector.GetService("Twitter");
-                        if (service != null)
-                            service.Configuration("MaxUploadFilesize", SettingDialog.TwitterConfiguration.PhotoSizeLimit);
+                        foreach (var service in this.ImageSelector.GetServices())
+                        {
+                            service.UpdateTwitterConfiguration(this.SettingDialog.TwitterConfiguration);
+                        }
                     }
                     this.PurgeListViewItemCache();
                     if (_curList != null) _curList.Refresh();
@@ -3921,14 +3915,12 @@ namespace OpenTween
                     ShortUrl.Instance.BitlyKey = SettingDialog.BitlyPwd;
                     HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl;
 
-                    HttpConnection.InitializeConnection(SettingDialog.DefaultTimeOut,
-                                                        SettingDialog.SelectedProxyType,
-                                                        SettingDialog.ProxyAddress,
-                                                        SettingDialog.ProxyPort,
-                                                        SettingDialog.ProxyUser,
-                                                        SettingDialog.ProxyPassword);
+                    Networking.DefaultTimeout = TimeSpan.FromSeconds(this.SettingDialog.DefaultTimeOut);
+                    Networking.SetWebProxy(this.SettingDialog.SelectedProxyType,
+                        this.SettingDialog.ProxyAddress, this.SettingDialog.ProxyPort,
+                        this.SettingDialog.ProxyUser, this.SettingDialog.ProxyPassword);
 
-                    ImageSelector.Reset(tw);
+                    ImageSelector.Reset(tw, SettingDialog.TwitterConfiguration);
 
                     try
                     {
@@ -4167,11 +4159,12 @@ namespace OpenTween
             foreach (TabPage tab in ListTab.TabPages)
             {
                 DetailsListView lst = (DetailsListView)tab.Tag;
+                TabClass tabInfo = _statuses.Tabs[tab.Text];
                 using (ControlTransaction.Update(lst))
                 {
                     this.SelectListItem(lst,
-                                        _statuses.IndexOf(tab.Text, selId[tab.Text]),
-                                        _statuses.IndexOf(tab.Text, focusedId[tab.Text]));
+                                        tabInfo.IndexOf(selId[tab.Text]),
+                                        tabInfo.IndexOf(focusedId[tab.Text]));
                 }
             }
         }
@@ -5114,12 +5107,14 @@ namespace OpenTween
             this.itemCacheLock.EnterWriteLock();
             try
             {
+                var tabInfo = _statuses.Tabs[_curTab.Text];
+
                 //キャッシュ要求(要求範囲±30を作成)
                 StartIndex -= 30;
                 if (StartIndex < 0) StartIndex = 0;
                 EndIndex += 30;
-                if (EndIndex >= _statuses.Tabs[_curTab.Text].AllCount) EndIndex = _statuses.Tabs[_curTab.Text].AllCount - 1;
-                _postCache = _statuses[_curTab.Text, StartIndex, EndIndex]; //配列で取得
+                if (EndIndex >= tabInfo.AllCount) EndIndex = tabInfo.AllCount - 1;
+                _postCache = tabInfo[StartIndex, EndIndex]; //配列で取得
                 _itemCacheIndex = StartIndex;
 
                 _itemCache = new ListViewItem[0] {};
@@ -5207,7 +5202,7 @@ namespace OpenTween
                                   Post.Source};
                 itm = new ImageListViewItem(sitem, this.IconCache, Post.ImageUrl);
             }
-            itm.StateImageIndex = Post.StateIndex;
+            itm.StateIndex = Post.StateIndex;
 
             bool read = Post.IsRead;
             //未読管理していなかったら既読として扱う
@@ -5466,14 +5461,14 @@ namespace OpenTween
                 //iconRect.Offset(0, Math.Max(0, (itemRect.Height - realIconSize.Height) / 2));
             }
 
-            if (item.StateImageIndex > -1)
+            if (item.StateIndex > -1)
             {
                 Rectangle stateRect = Rectangle.Intersect(new Rectangle(new Point(iconRect.X + realIconSize.Width + 2, iconRect.Y), realStateSize), itemRect);
                 if (stateRect.Width > 0)
                 {
                     //e.Graphics.FillRectangle(Brushes.White, stateRect);
                     //e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.High;
-                    e.Graphics.DrawImage(this.PostStateImageList.Images[item.StateImageIndex], stateRect);
+                    e.Graphics.DrawImage(this.PostStateImageList.Images[item.StateIndex], stateRect);
                 }
             }
         }
@@ -5917,7 +5912,7 @@ namespace OpenTween
             var versionInfoUrl = new Uri(ApplicationSettings.VersionInfoUrl + "?" +
                 DateTime.Now.ToString("yyMMddHHmmss") + Environment.TickCount);
 
-            var responseText = await this.http.GetStringAsync(versionInfoUrl)
+            var responseText = await Networking.Http.GetStringAsync(versionInfoUrl)
                 .ConfigureAwait(false);
 
             // 改行2つで前後パートを分割(前半がバージョン番号など、後半が詳細テキスト)
@@ -6042,7 +6037,7 @@ namespace OpenTween
             DispSelectedPost(false);
         }
 
-        private static PostClass displaypost = new PostClass();
+        private PostClass displayPost = new PostClass();
 
         /// <summary>
         /// サムネイルの表示処理を表すタスク
@@ -6059,10 +6054,12 @@ namespace OpenTween
             if (_curList.SelectedIndices.Count == 0 || _curPost == null)
                 return;
 
-            if (!forceupdate && _curPost.Equals(displaypost))
+            var oldDisplayPost = this.displayPost;
+            this.displayPost = this._curPost;
+
+            if (!forceupdate && this._curPost.Equals(oldDisplayPost))
                 return;
 
-            displaypost = _curPost;
             if (displayItem != null)
             {
                 displayItem.ImageDownloaded -= this.DisplayItemImage_Downloaded;
@@ -6071,134 +6068,125 @@ namespace OpenTween
             displayItem = (ImageListViewItem)_curList.Items[_curList.SelectedIndices[0]];
             displayItem.ImageDownloaded += this.DisplayItemImage_Downloaded;
 
-            string dTxt = createDetailHtml(_curPost.IsDeleted ? "(DELETED)" : _curPost.Text);
-            if (_curPost.IsDm)
+            using (ControlTransaction.Update(this.TableLayoutPanel1))
             {
-                SourceLinkLabel.Tag = null;
-                SourceLinkLabel.Text = "";
-            }
-            else
-            {
-                Match mc = Regex.Match(_curPost.SourceHtml, "<a href=\"(?<sourceurl>.+?)\"");
-                if (mc.Success)
+                var sourceText = "";
+                string sourceUrl = null;
+                if (!_curPost.IsDm)
                 {
-                    string src = mc.Groups["sourceurl"].Value;
-                    SourceLinkLabel.Tag = mc.Groups["sourceurl"].Value;
-                    mc = Regex.Match(src, "^https?://");
-                    if (!mc.Success)
+                    var mc = Regex.Match(_curPost.SourceHtml, "<a href=\"(?<sourceurl>.+?)\"");
+                    if (mc.Success)
                     {
-                        src = src.Insert(0, "https://twitter.com");
+                        var src = mc.Groups["sourceurl"].Value;
+                        if (Regex.IsMatch(src, "^https?://"))
+                            sourceUrl = src;
+                        else
+                            sourceUrl = "https://twitter.com/" + src;
                     }
-                    SourceLinkLabel.Tag = src;
-                }
-                else
-                {
-                    SourceLinkLabel.Tag = null;
+
+                    if (_curPost.Source != null)
+                        sourceText = _curPost.Source;
                 }
-                if (string.IsNullOrEmpty(_curPost.Source))
+                SourceLinkLabel.Text = sourceText;
+                SourceLinkLabel.Tag = sourceUrl;
+                SourceLinkLabel.TabStop = false; // Text を更新すると勝手に true にされる
+
+                string nameText;
+                if (_curPost.IsDm)
                 {
-                    SourceLinkLabel.Text = "";
-                    //SourceLinkLabel.Visible = false;
+                    if (_curPost.IsOwl)
+                        nameText = "DM FROM <- ";
+                    else
+                        nameText = "DM TO -> ";
                 }
                 else
                 {
-                    SourceLinkLabel.Text = _curPost.Source;
-                    //SourceLinkLabel.Visible = true;
+                    nameText = "";
                 }
-            }
-            SourceLinkLabel.TabStop = false;
+                nameText += _curPost.ScreenName + "/" + _curPost.Nickname;
+                if (_curPost.RetweetedId != null)
+                    nameText += " (RT:" + _curPost.RetweetedBy + ")";
 
-            if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage && !_curPost.IsOwl)
-            {
-                NameLabel.Text = "DM TO -> ";
-            }
-            else if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage)
-            {
-                NameLabel.Text = "DM FROM <- ";
-            }
-            else
-            {
-                NameLabel.Text = "";
-            }
-            NameLabel.Text += _curPost.ScreenName + "/" + _curPost.Nickname;
-            NameLabel.Tag = _curPost.ScreenName;
-            if (!string.IsNullOrEmpty(_curPost.RetweetedBy))
-            {
-                NameLabel.Text += " (RT:" + _curPost.RetweetedBy + ")";
-            }
+                NameLabel.Text = nameText;
+                NameLabel.Tag = _curPost.ScreenName;
 
-            this.ClearUserPicture();
+                var nameForeColor = SystemColors.ControlText;
+                if (_curPost.IsOwl && (this.SettingDialog.OneWayLove || _curPost.IsDm))
+                    nameForeColor = this._clOWL;
+                if (_curPost.RetweetedId != null)
+                    nameForeColor = this._clRetweet;
+                if (_curPost.IsFav)
+                    nameForeColor = this._clFav;
+                NameLabel.ForeColor = nameForeColor;
 
-            if (!string.IsNullOrEmpty(_curPost.ImageUrl))
-            {
-                var image = IconCache.TryGetFromCache(_curPost.ImageUrl);
-                try
+                this.ClearUserPicture();
+
+                if (!string.IsNullOrEmpty(_curPost.ImageUrl))
                 {
-                    UserPicture.Image = image != null ? image.Clone() : null;
+                    var image = IconCache.TryGetFromCache(_curPost.ImageUrl);
+                    try
+                    {
+                        UserPicture.Image = image != null ? image.Clone() : null;
+                    }
+                    catch (Exception)
+                    {
+                        UserPicture.ShowErrorImage();
+                    }
                 }
-                catch (Exception)
+
+                DateTimeLabel.Text = _curPost.CreatedAt.ToString();
+
+                if (DumpPostClassToolStripMenuItem.Checked)
                 {
-                    UserPicture.ShowErrorImage();
-                }
-            }
+                    StringBuilder sb = new StringBuilder(512);
 
-            NameLabel.ForeColor = System.Drawing.SystemColors.ControlText;
-            DateTimeLabel.Text = _curPost.CreatedAt.ToString();
-            if (_curPost.IsOwl && (SettingDialog.OneWayLove || _statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage)) NameLabel.ForeColor = _clOWL;
-            if (_curPost.RetweetedId != null) NameLabel.ForeColor = _clRetweet;
-            if (_curPost.IsFav) NameLabel.ForeColor = _clFav;
-
-            if (DumpPostClassToolStripMenuItem.Checked)
-            {
-                StringBuilder sb = new StringBuilder(512);
-
-                sb.Append("-----Start PostClass Dump<br>");
-                sb.AppendFormat("TextFromApi           : {0}<br>", _curPost.TextFromApi);
-                sb.AppendFormat("(PlainText)    : <xmp>{0}</xmp><br>", _curPost.TextFromApi);
-                sb.AppendFormat("StatusId             : {0}<br>", _curPost.StatusId.ToString());
-                //sb.AppendFormat("ImageIndex     : {0}<br>", _curPost.ImageIndex.ToString());
-                sb.AppendFormat("ImageUrl       : {0}<br>", _curPost.ImageUrl);
-                sb.AppendFormat("InReplyToStatusId    : {0}<br>", _curPost.InReplyToStatusId.ToString());
-                sb.AppendFormat("InReplyToUser  : {0}<br>", _curPost.InReplyToUser);
-                sb.AppendFormat("IsDM           : {0}<br>", _curPost.IsDm.ToString());
-                sb.AppendFormat("IsFav          : {0}<br>", _curPost.IsFav.ToString());
-                sb.AppendFormat("IsMark         : {0}<br>", _curPost.IsMark.ToString());
-                sb.AppendFormat("IsMe           : {0}<br>", _curPost.IsMe.ToString());
-                sb.AppendFormat("IsOwl          : {0}<br>", _curPost.IsOwl.ToString());
-                sb.AppendFormat("IsProtect      : {0}<br>", _curPost.IsProtect.ToString());
-                sb.AppendFormat("IsRead         : {0}<br>", _curPost.IsRead.ToString());
-                sb.AppendFormat("IsReply        : {0}<br>", _curPost.IsReply.ToString());
-            
-                foreach (string nm in _curPost.ReplyToList)
-                {
-                    sb.AppendFormat("ReplyToList    : {0}<br>", nm);
-                }
-
-                sb.AppendFormat("ScreenName           : {0}<br>", _curPost.ScreenName);
-                sb.AppendFormat("NickName       : {0}<br>", _curPost.Nickname);
-                sb.AppendFormat("Text   : {0}<br>", _curPost.Text);
-                sb.AppendFormat("(PlainText)    : <xmp>{0}</xmp><br>", _curPost.Text);
-                sb.AppendFormat("CreatedAt          : {0}<br>", _curPost.CreatedAt.ToString());
-                sb.AppendFormat("Source         : {0}<br>", _curPost.Source);
-                sb.AppendFormat("UserId            : {0}<br>", _curPost.UserId);
-                sb.AppendFormat("FilterHit      : {0}<br>", _curPost.FilterHit);
-                sb.AppendFormat("RetweetedBy    : {0}<br>", _curPost.RetweetedBy);
-                sb.AppendFormat("RetweetedId    : {0}<br>", _curPost.RetweetedId);
-                sb.AppendFormat("SearchTabName  : {0}<br>", _curPost.RelTabName);
-                sb.Append("-----End PostClass Dump<br>");
-
-                PostBrowser.Visible = false;
-                PostBrowser.DocumentText = detailHtmlFormatHeader + sb.ToString() + detailHtmlFormatFooter;
-                PostBrowser.Visible = true;
-            }
-            else
-            {
-                try
+                    sb.Append("-----Start PostClass Dump<br>");
+                    sb.AppendFormat("TextFromApi           : {0}<br>", _curPost.TextFromApi);
+                    sb.AppendFormat("(PlainText)    : <xmp>{0}</xmp><br>", _curPost.TextFromApi);
+                    sb.AppendFormat("StatusId             : {0}<br>", _curPost.StatusId.ToString());
+                    //sb.AppendFormat("ImageIndex     : {0}<br>", _curPost.ImageIndex.ToString());
+                    sb.AppendFormat("ImageUrl       : {0}<br>", _curPost.ImageUrl);
+                    sb.AppendFormat("InReplyToStatusId    : {0}<br>", _curPost.InReplyToStatusId.ToString());
+                    sb.AppendFormat("InReplyToUser  : {0}<br>", _curPost.InReplyToUser);
+                    sb.AppendFormat("IsDM           : {0}<br>", _curPost.IsDm.ToString());
+                    sb.AppendFormat("IsFav          : {0}<br>", _curPost.IsFav.ToString());
+                    sb.AppendFormat("IsMark         : {0}<br>", _curPost.IsMark.ToString());
+                    sb.AppendFormat("IsMe           : {0}<br>", _curPost.IsMe.ToString());
+                    sb.AppendFormat("IsOwl          : {0}<br>", _curPost.IsOwl.ToString());
+                    sb.AppendFormat("IsProtect      : {0}<br>", _curPost.IsProtect.ToString());
+                    sb.AppendFormat("IsRead         : {0}<br>", _curPost.IsRead.ToString());
+                    sb.AppendFormat("IsReply        : {0}<br>", _curPost.IsReply.ToString());
+
+                    foreach (string nm in _curPost.ReplyToList)
+                    {
+                        sb.AppendFormat("ReplyToList    : {0}<br>", nm);
+                    }
+
+                    sb.AppendFormat("ScreenName           : {0}<br>", _curPost.ScreenName);
+                    sb.AppendFormat("NickName       : {0}<br>", _curPost.Nickname);
+                    sb.AppendFormat("Text   : {0}<br>", _curPost.Text);
+                    sb.AppendFormat("(PlainText)    : <xmp>{0}</xmp><br>", _curPost.Text);
+                    sb.AppendFormat("CreatedAt          : {0}<br>", _curPost.CreatedAt.ToString());
+                    sb.AppendFormat("Source         : {0}<br>", _curPost.Source);
+                    sb.AppendFormat("UserId            : {0}<br>", _curPost.UserId);
+                    sb.AppendFormat("FilterHit      : {0}<br>", _curPost.FilterHit);
+                    sb.AppendFormat("RetweetedBy    : {0}<br>", _curPost.RetweetedBy);
+                    sb.AppendFormat("RetweetedId    : {0}<br>", _curPost.RetweetedId);
+                    sb.AppendFormat("SearchTabName  : {0}<br>", _curPost.RelTabName);
+                    sb.Append("-----End PostClass Dump<br>");
+
+                    PostBrowser.DocumentText = detailHtmlFormatHeader + sb.ToString() + detailHtmlFormatFooter;
+                }
+                else
                 {
-                    if (PostBrowser.DocumentText != dTxt)
+                    // 同じIDのツイートであれば WebBrowser とサムネイルの更新を行わない
+                    // (同一ツイートの RT は文面が同じであるため同様に更新しない)
+                    if (_curPost.StatusId != oldDisplayPost.StatusId)
                     {
-                        PostBrowser.Visible = false;
-                        PostBrowser.DocumentText = dTxt;
+                        this.PostBrowser.DocumentText =
+                            this.createDetailHtml(_curPost.IsDeleted ? "(DELETED)" : _curPost.Text);
+
+                        this.PostBrowser.Document.Window.ScrollTo(0, 0);
 
                         this.SplitContainer3.Panel2Collapsed = true;
 
@@ -6208,10 +6196,10 @@ namespace OpenTween
                             {
                                 var oldTokenSource = this.thumbnailTokenSource;
 
-                                // TODO: キャンセルを行うとUIスレッドが阻害される問題を調査
-                                //oldTokenSource.Cancel();
+                                var cancelTask = Task.Run(() => oldTokenSource.Cancel());
 
-                                this.thumbnailTask.ContinueWith(_ => oldTokenSource.Dispose());
+                                Task.WhenAll(this.thumbnailTask, cancelTask)
+                                    .ContinueWith(_ => oldTokenSource.Dispose(), TaskScheduler.Default);
                             }
 
                             this.thumbnailTokenSource = new CancellationTokenSource();
@@ -6221,18 +6209,6 @@ namespace OpenTween
                         }
                     }
                 }
-                catch (System.Runtime.InteropServices.COMException)
-                {
-                    //原因不明
-                }
-                catch (UriFormatException)
-                {
-                    PostBrowser.DocumentText = dTxt;
-                }
-                finally
-                {
-                    PostBrowser.Visible = true;
-                }
             }
         }
 
@@ -10004,6 +9980,15 @@ namespace OpenTween
                             var resultUri = await ShortUrl.Instance.ShortenUrlAsync(Converter_Type, srcUri);
                             result = resultUri.ToString();
                         }
+                        catch (HttpRequestException e)
+                        {
+                            // 例外のメッセージが「Response status code does not indicate success: 500 (Internal Server Error).」
+                            // のように長いので「:」が含まれていればそれ以降のみを抽出する
+                            var message = e.Message.Split(new[] { ':' }, count: 2).Last();
+
+                            this.StatusLabel.Text = Converter_Type + ":" + message;
+                            continue;
+                        }
                         catch (WebApiException e)
                         {
                             this.StatusLabel.Text = Converter_Type + ":" + e.Message;
@@ -12299,7 +12284,6 @@ namespace OpenTween
         private HookGlobalHotkey _hookGlobalHotkey;
         public TweenMain()
         {
-            this.http = MyCommon.CreateHttpClient();
             _hookGlobalHotkey = new HookGlobalHotkey(this);
 
             // この呼び出しは、Windows フォーム デザイナで必要です。
@@ -12313,7 +12297,7 @@ namespace OpenTween
             this.gh.NotifyClicked += GrowlHelper_Callback;
 
             // メイリオフォント指定時にタブの最小幅が広くなる問題の対策
-            this.ListTab.HandleCreated += (s, e) => Win32Api.SetMinTabWidth((TabControl)s, 40);
+            this.ListTab.HandleCreated += (s, e) => NativeMethods.SetMinTabWidth((TabControl)s, 40);
 
             this._apiGauge = new ToolStripAPIGauge();
             this._apiGauge.BorderSides = ToolStripStatusLabelBorderSides.Right;
@@ -12603,7 +12587,7 @@ namespace OpenTween
 #region "Userstream"
         private bool _isActiveUserstream = false;
 
-        private void tw_PostDeleted(long id)
+        private void tw_PostDeleted(object sender, PostDeletedEventArgs e)
         {
             try
             {
@@ -12611,12 +12595,12 @@ namespace OpenTween
                 {
                     Invoke((Action) (() =>
                            {
-                               _statuses.RemovePostReserve(id);
-                               if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(id))
+                               _statuses.RemovePostReserve(e.StatusId);
+                               if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(e.StatusId))
                                {
                                    this.PurgeListViewItemCache();
                                    ((DetailsListView)_curTab.Tag).Update();
-                                   if (_curPost != null && _curPost.StatusId == id) DispSelectedPost(true);
+                                   if (_curPost != null && _curPost.StatusId == e.StatusId) DispSelectedPost(true);
                                }
                            }));
                     return;
@@ -12632,7 +12616,7 @@ namespace OpenTween
             }
         }
 
-        private void tw_NewPostFromStream()
+        private void tw_NewPostFromStream(object sender, EventArgs e)
         {
             if (SettingDialog.ReadOldPosts)
             {
@@ -12692,14 +12676,14 @@ namespace OpenTween
             }
         }
 
-        private void tw_UserStreamStarted()
+        private void tw_UserStreamStarted(object sender, EventArgs e)
         {
             this._isActiveUserstream = true;
             try
             {
                 if (InvokeRequired && !IsDisposed)
                 {
-                    Invoke(new MethodInvoker(tw_UserStreamStarted));
+                    Invoke((Action)(() => this.tw_UserStreamStarted(sender, e)));
                     return;
                 }
             }
@@ -12720,14 +12704,14 @@ namespace OpenTween
             StatusLabel.Text = "UserStream Started.";
         }
 
-        private void tw_UserStreamStopped()
+        private void tw_UserStreamStopped(object sender, EventArgs e)
         {
             this._isActiveUserstream = false;
             try
             {
                 if (InvokeRequired && !IsDisposed)
                 {
-                    Invoke(new MethodInvoker(tw_UserStreamStopped));
+                    Invoke((Action)(() => this.tw_UserStreamStopped(sender, e)));
                     return;
                 }
             }
@@ -12748,13 +12732,13 @@ namespace OpenTween
             StatusLabel.Text = "UserStream Stopped.";
         }
 
-        private void tw_UserStreamEventArrived(Twitter.FormattedEvent ev)
+        private void tw_UserStreamEventArrived(object sender, UserStreamEventReceivedEventArgs e)
         {
             try
             {
                 if (InvokeRequired && !IsDisposed)
                 {
-                    Invoke(new Action<Twitter.FormattedEvent>(tw_UserStreamEventArrived), ev);
+                    Invoke((Action)(() => this.tw_UserStreamEventArrived(sender, e)));
                     return;
                 }
             }
@@ -12766,6 +12750,7 @@ namespace OpenTween
             {
                 return;
             }
+            var ev = e.EventData;
             StatusLabel.Text = "Event: " + ev.Event;
             //if (ev.Event == "favorite")
             //{
@@ -12981,7 +12966,7 @@ namespace OpenTween
             if (string.IsNullOrEmpty(str))
                 return;
 
-            var bing = new Bing(this.http);
+            var bing = new Bing();
             try
             {
                 var translatedText = await bing.TranslateAsync(str,