OSDN Git Service

TweenMain.ListTab.TabPagesとTabInformations.Tabsの順序を同期させる
[opentween/open-tween.git] / OpenTween / Tween.cs
index a77407a..ef95412 100644 (file)
@@ -52,6 +52,7 @@ using OpenTween.Api.DataModel;
 using OpenTween.Connection;
 using OpenTween.Models;
 using OpenTween.OpenTweenCustomControl;
+using OpenTween.Setting;
 using OpenTween.Thumbnail;
 
 namespace OpenTween
@@ -111,17 +112,12 @@ namespace OpenTween
         private bool soundfileListup = false;
         private FormWindowState _formWindowState = FormWindowState.Normal; // フォームの状態保存用 通知領域からアイコンをクリックして復帰した際に使用する
 
-        //設定ファイル関連
-        //private SettingToConfig _cfg; //旧
-        internal SettingLocal _cfgLocal;
-        private SettingCommon _cfgCommon;
-
         //twitter解析部
         private TwitterApi twitterApi = new TwitterApi();
         private Twitter tw;
 
         //Growl呼び出し部
-        private GrowlHelper gh = new GrowlHelper(Application.ProductName);
+        private GrowlHelper gh = new GrowlHelper(ApplicationSettings.ApplicationName);
 
         //サブ画面インスタンス
         internal SearchWordDialog SearchDialog = new SearchWordDialog();     //検索画面インスタンス
@@ -169,15 +165,15 @@ namespace OpenTween
         private PostClass _anchorPost;
         private bool _anchorFlag;        //true:関連発言移動中(関連移動以外のオペレーションをするとfalseへ。trueだとリスト背景色をアンカー発言選択中として描画)
 
-        private List<PostingStatus> _history = new List<PostingStatus>();   //発言履歴
+        private List<StatusTextHistory> _history = new List<StatusTextHistory>();   //発言履歴
         private int _hisIdx;                  //発言履歴カレントインデックス
 
         //発言投稿時のAPI引数(発言編集時に設定。手書きreplyでは設定されない)
-        private Tuple<long, string> inReplyTo = null; // リプライ先のステータスID・スクリーン名
+        private (long StatusId, string ScreenName)? inReplyTo = null; // リプライ先のステータスID・スクリーン名
 
         //時速表示用
-        private List<DateTime> _postTimestamps = new List<DateTime>();
-        private List<DateTime> _favTimestamps = new List<DateTime>();
+        private List<DateTimeUtc> _postTimestamps = new List<DateTimeUtc>();
+        private List<DateTimeUtc> _favTimestamps = new List<DateTimeUtc>();
 
         // 以下DrawItem関連
         private SolidBrush _brsHighLight = new SolidBrush(Color.FromKnownColor(KnownColor.Highlight));
@@ -254,10 +250,6 @@ namespace OpenTween
             }
         }
 
-        private TabPage _curTab;
-        private int _curItemIndex;
-        private DetailsListView _curList;
-        private PostClass _curPost;
         private bool _isColumnChanged = false;
 
         private const int MAX_WORKER_THREADS = 20;
@@ -278,8 +270,11 @@ namespace OpenTween
         private bool _colorize = false;
 
         private System.Timers.Timer TimerTimeline = new System.Timers.Timer();
+        private ThrottlingTimer RefreshThrottlingTimer;
 
         private string recommendedStatusFooter;
+        private bool urlMultibyteSplit = false;
+        private bool preventSmsCommand = true;
 
         //URL短縮のUndo用
         private struct urlUndo
@@ -294,9 +289,9 @@ namespace OpenTween
         {
             public long OriginalId;
             public long InReplyToId;
-            public TabPage OriginalTab;
+            public TabModel OriginalTab;
 
-            public ReplyChain(long originalId, long inReplyToId, TabPage originalTab)
+            public ReplyChain(long originalId, long inReplyToId, TabModel originalTab)
             {
                 this.OriginalId = originalId;
                 this.InReplyToId = inReplyToId;
@@ -305,7 +300,22 @@ namespace OpenTween
         }
 
         private Stack<ReplyChain> replyChains; //[, ]でのリプライ移動の履歴
-        private Stack<Tuple<TabPage, PostClass>> selectPostChains = new Stack<Tuple<TabPage, PostClass>>(); //ポスト選択履歴
+        private Stack<(TabModel, PostClass)> selectPostChains = new Stack<(TabModel, PostClass)>(); //ポスト選択履歴
+
+        public TabModel CurrentTab
+            => this._statuses.SelectedTab;
+
+        public string CurrentTabName
+            => this._statuses.SelectedTabName;
+
+        public TabPage CurrentTabPage
+            => this.ListTab.TabPages.Cast<TabPage>().First(x => x.Text == this.CurrentTabName);
+
+        public DetailsListView CurrentListView
+            => (DetailsListView)this.CurrentTabPage.Tag;
+
+        public PostClass CurrentPost
+            => this.CurrentTab.SelectedPost;
 
         //検索処理タイプ
         internal enum SEARCHTYPE
@@ -315,21 +325,19 @@ namespace OpenTween
             PrevSearch,
         }
 
-        private class PostingStatus
+        private class StatusTextHistory
         {
             public string status = "";
-            public long? inReplyToId = null;
-            public string inReplyToName = null;
+            public (long StatusId, string ScreenName)? inReplyTo = null;
             public string imageService = "";      //画像投稿サービス名
             public IMediaItem[] mediaItems = null;
-            public PostingStatus()
+            public StatusTextHistory()
             {
             }
-            public PostingStatus(string status, long? replyToId, string replyToName)
+            public StatusTextHistory(string status, (long StatusId, string ScreenName)? inReplyTo)
             {
                 this.status = status;
-                this.inReplyToId = replyToId;
-                this.inReplyToName = replyToName;
+                this.inReplyTo = inReplyTo;
             }
         }
 
@@ -404,6 +412,7 @@ namespace OpenTween
             // 終了時にRemoveHandlerしておかないとメモリリークする
             // http://msdn.microsoft.com/ja-jp/library/microsoft.win32.systemevents.powermodechanged.aspx
             Microsoft.Win32.SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
+            Microsoft.Win32.SystemEvents.TimeChanged -= SystemEvents_TimeChanged;
 
             this.disposed = true;
         }
@@ -517,17 +526,17 @@ namespace OpenTween
 
                     if (startup)
                     {
-                        var widthScaleFactor = this.CurrentAutoScaleDimensions.Width / this._cfgLocal.ScaleDimension.Width;
+                        var widthScaleFactor = this.CurrentAutoScaleDimensions.Width / SettingManager.Local.ScaleDimension.Width;
 
-                        columns[0].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width1);
-                        columns[1].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width3);
+                        columns[0].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width1);
+                        columns[1].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width3);
                         columns[0].DisplayIndex = 0;
                         columns[1].DisplayIndex = 1;
                     }
                     else
                     {
                         var idx = 0;
-                        foreach (var curListColumn in this._curList.Columns.Cast<ColumnHeader>())
+                        foreach (var curListColumn in this.CurrentListView.Columns.Cast<ColumnHeader>())
                         {
                             columns[idx].Width = curListColumn.Width;
                             columns[idx].DisplayIndex = curListColumn.DisplayIndex;
@@ -554,22 +563,22 @@ namespace OpenTween
 
                     if (startup)
                     {
-                        var widthScaleFactor = this.CurrentAutoScaleDimensions.Width / this._cfgLocal.ScaleDimension.Width;
+                        var widthScaleFactor = this.CurrentAutoScaleDimensions.Width / SettingManager.Local.ScaleDimension.Width;
 
-                        columns[0].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width1);
-                        columns[1].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width2);
-                        columns[2].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width3);
-                        columns[3].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width4);
-                        columns[4].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width5);
-                        columns[5].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width6);
-                        columns[6].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width7);
-                        columns[7].Width = ScaleBy(widthScaleFactor, _cfgLocal.Width8);
+                        columns[0].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width1);
+                        columns[1].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width2);
+                        columns[2].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width3);
+                        columns[3].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width4);
+                        columns[4].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width5);
+                        columns[5].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width6);
+                        columns[6].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width7);
+                        columns[7].Width = ScaleBy(widthScaleFactor, SettingManager.Local.Width8);
 
                         var displayIndex = new[] {
-                            this._cfgLocal.DisplayIndex1, this._cfgLocal.DisplayIndex2,
-                            this._cfgLocal.DisplayIndex3, this._cfgLocal.DisplayIndex4,
-                            this._cfgLocal.DisplayIndex5, this._cfgLocal.DisplayIndex6,
-                            this._cfgLocal.DisplayIndex7, this._cfgLocal.DisplayIndex8
+                            SettingManager.Local.DisplayIndex1, SettingManager.Local.DisplayIndex2,
+                            SettingManager.Local.DisplayIndex3, SettingManager.Local.DisplayIndex4,
+                            SettingManager.Local.DisplayIndex5, SettingManager.Local.DisplayIndex6,
+                            SettingManager.Local.DisplayIndex7, SettingManager.Local.DisplayIndex8
                         };
 
                         foreach (var i in Enumerable.Range(0, displayIndex.Length))
@@ -580,7 +589,7 @@ namespace OpenTween
                     else
                     {
                         var idx = 0;
-                        foreach (var curListColumn in this._curList.Columns.Cast<ColumnHeader>())
+                        foreach (var curListColumn in this.CurrentListView.Columns.Cast<ColumnHeader>())
                         {
                             columns[idx].Width = curListColumn.Width;
                             columns[idx].DisplayIndex = curListColumn.DisplayIndex;
@@ -696,7 +705,6 @@ namespace OpenTween
 
             //Win32Api.SetProxy(HttpConnection.ProxyType.Specified, "127.0.0.1", 8080, "user", "pass")
 
-            MyCommon.TwitterApiInfo.AccessLimitUpdated += TwitterApiStatus_AccessLimitUpdated;
             Microsoft.Win32.SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
 
             Regex.CacheSize = 100;
@@ -715,10 +723,10 @@ namespace OpenTween
             LoadConfig();
 
             // 現在の DPI と設定保存時の DPI との比を取得する
-            var configScaleFactor = this._cfgLocal.GetConfigScaleFactor(this.CurrentAutoScaleDimensions);
+            var configScaleFactor = SettingManager.Local.GetConfigScaleFactor(this.CurrentAutoScaleDimensions);
 
             // UIフォント設定
-            var fontUIGlobal = this._cfgLocal.FontUIGlobal;
+            var fontUIGlobal = SettingManager.Local.FontUIGlobal;
             if (fontUIGlobal != null)
             {
                 OTBaseForm.GlobalFont = fontUIGlobal;
@@ -728,54 +736,54 @@ namespace OpenTween
             //不正値チェック
             if (!MyApplication.StartupOptions.ContainsKey("nolimit"))
             {
-                if (this._cfgCommon.TimelinePeriod < 15 && this._cfgCommon.TimelinePeriod > 0)
-                    this._cfgCommon.TimelinePeriod = 15;
+                if (SettingManager.Common.TimelinePeriod < 15 && SettingManager.Common.TimelinePeriod > 0)
+                    SettingManager.Common.TimelinePeriod = 15;
 
-                if (this._cfgCommon.ReplyPeriod < 15 && this._cfgCommon.ReplyPeriod > 0)
-                    this._cfgCommon.ReplyPeriod = 15;
+                if (SettingManager.Common.ReplyPeriod < 15 && SettingManager.Common.ReplyPeriod > 0)
+                    SettingManager.Common.ReplyPeriod = 15;
 
-                if (this._cfgCommon.DMPeriod < 15 && this._cfgCommon.DMPeriod > 0)
-                    this._cfgCommon.DMPeriod = 15;
+                if (SettingManager.Common.DMPeriod < 15 && SettingManager.Common.DMPeriod > 0)
+                    SettingManager.Common.DMPeriod = 15;
 
-                if (this._cfgCommon.PubSearchPeriod < 30 && this._cfgCommon.PubSearchPeriod > 0)
-                    this._cfgCommon.PubSearchPeriod = 30;
+                if (SettingManager.Common.PubSearchPeriod < 30 && SettingManager.Common.PubSearchPeriod > 0)
+                    SettingManager.Common.PubSearchPeriod = 30;
 
-                if (this._cfgCommon.UserTimelinePeriod < 15 && this._cfgCommon.UserTimelinePeriod > 0)
-                    this._cfgCommon.UserTimelinePeriod = 15;
+                if (SettingManager.Common.UserTimelinePeriod < 15 && SettingManager.Common.UserTimelinePeriod > 0)
+                    SettingManager.Common.UserTimelinePeriod = 15;
 
-                if (this._cfgCommon.ListsPeriod < 15 && this._cfgCommon.ListsPeriod > 0)
-                    this._cfgCommon.ListsPeriod = 15;
+                if (SettingManager.Common.ListsPeriod < 15 && SettingManager.Common.ListsPeriod > 0)
+                    SettingManager.Common.ListsPeriod = 15;
             }
 
-            if (!Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.Timeline, this._cfgCommon.CountApi))
-                this._cfgCommon.CountApi = 60;
-            if (!Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.Reply, this._cfgCommon.CountApiReply))
-                this._cfgCommon.CountApiReply = 40;
+            if (!Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.Timeline, SettingManager.Common.CountApi))
+                SettingManager.Common.CountApi = 60;
+            if (!Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.Reply, SettingManager.Common.CountApiReply))
+                SettingManager.Common.CountApiReply = 40;
 
-            if (this._cfgCommon.MoreCountApi != 0 && !Twitter.VerifyMoreApiResultCount(this._cfgCommon.MoreCountApi))
-                this._cfgCommon.MoreCountApi = 200;
-            if (this._cfgCommon.FirstCountApi != 0 && !Twitter.VerifyFirstApiResultCount(this._cfgCommon.FirstCountApi))
-                this._cfgCommon.FirstCountApi = 100;
+            if (SettingManager.Common.MoreCountApi != 0 && !Twitter.VerifyMoreApiResultCount(SettingManager.Common.MoreCountApi))
+                SettingManager.Common.MoreCountApi = 200;
+            if (SettingManager.Common.FirstCountApi != 0 && !Twitter.VerifyFirstApiResultCount(SettingManager.Common.FirstCountApi))
+                SettingManager.Common.FirstCountApi = 100;
 
-            if (this._cfgCommon.FavoritesCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.Favorites, this._cfgCommon.FavoritesCountApi))
-                this._cfgCommon.FavoritesCountApi = 40;
-            if (this._cfgCommon.ListCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.List, this._cfgCommon.ListCountApi))
-                this._cfgCommon.ListCountApi = 100;
-            if (this._cfgCommon.SearchCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.PublicSearch, this._cfgCommon.SearchCountApi))
-                this._cfgCommon.SearchCountApi = 100;
-            if (this._cfgCommon.UserTimelineCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.UserTimeline, this._cfgCommon.UserTimelineCountApi))
-                this._cfgCommon.UserTimelineCountApi = 20;
+            if (SettingManager.Common.FavoritesCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.Favorites, SettingManager.Common.FavoritesCountApi))
+                SettingManager.Common.FavoritesCountApi = 40;
+            if (SettingManager.Common.ListCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.List, SettingManager.Common.ListCountApi))
+                SettingManager.Common.ListCountApi = 100;
+            if (SettingManager.Common.SearchCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.PublicSearch, SettingManager.Common.SearchCountApi))
+                SettingManager.Common.SearchCountApi = 100;
+            if (SettingManager.Common.UserTimelineCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.UserTimeline, SettingManager.Common.UserTimelineCountApi))
+                SettingManager.Common.UserTimelineCountApi = 20;
 
             //廃止サービスが選択されていた場合ux.nuへ読み替え
-            if (this._cfgCommon.AutoShortUrlFirst < 0)
-                this._cfgCommon.AutoShortUrlFirst = MyCommon.UrlConverter.Uxnu;
+            if (SettingManager.Common.AutoShortUrlFirst < 0)
+                SettingManager.Common.AutoShortUrlFirst = MyCommon.UrlConverter.Uxnu;
 
-            TwitterApiConnection.RestApiHost = this._cfgCommon.TwitterApiHost;
+            TwitterApiConnection.RestApiHost = SettingManager.Common.TwitterApiHost;
             this.tw = new Twitter(this.twitterApi);
 
             //認証関連
-            if (string.IsNullOrEmpty(this._cfgCommon.Token)) this._cfgCommon.UserName = "";
-            tw.Initialize(this._cfgCommon.Token, this._cfgCommon.TokenSecret, this._cfgCommon.UserName, this._cfgCommon.UserId);
+            if (string.IsNullOrEmpty(SettingManager.Common.Token)) SettingManager.Common.UserName = "";
+            tw.Initialize(SettingManager.Common.Token, SettingManager.Common.TokenSecret, SettingManager.Common.UserName, SettingManager.Common.UserId);
 
             _initial = true;
 
@@ -800,23 +808,24 @@ namespace OpenTween
             }
 
             //Twitter用通信クラス初期化
-            Networking.DefaultTimeout = TimeSpan.FromSeconds(this._cfgCommon.DefaultTimeOut);
-            Networking.UploadImageTimeout = TimeSpan.FromSeconds(this._cfgCommon.UploadImageTimeout);
-            Networking.SetWebProxy(this._cfgLocal.ProxyType,
-                this._cfgLocal.ProxyAddress, this._cfgLocal.ProxyPort,
-                this._cfgLocal.ProxyUser, this._cfgLocal.ProxyPassword);
-            Networking.ForceIPv4 = this._cfgCommon.ForceIPv4;
-
-            TwitterApiConnection.RestApiHost = this._cfgCommon.TwitterApiHost;
-            tw.RestrictFavCheck = this._cfgCommon.RestrictFavCheck;
-            tw.ReadOwnPost = this._cfgCommon.ReadOwnPost;
-            tw.TrackWord = this._cfgCommon.TrackWord;
+            Networking.DefaultTimeout = TimeSpan.FromSeconds(SettingManager.Common.DefaultTimeOut);
+            Networking.UploadImageTimeout = TimeSpan.FromSeconds(SettingManager.Common.UploadImageTimeout);
+            Networking.SetWebProxy(SettingManager.Local.ProxyType,
+                SettingManager.Local.ProxyAddress, SettingManager.Local.ProxyPort,
+                SettingManager.Local.ProxyUser, SettingManager.Local.ProxyPassword);
+            Networking.ForceIPv4 = SettingManager.Common.ForceIPv4;
+
+            TwitterApiConnection.RestApiHost = SettingManager.Common.TwitterApiHost;
+            tw.RestrictFavCheck = SettingManager.Common.RestrictFavCheck;
+            tw.ReadOwnPost = SettingManager.Common.ReadOwnPost;
+            tw.TrackWord = SettingManager.Common.TrackWord;
             TrackToolStripMenuItem.Checked = !String.IsNullOrEmpty(tw.TrackWord);
-            tw.AllAtReply = this._cfgCommon.AllAtReply;
+            tw.AllAtReply = SettingManager.Common.AllAtReply;
             AllrepliesToolStripMenuItem.Checked = tw.AllAtReply;
-            ShortUrl.Instance.DisableExpanding = !this._cfgCommon.TinyUrlResolve;
-            ShortUrl.Instance.BitlyId = this._cfgCommon.BilyUser;
-            ShortUrl.Instance.BitlyKey = this._cfgCommon.BitlyPwd;
+            ShortUrl.Instance.DisableExpanding = !SettingManager.Common.TinyUrlResolve;
+            ShortUrl.Instance.BitlyAccessToken = SettingManager.Common.BitlyAccessToken;
+            ShortUrl.Instance.BitlyId = SettingManager.Common.BilyUser;
+            ShortUrl.Instance.BitlyKey = SettingManager.Common.BitlyPwd;
 
             // アクセストークンが有効であるか確認する
             // ここが Twitter API への最初のアクセスになるようにすること
@@ -827,7 +836,7 @@ namespace OpenTween
             catch (WebApiException ex)
             {
                 MessageBox.Show(this, string.Format(Properties.Resources.StartupAuthError_Text, ex.Message),
-                    Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
+                    ApplicationSettings.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
             }
 
             //サムネイル関連の初期化
@@ -835,23 +844,23 @@ namespace OpenTween
             ThumbnailGenerator.InitializeGenerator();
 
             var imgazyobizinet = ThumbnailGenerator.ImgAzyobuziNetInstance;
-            imgazyobizinet.Enabled = this._cfgCommon.EnableImgAzyobuziNet;
-            imgazyobizinet.DisabledInDM = this._cfgCommon.ImgAzyobuziNetDisabledInDM;
+            imgazyobizinet.Enabled = SettingManager.Common.EnableImgAzyobuziNet;
+            imgazyobizinet.DisabledInDM = SettingManager.Common.ImgAzyobuziNetDisabledInDM;
 
             Thumbnail.Services.TonTwitterCom.GetApiConnection = () => this.twitterApi.Connection;
 
             //画像投稿サービス
-            ImageSelector.Initialize(tw, this.tw.Configuration, _cfgCommon.UseImageServiceName, _cfgCommon.UseImageService);
+            ImageSelector.Initialize(tw, this.tw.Configuration, SettingManager.Common.UseImageServiceName, SettingManager.Common.UseImageService);
 
             //ハッシュタグ/@id関連
-            AtIdSupl = new AtIdSupplement(SettingAtIdList.Load().AtIdList, "@");
-            HashSupl = new AtIdSupplement(_cfgCommon.HashTags, "#");
+            AtIdSupl = new AtIdSupplement(SettingManager.AtIdList.AtIdList, "@");
+            HashSupl = new AtIdSupplement(SettingManager.Common.HashTags, "#");
             HashMgr = new HashtagManage(HashSupl,
-                                    _cfgCommon.HashTags.ToArray(),
-                                    _cfgCommon.HashSelected,
-                                    _cfgCommon.HashIsPermanent,
-                                    _cfgCommon.HashIsHead,
-                                    _cfgCommon.HashIsNotAddToAtReply);
+                                    SettingManager.Common.HashTags.ToArray(),
+                                    SettingManager.Common.HashSelected,
+                                    SettingManager.Common.HashIsPermanent,
+                                    SettingManager.Common.HashIsHead,
+                                    SettingManager.Common.HashIsNotAddToAtReply);
             if (!string.IsNullOrEmpty(HashMgr.UseHash) && HashMgr.IsPermanent) HashStripSplitButton.Text = HashMgr.UseHash;
 
             //アイコンリスト作成
@@ -859,27 +868,27 @@ namespace OpenTween
             this.tweetDetailsView.IconCache = this.IconCache;
 
             //フォント&文字色&背景色保持
-            _fntUnread = this._cfgLocal.FontUnread;
-            _clUnread = this._cfgLocal.ColorUnread;
-            _fntReaded = this._cfgLocal.FontRead;
-            _clReaded = this._cfgLocal.ColorRead;
-            _clFav = this._cfgLocal.ColorFav;
-            _clOWL = this._cfgLocal.ColorOWL;
-            _clRetweet = this._cfgLocal.ColorRetweet;
-            _fntDetail = this._cfgLocal.FontDetail;
-            _clDetail = this._cfgLocal.ColorDetail;
-            _clDetailLink = this._cfgLocal.ColorDetailLink;
-            _clDetailBackcolor = this._cfgLocal.ColorDetailBackcolor;
-            _clSelf = this._cfgLocal.ColorSelf;
-            _clAtSelf = this._cfgLocal.ColorAtSelf;
-            _clTarget = this._cfgLocal.ColorTarget;
-            _clAtTarget = this._cfgLocal.ColorAtTarget;
-            _clAtFromTarget = this._cfgLocal.ColorAtFromTarget;
-            _clAtTo = this._cfgLocal.ColorAtTo;
-            _clListBackcolor = this._cfgLocal.ColorListBackcolor;
-            _clInputBackcolor = this._cfgLocal.ColorInputBackcolor;
-            _clInputFont = this._cfgLocal.ColorInputFont;
-            _fntInputFont = this._cfgLocal.FontInputFont;
+            _fntUnread = SettingManager.Local.FontUnread;
+            _clUnread = SettingManager.Local.ColorUnread;
+            _fntReaded = SettingManager.Local.FontRead;
+            _clReaded = SettingManager.Local.ColorRead;
+            _clFav = SettingManager.Local.ColorFav;
+            _clOWL = SettingManager.Local.ColorOWL;
+            _clRetweet = SettingManager.Local.ColorRetweet;
+            _fntDetail = SettingManager.Local.FontDetail;
+            _clDetail = SettingManager.Local.ColorDetail;
+            _clDetailLink = SettingManager.Local.ColorDetailLink;
+            _clDetailBackcolor = SettingManager.Local.ColorDetailBackcolor;
+            _clSelf = SettingManager.Local.ColorSelf;
+            _clAtSelf = SettingManager.Local.ColorAtSelf;
+            _clTarget = SettingManager.Local.ColorTarget;
+            _clAtTarget = SettingManager.Local.ColorAtTarget;
+            _clAtFromTarget = SettingManager.Local.ColorAtFromTarget;
+            _clAtTo = SettingManager.Local.ColorAtTo;
+            _clListBackcolor = SettingManager.Local.ColorListBackcolor;
+            _clInputBackcolor = SettingManager.Local.ColorInputBackcolor;
+            _clInputFont = SettingManager.Local.ColorInputFont;
+            _fntInputFont = SettingManager.Local.FontInputFont;
 
             _brsBackColorMine = new SolidBrush(_clSelf);
             _brsBackColorAt = new SolidBrush(_clAtSelf);
@@ -902,7 +911,7 @@ namespace OpenTween
             //Regex statregex = new Regex("^0*");
             this.recommendedStatusFooter = " [TWNv" + Regex.Replace(MyCommon.FileVersion.Replace(".", ""), "^0*", "") + "]";
 
-            _history.Add(new PostingStatus());
+            _history.Add(new StatusTextHistory());
             _hisIdx = 0;
             this.inReplyTo = null;
 
@@ -911,28 +920,24 @@ namespace OpenTween
             UrlDialog.Owner = this;
 
             //新着バルーン通知のチェック状態設定
-            NewPostPopMenuItem.Checked = _cfgCommon.NewAllPop;
+            NewPostPopMenuItem.Checked = SettingManager.Common.NewAllPop;
             this.NotifyFileMenuItem.Checked = NewPostPopMenuItem.Checked;
 
             //新着取得時のリストスクロールをするか。trueならスクロールしない
-            ListLockMenuItem.Checked = _cfgCommon.ListLock;
-            this.LockListFileMenuItem.Checked = _cfgCommon.ListLock;
+            ListLockMenuItem.Checked = SettingManager.Common.ListLock;
+            this.LockListFileMenuItem.Checked = SettingManager.Common.ListLock;
             //サウンド再生(タブ別設定より優先)
-            this.PlaySoundMenuItem.Checked = this._cfgCommon.PlaySound;
-            this.PlaySoundFileMenuItem.Checked = this._cfgCommon.PlaySound;
-
-            this.IdeographicSpaceToSpaceToolStripMenuItem.Checked = _cfgCommon.WideSpaceConvert;
-            this.ToolStripFocusLockMenuItem.Checked = _cfgCommon.FocusLockToStatusText;
+            this.PlaySoundMenuItem.Checked = SettingManager.Common.PlaySound;
+            this.PlaySoundFileMenuItem.Checked = SettingManager.Common.PlaySound;
 
             //ウィンドウ設定
-            this.ClientSize = ScaleBy(configScaleFactor, _cfgLocal.FormSize);
+            this.ClientSize = ScaleBy(configScaleFactor, SettingManager.Local.FormSize);
             _mySize = this.ClientSize; // サイズ保持(最小化・最大化されたまま終了した場合の対応用)
-            _myLoc = _cfgLocal.FormLocation;
+            _myLoc = SettingManager.Local.FormLocation;
             //タイトルバー領域
             if (this.WindowState != FormWindowState.Minimized)
             {
-                this.DesktopLocation = _cfgLocal.FormLocation;
-                Rectangle tbarRect = new Rectangle(this.Location, new Size(_mySize.Width, SystemInformation.CaptionHeight));
+                Rectangle tbarRect = new Rectangle(this._myLoc, new Size(_mySize.Width, SystemInformation.CaptionHeight));
                 bool outOfScreen = true;
                 if (Screen.AllScreens.Length == 1)    //ハングするとの報告
                 {
@@ -944,43 +949,41 @@ namespace OpenTween
                             break;
                         }
                     }
+
                     if (outOfScreen)
-                    {
-                        this.DesktopLocation = new Point(0, 0);
-                        _myLoc = this.DesktopLocation;
-                    }
+                        this._myLoc = new Point(0, 0);
                 }
+                this.DesktopLocation = this._myLoc;
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
-            _mySpDis = ScaleBy(configScaleFactor.Height, _cfgLocal.SplitterDistance);
-            _mySpDis2 = ScaleBy(configScaleFactor.Height, _cfgLocal.StatusTextHeight);
-            if (_cfgLocal.PreviewDistance == -1)
+            this.TopMost = SettingManager.Common.AlwaysTop;
+            _mySpDis = ScaleBy(configScaleFactor.Height, SettingManager.Local.SplitterDistance);
+            _mySpDis2 = ScaleBy(configScaleFactor.Height, SettingManager.Local.StatusTextHeight);
+            if (SettingManager.Local.PreviewDistance == -1)
             {
                 _mySpDis3 = _mySize.Width - ScaleBy(this.CurrentScaleFactor.Width, 150);
                 if (_mySpDis3 < 1) _mySpDis3 = ScaleBy(this.CurrentScaleFactor.Width, 50);
-                _cfgLocal.PreviewDistance = _mySpDis3;
+                SettingManager.Local.PreviewDistance = _mySpDis3;
             }
             else
             {
-                _mySpDis3 = ScaleBy(configScaleFactor.Width, _cfgLocal.PreviewDistance);
+                _mySpDis3 = ScaleBy(configScaleFactor.Width, SettingManager.Local.PreviewDistance);
             }
-            MultiLineMenuItem.Checked = _cfgLocal.StatusMultiline;
             //this.Tween_ClientSizeChanged(this, null);
-            this.PlaySoundMenuItem.Checked = this._cfgCommon.PlaySound;
-            this.PlaySoundFileMenuItem.Checked = this._cfgCommon.PlaySound;
+            this.PlaySoundMenuItem.Checked = SettingManager.Common.PlaySound;
+            this.PlaySoundFileMenuItem.Checked = SettingManager.Common.PlaySound;
             //入力欄
             StatusText.Font = _fntInputFont;
             StatusText.ForeColor = _clInputFont;
 
             // SplitContainer2.Panel2MinSize を一行表示の入力欄の高さに合わせる (MS UI Gothic 12pt (96dpi) の場合は 19px)
-            this.StatusText.Multiline = false; // _cfgLocal.StatusMultiline の設定は後で反映される
+            this.StatusText.Multiline = false; // SettingManager.Local.StatusMultiline の設定は後で反映される
             this.SplitContainer2.Panel2MinSize = this.StatusText.Height;
 
             // 必要であれば、発言一覧と発言詳細部・入力欄の上下を入れ替える
-            SplitContainer1.IsPanelInverted = !this._cfgCommon.StatusAreaAtBottom;
+            SplitContainer1.IsPanelInverted = !SettingManager.Common.StatusAreaAtBottom;
 
             //全新着通知のチェック状態により、Reply&DMの新着通知有効無効切り替え(タブ別設定にするため削除予定)
-            if (this._cfgCommon.UnreadManage == false)
+            if (SettingManager.Common.UnreadManage == false)
             {
                 ReadedStripMenuItem.Enabled = false;
                 UnreadStripMenuItem.Enabled = false;
@@ -993,7 +996,7 @@ namespace OpenTween
             StatusLabel.AutoToolTip = false;
             StatusLabel.ToolTipText = "";
             //文字カウンタ初期化
-            lblLen.Text = this.GetRestStatusCount(this.FormatStatusText("")).ToString();
+            lblLen.Text = this.GetRestStatusCount(this.FormatStatusTextExtended("")).ToString();
 
             this.JumpReadOpMenuItem.ShortcutKeyDisplayString = "Space";
             CopySTOTMenuItem.ShortcutKeyDisplayString = "Ctrl+C";
@@ -1006,9 +1009,9 @@ namespace OpenTween
             this.SplitContainer2.Panel2.AccessibleName = "";
 
             ////////////////////////////////////////////////////////////////////////////////
-            var sortOrder = (SortOrder)_cfgCommon.SortOrder;
+            var sortOrder = (SortOrder)SettingManager.Common.SortOrder;
             var mode = ComparerMode.Id;
-            switch (_cfgCommon.SortColumn)
+            switch (SettingManager.Common.SortColumn)
             {
                 case 0:    //0:アイコン,5:未読マーク,6:プロテクト・フィルターマーク
                 case 5:
@@ -1035,7 +1038,7 @@ namespace OpenTween
             _statuses.SetSortMode(mode, sortOrder);
             ////////////////////////////////////////////////////////////////////////////////
 
-            ApplyListViewIconSize(this._cfgCommon.IconSize);
+            ApplyListViewIconSize(SettingManager.Common.IconSize);
 
             //<<<<<<<<タブ関連>>>>>>>
             // タブの位置を調整する
@@ -1057,7 +1060,7 @@ namespace OpenTween
             if (this._statuses.GetTabByType<MuteTabModel>() == null)
                 this._statuses.AddTab(new MuteTabModel());
 
-            foreach (var tab in _statuses.Tabs.Values)
+            foreach (var tab in _statuses.Tabs)
             {
                 // ミュートタブは表示しない
                 if (tab.TabType == MyCommon.TabUsageType.Mute)
@@ -1067,11 +1070,12 @@ namespace OpenTween
                     throw new TabException(Properties.Resources.TweenMain_LoadText1);
             }
 
-            _curTab = ListTab.SelectedTab;
-            _curItemIndex = -1;
-            _curList = (DetailsListView)_curTab.Tag;
+            this._statuses.SelectTab(this.ListTab.SelectedTab.Text);
 
-            if (this._cfgCommon.TabIconDisp)
+            MyCommon.TwitterApiInfo.AccessLimitUpdated += TwitterApiStatus_AccessLimitUpdated;
+            Microsoft.Win32.SystemEvents.TimeChanged += SystemEvents_TimeChanged;
+
+            if (SettingManager.Common.TabIconDisp)
             {
                 ListTab.DrawMode = TabDrawMode.Normal;
             }
@@ -1082,23 +1086,23 @@ namespace OpenTween
                 ListTab.ImageList = null;
             }
 
-            if (this._cfgCommon.HotkeyEnabled)
+            if (SettingManager.Common.HotkeyEnabled)
             {
                 //////グローバルホットキーの登録
                 HookGlobalHotkey.ModKeys modKey = HookGlobalHotkey.ModKeys.None;
-                if ((this._cfgCommon.HotkeyModifier & Keys.Alt) == Keys.Alt)
+                if ((SettingManager.Common.HotkeyModifier & Keys.Alt) == Keys.Alt)
                     modKey |= HookGlobalHotkey.ModKeys.Alt;
-                if ((this._cfgCommon.HotkeyModifier & Keys.Control) == Keys.Control)
+                if ((SettingManager.Common.HotkeyModifier & Keys.Control) == Keys.Control)
                     modKey |= HookGlobalHotkey.ModKeys.Ctrl;
-                if ((this._cfgCommon.HotkeyModifier & Keys.Shift) == Keys.Shift)
+                if ((SettingManager.Common.HotkeyModifier & Keys.Shift) == Keys.Shift)
                     modKey |= HookGlobalHotkey.ModKeys.Shift;
-                if ((this._cfgCommon.HotkeyModifier & Keys.LWin) == Keys.LWin)
+                if ((SettingManager.Common.HotkeyModifier & Keys.LWin) == Keys.LWin)
                     modKey |= HookGlobalHotkey.ModKeys.Win;
 
-                _hookGlobalHotkey.RegisterOriginalHotkey(this._cfgCommon.HotkeyKey, this._cfgCommon.HotkeyValue, modKey);
+                _hookGlobalHotkey.RegisterOriginalHotkey(SettingManager.Common.HotkeyKey, SettingManager.Common.HotkeyValue, modKey);
             }
 
-            if (this._cfgCommon.IsUseNotifyGrowl)
+            if (SettingManager.Common.IsUseNotifyGrowl)
                 gh.RegisterGrowl();
 
             StatusLabel.Text = Properties.Resources.Form1_LoadText1;       //画面右下の状態表示を変更
@@ -1106,12 +1110,17 @@ namespace OpenTween
             SetMainWindowTitle();
             SetNotifyIconText();
 
-            if (!this._cfgCommon.MinimizeToTray || this.WindowState != FormWindowState.Minimized)
+            if (!SettingManager.Common.MinimizeToTray || this.WindowState != FormWindowState.Minimized)
             {
                 this.Visible = true;
             }
 
             //タイマー設定
+
+            var streamingRefreshInterval = TimeSpan.FromSeconds(SettingManager.Common.UserstreamPeriod);
+            this.RefreshThrottlingTimer = new ThrottlingTimer(streamingRefreshInterval,
+                () => this.InvokeAsync(() => this.RefreshTimeline()));
+
             TimerTimeline.AutoReset = true;
             TimerTimeline.SynchronizingObject = this;
             //Recent取得間隔
@@ -1125,9 +1134,9 @@ namespace OpenTween
             this.TweenMain_Resize(null, null);
             if (saveRequired) SaveConfigsAll(false);
 
-            foreach (var ua in this._cfgCommon.UserAccounts)
+            foreach (var ua in SettingManager.Common.UserAccounts)
             {
-                if (ua.UserId == 0 && ua.Username.ToLowerInvariant() == tw.Username.ToLowerInvariant())
+                if (ua.UserId == 0 && ua.Username.Equals(tw.Username, StringComparison.InvariantCultureIgnoreCase))
                 {
                     ua.UserId = tw.UserId;
                     break;
@@ -1143,7 +1152,7 @@ namespace OpenTween
 
         private void InitDetailHtmlFormat()
         {
-            if (this._cfgCommon.IsMonospace)
+            if (SettingManager.Common.IsMonospace)
             {
                 detailHtmlFormatHeader = detailHtmlFormatHeaderMono;
                 detailHtmlFormatFooter = detailHtmlFormatFooterMono;
@@ -1197,31 +1206,14 @@ namespace OpenTween
 
         private void LoadConfig()
         {
-            _cfgCommon = SettingCommon.Load();
-            SettingCommon.Instance = this._cfgCommon;
-            if (_cfgCommon.UserAccounts == null || _cfgCommon.UserAccounts.Count == 0)
-            {
-                _cfgCommon.UserAccounts = new List<UserAccount>();
-                if (!string.IsNullOrEmpty(_cfgCommon.UserName))
-                {
-                    UserAccount account = new UserAccount();
-                    account.Username = _cfgCommon.UserName;
-                    account.UserId = _cfgCommon.UserId;
-                    account.Token = _cfgCommon.Token;
-                    account.TokenSecret = _cfgCommon.TokenSecret;
-
-                    _cfgCommon.UserAccounts.Add(account);
-                }
-            }
-
-            _cfgLocal = SettingLocal.Load();
+            SettingManager.Local = SettingManager.Local;
 
             // v1.2.4 以前の設定には ScaleDimension の項目がないため、現在の DPI と同じとして扱う
-            if (_cfgLocal.ScaleDimension.IsEmpty)
-                _cfgLocal.ScaleDimension = this.CurrentAutoScaleDimensions;
+            if (SettingManager.Local.ScaleDimension.IsEmpty)
+                SettingManager.Local.ScaleDimension = this.CurrentAutoScaleDimensions;
 
-            var tabsSetting = SettingTabs.Load().Tabs;
-            foreach (var tabSetting in tabsSetting)
+            var tabSettings = SettingManager.Tabs;
+            foreach (var tabSetting in tabSettings.Tabs)
             {
                 TabModel tab;
                 switch (tabSetting.TabType)
@@ -1290,6 +1282,15 @@ namespace OpenTween
         private void TimerInterval_Changed(object sender, IntervalChangedEventArgs e) //Handles SettingDialog.IntervalChanged
         {
             if (!TimerTimeline.Enabled) return;
+
+            if (e.UserStream)
+            {
+                var interval = TimeSpan.FromSeconds(SettingManager.Common.UserstreamPeriod);
+                var newTimer = new ThrottlingTimer(interval, () => this.InvokeAsync(() => this.RefreshTimeline()));
+                var oldTimer = Interlocked.Exchange(ref this.RefreshThrottlingTimer, newTimer);
+                oldTimer.Dispose();
+            }
+
             ResetTimers = e;
         }
 
@@ -1301,7 +1302,6 @@ namespace OpenTween
         private static int pubSearchCounter = 0;
         private static int userTimelineCounter = 0;
         private static int listsCounter = 0;
-        private static int usCounter = 0;
         private static int ResumeWait = 0;
         private static int refreshFollowers = 0;
 
@@ -1313,61 +1313,53 @@ namespace OpenTween
             if (pubSearchCounter > 0) Interlocked.Decrement(ref pubSearchCounter);
             if (userTimelineCounter > 0) Interlocked.Decrement(ref userTimelineCounter);
             if (listsCounter > 0) Interlocked.Decrement(ref listsCounter);
-            if (usCounter > 0) Interlocked.Decrement(ref usCounter);
             Interlocked.Increment(ref refreshFollowers);
 
             var refreshTasks = new List<Task>();
 
             ////タイマー初期化
-            if (ResetTimers.Timeline || homeCounter <= 0 && this._cfgCommon.TimelinePeriod > 0)
+            if (ResetTimers.Timeline || homeCounter <= 0 && SettingManager.Common.TimelinePeriod > 0)
             {
-                Interlocked.Exchange(ref homeCounter, this._cfgCommon.TimelinePeriod);
+                Interlocked.Exchange(ref homeCounter, SettingManager.Common.TimelinePeriod);
                 if (!tw.IsUserstreamDataReceived && !ResetTimers.Timeline)
-                    refreshTasks.Add(this.GetHomeTimelineAsync());
+                    refreshTasks.Add(this.RefreshTabAsync<HomeTabModel>());
                 ResetTimers.Timeline = false;
             }
-            if (ResetTimers.Reply || mentionCounter <= 0 && this._cfgCommon.ReplyPeriod > 0)
+            if (ResetTimers.Reply || mentionCounter <= 0 && SettingManager.Common.ReplyPeriod > 0)
             {
-                Interlocked.Exchange(ref mentionCounter, this._cfgCommon.ReplyPeriod);
+                Interlocked.Exchange(ref mentionCounter, SettingManager.Common.ReplyPeriod);
                 if (!tw.IsUserstreamDataReceived && !ResetTimers.Reply)
-                    refreshTasks.Add(this.GetReplyAsync());
+                    refreshTasks.Add(this.RefreshTabAsync<MentionsTabModel>());
                 ResetTimers.Reply = false;
             }
-            if (ResetTimers.DirectMessage || dmCounter <= 0 && this._cfgCommon.DMPeriod > 0)
+            if (ResetTimers.DirectMessage || dmCounter <= 0 && SettingManager.Common.DMPeriod > 0)
             {
-                Interlocked.Exchange(ref dmCounter, this._cfgCommon.DMPeriod);
+                Interlocked.Exchange(ref dmCounter, SettingManager.Common.DMPeriod);
                 if (!tw.IsUserstreamDataReceived && !ResetTimers.DirectMessage)
-                    refreshTasks.Add(this.GetDirectMessagesAsync());
+                    refreshTasks.Add(this.RefreshTabAsync<DirectMessagesTabModel>());
                 ResetTimers.DirectMessage = false;
             }
-            if (ResetTimers.PublicSearch || pubSearchCounter <= 0 && this._cfgCommon.PubSearchPeriod > 0)
+            if (ResetTimers.PublicSearch || pubSearchCounter <= 0 && SettingManager.Common.PubSearchPeriod > 0)
             {
-                Interlocked.Exchange(ref pubSearchCounter, this._cfgCommon.PubSearchPeriod);
+                Interlocked.Exchange(ref pubSearchCounter, SettingManager.Common.PubSearchPeriod);
                 if (!ResetTimers.PublicSearch)
-                    refreshTasks.Add(this.GetPublicSearchAllAsync());
+                    refreshTasks.Add(this.RefreshTabAsync<PublicSearchTabModel>());
                 ResetTimers.PublicSearch = false;
             }
-            if (ResetTimers.UserTimeline || userTimelineCounter <= 0 && this._cfgCommon.UserTimelinePeriod > 0)
+            if (ResetTimers.UserTimeline || userTimelineCounter <= 0 && SettingManager.Common.UserTimelinePeriod > 0)
             {
-                Interlocked.Exchange(ref userTimelineCounter, this._cfgCommon.UserTimelinePeriod);
+                Interlocked.Exchange(ref userTimelineCounter, SettingManager.Common.UserTimelinePeriod);
                 if (!ResetTimers.UserTimeline)
-                    refreshTasks.Add(this.GetUserTimelineAllAsync());
+                    refreshTasks.Add(this.RefreshTabAsync<UserTimelineTabModel>());
                 ResetTimers.UserTimeline = false;
             }
-            if (ResetTimers.Lists || listsCounter <= 0 && this._cfgCommon.ListsPeriod > 0)
+            if (ResetTimers.Lists || listsCounter <= 0 && SettingManager.Common.ListsPeriod > 0)
             {
-                Interlocked.Exchange(ref listsCounter, this._cfgCommon.ListsPeriod);
+                Interlocked.Exchange(ref listsCounter, SettingManager.Common.ListsPeriod);
                 if (!ResetTimers.Lists)
-                    refreshTasks.Add(this.GetListTimelineAllAsync());
+                    refreshTasks.Add(this.RefreshTabAsync<ListTimelineTabModel>());
                 ResetTimers.Lists = false;
             }
-            if (ResetTimers.UserStream || usCounter <= 0 && this._cfgCommon.UserstreamPeriod > 0)
-            {
-                Interlocked.Exchange(ref usCounter, this._cfgCommon.UserstreamPeriod);
-                if (this.tw.UserStreamActive)
-                    this.RefreshTimeline();
-                ResetTimers.UserStream = false;
-            }
             if (refreshFollowers > 6 * 3600)
             {
                 Interlocked.Exchange(ref refreshFollowers, 0);
@@ -1387,12 +1379,12 @@ namespace OpenTween
                     Interlocked.Exchange(ref ResumeWait, 0);
                     refreshTasks.AddRange(new[]
                     {
-                        this.GetHomeTimelineAsync(),
-                        this.GetReplyAsync(),
-                        this.GetDirectMessagesAsync(),
-                        this.GetPublicSearchAllAsync(),
-                        this.GetUserTimelineAllAsync(),
-                        this.GetListTimelineAllAsync(),
+                        this.RefreshTabAsync<HomeTabModel>(),
+                        this.RefreshTabAsync<MentionsTabModel>(),
+                        this.RefreshTabAsync<DirectMessagesTabModel>(),
+                        this.RefreshTabAsync<PublicSearchTabModel>(),
+                        this.RefreshTabAsync<UserTimelineTabModel>(),
+                        this.RefreshTabAsync<ListTimelineTabModel>(),
                         this.doGetFollowersMenu(),
                         this.RefreshTwitterConfigurationAsync(),
                     });
@@ -1404,21 +1396,19 @@ namespace OpenTween
 
         private void RefreshTimeline()
         {
-            var curTabModel = this._statuses.Tabs[this._curTab.Text];
+            var curTabModel = this.CurrentTab;
+            var curListView = this.CurrentListView;
 
             // 現在表示中のタブのスクロール位置を退避
-            var curListScroll = this.SaveListViewScroll(this._curList, curTabModel);
+            var curListScroll = this.SaveListViewScroll(curListView, curTabModel);
 
             // 各タブのリスト上の選択位置などを退避
             var listSelections = this.SaveListViewSelection();
 
             //更新確定
-            PostClass[] notifyPosts;
-            string soundFile;
             int addCount;
-            bool newMentionOrDm;
-            bool isDelete;
-            addCount = _statuses.SubmitUpdate(out soundFile, out notifyPosts, out newMentionOrDm, out isDelete);
+            addCount = _statuses.SubmitUpdate(out var soundFile, out var notifyPosts,
+                out var newMentionOrDm, out var isDelete);
 
             if (MyCommon._endingFlag) return;
 
@@ -1432,7 +1422,7 @@ namespace OpenTween
                 {
                     using (ControlTransaction.Update(listView))
                     {
-                        if (listView == this._curList)
+                        if (listView == curListView)
                             this.PurgeListViewItemCache();
 
                         try
@@ -1455,7 +1445,7 @@ namespace OpenTween
 
             if (addCount > 0)
             {
-                if (this._cfgCommon.TabIconDisp)
+                if (SettingManager.Common.TabIconDisp)
                 {
                     foreach (var tabPage in this.ListTab.TabPages.Cast<TabPage>())
                     {
@@ -1471,7 +1461,7 @@ namespace OpenTween
             }
 
             // スクロール位置を復元
-            this.RestoreListViewScroll(this._curList, curTabModel, curListScroll);
+            this.RestoreListViewScroll(curListView, curTabModel, curListScroll);
 
             //新着通知
             NotifyNewPosts(notifyPosts, soundFile, addCount, newMentionOrDm);
@@ -1597,7 +1587,7 @@ namespace OpenTween
             {
                 return new ListViewSelection
                 {
-                    SelectedStatusIds = new long[0],
+                    SelectedStatusIds = Array.Empty<long>(),
                     SelectionMarkStatusId = null,
                     FocusedStatusId = null,
                 };
@@ -1605,21 +1595,12 @@ namespace OpenTween
 
             return new ListViewSelection
             {
-                SelectedStatusIds = this.GetSelectedStatusIds(listView, tab),
+                SelectedStatusIds = tab.SelectedStatusIds,
                 FocusedStatusId = this.GetFocusedStatusId(listView, tab),
                 SelectionMarkStatusId = this.GetSelectionMarkStatusId(listView, tab),
             };
         }
 
-        private long[] GetSelectedStatusIds(DetailsListView listView, TabModel tab)
-        {
-            var selectedIndices = listView.SelectedIndices;
-            if (selectedIndices.Count > 0 && selectedIndices.Count < 61)
-                return tab.GetStatusIdAt(selectedIndices.Cast<int>());
-            else
-                return null;
-        }
-
         private long? GetFocusedStatusId(DetailsListView listView, TabModel tab)
         {
             var index = listView.FocusedItem?.Index ?? -1;
@@ -1653,7 +1634,18 @@ namespace OpenTween
                 case ScrollLockMode.FixedToItem:
                     var topIndex = listScroll.TopItemStatusId != null ? tab.IndexOf(listScroll.TopItemStatusId.Value) : -1;
                     if (topIndex != -1)
-                        listView.TopItem = listView.Items[topIndex];
+                    {
+                        var topItem = listView.Items[topIndex];
+                        try
+                        {
+                            listView.TopItem = topItem;
+                        }
+                        catch (NullReferenceException)
+                        {
+                            listView.EnsureVisible(listView.VirtualListSize - 1);
+                            listView.EnsureVisible(topIndex);
+                        }
+                    }
                     break;
                 case ScrollLockMode.None:
                 default:
@@ -1684,8 +1676,10 @@ namespace OpenTween
 
         private bool BalloonRequired()
         {
-            Twitter.FormattedEvent ev = new Twitter.FormattedEvent();
-            ev.Eventtype = MyCommon.EVENTTYPE.None;
+            var ev = new Twitter.FormattedEvent
+            {
+                Eventtype = MyCommon.EVENTTYPE.None,
+            };
 
             return BalloonRequired(ev);
         }
@@ -1695,10 +1689,10 @@ namespace OpenTween
             if (type == MyCommon.EVENTTYPE.None)
                 return true;
 
-            if (!this._cfgCommon.EventNotifyEnabled)
+            if (!SettingManager.Common.EventNotifyEnabled)
                 return false;
 
-            return this._cfgCommon.EventNotifyFlag.HasFlag(type);
+            return SettingManager.Common.EventNotifyFlag.HasFlag(type);
         }
 
         private bool IsMyEventNotityAsEventType(Twitter.FormattedEvent ev)
@@ -1706,7 +1700,7 @@ namespace OpenTween
             if (!ev.IsMe)
                 return true;
 
-            return this._cfgCommon.IsMyEventNotifyFlag.HasFlag(ev.Eventtype);
+            return SettingManager.Common.IsMyEventNotifyFlag.HasFlag(ev.Eventtype);
         }
 
         private bool BalloonRequired(Twitter.FormattedEvent ev)
@@ -1721,12 +1715,12 @@ namespace OpenTween
             if (!this.NewPostPopMenuItem.Checked)
             {
                 // 「新着通知が無効でもイベントを通知する」にも該当しない
-                if (!this._cfgCommon.ForceEventNotify || ev.Eventtype == MyCommon.EVENTTYPE.None)
+                if (!SettingManager.Common.ForceEventNotify || ev.Eventtype == MyCommon.EVENTTYPE.None)
                     return false;
             }
 
             // 「画面最小化・アイコン時のみバルーンを表示する」が有効
-            if (this._cfgCommon.LimitBalloon)
+            if (SettingManager.Common.LimitBalloon)
             {
                 if (this.WindowState != FormWindowState.Minimized && this.Visible && Form.ActiveForm != null)
                     return false;
@@ -1737,7 +1731,7 @@ namespace OpenTween
 
         private void NotifyNewPosts(PostClass[] notifyPosts, string soundFile, int addCount, bool newMentions)
         {
-            if (this._cfgCommon.ReadOwnPost)
+            if (SettingManager.Common.ReadOwnPost)
             {
                 if (notifyPosts != null && notifyPosts.Length > 0 && notifyPosts.All(x => x.UserId == tw.UserId))
                     return;
@@ -1749,7 +1743,7 @@ namespace OpenTween
                 if (notifyPosts != null && notifyPosts.Length > 0)
                 {
                     //Growlは一個ずつばらして通知。ただし、3ポスト以上あるときはまとめる
-                    if (this._cfgCommon.IsUseNotifyGrowl)
+                    if (SettingManager.Common.IsUseNotifyGrowl)
                     {
                         StringBuilder sb = new StringBuilder();
                         bool reply = false;
@@ -1766,7 +1760,7 @@ namespace OpenTween
                             if (post.IsReply && !post.IsExcludeReply) reply = true;
                             if (post.IsDm) dm = true;
                             if (sb.Length > 0) sb.Append(System.Environment.NewLine);
-                            switch (this._cfgCommon.NameBalloon)
+                            switch (SettingManager.Common.NameBalloon)
                             {
                                 case MyCommon.NameBalloonEnum.UserID:
                                     sb.Append(post.ScreenName).Append(" : ");
@@ -1783,7 +1777,7 @@ namespace OpenTween
 
                             StringBuilder title = new StringBuilder();
                             GrowlHelper.NotifyType nt;
-                            if (this._cfgCommon.DispUsername)
+                            if (SettingManager.Common.DispUsername)
                             {
                                 title.Append(tw.Username);
                                 title.Append(" - ");
@@ -1796,7 +1790,7 @@ namespace OpenTween
                             {
                                 //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
                                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [DM] " + Properties.Resources.RefreshDirectMessageText1 + " " + addCount.ToString() + Properties.Resources.RefreshDirectMessageText2;
-                                title.Append(Application.ProductName);
+                                title.Append(ApplicationSettings.ApplicationName);
                                 title.Append(" [DM] ");
                                 title.AppendFormat(Properties.Resources.RefreshTimeline_NotifyText, addCount);
                                 nt = GrowlHelper.NotifyType.DirectMessage;
@@ -1805,7 +1799,7 @@ namespace OpenTween
                             {
                                 //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
                                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [Reply!] " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
-                                title.Append(Application.ProductName);
+                                title.Append(ApplicationSettings.ApplicationName);
                                 title.Append(" [Reply!] ");
                                 title.AppendFormat(Properties.Resources.RefreshTimeline_NotifyText, addCount);
                                 nt = GrowlHelper.NotifyType.Reply;
@@ -1814,7 +1808,7 @@ namespace OpenTween
                             {
                                 //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
                                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
-                                title.Append(Application.ProductName);
+                                title.Append(ApplicationSettings.ApplicationName);
                                 title.Append(" ");
                                 title.AppendFormat(Properties.Resources.RefreshTimeline_NotifyText, addCount);
                                 nt = GrowlHelper.NotifyType.Notify;
@@ -1823,7 +1817,7 @@ namespace OpenTween
                             if (string.IsNullOrEmpty(bText)) return;
 
                             var image = this.IconCache.TryGetFromCache(post.ImageUrl);
-                            gh.Notify(nt, post.StatusId.ToString(), title.ToString(), bText, image == null ? null : image.Image, post.ImageUrl);
+                            gh.Notify(nt, post.StatusId.ToString(), title.ToString(), bText, image?.Image, post.ImageUrl);
                         }
                     }
                     else
@@ -1836,7 +1830,7 @@ namespace OpenTween
                             if (post.IsReply && !post.IsExcludeReply) reply = true;
                             if (post.IsDm) dm = true;
                             if (sb.Length > 0) sb.Append(System.Environment.NewLine);
-                            switch (this._cfgCommon.NameBalloon)
+                            switch (SettingManager.Common.NameBalloon)
                             {
                                 case MyCommon.NameBalloonEnum.UserID:
                                     sb.Append(post.ScreenName).Append(" : ");
@@ -1851,7 +1845,7 @@ namespace OpenTween
                         //if (SettingDialog.DispUsername) { NotifyIcon1.BalloonTipTitle = tw.Username + " - "; } else { NotifyIcon1.BalloonTipTitle = ""; }
                         StringBuilder title = new StringBuilder();
                         ToolTipIcon ntIcon;
-                        if (this._cfgCommon.DispUsername)
+                        if (SettingManager.Common.DispUsername)
                         {
                             title.Append(tw.Username);
                             title.Append(" - ");
@@ -1865,7 +1859,7 @@ namespace OpenTween
                             //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
                             //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [DM] " + Properties.Resources.RefreshDirectMessageText1 + " " + addCount.ToString() + Properties.Resources.RefreshDirectMessageText2;
                             ntIcon = ToolTipIcon.Warning;
-                            title.Append(Application.ProductName);
+                            title.Append(ApplicationSettings.ApplicationName);
                             title.Append(" [DM] ");
                             title.AppendFormat(Properties.Resources.RefreshTimeline_NotifyText, addCount);
                         }
@@ -1874,7 +1868,7 @@ namespace OpenTween
                             //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
                             //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [Reply!] " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
                             ntIcon = ToolTipIcon.Warning;
-                            title.Append(Application.ProductName);
+                            title.Append(ApplicationSettings.ApplicationName);
                             title.Append(" [Reply!] ");
                             title.AppendFormat(Properties.Resources.RefreshTimeline_NotifyText, addCount);
                         }
@@ -1883,7 +1877,7 @@ namespace OpenTween
                             //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
                             //NotifyIcon1.BalloonTipTitle += Application.ProductName + " " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
                             ntIcon = ToolTipIcon.Info;
-                            title.Append(Application.ProductName);
+                            title.Append(ApplicationSettings.ApplicationName);
                             title.Append(" ");
                             title.AppendFormat(Properties.Resources.RefreshTimeline_NotifyText, addCount);
                         }
@@ -1900,7 +1894,7 @@ namespace OpenTween
             }
 
             //サウンド再生
-            if (!_initial && this._cfgCommon.PlaySound && !string.IsNullOrEmpty(soundFile))
+            if (!_initial && SettingManager.Common.PlaySound && !string.IsNullOrEmpty(soundFile))
             {
                 try
                 {
@@ -1920,7 +1914,7 @@ namespace OpenTween
             }
 
             //mentions新着時に画面ブリンク
-            if (!_initial && this._cfgCommon.BlinkNewMentions && newMentions && Form.ActiveForm == null)
+            if (!_initial && SettingManager.Common.BlinkNewMentions && newMentions && Form.ActiveForm == null)
             {
                 NativeMethods.FlashMyWindow(this.Handle, NativeMethods.FlashSpecification.FlashTray, 3);
             }
@@ -1928,25 +1922,25 @@ namespace OpenTween
 
         private void MyList_SelectedIndexChanged(object sender, EventArgs e)
         {
-            if (_curList == null || !_curList.Equals(sender) || _curList.SelectedIndices.Count != 1) return;
+            var listView = this.CurrentListView;
+            if (listView != sender)
+                return;
 
-            _curItemIndex = _curList.SelectedIndices[0];
-            if (_curItemIndex > _curList.VirtualListSize - 1) return;
+            var indices = listView.SelectedIndices.Cast<int>().ToArray();
+            this.CurrentTab.SelectPosts(indices);
 
-            try
-            {
-                this._curPost = GetCurTabPost(_curItemIndex);
-            }
-            catch (ArgumentException)
-            {
+            if (listView.SelectedIndices.Count != 1)
                 return;
-            }
+
+            var index = listView.SelectedIndices[0];
+            if (index > listView.VirtualListSize - 1) return;
 
             this.PushSelectPostChain();
 
-            this._statuses.SetReadAllTab(_curPost.StatusId, read: true);
+            var post = this.CurrentPost;
+            this._statuses.SetReadAllTab(post.StatusId, read: true);
             //キャッシュの書き換え
-            ChangeCacheStyleRead(true, _curItemIndex);   //既読へ(フォント、文字色)
+            ChangeCacheStyleRead(true, index); // 既読へ(フォント、文字色)
 
             ColorizeList();
             _colorize = true;
@@ -1954,23 +1948,21 @@ namespace OpenTween
 
         private void ChangeCacheStyleRead(bool Read, int Index)
         {
-            var tabInfo = _statuses.Tabs[_curTab.Text];
+            var tabInfo = this.CurrentTab;
             //Read:true=既読 false=未読
             //未読管理していなかったら既読として扱う
             if (!tabInfo.UnreadManage ||
-               !this._cfgCommon.UnreadManage) Read = true;
+               !SettingManager.Common.UnreadManage) Read = true;
 
             var listCache = this._listItemCache;
             if (listCache == null)
                 return;
 
             // キャッシュに含まれていないアイテムは対象外
-            ListViewItem itm;
-            PostClass post;
-            if (!listCache.TryGetValue(Index, out itm, out post))
+            if (!listCache.TryGetValue(Index, out var itm, out var post))
                 return;
 
-            ChangeItemStyleRead(Read, itm, post, ((DetailsListView)_curTab.Tag));
+            ChangeItemStyleRead(Read, itm, post, (DetailsListView)listCache.TargetList);
         }
 
         private void ChangeItemStyleRead(bool Read, ListViewItem Item, PostClass Post, DetailsListView DList)
@@ -1993,9 +1985,9 @@ namespace OpenTween
                 cl = _clFav;
             else if (Post.RetweetedId != null)
                 cl = _clRetweet;
-            else if (Post.IsOwl && (Post.IsDm || this._cfgCommon.OneWayLove))
+            else if (Post.IsOwl && (Post.IsDm || SettingManager.Common.OneWayLove))
                 cl = _clOWL;
-            else if (Read || !this._cfgCommon.UseUnreadStyle)
+            else if (Read || !SettingManager.Common.UseUnreadStyle)
                 cl = _clReaded;
             else
                 cl = _clUnread;
@@ -2003,13 +1995,13 @@ namespace OpenTween
             if (DList == null || Item.Index == -1)
             {
                 Item.ForeColor = cl;
-                if (this._cfgCommon.UseUnreadStyle)
+                if (SettingManager.Common.UseUnreadStyle)
                     Item.Font = fnt;
             }
             else
             {
                 DList.Update();
-                if (this._cfgCommon.UseUnreadStyle)
+                if (SettingManager.Common.UseUnreadStyle)
                     DList.ChangeItemFontAndColor(Item.Index, cl, fnt);
                 else
                     DList.ChangeItemForeColor(Item.Index, cl);
@@ -2025,7 +2017,7 @@ namespace OpenTween
             if (_anchorFlag)
                 _post = _anchorPost;
             else
-                _post = _curPost;
+                _post = this.CurrentPost;
 
             if (_post == null) return;
 
@@ -2034,10 +2026,11 @@ namespace OpenTween
                 return;
 
             var index = listCache.StartIndex;
+            var listView = (DetailsListView)listCache.TargetList;
             foreach (var cachedPost in listCache.Post)
             {
                 var backColor = this.JudgeColor(_post, cachedPost);
-                this._curList.ChangeItemBackColor(index++, backColor);
+                listView.ChangeItemBackColor(index++, backColor);
             }
         }
 
@@ -2049,7 +2042,7 @@ namespace OpenTween
             if (_anchorFlag)
                 _post = _anchorPost;
             else
-                _post = _curPost;
+                _post = this.CurrentPost;
 
             PostClass tPost = GetCurTabPost(Index);
 
@@ -2058,7 +2051,7 @@ namespace OpenTween
             if (Item.Index == -1)
                 Item.BackColor = JudgeColor(_post, tPost);
             else
-                _curList.ChangeItemBackColor(Item.Index, JudgeColor(_post, tPost));
+                this.CurrentListView.ChangeItemBackColor(Item.Index, JudgeColor(_post, tPost));
         }
 
         private Color JudgeColor(PostClass BasePost, PostClass TargetPost)
@@ -2073,10 +2066,10 @@ namespace OpenTween
             else if (TargetPost.IsReply)
                 //自分宛返信
                 cl = _clAtSelf;
-            else if (BasePost.ReplyToList.Contains(TargetPost.ScreenName.ToLowerInvariant()))
+            else if (BasePost.ReplyToList.Any(x => x.UserId == TargetPost.UserId))
                 //返信先
                 cl = _clAtFromTarget;
-            else if (TargetPost.ReplyToList.Contains(BasePost.ScreenName.ToLowerInvariant()))
+            else if (TargetPost.ReplyToList.Any(x => x.UserId == BasePost.UserId))
                 //その人への返信
                 cl = _clAtTarget;
             else if (TargetPost.ScreenName.Equals(BasePost.ScreenName, StringComparison.OrdinalIgnoreCase))
@@ -2089,6 +2082,36 @@ namespace OpenTween
             return cl;
         }
 
+        private void StatusTextHistoryBack()
+        {
+            if (!string.IsNullOrWhiteSpace(this.StatusText.Text))
+                this._history[_hisIdx] = new StatusTextHistory(this.StatusText.Text, this.inReplyTo);
+
+            this._hisIdx -= 1;
+            if (this._hisIdx < 0)
+                this._hisIdx = 0;
+
+            var historyItem = this._history[this._hisIdx];
+            this.inReplyTo = historyItem.inReplyTo;
+            this.StatusText.Text = historyItem.status;
+            this.StatusText.SelectionStart = this.StatusText.Text.Length;
+        }
+
+        private void StatusTextHistoryForward()
+        {
+            if (!string.IsNullOrWhiteSpace(this.StatusText.Text))
+                this._history[this._hisIdx] = new StatusTextHistory(this.StatusText.Text, this.inReplyTo);
+
+            this._hisIdx += 1;
+            if (this._hisIdx > this._history.Count - 1)
+                this._hisIdx = this._history.Count - 1;
+
+            var historyItem = this._history[this._hisIdx];
+            this.inReplyTo = historyItem.inReplyTo;
+            this.StatusText.Text = historyItem.status;
+            this.StatusText.SelectionStart = this.StatusText.Text.Length;
+        }
+
         private async void PostButton_Click(object sender, EventArgs e)
         {
             if (StatusText.Text.Trim().Length == 0)
@@ -2100,7 +2123,8 @@ namespace OpenTween
                 }
             }
 
-            if (this.ExistCurrentPost && StatusText.Text.Trim() == string.Format("RT @{0}: {1}", _curPost.ScreenName, _curPost.TextFromApi))
+            var currentPost = this.CurrentPost;
+            if (this.ExistCurrentPost && StatusText.Text.Trim() == string.Format("RT @{0}: {1}", currentPost.ScreenName, currentPost.TextFromApi))
             {
                 DialogResult rtResult = MessageBox.Show(string.Format(Properties.Resources.PostButton_Click1, Environment.NewLine),
                                                                "Retweet",
@@ -2117,11 +2141,18 @@ namespace OpenTween
                 }
             }
 
-            var inReplyToStatusId = this.inReplyTo?.Item1;
-            var inReplyToScreenName = this.inReplyTo?.Item2;
-            _history[_history.Count - 1] = new PostingStatus(StatusText.Text, inReplyToStatusId, inReplyToScreenName);
+            if (TextContainsOnlyMentions(this.StatusText.Text))
+            {
+                var message = string.Format(Properties.Resources.PostConfirmText, this.StatusText.Text);
+                var ret = MessageBox.Show(message, ApplicationSettings.ApplicationName, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
+
+                if (ret != DialogResult.OK)
+                    return;
+            }
+
+            _history[_history.Count - 1] = new StatusTextHistory(StatusText.Text, this.inReplyTo);
 
-            if (this._cfgCommon.Nicoms)
+            if (SettingManager.Common.Nicoms)
             {
                 StatusText.SelectionStart = StatusText.Text.Length;
                 await UrlConvertAsync(MyCommon.UrlConverter.Nicoms);
@@ -2139,9 +2170,37 @@ namespace OpenTween
             StatusText.SelectionStart = StatusText.Text.Length;
             CheckReplyTo(StatusText.Text);
 
-            var statusText = this.FormatStatusText(this.StatusText.Text);
+            var status = new PostStatusParams();
+
+            var statusTextCompat = this.FormatStatusText(this.StatusText.Text);
+            if (this.GetRestStatusCount(statusTextCompat) >= 0)
+            {
+                // auto_populate_reply_metadata や attachment_url を使用しなくても 140 字以内に
+                // 収まる場合はこれらのオプションを使用せずに投稿する
+                status.Text = statusTextCompat;
+                status.InReplyToStatusId = this.inReplyTo?.StatusId;
+            }
+            else
+            {
+                status.Text = this.FormatStatusTextExtended(this.StatusText.Text, out var autoPopulatedUserIds, out var attachmentUrl);
+                status.InReplyToStatusId = this.inReplyTo?.StatusId;
+
+                status.AttachmentUrl = attachmentUrl;
+
+                // リプライ先がセットされていても autoPopulatedUserIds が空の場合は auto_populate_reply_metadata を有効にしない
+                //  (非公式 RT の場合など)
+                var replyToPost = this.inReplyTo != null ? this._statuses[this.inReplyTo.Value.StatusId] : null;
+                if (replyToPost != null && autoPopulatedUserIds.Length != 0)
+                {
+                    status.AutoPopulateReplyMetadata = true;
+
+                    // ReplyToList のうち autoPopulatedUserIds に含まれていないユーザー ID を抽出
+                    status.ExcludeReplyUserIds = replyToPost.ReplyToList.Select(x => x.UserId).Except(autoPopulatedUserIds)
+                        .ToArray();
+                }
+            }
 
-            if (this.GetRestStatusCount(statusText) < 0)
+            if (this.GetRestStatusCount(status.Text) < 0)
             {
                 // 文字数制限を超えているが強制的に投稿するか
                 var ret = MessageBox.Show(Properties.Resources.PostLengthOverMessage1, Properties.Resources.PostLengthOverMessage2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
@@ -2149,24 +2208,23 @@ namespace OpenTween
                     return;
             }
 
-            var status = new PostingStatus();
-            status.status = statusText;
-
-            status.inReplyToId = this.inReplyTo?.Item1;
-            status.inReplyToName = this.inReplyTo?.Item2;
+            IMediaUploadService uploadService = null;
+            IMediaItem[] uploadItems = null;
             if (ImageSelector.Visible)
             {
                 //画像投稿
-                if (!ImageSelector.TryGetSelectedMedia(out status.imageService, out status.mediaItems))
+                if (!ImageSelector.TryGetSelectedMedia(out var serviceName, out uploadItems))
                     return;
+
+                uploadService = this.ImageSelector.GetService(serviceName);
             }
 
             this.inReplyTo = null;
             StatusText.Text = "";
-            _history.Add(new PostingStatus());
+            _history.Add(new StatusTextHistory());
             _hisIdx = _history.Count - 1;
-            if (!ToolStripFocusLockMenuItem.Checked)
-                ((Control)ListTab.SelectedTab.Tag).Focus();
+            if (!SettingManager.Common.FocusLockToStatusText)
+                this.CurrentListView.Focus();
             urlUndoBuffer = null;
             UrlUndoToolStripMenuItem.Enabled = false;  //Undoをできないように設定
 
@@ -2177,7 +2235,7 @@ namespace OpenTween
                 await this.OpenUriInBrowserAsync(tmp);
             }
 
-            await this.PostMessageAsync(status);
+            await this.PostMessageAsync(status, uploadService, uploadItems);
         }
 
         private void EndToolStripMenuItem_Click(object sender, EventArgs e)
@@ -2188,7 +2246,7 @@ namespace OpenTween
 
         private void TweenMain_FormClosing(object sender, FormClosingEventArgs e)
         {
-            if (!this._cfgCommon.CloseToExit && e.CloseReason == CloseReason.UserClosing && MyCommon._endingFlag == false)
+            if (!SettingManager.Common.CloseToExit && e.CloseReason == CloseReason.UserClosing && MyCommon._endingFlag == false)
             {
                 //_endingFlag=false:フォームの×ボタン
                 e.Cancel = true;
@@ -2234,260 +2292,71 @@ namespace OpenTween
             return true;
         }
 
-        private Task GetHomeTimelineAsync()
-        {
-            return this.GetHomeTimelineAsync(loadMore: false);
-        }
-
-        private async Task GetHomeTimelineAsync(bool loadMore)
-        {
-            await this.workerSemaphore.WaitAsync();
-
-            try
-            {
-                var homeTab = this._statuses.GetTabByType<HomeTabModel>();
-                await homeTab.RefreshAsync(this.tw, loadMore, this._initial, this.workerProgress);
-
-                this.RefreshTimeline();
-            }
-            catch (WebApiException ex)
-            {
-                this._myStatusError = true;
-                this.StatusLabel.Text = $"Err:{ex.Message}(GetTimeline)";
-            }
-            finally
-            {
-                this.workerSemaphore.Release();
-            }
-        }
-
-        private Task GetReplyAsync()
-        {
-            return this.GetReplyAsync(loadMore: false);
-        }
-
-        private async Task GetReplyAsync(bool loadMore)
-        {
-            await this.workerSemaphore.WaitAsync();
-
-            try
-            {
-                var replyTab = this._statuses.GetTabByType<MentionsTabModel>();
-                await replyTab.RefreshAsync(this.tw, loadMore, this._initial, this.workerProgress);
-
-                this.RefreshTimeline();
-            }
-            catch (WebApiException ex)
-            {
-                this._myStatusError = true;
-                this.StatusLabel.Text = $"Err:{ex.Message}(GetTimeline)";
-            }
-            finally
-            {
-                this.workerSemaphore.Release();
-            }
-        }
-
-        private Task GetDirectMessagesAsync()
-        {
-            return this.GetDirectMessagesAsync(loadMore: false);
-        }
+        /// <summary>指定された型 <typeparamref name="T"/> に合致する全てのタブを更新します</summary>
+        private Task RefreshTabAsync<T>() where T : TabModel
+            => this.RefreshTabAsync<T>(backward: false);
 
-        private async Task GetDirectMessagesAsync(bool loadMore)
+        /// <summary>指定された型 <typeparamref name="T"/> に合致する全てのタブを更新します</summary>
+        private Task RefreshTabAsync<T>(bool backward) where T : TabModel
         {
-            await this.workerSemaphore.WaitAsync();
-
-            try
-            {
-                var dmTab = this._statuses.GetTabByType<DirectMessagesTabModel>();
-                await dmTab.RefreshAsync(this.tw, loadMore, this._initial, this.workerProgress);
+            var loadTasks =
+                from tab in this._statuses.GetTabsByType<T>()
+                select this.RefreshTabAsync(tab, backward);
 
-                this.RefreshTimeline();
-            }
-            catch (WebApiException ex)
-            {
-                this._myStatusError = true;
-                this.StatusLabel.Text = $"Err:{ex.Message}(GetDirectMessage)";
-            }
-            finally
-            {
-                this.workerSemaphore.Release();
-            }
+            return Task.WhenAll(loadTasks);
         }
 
-        private Task GetFavoritesAsync()
-        {
-            return this.GetFavoritesAsync(loadMore: false);
-        }
+        /// <summary>指定されたタブ <paramref name="tab"/> を更新します</summary>
+        private Task RefreshTabAsync(TabModel tab)
+            => this.RefreshTabAsync(tab, backward: false);
 
-        private async Task GetFavoritesAsync(bool loadMore)
+        /// <summary>指定されたタブ <paramref name="tab"/> を更新します</summary>
+        private async Task RefreshTabAsync(TabModel tab, bool backward)
         {
             await this.workerSemaphore.WaitAsync();
 
             try
             {
-                var favTab = this._statuses.GetTabByType<FavoritesTabModel>();
-                await favTab.RefreshAsync(this.tw, loadMore, this._initial, this.workerProgress);
-
+                await Task.Run(() => tab.RefreshAsync(this.tw, backward, this._initial, this.workerProgress));
                 this.RefreshTimeline();
             }
             catch (WebApiException ex)
             {
                 this._myStatusError = true;
-                this.StatusLabel.Text = ex.Message;
-            }
-            finally
-            {
-                this.workerSemaphore.Release();
-            }
-        }
-
-        private Task GetPublicSearchAllAsync()
-        {
-            var tabs = this._statuses.GetTabsByType<PublicSearchTabModel>();
-
-            return this.GetPublicSearchAsync(tabs, loadMore: false);
-        }
-
-        private Task GetPublicSearchAsync(PublicSearchTabModel tab)
-        {
-            return this.GetPublicSearchAsync(tab, loadMore: false);
-        }
 
-        private Task GetPublicSearchAsync(PublicSearchTabModel tab, bool loadMore)
-        {
-            return this.GetPublicSearchAsync(new[] { tab }, loadMore);
-        }
-
-        private async Task GetPublicSearchAsync(IEnumerable<PublicSearchTabModel> tabs, bool loadMore)
-        {
-            await this.workerSemaphore.WaitAsync();
-
-            try
-            {
-                foreach (var tab in tabs)
+                string tabType;
+                switch (tab)
                 {
-                    try
-                    {
-                        await tab.RefreshAsync(this.tw, loadMore, this._initial, this.workerProgress);
-                    }
-                    catch (WebApiException ex)
-                    {
-                        this._myStatusError = true;
-                        this.StatusLabel.Text = $"Err:{ex.Message}(GetSearch)";
-                    }
-                }
-
-                this.RefreshTimeline();
-            }
-            finally
-            {
-                this.workerSemaphore.Release();
-            }
-        }
-
-        private Task GetUserTimelineAllAsync()
-        {
-            var tabs = this._statuses.GetTabsByType<UserTimelineTabModel>();
-
-            return this.GetUserTimelineAsync(tabs, loadMore: false);
-        }
-
-        private Task GetUserTimelineAsync(UserTimelineTabModel tab)
-        {
-            return this.GetUserTimelineAsync(tab, loadMore: false);
-        }
-
-        private Task GetUserTimelineAsync(UserTimelineTabModel tab, bool loadMore)
-        {
-            return this.GetUserTimelineAsync(new[] { tab }, loadMore);
-        }
-
-        private async Task GetUserTimelineAsync(IEnumerable<UserTimelineTabModel> tabs, bool loadMore)
-        {
-            await this.workerSemaphore.WaitAsync();
-
-            try
-            {
-                foreach (var tab in tabs)
-                {
-                    try
-                    {
-                        await tab.RefreshAsync(this.tw, loadMore, this._initial, this.workerProgress);
-                    }
-                    catch (WebApiException ex)
-                    {
-                        this._myStatusError = true;
-                        this.StatusLabel.Text = $"Err:{ex.Message}(GetUserTimeline)";
-                    }
-                }
-
-                this.RefreshTimeline();
-            }
-            finally
-            {
-                this.workerSemaphore.Release();
-            }
-        }
-
-        private Task GetListTimelineAllAsync()
-        {
-            var tabs = this._statuses.GetTabsByType<ListTimelineTabModel>();
-
-            return this.GetListTimelineAsync(tabs, loadMore: false);
-        }
-
-        private Task GetListTimelineAsync(ListTimelineTabModel tab)
-        {
-            return this.GetListTimelineAsync(tab, loadMore: false);
-        }
-
-        private Task GetListTimelineAsync(ListTimelineTabModel tab, bool loadMore)
-        {
-            return this.GetListTimelineAsync(new[] { tab }, loadMore);
-        }
-
-        private async Task GetListTimelineAsync(IEnumerable<ListTimelineTabModel> tabs, bool loadMore)
-        {
-            await this.workerSemaphore.WaitAsync();
-
-            try
-            {
-                foreach (var tab in tabs)
-                {
-                    try
-                    {
-                        await tab.RefreshAsync(this.tw, loadMore, this._initial, this.workerProgress);
-                    }
-                    catch (WebApiException ex)
-                    {
-                        this._myStatusError = true;
-                        this.StatusLabel.Text = $"Err:{ex.Message}(GetListStatus)";
-                    }
+                    case HomeTabModel _:
+                        tabType = "GetTimeline";
+                        break;
+                    case MentionsTabModel _:
+                        tabType = "GetTimeline";
+                        break;
+                    case DirectMessagesTabModel _:
+                        tabType = "GetDirectMessage";
+                        break;
+                    case FavoritesTabModel _:
+                        tabType = "GetFavorites";
+                        break;
+                    case PublicSearchTabModel _:
+                        tabType = "GetSearch";
+                        break;
+                    case UserTimelineTabModel _:
+                        tabType = "GetUserTimeline";
+                        break;
+                    case ListTimelineTabModel _:
+                        tabType = "GetListStatus";
+                        break;
+                    case RelatedPostsTabModel _:
+                        tabType = "GetRelatedTweets";
+                        break;
+                    default:
+                        tabType = tab.GetType().Name.Replace("Model", "");
+                        break;
                 }
 
-                this.RefreshTimeline();
-            }
-            finally
-            {
-                this.workerSemaphore.Release();
-            }
-        }
-
-        private async Task GetRelatedTweetsAsync(RelatedPostsTabModel tab)
-        {
-            await this.workerSemaphore.WaitAsync();
-
-            try
-            {
-                await tab.RefreshAsync(this.tw, this._initial, this.workerProgress);
-
-                this.RefreshTimeline();
-            }
-            catch (WebApiException ex)
-            {
-                this._myStatusError = true;
-                this.StatusLabel.Text = $"Err:{ex.Message}(GetRelatedTweets)";
+                this.StatusLabel.Text = $"Err:{ex.Message}({tabType})";
             }
             finally
             {
@@ -2524,8 +2393,7 @@ namespace OpenTween
             if (!CheckAccountValid())
                 throw new WebApiException("Auth error. Check your account");
 
-            PostClass post;
-            if (!tab.Posts.TryGetValue(statusId, out post))
+            if (!tab.Posts.TryGetValue(statusId, out var post))
                 return;
 
             if (post.IsFav)
@@ -2537,11 +2405,19 @@ namespace OpenTween
 
                 try
                 {
-                    await this.twitterApi.FavoritesCreate(post.RetweetedId ?? post.StatusId)
-                        .IgnoreResponse()
-                        .ConfigureAwait(false);
+                    try
+                    {
+                        await this.twitterApi.FavoritesCreate(post.RetweetedId ?? post.StatusId)
+                            .IgnoreResponse()
+                            .ConfigureAwait(false);
+                    }
+                    catch (TwitterApiException ex)
+                        when (ex.ErrorResponse.Errors.All(x => x.Code == TwitterErrorCode.AlreadyFavorited))
+                    {
+                        // エラーコード 139 のみの場合は成功と見なす
+                    }
 
-                    if (this._cfgCommon.RestrictFavCheck)
+                    if (SettingManager.Common.RestrictFavCheck)
                     {
                         var status = await this.twitterApi.StatusesShow(post.RetweetedId ?? post.StatusId)
                             .ConfigureAwait(false);
@@ -2550,7 +2426,7 @@ namespace OpenTween
                             throw new WebApiException("NG(Restricted?)");
                     }
 
-                    this._favTimestamps.Add(DateTime.Now);
+                    this._favTimestamps.Add(DateTimeUtc.Now);
 
                     // TLでも取得済みならfav反映
                     if (this._statuses.ContainsKey(statusId))
@@ -2578,7 +2454,7 @@ namespace OpenTween
                 }
 
                 // 時速表示用
-                var oneHour = DateTime.Now - TimeSpan.FromHours(1);
+                var oneHour = DateTimeUtc.Now - TimeSpan.FromHours(1);
                 foreach (var i in MyCommon.CountDown(this._favTimestamps.Count - 1, 0))
                 {
                     if (this._favTimestamps[i] < oneHour)
@@ -2593,16 +2469,17 @@ namespace OpenTween
 
             this.RefreshTimeline();
 
-            if (this._curList != null && this._curTab != null && this._curTab.Text == tab.TabName)
+            if (this.CurrentTabName == tab.TabName)
             {
-                using (ControlTransaction.Update(this._curList))
+                using (ControlTransaction.Update(this.CurrentListView))
                 {
                     var idx = tab.IndexOf(statusId);
                     if (idx != -1)
                         this.ChangeCacheStyleRead(post.IsRead, idx);
                 }
 
-                if (statusId == this._curPost.StatusId)
+                var currentPost = this.CurrentPost;
+                if (currentPost != null && statusId == currentPost.StatusId)
                     await this.DispSelectedPost(true); // 選択アイテム再表示
             }
         }
@@ -2695,7 +2572,7 @@ namespace OpenTween
 
             this.RefreshTimeline();
 
-            if (this._curList != null && this._curTab != null && this._curTab.Text == tab.TabName)
+            if (this.CurrentTabName == tab.TabName)
             {
                 if (tab.TabType == MyCommon.TabUsageType.Favorites)
                 {
@@ -2703,7 +2580,7 @@ namespace OpenTween
                 }
                 else
                 {
-                    using (ControlTransaction.Update(this._curList))
+                    using (ControlTransaction.Update(this.CurrentListView))
                     {
                         foreach (var statusId in successIds)
                         {
@@ -2716,13 +2593,14 @@ namespace OpenTween
                         }
                     }
 
-                    if (successIds.Contains(this._curPost.StatusId))
+                    var currentPost = this.CurrentPost;
+                    if (currentPost != null && successIds.Contains(currentPost.StatusId))
                         await this.DispSelectedPost(true); // 選択アイテム再表示
                 }
             }
         }
 
-        private async Task PostMessageAsync(PostingStatus status)
+        private async Task PostMessageAsync(PostStatusParams postParams, IMediaUploadService uploadService, IMediaItem[] uploadItems)
         {
             await this.workerSemaphore.WaitAsync();
 
@@ -2730,7 +2608,7 @@ namespace OpenTween
             {
                 var progress = new Progress<string>(x => this.StatusLabel.Text = x);
 
-                await this.PostMessageAsyncInternal(progress, this.workerCts.Token, status);
+                await this.PostMessageAsyncInternal(progress, this.workerCts.Token, postParams, uploadService, uploadItems);
             }
             catch (WebApiException ex)
             {
@@ -2743,7 +2621,8 @@ namespace OpenTween
             }
         }
 
-        private async Task PostMessageAsyncInternal(IProgress<string> p, CancellationToken ct, PostingStatus status)
+        private async Task PostMessageAsyncInternal(IProgress<string> p, CancellationToken ct, PostStatusParams postParams,
+            IMediaUploadService uploadService, IMediaItem[] uploadItems)
         {
             if (ct.IsCancellationRequested)
                 return;
@@ -2753,23 +2632,23 @@ namespace OpenTween
 
             p.Report("Posting...");
 
+            PostClass post = null;
             var errMsg = "";
 
             try
             {
                 await Task.Run(async () =>
                 {
-                    if (status.mediaItems == null || status.mediaItems.Length == 0)
-                    {
-                        await this.tw.PostStatus(status.status, status.inReplyToId)
-                            .ConfigureAwait(false);
-                    }
-                    else
+                    var postParamsWithMedia = postParams;
+
+                    if (uploadService != null && uploadItems != null && uploadItems.Length > 0)
                     {
-                        var service = ImageSelector.GetService(status.imageService);
-                        await service.PostStatusAsync(status.status, status.inReplyToId, status.mediaItems)
+                        postParamsWithMedia = await uploadService.UploadAsync(uploadItems, postParamsWithMedia)
                             .ConfigureAwait(false);
                     }
+
+                    post = await this.tw.PostStatus(postParamsWithMedia)
+                        .ConfigureAwait(false);
                 });
 
                 p.Report(Properties.Resources.PostWorker_RunWorkerCompletedText4);
@@ -2791,9 +2670,9 @@ namespace OpenTween
             finally
             {
                 // 使い終わった MediaItem は破棄する
-                if (status.mediaItems != null)
+                if (uploadItems != null)
                 {
-                    foreach (var disposableItem in status.mediaItems.OfType<IDisposable>())
+                    foreach (var disposableItem in uploadItems.OfType<IDisposable>())
                     {
                         disposableItem.Dispose();
                     }
@@ -2807,7 +2686,7 @@ namespace OpenTween
                 !errMsg.StartsWith("OK:", StringComparison.Ordinal) &&
                 !errMsg.StartsWith("Warn:", StringComparison.Ordinal))
             {
-                var message = string.Format(Properties.Resources.StatusUpdateFailed, errMsg, status.status);
+                var message = string.Format(Properties.Resources.StatusUpdateFailed, errMsg, postParams.Text);
 
                 var ret = MessageBox.Show(
                     message,
@@ -2817,20 +2696,23 @@ namespace OpenTween
 
                 if (ret == DialogResult.Retry)
                 {
-                    await this.PostMessageAsync(status);
+                    await this.PostMessageAsync(postParams, uploadService, uploadItems);
                 }
                 else
                 {
+                    this.StatusTextHistoryBack();
+                    this.StatusText.Focus();
+
                     // 連投モードのときだけEnterイベントが起きないので強制的に背景色を戻す
-                    if (this.ToolStripFocusLockMenuItem.Checked)
+                    if (SettingManager.Common.FocusLockToStatusText)
                         this.StatusText_Enter(this.StatusText, EventArgs.Empty);
                 }
                 return;
             }
 
-            this._postTimestamps.Add(DateTime.Now);
+            this._postTimestamps.Add(DateTimeUtc.Now);
 
-            var oneHour = DateTime.Now - TimeSpan.FromHours(1);
+            var oneHour = DateTimeUtc.Now - TimeSpan.FromHours(1);
             foreach (var i in MyCommon.CountDown(this._postTimestamps.Count - 1, 0))
             {
                 if (this._postTimestamps[i] < oneHour)
@@ -2841,18 +2723,26 @@ namespace OpenTween
             {
                 this.HashMgr.ClearHashtag();
                 this.HashStripSplitButton.Text = "#[-]";
+                this.HashTogglePullDownMenuItem.Checked = false;
                 this.HashToggleMenuItem.Checked = false;
-                this.HashToggleToolStripMenuItem.Checked = false;
             }
 
             this.SetMainWindowTitle();
 
-            if (this._cfgCommon.PostAndGet)
+            // TLに反映
+            if (!this.tw.UserStreamActive)
             {
-                if (this.tw.UserStreamActive)
-                    this.RefreshTimeline();
+                if (SettingManager.Common.PostAndGet)
+                    await this.RefreshTabAsync<HomeTabModel>();
                 else
-                    await this.GetHomeTimelineAsync();
+                {
+                    if (post != null)
+                    {
+                        this._statuses.AddPost(post);
+                        this._statuses.DistributePosts();
+                        this.RefreshTimeline();
+                    }
+                }
             }
         }
 
@@ -2865,9 +2755,6 @@ namespace OpenTween
                 var progress = new Progress<string>(x => this.StatusLabel.Text = x);
 
                 await this.RetweetAsyncInternal(progress, this.workerCts.Token, statusIds);
-
-                if (this._cfgCommon.PostAndGet && !this.tw.UserStreamActive)
-                    await this.GetHomeTimelineAsync();
             }
             catch (WebApiException ex)
             {
@@ -2889,31 +2776,53 @@ namespace OpenTween
                 throw new WebApiException("Auth error. Check your account");
 
             bool read;
-            if (!this._cfgCommon.UnreadManage)
+            if (!SettingManager.Common.UnreadManage)
                 read = true;
             else
-                read = this._initial && this._cfgCommon.Read;
+                read = this._initial && SettingManager.Common.Read;
 
             p.Report("Posting...");
 
-            foreach (var statusId in statusIds)
+            var posts = new List<PostClass>();
+
+            await Task.Run(async () =>
             {
-                await this.tw.PostRetweet(statusId, read).ConfigureAwait(false);
-            }
+                foreach (var statusId in statusIds)
+                {
+                    var post = await this.tw.PostRetweet(statusId, read).ConfigureAwait(false);
+                    if (post != null) posts.Add(post);
+                }
+            });
 
             if (ct.IsCancellationRequested)
                 return;
 
             p.Report(Properties.Resources.PostWorker_RunWorkerCompletedText4);
 
-            this._postTimestamps.Add(DateTime.Now);
+            this._postTimestamps.Add(DateTimeUtc.Now);
 
-            var oneHour = DateTime.Now - TimeSpan.FromHours(1);
+            var oneHour = DateTimeUtc.Now - TimeSpan.FromHours(1);
             foreach (var i in MyCommon.CountDown(this._postTimestamps.Count - 1, 0))
             {
                 if (this._postTimestamps[i] < oneHour)
                     this._postTimestamps.RemoveAt(i);
             }
+
+            // TLに反映
+            if (!this.tw.UserStreamActive)
+            {
+                // 自分のRTはTLの更新では取得できない場合があるので、
+                // 投稿時取得の有無に関わらず追加しておく
+                posts.ForEach(post => this._statuses.AddPost(post));
+
+                if (SettingManager.Common.PostAndGet)
+                    await this.RefreshTabAsync<HomeTabModel>();
+                else
+                {
+                    this._statuses.DistributePosts();
+                    this.RefreshTimeline();
+                }
+            }
         }
 
         private async Task RefreshFollowerIdsAsync()
@@ -2929,7 +2838,7 @@ namespace OpenTween
 
                 this.RefreshTimeline();
                 this.PurgeListViewItemCache();
-                this._curList?.Refresh();
+                this.CurrentListView.Refresh();
             }
             catch (WebApiException ex)
             {
@@ -2997,8 +2906,7 @@ namespace OpenTween
                 }
 
                 this.PurgeListViewItemCache();
-
-                this._curList?.Refresh();
+                this.CurrentListView.Refresh();
             }
             catch (WebApiException ex)
             {
@@ -3043,7 +2951,7 @@ namespace OpenTween
 
         private async void MyList_MouseDoubleClick(object sender, MouseEventArgs e)
         {
-            switch (this._cfgCommon.ListDoubleClickAction)
+            switch (SettingManager.Common.ListDoubleClickAction)
             {
                 case 0:
                     MakeReplyOrDirectStatus();
@@ -3052,11 +2960,12 @@ namespace OpenTween
                     await this.FavoriteChange(true);
                     break;
                 case 2:
-                    if (_curPost != null)
-                        await this.ShowUserStatus(_curPost.ScreenName, false);
+                    var post = this.CurrentPost;
+                    if (post != null)
+                        await this.ShowUserStatus(post.ScreenName, false);
                     break;
                 case 3:
-                    ShowUserTimeline();
+                    await ShowUserTimeline();
                     break;
                 case 4:
                     ShowRelatedStatusesMenuItem_Click(null, null);
@@ -3074,37 +2983,28 @@ namespace OpenTween
         }
 
         private async void FavAddToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.FavoriteChange(true);
-        }
+            => await this.FavoriteChange(true);
 
         private async void FavRemoveToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.FavoriteChange(false);
-        }
+            => await this.FavoriteChange(false);
 
 
         private async void FavoriteRetweetMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.FavoritesRetweetOfficial();
-        }
+            => await this.FavoritesRetweetOfficial();
 
         private async void FavoriteRetweetUnofficialMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.FavoritesRetweetUnofficial();
-        }
+            => await this.FavoritesRetweetUnofficial();
 
         private async Task FavoriteChange(bool FavAdd, bool multiFavoriteChangeDialogEnable = true)
         {
-            TabModel tab;
-            if (!this._statuses.Tabs.TryGetValue(this._curTab.Text, out tab))
-                return;
+            var tab = this.CurrentTab;
+            var posts = tab.SelectedPosts;
 
             //trueでFavAdd,falseでFavRemove
-            if (tab.TabType == MyCommon.TabUsageType.DirectMessage || _curList.SelectedIndices.Count == 0
+            if (tab.TabType == MyCommon.TabUsageType.DirectMessage || posts.Length == 0
                 || !this.ExistCurrentPost) return;
 
-            if (this._curList.SelectedIndices.Count > 1)
+            if (posts.Length > 1)
             {
                 if (FavAdd)
                 {
@@ -3130,7 +3030,7 @@ namespace OpenTween
 
             if (FavAdd)
             {
-                var selectedPost = this.GetCurTabPost(_curList.SelectedIndices[0]);
+                var selectedPost = posts.Single();
                 if (selectedPost.IsFav)
                 {
                     this.StatusLabel.Text = Properties.Resources.FavAddToolStripMenuItem_ClickText4;
@@ -3141,10 +3041,7 @@ namespace OpenTween
             }
             else
             {
-                var selectedPosts = this._curList.SelectedIndices.Cast<int>()
-                    .Select(x => this.GetCurTabPost(x))
-                    .Where(x => x.IsFav);
-
+                var selectedPosts = posts.Where(x => x.IsFav);
                 var statusIds = selectedPosts.Select(x => x.StatusId).ToArray();
                 if (statusIds.Length == 0)
                 {
@@ -3161,27 +3058,27 @@ namespace OpenTween
             var listCache = this._listItemCache;
             if (listCache != null)
             {
-                ListViewItem item;
-                PostClass post;
-                if (listCache.TryGetValue(Index, out item, out post))
+                if (listCache.TryGetValue(Index, out var item, out var post))
                     return post;
             }
 
-            return _statuses.Tabs[_curTab.Text][Index];
+            return this.CurrentTab[Index];
         }
 
         private async void MoveToHomeToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            if (_curList.SelectedIndices.Count > 0)
-                await this.OpenUriInBrowserAsync(MyCommon.TwitterUrl + GetCurTabPost(_curList.SelectedIndices[0]).ScreenName);
-            else if (_curList.SelectedIndices.Count == 0)
+            var post = this.CurrentPost;
+            if (post != null)
+                await this.OpenUriInBrowserAsync(MyCommon.TwitterUrl + post.ScreenName);
+            else
                 await this.OpenUriInBrowserAsync(MyCommon.TwitterUrl);
         }
 
         private async void MoveToFavToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            if (_curList.SelectedIndices.Count > 0)
-                await this.OpenUriInBrowserAsync(MyCommon.TwitterUrl + "#!/" + GetCurTabPost(_curList.SelectedIndices[0]).ScreenName + "/favorites");
+            var post = this.CurrentPost;
+            if (post != null)
+                await this.OpenUriInBrowserAsync(MyCommon.TwitterUrl + "#!/" + post.ScreenName + "/favorites");
         }
 
         private void TweenMain_ClientSizeChanged(object sender, EventArgs e)
@@ -3243,7 +3140,7 @@ namespace OpenTween
         private void SetSortColumnByDisplayIndex(int columnIndex)
         {
             // 表示上の列の位置から ColumnHeader を求める
-            var col = this._curList.Columns.Cast<ColumnHeader>()
+            var col = this.CurrentListView.Columns.Cast<ColumnHeader>()
                 .FirstOrDefault(x => x.DisplayIndex == columnIndex);
 
             if (col == null)
@@ -3262,7 +3159,7 @@ namespace OpenTween
         private void SetSortLastColumn()
         {
             // 表示上の最後列にある ColumnHeader を求める
-            var col = this._curList.Columns.Cast<ColumnHeader>()
+            var col = this.CurrentListView.Columns.Cast<ColumnHeader>()
                 .OrderByDescending(x => x.DisplayIndex)
                 .First();
 
@@ -3278,13 +3175,13 @@ namespace OpenTween
         /// </summary>
         private void SetSortColumn(ComparerMode sortColumn)
         {
-            if (this._cfgCommon.SortOrderLock)
+            if (SettingManager.Common.SortOrderLock)
                 return;
 
             this._statuses.ToggleSortOrder(sortColumn);
             this.InitColumnText();
 
-            var list = this._curList;
+            var list = this.CurrentListView;
             if (_iconCol)
             {
                 list.Columns[0].Text = this.ColumnText[0];
@@ -3300,10 +3197,11 @@ namespace OpenTween
 
             this.PurgeListViewItemCache();
 
-            var tab = this._statuses.Tabs[this._curTab.Text];
-            if (tab.AllCount > 0 && this._curPost != null)
+            var tab = this.CurrentTab;
+            var post = this.CurrentPost;
+            if (tab.AllCount > 0 && post != null)
             {
-                var idx = tab.IndexOf(this._curPost.StatusId);
+                var idx = tab.IndexOf(post.StatusId);
                 if (idx > -1)
                 {
                     this.SelectListItem(list, idx);
@@ -3326,8 +3224,6 @@ namespace OpenTween
 
         private void ContextMenuOperate_Opening(object sender, CancelEventArgs e)
         {
-            if (ListTab.SelectedTab == null) return;
-            if (_statuses == null || _statuses.Tabs == null || !_statuses.Tabs.ContainsKey(ListTab.SelectedTab.Text)) return;
             if (!this.ExistCurrentPost)
             {
                 ReplyStripMenuItem.Enabled = false;
@@ -3358,12 +3254,13 @@ namespace OpenTween
                 ReadedStripMenuItem.Enabled = true;
                 UnreadStripMenuItem.Enabled = true;
             }
-            if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || _curPost.IsDm)
+            var tab = this.CurrentTab;
+            var post = this.CurrentPost;
+            if (tab.TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || post.IsDm)
             {
                 FavAddToolStripMenuItem.Enabled = false;
                 FavRemoveToolStripMenuItem.Enabled = false;
                 StatusOpenMenuItem.Enabled = false;
-                FavorareMenuItem.Enabled = false;
                 ShowRelatedStatusesMenuItem.Enabled = false;
 
                 ReTweetStripMenuItem.Enabled = false;
@@ -3377,10 +3274,9 @@ namespace OpenTween
                 FavAddToolStripMenuItem.Enabled = true;
                 FavRemoveToolStripMenuItem.Enabled = true;
                 StatusOpenMenuItem.Enabled = true;
-                FavorareMenuItem.Enabled = true;
                 ShowRelatedStatusesMenuItem.Enabled = true;  //PublicSearchの時問題出るかも
 
-                if (!_curPost.CanRetweetBy(this.twitterApi.CurrentUserId))
+                if (!post.CanRetweetBy(this.twitterApi.CurrentUserId))
                 {
                     ReTweetStripMenuItem.Enabled = false;
                     ReTweetUnofficialStripMenuItem.Enabled = false;
@@ -3405,8 +3301,7 @@ namespace OpenTween
             //{
             //    RefreshMoreStripMenuItem.Enabled = false;
             //}
-            if (!this.ExistCurrentPost
-                || _curPost.InReplyToStatusId == null)
+            if (!this.ExistCurrentPost || post.InReplyToStatusId == null)
             {
                 RepliedStatusOpenMenuItem.Enabled = false;
             }
@@ -3414,7 +3309,7 @@ namespace OpenTween
             {
                 RepliedStatusOpenMenuItem.Enabled = true;
             }
-            if (!this.ExistCurrentPost || string.IsNullOrEmpty(_curPost.RetweetedBy))
+            if (!this.ExistCurrentPost || string.IsNullOrEmpty(post.RetweetedBy))
             {
                 MoveToRTHomeMenuItem.Enabled = false;
             }
@@ -3425,8 +3320,8 @@ namespace OpenTween
 
             if (this.ExistCurrentPost)
             {
-                this.DeleteStripMenuItem.Enabled = this._curPost.CanDeleteBy(this.tw.UserId);
-                if (this._curPost.RetweetedByUserId == this.tw.UserId)
+                this.DeleteStripMenuItem.Enabled = post.CanDeleteBy(this.tw.UserId);
+                if (post.RetweetedByUserId == this.tw.UserId)
                     this.DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText2;
                 else
                     this.DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText1;
@@ -3434,27 +3329,17 @@ namespace OpenTween
         }
 
         private void ReplyStripMenuItem_Click(object sender, EventArgs e)
-        {
-            MakeReplyOrDirectStatus(false, true);
-        }
+            => this.MakeReplyOrDirectStatus(false, true);
 
         private void DMStripMenuItem_Click(object sender, EventArgs e)
-        {
-            MakeReplyOrDirectStatus(false, false);
-        }
+            => this.MakeReplyOrDirectStatus(false, false);
 
         private async Task doStatusDelete()
         {
-            if (this._curTab == null || this._curList == null)
-                return;
-
-            if (this._curList.SelectedIndices.Count == 0)
+            var posts = this.CurrentTab.SelectedPosts;
+            if (posts.Length == 0)
                 return;
 
-            var posts = this._curList.SelectedIndices.Cast<int>()
-                .Select(x => this.GetCurTabPost(x))
-                .ToArray();
-
             // 選択されたツイートの中に削除可能なものが一つでもあるか
             if (!posts.Any(x => x.CanDeleteBy(this.tw.UserId)))
                 return;
@@ -3467,7 +3352,8 @@ namespace OpenTween
             if (ret != DialogResult.OK)
                 return;
 
-            var focusedIndex = this._curList.FocusedItem?.Index ?? this._curList.TopItem?.Index ?? 0;
+            var currentListView = this.CurrentListView;
+            var focusedIndex = currentListView.FocusedItem?.Index ?? currentListView.TopItem?.Index ?? 0;
 
             using (ControlTransaction.Cursor(this, Cursors.WaitCursor))
             {
@@ -3481,8 +3367,7 @@ namespace OpenTween
                     {
                         if (post.IsDm)
                         {
-                            await this.twitterApi.DirectMessagesDestroy(post.StatusId)
-                                .IgnoreResponse();
+                            await this.twitterApi.DirectMessagesEventsDestroy(post.StatusId.ToString(CultureInfo.InvariantCulture));
                         }
                         else
                         {
@@ -3526,8 +3411,6 @@ namespace OpenTween
                     this.StatusLabel.Text = Properties.Resources.DeleteStripMenuItem_ClickText3; // 失敗
 
                 this.PurgeListViewItemCache();
-                this._curPost = null;
-                this._curItemIndex = -1;
 
                 foreach (var tabPage in this.ListTab.TabPages.Cast<TabPage>())
                 {
@@ -3538,7 +3421,7 @@ namespace OpenTween
                     {
                         listView.VirtualListSize = tab.AllCount;
 
-                        if (tabPage == this._curTab)
+                        if (tab.TabName == this.CurrentTabName)
                         {
                             listView.SelectedIndices.Clear();
 
@@ -3557,31 +3440,30 @@ namespace OpenTween
                         }
                     }
 
-                    if (this._cfgCommon.TabIconDisp && tab.UnreadCount == 0)
+                    if (SettingManager.Common.TabIconDisp && tab.UnreadCount == 0)
                     {
                         if (tabPage.ImageIndex == 0)
                             tabPage.ImageIndex = -1; // タブアイコン
                     }
                 }
 
-                if (!this._cfgCommon.TabIconDisp)
+                if (!SettingManager.Common.TabIconDisp)
                     this.ListTab.Refresh();
             }
         }
 
         private async void DeleteStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.doStatusDelete();
-        }
+            => await this.doStatusDelete();
 
         private void ReadedStripMenuItem_Click(object sender, EventArgs e)
         {
-            using (ControlTransaction.Update(this._curList))
+            using (ControlTransaction.Update(this.CurrentListView))
             {
-                foreach (int idx in _curList.SelectedIndices)
+                var tab = this.CurrentTab;
+                foreach (var statusId in tab.SelectedStatusIds)
                 {
-                    var post = this._statuses.Tabs[this._curTab.Text][idx];
-                    this._statuses.SetReadAllTab(post.StatusId, read: true);
+                    this._statuses.SetReadAllTab(statusId, read: true);
+                    var idx = tab.IndexOf(statusId);
                     ChangeCacheStyleRead(true, idx);
                 }
                 ColorizeList();
@@ -3590,23 +3472,24 @@ namespace OpenTween
             {
                 if (_statuses.Tabs[tb.Text].UnreadCount == 0)
                 {
-                    if (this._cfgCommon.TabIconDisp)
+                    if (SettingManager.Common.TabIconDisp)
                     {
                         if (tb.ImageIndex == 0) tb.ImageIndex = -1; //タブアイコン
                     }
                 }
             }
-            if (!this._cfgCommon.TabIconDisp) ListTab.Refresh();
+            if (!SettingManager.Common.TabIconDisp) ListTab.Refresh();
         }
 
         private void UnreadStripMenuItem_Click(object sender, EventArgs e)
         {
-            using (ControlTransaction.Update(this._curList))
+            using (ControlTransaction.Update(this.CurrentListView))
             {
-                foreach (int idx in _curList.SelectedIndices)
+                var tab = this.CurrentTab;
+                foreach (var statusId in tab.SelectedStatusIds)
                 {
-                    var post = this._statuses.Tabs[this._curTab.Text][idx];
-                    this._statuses.SetReadAllTab(post.StatusId, read: false);
+                    this._statuses.SetReadAllTab(statusId, read: false);
+                    var idx = tab.IndexOf(statusId);
                     ChangeCacheStyleRead(false, idx);
                 }
                 ColorizeList();
@@ -3615,111 +3498,23 @@ namespace OpenTween
             {
                 if (_statuses.Tabs[tb.Text].UnreadCount > 0)
                 {
-                    if (this._cfgCommon.TabIconDisp)
+                    if (SettingManager.Common.TabIconDisp)
                     {
                         if (tb.ImageIndex == -1) tb.ImageIndex = 0; //タブアイコン
                     }
                 }
             }
-            if (!this._cfgCommon.TabIconDisp) ListTab.Refresh();
+            if (!SettingManager.Common.TabIconDisp) ListTab.Refresh();
         }
 
         private async void RefreshStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.DoRefresh();
-        }
+            => await this.DoRefresh();
 
         private async Task DoRefresh()
-        {
-            if (_curTab != null)
-            {
-                TabModel tab;
-                if (!this._statuses.Tabs.TryGetValue(this._curTab.Text, out tab))
-                    return;
-
-                switch (_statuses.Tabs[_curTab.Text].TabType)
-                {
-                    case MyCommon.TabUsageType.Mentions:
-                        await this.GetReplyAsync();
-                        break;
-                    case MyCommon.TabUsageType.DirectMessage:
-                        await this.GetDirectMessagesAsync();
-                        break;
-                    case MyCommon.TabUsageType.Favorites:
-                        await this.GetFavoritesAsync();
-                        break;
-                    //case MyCommon.TabUsageType.Profile:
-                        //// TODO
-                    case MyCommon.TabUsageType.PublicSearch:
-                        var searchTab = (PublicSearchTabModel)tab;
-                        if (string.IsNullOrEmpty(searchTab.SearchWords)) return;
-                        await this.GetPublicSearchAsync(searchTab);
-                        break;
-                    case MyCommon.TabUsageType.UserTimeline:
-                        await this.GetUserTimelineAsync((UserTimelineTabModel)tab);
-                        break;
-                    case MyCommon.TabUsageType.Lists:
-                        var listTab = (ListTimelineTabModel)tab;
-                        if (listTab.ListInfo == null || listTab.ListInfo.Id == 0) return;
-                        await this.GetListTimelineAsync(listTab);
-                        break;
-                    default:
-                        await this.GetHomeTimelineAsync();
-                        break;
-                }
-            }
-            else
-            {
-                await this.GetHomeTimelineAsync();
-            }
-        }
+            => await this.RefreshTabAsync(this.CurrentTab);
 
         private async Task DoRefreshMore()
-        {
-            //ページ指定をマイナス1に
-            if (_curTab != null)
-            {
-                TabModel tab;
-                if (!this._statuses.Tabs.TryGetValue(this._curTab.Text, out tab))
-                    return;
-
-                switch (_statuses.Tabs[_curTab.Text].TabType)
-                {
-                    case MyCommon.TabUsageType.Mentions:
-                        await this.GetReplyAsync(loadMore: true);
-                        break;
-                    case MyCommon.TabUsageType.DirectMessage:
-                        await this.GetDirectMessagesAsync(loadMore: true);
-                        break;
-                    case MyCommon.TabUsageType.Favorites:
-                        await this.GetFavoritesAsync(loadMore: true);
-                        break;
-                    case MyCommon.TabUsageType.Profile:
-                        //// TODO
-                        break;
-                    case MyCommon.TabUsageType.PublicSearch:
-                        var searchTab = (PublicSearchTabModel)tab;
-                        if (string.IsNullOrEmpty(searchTab.SearchWords)) return;
-                        await this.GetPublicSearchAsync(searchTab, loadMore: true);
-                        break;
-                    case MyCommon.TabUsageType.UserTimeline:
-                        await this.GetUserTimelineAsync((UserTimelineTabModel)tab, loadMore: true);
-                        break;
-                    case MyCommon.TabUsageType.Lists:
-                        var listTab = (ListTimelineTabModel)tab;
-                        if (listTab.ListInfo == null || listTab.ListInfo.Id == 0) return;
-                        await this.GetListTimelineAsync(listTab, loadMore: true);
-                        break;
-                    default:
-                        await this.GetHomeTimelineAsync(loadMore: true);
-                        break;
-                }
-            }
-            else
-            {
-                await this.GetHomeTimelineAsync(loadMore: true);
-            }
-        }
+            => await this.RefreshTabAsync(this.CurrentTab, backward: true);
 
         private DialogResult ShowSettingDialog(bool showTaskbarIcon = false)
         {
@@ -3735,7 +3530,7 @@ namespace OpenTween
                 settingDialog.tw = this.tw;
                 settingDialog.twitterApi = this.twitterApi;
 
-                settingDialog.LoadConfig(this._cfgCommon, this._cfgLocal);
+                settingDialog.LoadConfig(SettingManager.Common, SettingManager.Local);
 
                 try
                 {
@@ -3750,7 +3545,7 @@ namespace OpenTween
                 {
                     lock (_syncObject)
                     {
-                        settingDialog.SaveConfig(this._cfgCommon, this._cfgLocal);
+                        settingDialog.SaveConfig(SettingManager.Common, SettingManager.Local);
                     }
                 }
             }
@@ -3763,31 +3558,32 @@ namespace OpenTween
             // 設定画面表示前のユーザー情報
             var oldUser = new { tw.AccessToken, tw.AccessTokenSecret, tw.Username, tw.UserId };
 
-            var oldIconSz = this._cfgCommon.IconSize;
+            var oldIconSz = SettingManager.Common.IconSize;
 
             if (ShowSettingDialog() == DialogResult.OK)
             {
                 lock (_syncObject)
                 {
-                    tw.RestrictFavCheck = this._cfgCommon.RestrictFavCheck;
-                    tw.ReadOwnPost = this._cfgCommon.ReadOwnPost;
-                    ShortUrl.Instance.DisableExpanding = !this._cfgCommon.TinyUrlResolve;
-                    ShortUrl.Instance.BitlyId = this._cfgCommon.BilyUser;
-                    ShortUrl.Instance.BitlyKey = this._cfgCommon.BitlyPwd;
-                    TwitterApiConnection.RestApiHost = this._cfgCommon.TwitterApiHost;
-
-                    Networking.DefaultTimeout = TimeSpan.FromSeconds(this._cfgCommon.DefaultTimeOut);
-                    Networking.UploadImageTimeout = TimeSpan.FromSeconds(this._cfgCommon.UploadImageTimeout);
-                    Networking.SetWebProxy(this._cfgLocal.ProxyType,
-                        this._cfgLocal.ProxyAddress, this._cfgLocal.ProxyPort,
-                        this._cfgLocal.ProxyUser, this._cfgLocal.ProxyPassword);
-                    Networking.ForceIPv4 = this._cfgCommon.ForceIPv4;
+                    tw.RestrictFavCheck = SettingManager.Common.RestrictFavCheck;
+                    tw.ReadOwnPost = SettingManager.Common.ReadOwnPost;
+                    ShortUrl.Instance.DisableExpanding = !SettingManager.Common.TinyUrlResolve;
+                    ShortUrl.Instance.BitlyAccessToken = SettingManager.Common.BitlyAccessToken;
+                    ShortUrl.Instance.BitlyId = SettingManager.Common.BilyUser;
+                    ShortUrl.Instance.BitlyKey = SettingManager.Common.BitlyPwd;
+                    TwitterApiConnection.RestApiHost = SettingManager.Common.TwitterApiHost;
+
+                    Networking.DefaultTimeout = TimeSpan.FromSeconds(SettingManager.Common.DefaultTimeOut);
+                    Networking.UploadImageTimeout = TimeSpan.FromSeconds(SettingManager.Common.UploadImageTimeout);
+                    Networking.SetWebProxy(SettingManager.Local.ProxyType,
+                        SettingManager.Local.ProxyAddress, SettingManager.Local.ProxyPort,
+                        SettingManager.Local.ProxyUser, SettingManager.Local.ProxyPassword);
+                    Networking.ForceIPv4 = SettingManager.Common.ForceIPv4;
 
                     ImageSelector.Reset(tw, this.tw.Configuration);
 
                     try
                     {
-                        if (this._cfgCommon.TabIconDisp)
+                        if (SettingManager.Common.TabIconDisp)
                         {
                             ListTab.DrawItem -= ListTab_DrawItem;
                             ListTab.DrawMode = TabDrawMode.Normal;
@@ -3810,11 +3606,11 @@ namespace OpenTween
 
                     try
                     {
-                        if (!this._cfgCommon.UnreadManage)
+                        if (!SettingManager.Common.UnreadManage)
                         {
                             ReadedStripMenuItem.Enabled = false;
                             UnreadStripMenuItem.Enabled = false;
-                            if (this._cfgCommon.TabIconDisp)
+                            if (SettingManager.Common.TabIconDisp)
                             {
                                 foreach (TabPage myTab in ListTab.TabPages)
                                 {
@@ -3838,35 +3634,35 @@ namespace OpenTween
                     // タブの表示位置の決定
                     SetTabAlignment();
 
-                    SplitContainer1.IsPanelInverted = !this._cfgCommon.StatusAreaAtBottom;
+                    SplitContainer1.IsPanelInverted = !SettingManager.Common.StatusAreaAtBottom;
 
                     var imgazyobizinet = ThumbnailGenerator.ImgAzyobuziNetInstance;
-                    imgazyobizinet.Enabled = this._cfgCommon.EnableImgAzyobuziNet;
-                    imgazyobizinet.DisabledInDM = this._cfgCommon.ImgAzyobuziNetDisabledInDM;
-
-                    this.PlaySoundMenuItem.Checked = this._cfgCommon.PlaySound;
-                    this.PlaySoundFileMenuItem.Checked = this._cfgCommon.PlaySound;
-                    _fntUnread = this._cfgLocal.FontUnread;
-                    _clUnread = this._cfgLocal.ColorUnread;
-                    _fntReaded = this._cfgLocal.FontRead;
-                    _clReaded = this._cfgLocal.ColorRead;
-                    _clFav = this._cfgLocal.ColorFav;
-                    _clOWL = this._cfgLocal.ColorOWL;
-                    _clRetweet = this._cfgLocal.ColorRetweet;
-                    _fntDetail = this._cfgLocal.FontDetail;
-                    _clDetail = this._cfgLocal.ColorDetail;
-                    _clDetailLink = this._cfgLocal.ColorDetailLink;
-                    _clDetailBackcolor = this._cfgLocal.ColorDetailBackcolor;
-                    _clSelf = this._cfgLocal.ColorSelf;
-                    _clAtSelf = this._cfgLocal.ColorAtSelf;
-                    _clTarget = this._cfgLocal.ColorTarget;
-                    _clAtTarget = this._cfgLocal.ColorAtTarget;
-                    _clAtFromTarget = this._cfgLocal.ColorAtFromTarget;
-                    _clAtTo = this._cfgLocal.ColorAtTo;
-                    _clListBackcolor = this._cfgLocal.ColorListBackcolor;
-                    _clInputBackcolor = this._cfgLocal.ColorInputBackcolor;
-                    _clInputFont = this._cfgLocal.ColorInputFont;
-                    _fntInputFont = this._cfgLocal.FontInputFont;
+                    imgazyobizinet.Enabled = SettingManager.Common.EnableImgAzyobuziNet;
+                    imgazyobizinet.DisabledInDM = SettingManager.Common.ImgAzyobuziNetDisabledInDM;
+
+                    this.PlaySoundMenuItem.Checked = SettingManager.Common.PlaySound;
+                    this.PlaySoundFileMenuItem.Checked = SettingManager.Common.PlaySound;
+                    _fntUnread = SettingManager.Local.FontUnread;
+                    _clUnread = SettingManager.Local.ColorUnread;
+                    _fntReaded = SettingManager.Local.FontRead;
+                    _clReaded = SettingManager.Local.ColorRead;
+                    _clFav = SettingManager.Local.ColorFav;
+                    _clOWL = SettingManager.Local.ColorOWL;
+                    _clRetweet = SettingManager.Local.ColorRetweet;
+                    _fntDetail = SettingManager.Local.FontDetail;
+                    _clDetail = SettingManager.Local.ColorDetail;
+                    _clDetailLink = SettingManager.Local.ColorDetailLink;
+                    _clDetailBackcolor = SettingManager.Local.ColorDetailBackcolor;
+                    _clSelf = SettingManager.Local.ColorSelf;
+                    _clAtSelf = SettingManager.Local.ColorAtSelf;
+                    _clTarget = SettingManager.Local.ColorTarget;
+                    _clAtTarget = SettingManager.Local.ColorAtTarget;
+                    _clAtFromTarget = SettingManager.Local.ColorAtFromTarget;
+                    _clAtTo = SettingManager.Local.ColorAtTo;
+                    _clListBackcolor = SettingManager.Local.ColorListBackcolor;
+                    _clInputBackcolor = SettingManager.Local.ColorInputBackcolor;
+                    _clInputFont = SettingManager.Local.ColorInputFont;
+                    _fntInputFont = SettingManager.Local.FontInputFont;
                     _brsBackColorMine.Dispose();
                     _brsBackColorAt.Dispose();
                     _brsBackColorYou.Dispose();
@@ -3908,7 +3704,7 @@ namespace OpenTween
                     {
                         foreach (TabPage tb in ListTab.TabPages)
                         {
-                            if (this._cfgCommon.TabIconDisp)
+                            if (SettingManager.Common.TabIconDisp)
                             {
                                 if (_statuses.Tabs[tb.Text].UnreadCount == 0)
                                     tb.ImageIndex = -1;
@@ -3928,8 +3724,8 @@ namespace OpenTween
                     {
                         var oldIconCol = _iconCol;
 
-                        if (this._cfgCommon.IconSize != oldIconSz)
-                            ApplyListViewIconSize(this._cfgCommon.IconSize);
+                        if (SettingManager.Common.IconSize != oldIconSz)
+                            ApplyListViewIconSize(SettingManager.Common.IconSize);
 
                         foreach (TabPage tp in ListTab.TabPages)
                         {
@@ -3937,7 +3733,7 @@ namespace OpenTween
 
                             using (ControlTransaction.Update(lst))
                             {
-                                lst.GridLines = this._cfgCommon.ShowGrid;
+                                lst.GridLines = SettingManager.Common.ShowGrid;
                                 lst.Font = _fntReaded;
                                 lst.BackColor = _clListBackcolor;
 
@@ -3957,27 +3753,27 @@ namespace OpenTween
                     SetNotifyIconText();
 
                     this.PurgeListViewItemCache();
-                    _curList?.Refresh();
+                    this.CurrentListView.Refresh();
                     ListTab.Refresh();
 
                     _hookGlobalHotkey.UnregisterAllOriginalHotkey();
-                    if (this._cfgCommon.HotkeyEnabled)
+                    if (SettingManager.Common.HotkeyEnabled)
                     {
                         ///グローバルホットキーの登録。設定で変更可能にするかも
                         HookGlobalHotkey.ModKeys modKey = HookGlobalHotkey.ModKeys.None;
-                        if ((this._cfgCommon.HotkeyModifier & Keys.Alt) == Keys.Alt)
+                        if ((SettingManager.Common.HotkeyModifier & Keys.Alt) == Keys.Alt)
                             modKey |= HookGlobalHotkey.ModKeys.Alt;
-                        if ((this._cfgCommon.HotkeyModifier & Keys.Control) == Keys.Control)
+                        if ((SettingManager.Common.HotkeyModifier & Keys.Control) == Keys.Control)
                             modKey |= HookGlobalHotkey.ModKeys.Ctrl;
-                        if ((this._cfgCommon.HotkeyModifier & Keys.Shift) == Keys.Shift)
+                        if ((SettingManager.Common.HotkeyModifier & Keys.Shift) == Keys.Shift)
                             modKey |=  HookGlobalHotkey.ModKeys.Shift;
-                        if ((this._cfgCommon.HotkeyModifier & Keys.LWin) == Keys.LWin)
+                        if ((SettingManager.Common.HotkeyModifier & Keys.LWin) == Keys.LWin)
                             modKey |= HookGlobalHotkey.ModKeys.Win;
 
-                        _hookGlobalHotkey.RegisterOriginalHotkey(this._cfgCommon.HotkeyKey, this._cfgCommon.HotkeyValue, modKey);
+                        _hookGlobalHotkey.RegisterOriginalHotkey(SettingManager.Common.HotkeyKey, SettingManager.Common.HotkeyValue, modKey);
                     }
 
-                    if (this._cfgCommon.IsUseNotifyGrowl) gh.RegisterGrowl();
+                    if (SettingManager.Common.IsUseNotifyGrowl) gh.RegisterGrowl();
                     try
                     {
                         StatusText_TextChanged(null, null);
@@ -3995,10 +3791,10 @@ namespace OpenTween
 
             Twitter.AccountState = MyCommon.ACCOUNT_STATE.Valid;
 
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
             SaveConfigsAll(false);
 
-            if (tw.Username != oldUser.Username)
+            if (tw.UserId != oldUser.UserId)
                 await this.doGetFollowersMenu();
         }
 
@@ -4007,7 +3803,7 @@ namespace OpenTween
         /// </summary>
         private void SetTabAlignment()
         {
-            var newAlignment = this._cfgCommon.ViewTabBottom ? TabAlignment.Bottom : TabAlignment.Top;
+            var newAlignment = SettingManager.Common.ViewTabBottom ? TabAlignment.Bottom : TabAlignment.Top;
             if (ListTab.Alignment == newAlignment) return;
 
             // 各タブのリスト上の選択位置などを退避
@@ -4130,24 +3926,23 @@ namespace OpenTween
             this.SearchButton_Click(ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"], null);
         }
 
-        private void ShowUserTimeline()
+        private async Task ShowUserTimeline()
         {
             if (!this.ExistCurrentPost) return;
-            AddNewTabForUserTimeline(_curPost.ScreenName);
+            await this.AddNewTabForUserTimeline(this.CurrentPost.ScreenName);
         }
 
         private void SearchComboBox_KeyDown(object sender, KeyEventArgs e)
         {
             if (e.KeyCode == Keys.Escape)
             {
-                TabPage relTp = ListTab.SelectedTab;
-                RemoveSpecifiedTab(relTp.Text, false);
+                RemoveSpecifiedTab(this.CurrentTabName, false);
                 SaveConfigsTabs();
                 e.SuppressKeyPress = true;
             }
         }
 
-        public void AddNewTabForUserTimeline(string user)
+        public async Task AddNewTabForUserTimeline(string user)
         {
             //同一検索条件のタブが既に存在すれば、そのタブアクティブにして終了
             foreach (var tb in _statuses.GetTabsByType<UserTimelineTabModel>())
@@ -4178,7 +3973,7 @@ namespace OpenTween
             ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
             SaveConfigsTabs();
             //検索実行
-            this.GetUserTimelineAsync(tab);
+            await this.RefreshTabAsync(tab);
         }
 
         public bool AddNewTab(TabModel tab, bool startup)
@@ -4216,10 +4011,12 @@ namespace OpenTween
 
                 if (userTab != null || listTab != null)
                 {
-                    var label = new Label();
-                    label.Dock = DockStyle.Top;
-                    label.Name = "labelUser";
-                    label.TabIndex = 0;
+                    var label = new Label
+                    {
+                        Dock = DockStyle.Top,
+                        Name = "labelUser",
+                        TabIndex = 0,
+                    };
 
                     if (listTab != null)
                     {
@@ -4358,7 +4155,7 @@ namespace OpenTween
                 _listCustom.Font = _fntReaded;
                 _listCustom.BackColor = _clListBackcolor;
 
-                _listCustom.GridLines = this._cfgCommon.ShowGrid;
+                _listCustom.GridLines = SettingManager.Common.ShowGrid;
                 _listCustom.AllowDrop = true;
 
                 _listCustom.SmallImageList = _listViewImageList;
@@ -4485,14 +4282,7 @@ namespace OpenTween
                 _listCustom.SmallImageList = null;
                 _listCustom.ListViewItemSorter = null;
 
-                //キャッシュのクリア
-                if (_curTab.Equals(_tabPage))
-                {
-                    _curTab = null;
-                    _curItemIndex = -1;
-                    _curList = null;
-                    _curPost = null;
-                }
+                // キャッシュのクリア
                 this.PurgeListViewItemCache();
             }
 
@@ -4520,7 +4310,7 @@ namespace OpenTween
         {
             //タブのD&D
 
-            if (!this._cfgCommon.TabMouseLock && e.Button == MouseButtons.Left && _tabDrag)
+            if (!SettingManager.Common.TabMouseLock && e.Button == MouseButtons.Left && _tabDrag)
             {
                 string tn = "";
                 Rectangle dragEnableRectangle = new Rectangle(_tabMouseDownPoint.X - (SystemInformation.DragSize.Width / 2), _tabMouseDownPoint.Y - (SystemInformation.DragSize.Height / 2), SystemInformation.DragSize.Width, SystemInformation.DragSize.Height);
@@ -4573,16 +4363,16 @@ namespace OpenTween
 
         private void SetListProperty()
         {
-            //削除などで見つからない場合は処理せず
-            if (_curList == null) return;
             if (!_isColumnChanged) return;
 
-            int[] dispOrder = new int[_curList.Columns.Count];
-            for (int i = 0; i < _curList.Columns.Count; i++)
+            var currentListView = this.CurrentListView;
+
+            int[] dispOrder = new int[currentListView.Columns.Count];
+            for (int i = 0; i < currentListView.Columns.Count; i++)
             {
-                for (int j = 0; j < _curList.Columns.Count; j++)
+                for (int j = 0; j < currentListView.Columns.Count; j++)
                 {
-                    if (_curList.Columns[j].DisplayIndex == i)
+                    if (currentListView.Columns[j].DisplayIndex == i)
                     {
                         dispOrder[i] = j;
                         break;
@@ -4593,16 +4383,16 @@ namespace OpenTween
             //列幅、列並びを他のタブに設定
             foreach (TabPage tb in ListTab.TabPages)
             {
-                if (!tb.Equals(_curTab))
+                if (tb.Text == this.CurrentTabName)
+                    continue;
+
+                if (tb.Tag != null && tb.Controls.Count > 0)
                 {
-                    if (tb.Tag != null && tb.Controls.Count > 0)
+                    DetailsListView lst = (DetailsListView)tb.Tag;
+                    for (int i = 0; i < lst.Columns.Count; i++)
                     {
-                        DetailsListView lst = (DetailsListView)tb.Tag;
-                        for (int i = 0; i < lst.Columns.Count; i++)
-                        {
-                            lst.Columns[dispOrder[i]].DisplayIndex = i;
-                            lst.Columns[i].Width = _curList.Columns[i].Width;
-                        }
+                        lst.Columns[dispOrder[i]].DisplayIndex = i;
+                        lst.Columns[i].Width = currentListView.Columns[i].Width;
                     }
                 }
             }
@@ -4614,7 +4404,7 @@ namespace OpenTween
         {
             if (e.KeyChar == '@')
             {
-                if (!this._cfgCommon.UseAtIdSupplement) return;
+                if (!SettingManager.Common.UseAtIdSupplement) return;
                 //@マーク
                 int cnt = AtIdSupl.ItemCount;
                 ShowSuplDialog(StatusText, AtIdSupl);
@@ -4623,21 +4413,17 @@ namespace OpenTween
             }
             else if (e.KeyChar == '#')
             {
-                if (!this._cfgCommon.UseHashSupplement) return;
+                if (!SettingManager.Common.UseHashSupplement) return;
                 ShowSuplDialog(StatusText, HashSupl);
                 e.Handled = true;
             }
         }
 
         public void ShowSuplDialog(TextBox owner, AtIdSupplement dialog)
-        {
-            ShowSuplDialog(owner, dialog, 0, "");
-        }
+            => this.ShowSuplDialog(owner, dialog, 0, "");
 
         public void ShowSuplDialog(TextBox owner, AtIdSupplement dialog, int offset)
-        {
-            ShowSuplDialog(owner, dialog, offset, "");
-        }
+            => this.ShowSuplDialog(owner, dialog, offset, "");
 
         public void ShowSuplDialog(TextBox owner, AtIdSupplement dialog, int offset, string startswith)
         {
@@ -4650,7 +4436,7 @@ namespace OpenTween
             {
                 dialog.ShowDialog();
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
             int selStart = owner.SelectionStart;
             string fHalf = "";
             string eHalf = "";
@@ -4720,26 +4506,122 @@ namespace OpenTween
             this.StatusText_TextChanged(null, null);
         }
 
-        private void StatusText_TextChanged(object sender, EventArgs e)
+        private void StatusText_TextChanged(object sender, EventArgs e)
+        {
+            //文字数カウント
+            int pLen = this.GetRestStatusCount(this.FormatStatusTextExtended(this.StatusText.Text));
+            lblLen.Text = pLen.ToString();
+            if (pLen < 0)
+            {
+                StatusText.ForeColor = Color.Red;
+            }
+            else
+            {
+                StatusText.ForeColor = _clInputFont;
+            }
+
+            this.StatusText.AccessibleDescription = string.Format(Properties.Resources.StatusText_AccessibleDescription, pLen);
+
+            if (string.IsNullOrEmpty(StatusText.Text))
+            {
+                this.inReplyTo = null;
+            }
+        }
+
+        /// <summary>
+        /// メンション以外の文字列が含まれていないテキストであるか判定します
+        /// </summary>
+        internal static bool TextContainsOnlyMentions(string text)
+        {
+            var mentions = TweetExtractor.ExtractMentionEntities(text).OrderBy(x => x.Indices[0]);
+            var startIndex = 0;
+
+            foreach (var mention in mentions)
+            {
+                var textPart = text.Substring(startIndex, mention.Indices[0] - startIndex);
+
+                if (!string.IsNullOrWhiteSpace(textPart))
+                    return false;
+
+                startIndex = mention.Indices[1];
+            }
+
+            var textPartLast = text.Substring(startIndex);
+
+            if (!string.IsNullOrWhiteSpace(textPartLast))
+                return false;
+
+            return true;
+        }
+
+        /// <summary>
+        /// 投稿時に auto_populate_reply_metadata オプションによって自動で追加されるメンションを除去します
+        /// </summary>
+        private string RemoveAutoPopuratedMentions(string statusText, out long[] autoPopulatedUserIds)
+        {
+            List<long> _autoPopulatedUserIds = new List<long>();
+
+            var replyToPost = this.inReplyTo != null ? this._statuses[this.inReplyTo.Value.StatusId] : null;
+            if (replyToPost != null)
+            {
+                if (statusText.StartsWith($"@{replyToPost.ScreenName} ", StringComparison.Ordinal))
+                {
+                    statusText = statusText.Substring(replyToPost.ScreenName.Length + 2);
+                    _autoPopulatedUserIds.Add(replyToPost.UserId);
+
+                    foreach (var (userId, screenName) in replyToPost.ReplyToList)
+                    {
+                        if (statusText.StartsWith($"@{screenName} ", StringComparison.Ordinal))
+                        {
+                            statusText = statusText.Substring(screenName.Length + 2);
+                            _autoPopulatedUserIds.Add(userId);
+                        }
+                    }
+                }
+            }
+
+            autoPopulatedUserIds = _autoPopulatedUserIds.ToArray();
+
+            return statusText;
+        }
+
+        /// <summary>
+        /// attachment_url に指定可能な URL が含まれていれば除去
+        /// </summary>
+        private string RemoveAttachmentUrl(string statusText, out string attachmentUrl)
         {
-            //文字数カウント
-            int pLen = this.GetRestStatusCount(this.FormatStatusText(this.StatusText.Text));
-            lblLen.Text = pLen.ToString();
-            if (pLen < 0)
-            {
-                StatusText.ForeColor = Color.Red;
-            }
-            else
-            {
-                StatusText.ForeColor = _clInputFont;
-            }
+            attachmentUrl = null;
 
-            this.StatusText.AccessibleDescription = string.Format(Properties.Resources.StatusText_AccessibleDescription, pLen);
+            // attachment_url は media_id と同時に使用できない
+            if (this.ImageSelector.Visible && this.ImageSelector.SelectedService is TwitterPhoto)
+                return statusText;
 
-            if (string.IsNullOrEmpty(StatusText.Text))
-            {
-                this.inReplyTo = null;
-            }
+            var match = Twitter.AttachmentUrlRegex.Match(statusText);
+            if (!match.Success)
+                return statusText;
+
+            attachmentUrl = match.Value;
+
+            // マッチした URL を空白に置換
+            statusText = statusText.Substring(0, match.Index);
+
+            // テキストと URL の間にスペースが含まれていれば除去
+            return statusText.TrimEnd(' ');
+        }
+
+        private string FormatStatusTextExtended(string statusText)
+            => this.FormatStatusTextExtended(statusText, out var autoPopulatedUserIds, out var attachmentUrl);
+
+        /// <summary>
+        /// <see cref="FormatStatusText"/> に加えて、拡張モードで140字にカウントされない文字列の除去を行います
+        /// </summary>
+        private string FormatStatusTextExtended(string statusText, out long[] autoPopulatedUserIds, out string attachmentUrl)
+        {
+            statusText = this.RemoveAutoPopuratedMentions(statusText, out autoPopulatedUserIds);
+
+            statusText = this.RemoveAttachmentUrl(statusText, out attachmentUrl);
+
+            return this.FormatStatusText(statusText);
         }
 
         /// <summary>
@@ -4749,13 +4631,13 @@ namespace OpenTween
         {
             statusText = statusText.Replace("\r\n", "\n");
 
-            if (this.ToolStripMenuItemUrlMultibyteSplit.Checked)
+            if (this.urlMultibyteSplit)
             {
                 // URLと全角文字の切り離し
                 statusText = Regex.Replace(statusText, @"https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#^]+", "$& ");
             }
 
-            if (this.IdeographicSpaceToSpaceToolStripMenuItem.Checked)
+            if (SettingManager.Common.WideSpaceConvert)
             {
                 // 文中の全角スペースを半角スペース1個にする
                 statusText = statusText.Replace(" ", " ");
@@ -4766,13 +4648,13 @@ namespace OpenTween
                 return statusText;
 
             bool disableFooter;
-            if (this._cfgCommon.PostShiftEnter)
+            if (SettingManager.Common.PostShiftEnter)
             {
                 disableFooter = MyCommon.IsKeyDown(Keys.Control);
             }
             else
             {
-                if (this.StatusText.Multiline && !this._cfgCommon.PostCtrlEnter)
+                if (this.StatusText.Multiline && !SettingManager.Common.PostCtrlEnter)
                     disableFooter = MyCommon.IsKeyDown(Keys.Control);
                 else
                     disableFooter = MyCommon.IsKeyDown(Keys.Shift);
@@ -4781,6 +4663,17 @@ namespace OpenTween
             if (statusText.Contains("RT @"))
                 disableFooter = true;
 
+            // 自分宛のリプライの場合は先頭の「@screen_name 」の部分を除去する (in_reply_to_status_id は維持される)
+            if (this.inReplyTo != null && this.inReplyTo.Value.ScreenName == this.tw.Username)
+            {
+                var mentionSelf = $"@{this.tw.Username} ";
+                if (statusText.StartsWith(mentionSelf, StringComparison.OrdinalIgnoreCase))
+                {
+                    if (statusText.Length > mentionSelf.Length || this.GetSelectedImageService() != null)
+                        statusText = statusText.Substring(mentionSelf.Length);
+                }
+            }
+
             var header = "";
             var footer = "";
 
@@ -4795,21 +4688,21 @@ namespace OpenTween
 
             if (!disableFooter)
             {
-                if (this._cfgLocal.UseRecommendStatus)
+                if (SettingManager.Local.UseRecommendStatus)
                 {
                     // 推奨ステータスを使用する
                     footer += this.recommendedStatusFooter;
                 }
-                else if (!string.IsNullOrEmpty(this._cfgLocal.StatusText))
+                else if (!string.IsNullOrEmpty(SettingManager.Local.StatusText))
                 {
                     // テキストボックスに入力されている文字列を使用する
-                    footer += " " + this._cfgLocal.StatusText.Trim();
+                    footer += " " + SettingManager.Local.StatusText.Trim();
                 }
             }
 
             statusText = header + statusText + footer;
 
-            if (this.ToolStripMenuItemPreventSmsCommand.Checked)
+            if (this.preventSmsCommand)
             {
                 // ツイートが意図せず SMS コマンドとして解釈されることを回避 (D, DM, M のみ)
                 // 参照: https://support.twitter.com/articles/14020
@@ -4830,11 +4723,10 @@ namespace OpenTween
         /// </summary>
         private int GetRestStatusCount(string statusText)
         {
-            //文字数カウント
             var remainCount = this.tw.GetTextLengthRemain(statusText);
 
-            var uploadService = this.ImageSelector.SelectedService;
-            if (this.ImageSelector.Visible && uploadService != null)
+            var uploadService = this.GetSelectedImageService();
+            if (uploadService != null)
             {
                 // TODO: ImageSelector で選択中の画像の枚数が mediaCount 引数に渡るようにする
                 remainCount -= uploadService.GetReservedTextLength(1);
@@ -4843,9 +4735,12 @@ namespace OpenTween
             return remainCount;
         }
 
+        private IMediaUploadService GetSelectedImageService()
+            => this.ImageSelector.Visible ? this.ImageSelector.SelectedService : null;
+
         private void MyList_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
         {
-            if (sender != this._curList)
+            if (sender != this.CurrentListView)
                 return;
 
             var listCache = this._listItemCache;
@@ -4865,9 +4760,7 @@ namespace OpenTween
             var listCache = this._listItemCache;
             if (listCache?.TargetList == sender)
             {
-                ListViewItem item;
-                PostClass cacheItemPost;
-                if (listCache.TryGetValue(e.ItemIndex, out item, out cacheItemPost))
+                if (listCache.TryGetValue(e.ItemIndex, out var item, out var cacheItemPost))
                 {
                     e.Item = item;
                     return;
@@ -4875,10 +4768,11 @@ namespace OpenTween
             }
 
             // A cache miss, so create a new ListViewItem and pass it back.
-            TabPage tb = (TabPage)((DetailsListView)sender).Parent;
+            var tabPage = (TabPage)((DetailsListView)sender).Parent;
+            var tab = this._statuses.Tabs[tabPage.Text];
             try
             {
-                e.Item = this.CreateItem(tb, _statuses.Tabs[tb.Text][e.ItemIndex], e.ItemIndex);
+                e.Item = this.CreateItem(tab, tab[e.ItemIndex], e.ItemIndex);
             }
             catch (Exception)
             {
@@ -4890,25 +4784,30 @@ namespace OpenTween
 
         private void CreateCache(int startIndex, int endIndex)
         {
-            var tabInfo = this._statuses.Tabs[this._curTab.Text];
+            var tabInfo = this.CurrentTab;
 
             if (tabInfo.AllCount == 0)
                 return;
 
+            // インデックスを 0...(tabInfo.AllCount - 1) の範囲内にする
+            int FilterRange(int index)
+                => Math.Max(Math.Min(index, tabInfo.AllCount - 1), 0);
+
             // キャッシュ要求(要求範囲±30を作成)
-            startIndex = Math.Max(startIndex - 30, 0);
-            endIndex = Math.Min(endIndex + 30, tabInfo.AllCount - 1);
+            startIndex = FilterRange(startIndex - 30);
+            endIndex = FilterRange(endIndex + 30);
 
             var cacheLength = endIndex - startIndex + 1;
 
+            var tab = this.CurrentTab;
             var posts = tabInfo[startIndex, endIndex]; //配列で取得
             var listItems = Enumerable.Range(0, cacheLength)
-                .Select(x => this.CreateItem(this._curTab, posts[x], startIndex + x))
+                .Select(x => this.CreateItem(tab, posts[x], startIndex + x))
                 .ToArray();
 
             var listCache = new ListViewItemCache
             {
-                TargetList = this._curList,
+                TargetList = this.CurrentListView,
                 StartIndex = startIndex,
                 EndIndex = endIndex,
                 Post = posts,
@@ -4922,11 +4821,9 @@ namespace OpenTween
         /// DetailsListView のための ListViewItem のキャッシュを消去する
         /// </summary>
         private void PurgeListViewItemCache()
-        {
-            Interlocked.Exchange(ref this._listItemCache, null);
-        }
+            => Interlocked.Exchange(ref this._listItemCache, null);
 
-        private ListViewItem CreateItem(TabPage Tab, PostClass Post, int Index)
+        private ListViewItem CreateItem(TabModel tab, PostClass Post, int Index)
         {
             StringBuilder mk = new StringBuilder();
             //if (Post.IsDeleted) mk.Append("×");
@@ -4939,8 +4836,8 @@ namespace OpenTween
             {
                 string[] sitem= {"",
                                  Post.Nickname,
-                                 Post.IsDeleted ? "(DELETED)" : Post.AccessibleText,
-                                 Post.CreatedAt.ToString(this._cfgCommon.DateTimeFormat),
+                                 Post.IsDeleted ? "(DELETED)" : Post.AccessibleText.Replace('\n', ' '),
+                                 Post.CreatedAt.ToLocalTimeString(SettingManager.Common.DateTimeFormat),
                                  Post.ScreenName,
                                  "",
                                  mk.ToString(),
@@ -4951,8 +4848,8 @@ namespace OpenTween
             {
                 string[] sitem = {"",
                                   Post.Nickname,
-                                  Post.IsDeleted ? "(DELETED)" : Post.AccessibleText,
-                                  Post.CreatedAt.ToString(this._cfgCommon.DateTimeFormat),
+                                  Post.IsDeleted ? "(DELETED)" : Post.AccessibleText.Replace('\n', ' '),
+                                  Post.CreatedAt.ToLocalTimeString(SettingManager.Common.DateTimeFormat),
                                   Post.ScreenName + Environment.NewLine + "(RT:" + Post.RetweetedBy + ")",
                                   "",
                                   mk.ToString(),
@@ -4963,10 +4860,15 @@ namespace OpenTween
             itm.Tag = Post;
 
             bool read = Post.IsRead;
-            //未読管理していなかったら既読として扱う
-            if (!_statuses.Tabs[Tab.Text].UnreadManage || !this._cfgCommon.UnreadManage) read = true;
+            // 未読管理していなかったら既読として扱う
+            if (!tab.UnreadManage || !SettingManager.Common.UnreadManage)
+                read = true;
+
             ChangeItemStyleRead(read, itm, Post, null);
-            if (Tab.Equals(_curTab)) ColorizeList(itm, Index);
+
+            if (tab.TabName == this.CurrentTabName)
+                this.ColorizeList(itm, Index);
+
             return itm;
         }
 
@@ -4978,8 +4880,6 @@ namespace OpenTween
             using (ControlTransaction.Cursor(this, Cursors.WaitCursor))
             {
                 this.PurgeListViewItemCache();
-                this._curPost = null;
-                this._curItemIndex = -1;
                 this._statuses.FilterAll();
 
                 foreach (TabPage tabPage in this.ListTab.TabPages)
@@ -4992,7 +4892,7 @@ namespace OpenTween
                         listview.VirtualListSize = tab.AllCount;
                     }
 
-                    if (this._cfgCommon.TabIconDisp)
+                    if (SettingManager.Common.TabIconDisp)
                     {
                         if (tab.UnreadCount > 0)
                             tabPage.ImageIndex = 0;
@@ -5001,7 +4901,7 @@ namespace OpenTween
                     }
                 }
 
-                if (!this._cfgCommon.TabIconDisp)
+                if (!SettingManager.Common.TabIconDisp)
                     this.ListTab.Refresh();
 
                 SetMainWindowTitle();
@@ -5010,15 +4910,10 @@ namespace OpenTween
         }
 
         private void MyList_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
-        {
-            e.DrawDefault = true;
-        }
+            => e.DrawDefault = true;
 
         private void MyList_HScrolled(object sender, EventArgs e)
-        {
-            DetailsListView listView = (DetailsListView)sender;
-            listView.Refresh();
-        }
+            => ((DetailsListView)sender).Refresh();
 
         private void MyList_DrawItem(object sender, DrawListViewItemEventArgs e)
         {
@@ -5074,8 +4969,7 @@ namespace OpenTween
                     rct.Height -= fontHeight;
                 }
 
-                int heightDiff;
-                int drawLineCount = Math.Max(1, Math.DivRem((int)rct.Height, fontHeight, out heightDiff));
+                int drawLineCount = Math.Max(1, Math.DivRem((int)rct.Height, fontHeight, out var heightDiff));
 
                 //if (heightDiff > fontHeight * 0.7)
                 //{
@@ -5291,7 +5185,7 @@ namespace OpenTween
 
         internal void DoTabSearch(string searchWord, bool caseSensitive, bool useRegex, SEARCHTYPE searchType)
         {
-            var tab = this._statuses.Tabs[this._curTab.Text];
+            var tab = this.CurrentTab;
 
             if (tab.AllCount == 0)
             {
@@ -5299,7 +5193,7 @@ namespace OpenTween
                 return;
             }
 
-            var selectedIndex = this._curList.SelectedIndices.Count != 0 ? this._curList.SelectedIndices[0] : -1;
+            var selectedIndex = tab.SelectedIndex;
 
             int startIndex;
             switch (searchType)
@@ -5346,15 +5240,13 @@ namespace OpenTween
                 return;
             }
 
-            this.SelectListItem(this._curList, foundIndex);
-            this._curList.EnsureVisible(foundIndex);
+            var listView = this.CurrentListView;
+            this.SelectListItem(listView, foundIndex);
+            listView.EnsureVisible(foundIndex);
         }
 
         private void MenuItemSubSearch_Click(object sender, EventArgs e)
-        {
-            // 検索メニュー
-            this.ShowSearchDialog();
-        }
+            => this.ShowSearchDialog(); // 検索メニュー
 
         private void MenuItemSearchNext_Click(object sender, EventArgs e)
         {
@@ -5399,10 +5291,10 @@ namespace OpenTween
         {
             if (this.SearchDialog.ShowDialog(this) != DialogResult.OK)
             {
-                this.TopMost = this._cfgCommon.AlwaysTop;
+                this.TopMost = SettingManager.Common.AlwaysTop;
                 return;
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
 
             var searchOptions = this.SearchDialog.ResultOptions;
             if (searchOptions.Type == SearchWordDialog.SearchType.Timeline)
@@ -5417,14 +5309,14 @@ namespace OpenTween
                     }
                     catch (TabException ex)
                     {
-                        MessageBox.Show(this, ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
+                        MessageBox.Show(this, ex.Message, ApplicationSettings.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                     }
 
                     var resultTab = new LocalSearchTabModel(tabName);
                     this.AddNewTab(resultTab, startup: false);
                     this._statuses.AddTab(resultTab);
 
-                    var targetTab = this._statuses.Tabs[this._curTab.Text];
+                    var targetTab = this.CurrentTab;
 
                     Func<string, bool> stringComparer;
                     try
@@ -5500,12 +5392,12 @@ namespace OpenTween
             {
                 about.ShowDialog(this);
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
         }
 
         private void JumpUnreadMenuItem_Click(object sender, EventArgs e)
         {
-            int bgnIdx = ListTab.TabPages.IndexOf(_curTab);
+            int bgnIdx = ListTab.TabPages.IndexOf(this.CurrentTabPage);
 
             if (ImageSelector.Enabled)
                 return;
@@ -5594,34 +5486,25 @@ namespace OpenTween
 
         private async void StatusOpenMenuItem_Click(object sender, EventArgs e)
         {
-            if (_curList.SelectedIndices.Count > 0 && _statuses.Tabs[_curTab.Text].TabType != MyCommon.TabUsageType.DirectMessage)
-            {
-                var post = _statuses.Tabs[_curTab.Text][_curList.SelectedIndices[0]];
+            var tab = this.CurrentTab;
+            var post = this.CurrentPost;
+            if (post != null && tab.TabType != MyCommon.TabUsageType.DirectMessage)
                 await this.OpenUriInBrowserAsync(MyCommon.GetStatusUrl(post));
-            }
-        }
-
-        private async void FavorareMenuItem_Click(object sender, EventArgs e)
-        {
-            if (_curList.SelectedIndices.Count > 0)
-            {
-                PostClass post = _statuses.Tabs[_curTab.Text][_curList.SelectedIndices[0]];
-                await this.OpenUriInBrowserAsync(Properties.Resources.FavstarUrl + "users/" + post.ScreenName + "/recent");
-            }
         }
 
         private async void VerUpMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.CheckNewVersion(false);
-        }
+            => await this.CheckNewVersion(false);
 
         private void RunTweenUp()
         {
-            ProcessStartInfo pinfo = new ProcessStartInfo();
-            pinfo.UseShellExecute = true;
-            pinfo.WorkingDirectory = MyCommon.settingPath;
-            pinfo.FileName = Path.Combine(MyCommon.settingPath, "TweenUp3.exe");
-            pinfo.Arguments = "\"" + Application.StartupPath + "\"";
+            var pinfo = new ProcessStartInfo
+            {
+                UseShellExecute = true,
+                WorkingDirectory = MyCommon.settingPath,
+                FileName = Path.Combine(MyCommon.settingPath, "TweenUp3.exe"),
+                Arguments = "\"" + Application.StartupPath + "\"",
+            };
+
             try
             {
                 Process.Start(pinfo);
@@ -5645,7 +5528,7 @@ namespace OpenTween
         public async Task<VersionInfo> GetVersionInfoAsync()
         {
             var versionInfoUrl = new Uri(ApplicationSettings.VersionInfoUrl + "?" +
-                DateTime.Now.ToString("yyMMddHHmmss") + Environment.TickCount);
+                DateTimeUtc.Now.ToString("yyMMddHHmmss") + Environment.TickCount);
 
             var responseText = await Networking.Http.GetStringAsync(versionInfoUrl)
                 .ConfigureAwait(false);
@@ -5691,6 +5574,9 @@ namespace OpenTween
                     return;
                 }
 
+                if (startup && versionInfo.Version <= SettingManager.Common.SkipUpdateVersion)
+                    return;
+
                 using (var dialog = new UpdateDialog())
                 {
                     dialog.SummaryText = string.Format(Properties.Resources.CheckNewVersionText3,
@@ -5701,6 +5587,11 @@ namespace OpenTween
                     {
                         await this.OpenUriInBrowserAsync(versionInfo.DownloadUri.OriginalString);
                     }
+                    else if (dialog.SkipButtonPressed)
+                    {
+                        SettingManager.Common.SkipUpdateVersion = versionInfo.Version;
+                        this.ModifySettingCommon = true;
+                    }
                 }
             }
             catch (Exception)
@@ -5720,10 +5611,10 @@ namespace OpenTween
             _colorize = false;
             await this.DispSelectedPost();
             //件数関連の場合、タイトル即時書き換え
-            if (this._cfgCommon.DispLatestPost != MyCommon.DispTitleEnum.None &&
-               this._cfgCommon.DispLatestPost != MyCommon.DispTitleEnum.Post &&
-               this._cfgCommon.DispLatestPost != MyCommon.DispTitleEnum.Ver &&
-               this._cfgCommon.DispLatestPost != MyCommon.DispTitleEnum.OwnStatus)
+            if (SettingManager.Common.DispLatestPost != MyCommon.DispTitleEnum.None &&
+               SettingManager.Common.DispLatestPost != MyCommon.DispTitleEnum.Post &&
+               SettingManager.Common.DispLatestPost != MyCommon.DispTitleEnum.Ver &&
+               SettingManager.Common.DispLatestPost != MyCommon.DispTitleEnum.OwnStatus)
             {
                 SetMainWindowTitle();
             }
@@ -5733,27 +5624,20 @@ namespace OpenTween
             {
                 if (_statuses.Tabs[tb.Text].UnreadCount == 0)
                 {
-                    if (this._cfgCommon.TabIconDisp)
+                    if (SettingManager.Common.TabIconDisp)
                     {
                         if (tb.ImageIndex == 0) tb.ImageIndex = -1;
                     }
                 }
             }
-            if (!this._cfgCommon.TabIconDisp) ListTab.Refresh();
+            if (!SettingManager.Common.TabIconDisp) ListTab.Refresh();
         }
 
         public string createDetailHtml(string orgdata)
-        {
-            if (this._cfgLocal.UseTwemoji)
-                orgdata = EmojiFormatter.ReplaceEmojiToImg(orgdata);
-
-            return detailHtmlFormatHeader + orgdata + detailHtmlFormatFooter;
-        }
+            => detailHtmlFormatHeader + orgdata + detailHtmlFormatFooter;
 
         private Task DispSelectedPost()
-        {
-            return this.DispSelectedPost(false);
-        }
+            => this.DispSelectedPost(false);
 
         private PostClass displayPost = new PostClass();
 
@@ -5764,29 +5648,30 @@ namespace OpenTween
 
         private async Task DispSelectedPost(bool forceupdate)
         {
-            if (_curList.SelectedIndices.Count == 0 || _curPost == null)
+            var currentPost = this.CurrentPost;
+            if (currentPost == null)
                 return;
 
             var oldDisplayPost = this.displayPost;
-            this.displayPost = this._curPost;
+            this.displayPost = currentPost;
 
-            if (!forceupdate && this._curPost.Equals(oldDisplayPost))
+            if (!forceupdate && currentPost.Equals(oldDisplayPost))
                 return;
 
             var loadTasks = new List<Task>
             {
-                this.tweetDetailsView.ShowPostDetails(this._curPost),
+                this.tweetDetailsView.ShowPostDetails(currentPost),
             };
 
             this.SplitContainer3.Panel2Collapsed = true;
 
-            if (this._cfgCommon.PreviewEnable)
+            if (SettingManager.Common.PreviewEnable)
             {
                 var oldTokenSource = Interlocked.Exchange(ref this.thumbnailTokenSource, new CancellationTokenSource());
                 oldTokenSource?.Cancel();
 
                 var token = this.thumbnailTokenSource.Token;
-                loadTasks.Add(this.tweetThumbnail1.ShowThumbnailAsync(_curPost, token));
+                loadTasks.Add(this.tweetThumbnail1.ShowThumbnailAsync(currentPost, token));
             }
 
             try
@@ -5797,48 +5682,39 @@ namespace OpenTween
         }
 
         private async void MatomeMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.OpenApplicationWebsite();
-        }
+            => await this.OpenApplicationWebsite();
 
         private async Task OpenApplicationWebsite()
-        {
-            await this.OpenUriInBrowserAsync(ApplicationSettings.WebsiteUrl);
-        }
+            => await this.OpenUriInBrowserAsync(ApplicationSettings.WebsiteUrl);
 
         private async void ShortcutKeyListMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.OpenUriInBrowserAsync(ApplicationSettings.ShortcutKeyUrl);
-        }
+            => await this.OpenUriInBrowserAsync(ApplicationSettings.ShortcutKeyUrl);
 
         private async void ListTab_KeyDown(object sender, KeyEventArgs e)
         {
-            if (ListTab.SelectedTab != null)
+            var tab = this.CurrentTab;
+            if (tab.TabType == MyCommon.TabUsageType.PublicSearch)
             {
-                if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch)
-                {
-                    Control pnl = ListTab.SelectedTab.Controls["panelSearch"];
-                    if (pnl.Controls["comboSearch"].Focused ||
-                        pnl.Controls["comboLang"].Focused ||
-                        pnl.Controls["buttonSearch"].Focused) return;
-                }
-
-                if (e.Control || e.Shift || e.Alt)
-                    this._anchorFlag = false;
+                Control pnl = ListTab.SelectedTab.Controls["panelSearch"];
+                if (pnl.Controls["comboSearch"].Focused ||
+                    pnl.Controls["comboLang"].Focused ||
+                    pnl.Controls["buttonSearch"].Focused) return;
+            }
 
-                Task asyncTask;
-                if (CommonKeyDown(e.KeyData, FocusedControl.ListTab, out asyncTask))
-                {
-                    e.Handled = true;
-                    e.SuppressKeyPress = true;
-                }
+            if (e.Control || e.Shift || e.Alt)
+                this._anchorFlag = false;
 
-                if (asyncTask != null)
-                    await asyncTask;
+            if (CommonKeyDown(e.KeyData, FocusedControl.ListTab, out var asyncTask))
+            {
+                e.Handled = true;
+                e.SuppressKeyPress = true;
             }
+
+            if (asyncTask != null)
+                await asyncTask;
         }
 
-        private ShortcutCommand[] shortcutCommands = new ShortcutCommand[0];
+        private ShortcutCommand[] shortcutCommands = Array.Empty<ShortcutCommand>();
 
         private void InitializeShortcuts()
         {
@@ -5871,10 +5747,10 @@ namespace OpenTween
                     .Do(() => this.DoRefresh()),
 
                 ShortcutCommand.Create(Keys.F6)
-                    .Do(() => this.GetReplyAsync()),
+                    .Do(() => this.RefreshTabAsync<MentionsTabModel>()),
 
                 ShortcutCommand.Create(Keys.F7)
-                    .Do(() => this.GetDirectMessagesAsync()),
+                    .Do(() => this.RefreshTabAsync<DirectMessagesTabModel>()),
 
                 ShortcutCommand.Create(Keys.Space, Keys.ProcessKey)
                     .NotFocusedOn(FocusedControl.StatusText)
@@ -5943,15 +5819,12 @@ namespace OpenTween
                     .FocusedOn(FocusedControl.ListTab)
                     .Do(() => {
                         this._anchorFlag = false;
-                        if (ListTab.SelectedTab != null)
+                        var tab = this.CurrentTab;
+                        var tabtype = tab.TabType;
+                        if (tabtype == MyCommon.TabUsageType.Related || tabtype == MyCommon.TabUsageType.UserTimeline || tabtype == MyCommon.TabUsageType.PublicSearch || tabtype == MyCommon.TabUsageType.SearchResults)
                         {
-                            var tabtype = _statuses.Tabs[ListTab.SelectedTab.Text].TabType;
-                            if (tabtype == MyCommon.TabUsageType.Related || tabtype == MyCommon.TabUsageType.UserTimeline || tabtype == MyCommon.TabUsageType.PublicSearch || tabtype == MyCommon.TabUsageType.SearchResults)
-                            {
-                                var relTp = ListTab.SelectedTab;
-                                RemoveSpecifiedTab(relTp.Text, false);
-                                SaveConfigsTabs();
-                            }
+                            RemoveSpecifiedTab(tab.TabName, false);
+                            SaveConfigsTabs();
                         }
                     }),
 
@@ -6085,45 +5958,11 @@ namespace OpenTween
 
                 ShortcutCommand.Create(Keys.Control | Keys.Up)
                     .FocusedOn(FocusedControl.StatusText)
-                    .Do(() => {
-                        if (!string.IsNullOrWhiteSpace(StatusText.Text))
-                        {
-                            var inReplyToStatusId = this.inReplyTo?.Item1;
-                            var inReplyToScreenName = this.inReplyTo?.Item2;
-                            _history[_hisIdx] = new PostingStatus(StatusText.Text, inReplyToStatusId, inReplyToScreenName);
-                        }
-                        _hisIdx -= 1;
-                        if (_hisIdx < 0) _hisIdx = 0;
-
-                        var historyItem = this._history[this._hisIdx];
-                        StatusText.Text = historyItem.status;
-                        StatusText.SelectionStart = StatusText.Text.Length;
-                        if (historyItem.inReplyToId != null)
-                            this.inReplyTo = Tuple.Create(historyItem.inReplyToId.Value, historyItem.inReplyToName);
-                        else
-                            this.inReplyTo = null;
-                    }),
+                    .Do(() => this.StatusTextHistoryBack()),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Down)
                     .FocusedOn(FocusedControl.StatusText)
-                    .Do(() => {
-                        if (!string.IsNullOrWhiteSpace(StatusText.Text))
-                        {
-                            var inReplyToStatusId = this.inReplyTo?.Item1;
-                            var inReplyToScreenName = this.inReplyTo?.Item2;
-                            _history[_hisIdx] = new PostingStatus(StatusText.Text, inReplyToStatusId, inReplyToScreenName);
-                        }
-                        _hisIdx += 1;
-                        if (_hisIdx > _history.Count - 1) _hisIdx = _history.Count - 1;
-
-                        var historyItem = this._history[this._hisIdx];
-                        StatusText.Text = historyItem.status;
-                        StatusText.SelectionStart = StatusText.Text.Length;
-                        if (historyItem.inReplyToId != null)
-                            this.inReplyTo = Tuple.Create(historyItem.inReplyToId.Value, historyItem.inReplyToName);
-                        else
-                            this.inReplyTo = null;
-                    }),
+                    .Do(() => this.StatusTextHistoryForward()),
 
                 ShortcutCommand.Create(Keys.Control | Keys.PageUp, Keys.Control | Keys.P)
                     .FocusedOn(FocusedControl.StatusText)
@@ -6156,8 +5995,10 @@ namespace OpenTween
                 ShortcutCommand.Create(Keys.Control | Keys.Y)
                     .FocusedOn(FocusedControl.PostBrowser)
                     .Do(() => {
-                        MultiLineMenuItem.Checked = !MultiLineMenuItem.Checked;
-                        MultiLineMenuItem_Click(null, null);
+                        var multiline = !SettingManager.Local.StatusMultiline;
+                        SettingManager.Local.StatusMultiline = multiline;
+                        MultiLineMenuItem.Checked = multiline;
+                        MultiLineMenuItem_Click(this.MultiLineMenuItem, EventArgs.Empty);
                     }),
 
                 ShortcutCommand.Create(Keys.Shift | Keys.F3)
@@ -6167,10 +6008,10 @@ namespace OpenTween
                     .Do(() => this.DoRefreshMore()),
 
                 ShortcutCommand.Create(Keys.Shift | Keys.F6)
-                    .Do(() => this.GetReplyAsync(loadMore: true)),
+                    .Do(() => this.RefreshTabAsync<MentionsTabModel>(backward: true)),
 
                 ShortcutCommand.Create(Keys.Shift | Keys.F7)
-                    .Do(() => this.GetDirectMessagesAsync(loadMore: true)),
+                    .Do(() => this.RefreshTabAsync<DirectMessagesTabModel>(backward: true)),
 
                 ShortcutCommand.Create(Keys.Shift | Keys.R)
                     .NotFocusedOn(FocusedControl.StatusText)
@@ -6222,8 +6063,8 @@ namespace OpenTween
                     .Do(() => this.doReTweetOfficial(isConfirm: true)),
 
                 ShortcutCommand.Create(Keys.Alt | Keys.P)
-                    .OnlyWhen(() => this._curPost != null)
-                    .Do(() => this.doShowUserStatus(_curPost.ScreenName, ShowInputDialog: false)),
+                    .OnlyWhen(() => this.CurrentPost != null)
+                    .Do(() => this.doShowUserStatus(this.CurrentPost.ScreenName, ShowInputDialog: false)),
 
                 ShortcutCommand.Create(Keys.Alt | Keys.Up)
                     .Do(() => this.tweetDetailsView.ScrollDownPostBrowser(forward: false)),
@@ -6253,9 +6094,8 @@ namespace OpenTween
                     .Do(() => this.CopyIdUri()),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.F)
-                    .OnlyWhen(() => this.ListTab.SelectedTab != null &&
-                        this._statuses.Tabs[this.ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch)
-                    .Do(() => this.ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focus()),
+                    .OnlyWhen(() => this.CurrentTab.TabType == MyCommon.TabUsageType.PublicSearch)
+                    .Do(() => this.CurrentTabPage.Controls["panelSearch"].Controls["comboSearch"].Focus()),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.S)
                     .Do(() => this.FavoriteChange(FavAdd: false)),
@@ -6272,30 +6112,31 @@ namespace OpenTween
                 ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.H)
                     .Do(() => this.doMoveToRTHome()),
 
-                ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.O)
-                    .Do(() => this.FavorareMenuItem_Click(null, null)),
-
                 ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.Up)
                     .FocusedOn(FocusedControl.StatusText)
                     .Do(() => {
-                        if (_curList != null && _curList.VirtualListSize != 0 &&
-                                    _curList.SelectedIndices.Count > 0 && _curList.SelectedIndices[0] > 0)
+                        var tab = this.CurrentTab;
+                        var selectedIndex = tab.SelectedIndex;
+                        if (selectedIndex != -1 && selectedIndex > 0)
                         {
-                            var idx = _curList.SelectedIndices[0] - 1;
-                            SelectListItem(_curList, idx);
-                            _curList.EnsureVisible(idx);
+                            var listView = this.CurrentListView;
+                            var idx = selectedIndex - 1;
+                            SelectListItem(listView, idx);
+                            listView.EnsureVisible(idx);
                         }
                     }),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.Down)
                     .FocusedOn(FocusedControl.StatusText)
                     .Do(() => {
-                        if (_curList != null && _curList.VirtualListSize != 0 && _curList.SelectedIndices.Count > 0
-                                    && _curList.SelectedIndices[0] < _curList.VirtualListSize - 1)
+                        var tab = this.CurrentTab;
+                        var selectedIndex = tab.SelectedIndex;
+                        if (selectedIndex != -1 && selectedIndex < tab.AllCount - 1)
                         {
-                            var idx = _curList.SelectedIndices[0] + 1;
-                            SelectListItem(_curList, idx);
-                            _curList.EnsureVisible(idx);
+                            var listView = this.CurrentListView;
+                            var idx = selectedIndex + 1;
+                            SelectListItem(listView, idx);
+                            listView.EnsureVisible(idx);
                         }
                     }),
 
@@ -6371,12 +6212,15 @@ namespace OpenTween
                     .Do(() => this.SetSortLastColumn()),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Alt | Keys.S)
+                    .FocusedOn(FocusedControl.ListTab)
                     .Do(() => this.FavoritesRetweetOfficial()),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Alt | Keys.R)
+                    .FocusedOn(FocusedControl.ListTab)
                     .Do(() => this.FavoritesRetweetUnofficial()),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Alt | Keys.H)
+                    .FocusedOn(FocusedControl.ListTab)
                     .Do(() => this.OpenUserAppointUrl()),
 
                 ShortcutCommand.Create(Keys.Alt | Keys.Shift | Keys.R)
@@ -6444,12 +6288,11 @@ namespace OpenTween
         {
             string clstr = "";
             StringBuilder sb = new StringBuilder();
+            var tab = this.CurrentTab;
             bool IsProtected = false;
-            bool isDm = false;
-            if (this._curTab != null && this._statuses.GetTabByName(this._curTab.Text) != null) isDm = this._statuses.GetTabByName(this._curTab.Text).TabType == MyCommon.TabUsageType.DirectMessage;
-            foreach (int idx in _curList.SelectedIndices)
+            var isDm = tab.TabType == MyCommon.TabUsageType.DirectMessage;
+            foreach (var post in tab.SelectedPosts)
             {
-                PostClass post = _statuses.Tabs[_curTab.Text][idx];
                 if (post.IsDeleted) continue;
                 if (!isDm)
                 {
@@ -6483,19 +6326,13 @@ namespace OpenTween
 
         private void CopyIdUri()
         {
-            if (this._curTab == null)
-                return;
-
-            var tab = this._statuses.GetTabByName(this._curTab.Text);
+            var tab = this.CurrentTab;
             if (tab == null || tab is DirectMessagesTabModel)
                 return;
 
             var copyUrls = new List<string>();
-            foreach (int idx in _curList.SelectedIndices)
-            {
-                var post = tab[idx];
+            foreach (var post in tab.SelectedPosts)
                 copyUrls.Add(MyCommon.GetStatusUrl(post));
-            }
 
             if (copyUrls.Count == 0)
                 return;
@@ -6512,34 +6349,39 @@ namespace OpenTween
 
         private void GoFav(bool forward)
         {
-            if (_curList.VirtualListSize == 0) return;
+            var tab = this.CurrentTab;
+            if (tab.AllCount == 0)
+                return;
+
+            var selectedIndex = tab.SelectedIndex;
+
             int fIdx = 0;
             int toIdx = 0;
             int stp = 1;
 
             if (forward)
             {
-                if (_curList.SelectedIndices.Count == 0)
+                if (selectedIndex == -1)
                 {
                     fIdx = 0;
                 }
                 else
                 {
-                    fIdx = _curList.SelectedIndices[0] + 1;
-                    if (fIdx > _curList.VirtualListSize - 1) return;
+                    fIdx = selectedIndex + 1;
+                    if (fIdx > tab.AllCount - 1) return;
                 }
-                toIdx = _curList.VirtualListSize;
+                toIdx = tab.AllCount;
                 stp = 1;
             }
             else
             {
-                if (_curList.SelectedIndices.Count == 0)
+                if (selectedIndex == -1)
                 {
-                    fIdx = _curList.VirtualListSize - 1;
+                    fIdx = tab.AllCount - 1;
                 }
                 else
                 {
-                    fIdx = _curList.SelectedIndices[0] - 1;
+                    fIdx = selectedIndex - 1;
                     if (fIdx < 0) return;
                 }
                 toIdx = -1;
@@ -6548,10 +6390,11 @@ namespace OpenTween
 
             for (int idx = fIdx; idx != toIdx; idx += stp)
             {
-                if (_statuses.Tabs[_curTab.Text][idx].IsFav)
+                if (tab[idx].IsFav)
                 {
-                    SelectListItem(_curList, idx);
-                    _curList.EnsureVisible(idx);
+                    var listView = this.CurrentListView;
+                    SelectListItem(listView, idx);
+                    listView.EnsureVisible(idx);
                     break;
                 }
             }
@@ -6559,17 +6402,15 @@ namespace OpenTween
 
         private void GoSamePostToAnotherTab(bool left)
         {
-            if (this._curList.SelectedIndices.Count == 0)
-                return;
-
-            var tab = this._statuses.Tabs[this._curTab.Text];
+            var tab = this.CurrentTab;
 
             // Directタブは対象外(見つかるはずがない)
             if (tab.TabType == MyCommon.TabUsageType.DirectMessage)
                 return;
 
-            var selectedIndex = this._curList.SelectedIndices[0];
-            var selectedStatusId = tab.GetStatusIdAt(selectedIndex);
+            var selectedStatusId = tab.SelectedStatusId;
+            if (selectedStatusId == -1)
+                return;
 
             int fIdx, toIdx, stp;
 
@@ -6614,8 +6455,9 @@ namespace OpenTween
                 if (foundIndex != -1)
                 {
                     ListTab.SelectedIndex = tabidx;
-                    SelectListItem(_curList, foundIndex);
-                    _curList.EnsureVisible(foundIndex);
+                    var listView = this.CurrentListView;
+                    SelectListItem(listView, foundIndex);
+                    listView.EnsureVisible(foundIndex);
                     return;
                 }
             }
@@ -6623,11 +6465,13 @@ namespace OpenTween
 
         private void GoPost(bool forward)
         {
-            if (_curList.SelectedIndices.Count == 0 || _curPost == null)
+            var tab = this.CurrentTab;
+            var currentPost = this.CurrentPost;
+
+            if (currentPost == null)
                 return;
 
-            var tab = this._statuses.Tabs[this._curTab.Text];
-            var selectedIndex = this._curList.SelectedIndices[0];
+            var selectedIndex = tab.SelectedIndex;
 
             int fIdx, toIdx, stp;
 
@@ -6647,13 +6491,13 @@ namespace OpenTween
             }
 
             string name = "";
-            if (_curPost.RetweetedId == null)
+            if (currentPost.RetweetedId == null)
             {
-                name = _curPost.ScreenName;
+                name = currentPost.ScreenName;
             }
             else
             {
-                name = _curPost.RetweetedBy;
+                name = currentPost.RetweetedBy;
             }
             for (int idx = fIdx; idx != toIdx; idx += stp)
             {
@@ -6662,8 +6506,9 @@ namespace OpenTween
                 {
                     if (post.ScreenName == name)
                     {
-                        SelectListItem(_curList, idx);
-                        _curList.EnsureVisible(idx);
+                        var listView = this.CurrentListView;
+                        SelectListItem(listView, idx);
+                        listView.EnsureVisible(idx);
                         break;
                     }
                 }
@@ -6671,8 +6516,9 @@ namespace OpenTween
                 {
                     if (post.RetweetedBy == name)
                     {
-                        SelectListItem(_curList, idx);
-                        _curList.EnsureVisible(idx);
+                        var listView = this.CurrentListView;
+                        SelectListItem(listView, idx);
+                        listView.EnsureVisible(idx);
                         break;
                     }
                 }
@@ -6681,11 +6527,11 @@ namespace OpenTween
 
         private void GoRelPost(bool forward)
         {
-            if (this._curList.SelectedIndices.Count == 0)
-                return;
+            var tab = this.CurrentTab;
+            var selectedIndex = tab.SelectedIndex;
 
-            var tab = this._statuses.Tabs[this._curTab.Text];
-            var selectedIndex = this._curList.SelectedIndices[0];
+            if (selectedIndex == -1)
+                return;
 
             int fIdx, toIdx, stp;
 
@@ -6706,8 +6552,9 @@ namespace OpenTween
 
             if (!_anchorFlag)
             {
-                if (_curPost == null) return;
-                _anchorPost = _curPost;
+                var currentPost = this.CurrentPost;
+                if (currentPost == null) return;
+                _anchorPost = currentPost;
                 _anchorFlag = true;
             }
             else
@@ -6722,13 +6569,14 @@ namespace OpenTween
                     post.RetweetedBy == _anchorPost.ScreenName ||
                     post.ScreenName == _anchorPost.RetweetedBy ||
                     (!string.IsNullOrEmpty(post.RetweetedBy) && post.RetweetedBy == _anchorPost.RetweetedBy) ||
-                    _anchorPost.ReplyToList.Contains(post.ScreenName.ToLowerInvariant()) ||
-                    _anchorPost.ReplyToList.Contains(post.RetweetedBy.ToLowerInvariant()) ||
-                    post.ReplyToList.Contains(_anchorPost.ScreenName.ToLowerInvariant()) ||
-                    post.ReplyToList.Contains(_anchorPost.RetweetedBy.ToLowerInvariant()))
-                {
-                    SelectListItem(_curList, idx);
-                    _curList.EnsureVisible(idx);
+                    _anchorPost.ReplyToList.Any(x => x.UserId == post.UserId) ||
+                    _anchorPost.ReplyToList.Any(x => x.UserId == post.RetweetedByUserId) ||
+                    post.ReplyToList.Any(x => x.UserId == _anchorPost.UserId) ||
+                    post.ReplyToList.Any(x => x.UserId == _anchorPost.RetweetedByUserId))
+                {
+                    var listView = this.CurrentListView;
+                    SelectListItem(listView, idx);
+                    listView.EnsureVisible(idx);
                     break;
                 }
             }
@@ -6737,16 +6585,18 @@ namespace OpenTween
         private void GoAnchor()
         {
             if (_anchorPost == null) return;
-            int idx = _statuses.Tabs[_curTab.Text].IndexOf(_anchorPost.StatusId);
+            int idx = this.CurrentTab.IndexOf(_anchorPost.StatusId);
             if (idx == -1) return;
 
-            SelectListItem(_curList, idx);
-            _curList.EnsureVisible(idx);
+            var listView = this.CurrentListView;
+            SelectListItem(listView, idx);
+            listView.EnsureVisible(idx);
         }
 
         private void GoTopEnd(bool GoTop)
         {
-            if (_curList.VirtualListSize == 0)
+            var listView = this.CurrentListView;
+            if (listView.VirtualListSize == 0)
                 return;
 
             ListViewItem _item;
@@ -6754,7 +6604,7 @@ namespace OpenTween
 
             if (GoTop)
             {
-                _item = _curList.GetItemAt(0, 25);
+                _item = listView.GetItemAt(0, 25);
                 if (_item == null)
                     idx = 0;
                 else
@@ -6762,18 +6612,19 @@ namespace OpenTween
             }
             else
             {
-                _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);
+                _item = listView.GetItemAt(0, listView.ClientSize.Height - 1);
                 if (_item == null)
-                    idx = _curList.VirtualListSize - 1;
+                    idx = listView.VirtualListSize - 1;
                 else
                     idx = _item.Index;
             }
-            SelectListItem(_curList, idx);
+            SelectListItem(listView, idx);
         }
 
         private void GoMiddle()
         {
-            if (_curList.VirtualListSize == 0)
+            var listView = this.CurrentListView;
+            if (listView.VirtualListSize == 0)
                 return;
 
             ListViewItem _item;
@@ -6781,7 +6632,7 @@ namespace OpenTween
             int idx2;
             int idx3;
 
-            _item = _curList.GetItemAt(0, 0);
+            _item = listView.GetItemAt(0, 0);
             if (_item == null)
             {
                 idx1 = 0;
@@ -6791,10 +6642,10 @@ namespace OpenTween
                 idx1 = _item.Index;
             }
 
-            _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);
+            _item = listView.GetItemAt(0, listView.ClientSize.Height - 1);
             if (_item == null)
             {
-                idx2 = _curList.VirtualListSize - 1;
+                idx2 = listView.VirtualListSize - 1;
             }
             else
             {
@@ -6802,57 +6653,63 @@ namespace OpenTween
             }
             idx3 = (idx1 + idx2) / 2;
 
-            SelectListItem(_curList, idx3);
+            SelectListItem(listView, idx3);
         }
 
         private void GoLast()
         {
-            if (_curList.VirtualListSize == 0) return;
+            var listView = this.CurrentListView;
+            if (listView.VirtualListSize == 0) return;
 
             if (_statuses.SortOrder == SortOrder.Ascending)
             {
-                SelectListItem(_curList, _curList.VirtualListSize - 1);
-                _curList.EnsureVisible(_curList.VirtualListSize - 1);
+                SelectListItem(listView, listView.VirtualListSize - 1);
+                listView.EnsureVisible(listView.VirtualListSize - 1);
             }
             else
             {
-                SelectListItem(_curList, 0);
-                _curList.EnsureVisible(0);
+                SelectListItem(listView, 0);
+                listView.EnsureVisible(0);
             }
         }
 
         private void MoveTop()
         {
-            if (_curList.SelectedIndices.Count == 0) return;
-            int idx = _curList.SelectedIndices[0];
+            var listView = this.CurrentListView;
+            if (listView.SelectedIndices.Count == 0) return;
+            int idx = listView.SelectedIndices[0];
             if (_statuses.SortOrder == SortOrder.Ascending)
             {
-                _curList.EnsureVisible(_curList.VirtualListSize - 1);
+                listView.EnsureVisible(listView.VirtualListSize - 1);
             }
             else
             {
-                _curList.EnsureVisible(0);
+                listView.EnsureVisible(0);
             }
-            _curList.EnsureVisible(idx);
+            listView.EnsureVisible(idx);
         }
 
         private async Task GoInReplyToPostTree()
         {
-            if (_curPost == null) return;
+            var curTabClass = this.CurrentTab;
+            var currentPost = this.CurrentPost;
 
-            TabModel curTabClass = _statuses.Tabs[_curTab.Text];
+            if (currentPost == null)
+                return;
 
-            if (curTabClass.TabType == MyCommon.TabUsageType.PublicSearch && _curPost.InReplyToStatusId == null && _curPost.TextFromApi.Contains("@"))
+            if (curTabClass.TabType == MyCommon.TabUsageType.PublicSearch && currentPost.InReplyToStatusId == null && currentPost.TextFromApi.Contains("@"))
             {
                 try
                 {
-                    var post = await tw.GetStatusApi(false, _curPost.StatusId);
+                    var post = await tw.GetStatusApi(false, currentPost.StatusId);
 
-                    _curPost.InReplyToStatusId = post.InReplyToStatusId;
-                    _curPost.InReplyToUser = post.InReplyToUser;
-                    _curPost.IsReply = post.IsReply;
+                    currentPost.InReplyToStatusId = post.InReplyToStatusId;
+                    currentPost.InReplyToUser = post.InReplyToUser;
+                    currentPost.IsReply = post.IsReply;
                     this.PurgeListViewItemCache();
-                    _curList.RedrawItems(_curItemIndex, _curItemIndex, false);
+
+                    var index = curTabClass.SelectedIndex;
+                    this.CurrentListView.RedrawItems(index, index, false);
                 }
                 catch (WebApiException ex)
                 {
@@ -6860,21 +6717,20 @@ namespace OpenTween
                 }
             }
 
-            if (!(this.ExistCurrentPost && _curPost.InReplyToUser != null && _curPost.InReplyToStatusId != null)) return;
+            if (!(this.ExistCurrentPost && currentPost.InReplyToUser != null && currentPost.InReplyToStatusId != null)) return;
 
-            if (replyChains == null || (replyChains.Count > 0 && replyChains.Peek().InReplyToId != _curPost.StatusId))
+            if (replyChains == null || (replyChains.Count > 0 && replyChains.Peek().InReplyToId != currentPost.StatusId))
             {
                 replyChains = new Stack<ReplyChain>();
             }
-            replyChains.Push(new ReplyChain(_curPost.StatusId, _curPost.InReplyToStatusId.Value, _curTab));
+            replyChains.Push(new ReplyChain(currentPost.StatusId, currentPost.InReplyToStatusId.Value, curTabClass));
 
             int inReplyToIndex;
             string inReplyToTabName;
-            long inReplyToId = _curPost.InReplyToStatusId.Value;
-            string inReplyToUser = _curPost.InReplyToUser;
-            //Dictionary<long, PostClass> curTabPosts = curTabClass.Posts;
+            var inReplyToId = currentPost.InReplyToStatusId.Value;
+            var inReplyToUser = currentPost.InReplyToUser;
 
-            var inReplyToPosts = from tab in _statuses.Tabs.Values
+            var inReplyToPosts = from tab in _statuses.Tabs
                                  orderby tab != curTabClass
                                  from post in tab.Posts.Values
                                  where post.StatusId == inReplyToId
@@ -6889,7 +6745,7 @@ namespace OpenTween
                 {
                     await Task.Run(async () =>
                     {
-                        var post = await tw.GetStatusApi(false, _curPost.InReplyToStatusId.Value)
+                        var post = await tw.GetStatusApi(false, currentPost.InReplyToStatusId.Value)
                             .ConfigureAwait(false);
                         post.IsRead = true;
 
@@ -6919,7 +6775,7 @@ namespace OpenTween
             TabPage tabPage = this.ListTab.TabPages.Cast<TabPage>().First((tp) => { return tp.Text == inReplyToTabName; });
             DetailsListView listView = (DetailsListView)tabPage.Tag;
 
-            if (_curTab != tabPage)
+            if (this.CurrentTabName != inReplyToTabName)
             {
                 this.ListTab.SelectTab(tabPage);
             }
@@ -6930,23 +6786,24 @@ namespace OpenTween
 
         private void GoBackInReplyToPostTree(bool parallel = false, bool isForward = true)
         {
-            if (_curPost == null) return;
+            var curTabClass = this.CurrentTab;
+            var currentPost = this.CurrentPost;
 
-            TabModel curTabClass = _statuses.Tabs[_curTab.Text];
-            //Dictionary<long, PostClass> curTabPosts = curTabClass.Posts;
+            if (currentPost == null)
+                return;
 
             if (parallel)
             {
-                if (_curPost.InReplyToStatusId != null)
+                if (currentPost.InReplyToStatusId != null)
                 {
                     var posts = from t in _statuses.Tabs
-                                from p in t.Value.Posts
-                                where p.Value.StatusId != _curPost.StatusId && p.Value.InReplyToStatusId == _curPost.InReplyToStatusId
-                                let indexOf = t.Value.IndexOf(p.Value.StatusId)
+                                from p in t.Posts
+                                where p.Value.StatusId != currentPost.StatusId && p.Value.InReplyToStatusId == currentPost.InReplyToStatusId
+                                let indexOf = t.IndexOf(p.Value.StatusId)
                                 where indexOf > -1
                                 orderby isForward ? indexOf : indexOf * -1
-                                orderby t.Value != curTabClass
-                                select new {Tab = t.Value, Post = p.Value, Index = indexOf};
+                                orderby t != curTabClass
+                                select new {Tab = t, Post = p.Value, Index = indexOf};
                     try
                     {
                         var postList = posts.ToList();
@@ -6958,11 +6815,12 @@ namespace OpenTween
                                 postList.RemoveAt(index);
                             }
                         }
-                        var post = postList.FirstOrDefault((pst) => { return pst.Tab == curTabClass && isForward ? pst.Index > _curItemIndex : pst.Index < _curItemIndex; });
+                        var currentIndex = this.CurrentTab.SelectedIndex;
+                        var post = postList.FirstOrDefault((pst) => { return pst.Tab == curTabClass && isForward ? pst.Index > currentIndex : pst.Index < currentIndex; });
                         if (post == null) post = postList.FirstOrDefault((pst) => { return pst.Tab != curTabClass; });
                         if (post == null) post = postList.First();
                         this.ListTab.SelectTab(this.ListTab.TabPages.Cast<TabPage>().First((tp) => { return tp.Text == post.Tab.TabName; }));
-                        DetailsListView listView = (DetailsListView)this.ListTab.SelectedTab.Tag;
+                        var listView = this.CurrentListView;
                         SelectListItem(listView, post.Index);
                         listView.EnsureVisible(post.Index);
                     }
@@ -6977,18 +6835,18 @@ namespace OpenTween
                 if (replyChains == null || replyChains.Count < 1)
                 {
                     var posts = from t in _statuses.Tabs
-                                from p in t.Value.Posts
-                                where p.Value.InReplyToStatusId == _curPost.StatusId
-                                let indexOf = t.Value.IndexOf(p.Value.StatusId)
+                                from p in t.Posts
+                                where p.Value.InReplyToStatusId == currentPost.StatusId
+                                let indexOf = t.IndexOf(p.Value.StatusId)
                                 where indexOf > -1
                                 orderby indexOf
-                                orderby t.Value != curTabClass
-                                select new {Tab = t.Value, Index = indexOf};
+                                orderby t != curTabClass
+                                select new {Tab = t, Index = indexOf};
                     try
                     {
                         var post = posts.First();
                         this.ListTab.SelectTab(this.ListTab.TabPages.Cast<TabPage>().First((tp) => { return tp.Text == post.Tab.TabName; }));
-                        DetailsListView listView = (DetailsListView)this.ListTab.SelectedTab.Tag;
+                        var listView = this.CurrentListView;
                         SelectListItem(listView, post.Index);
                         listView.EnsureVisible(post.Index);
                     }
@@ -7000,25 +6858,35 @@ namespace OpenTween
                 else
                 {
                     ReplyChain chainHead = replyChains.Pop();
-                    if (chainHead.InReplyToId == _curPost.StatusId)
+                    if (chainHead.InReplyToId == currentPost.StatusId)
                     {
-                        int idx = _statuses.Tabs[chainHead.OriginalTab.Text].IndexOf(chainHead.OriginalId);
-                        if (idx == -1)
+                        var tab = chainHead.OriginalTab;
+                        if (!this._statuses.Tabs.Contains(tab))
                         {
                             replyChains = null;
                         }
                         else
                         {
-                            try
+                            var idx = tab.IndexOf(chainHead.OriginalId);
+                            if (idx == -1)
                             {
-                                ListTab.SelectTab(chainHead.OriginalTab);
+                                replyChains = null;
                             }
-                            catch (Exception)
+                            else
                             {
-                                replyChains = null;
+                                var tabPage = this.ListTab.TabPages.Cast<TabPage>().First(x => x.Text == tab.TabName);
+                                try
+                                {
+                                    ListTab.SelectTab(tabPage);
+                                }
+                                catch (Exception)
+                                {
+                                    replyChains = null;
+                                }
+                                var listView = this.CurrentListView;
+                                SelectListItem(listView, idx);
+                                listView.EnsureVisible(idx);
                             }
-                            SelectListItem(_curList, idx);
-                            _curList.EnsureVisible(idx);
                         }
                     }
                     else
@@ -7035,24 +6903,25 @@ namespace OpenTween
             if (this.selectPostChains.Count > 1)
             {
                 var idx = -1;
-                TabPage tp = null;
+                TabModel foundTab = null;
 
                 do
                 {
                     try
                     {
                         this.selectPostChains.Pop();
-                        var tabPostPair = this.selectPostChains.Peek();
+                        var (tab, post) = this.selectPostChains.Peek();
 
-                        if (!this.ListTab.TabPages.Contains(tabPostPair.Item1)) continue;  //該当タブが存在しないので無視
+                        if (!this._statuses.Tabs.Contains(tab))
+                            continue; // 該当タブが存在しないので無視
 
-                        if (tabPostPair.Item2 != null)
+                        if (post != null)
                         {
-                            idx = this._statuses.Tabs[tabPostPair.Item1.Text].IndexOf(tabPostPair.Item2.StatusId);
+                            idx = tab.IndexOf(post.StatusId);
                             if (idx == -1) continue;  //該当ポストが存在しないので無視
                         }
 
-                        tp = tabPostPair.Item1;
+                        foundTab = tab;
 
                         this.selectPostChains.Pop();
                     }
@@ -7064,7 +6933,7 @@ namespace OpenTween
                 }
                 while (this.selectPostChains.Count > 1);
 
-                if (tp == null)
+                if (foundTab == null)
                 {
                     //状態がおかしいので処理を中断
                     //履歴が残り1つであればクリアしておく
@@ -7073,8 +6942,10 @@ namespace OpenTween
                     return;
                 }
 
-                DetailsListView lst = (DetailsListView)tp.Tag;
-                this.ListTab.SelectedTab = tp;
+                var tabPage = this.ListTab.TabPages.Cast<TabPage>().First(x => x.Text == foundTab.TabName);
+                var lst = (DetailsListView)tabPage.Tag;
+                this.ListTab.SelectedTab = tabPage;
+
                 if (idx > -1)
                 {
                     SelectListItem(lst, idx);
@@ -7086,24 +6957,27 @@ namespace OpenTween
 
         private void PushSelectPostChain()
         {
+            var currentTab = this.CurrentTab;
+            var currentPost = this.CurrentPost;
+
             int count = this.selectPostChains.Count;
             if (count > 0)
             {
-                var p = this.selectPostChains.Peek();
-                if (p.Item1 == this._curTab)
+                var (tab, post) = this.selectPostChains.Peek();
+                if (tab == currentTab)
                 {
-                    if (p.Item2 == this._curPost) return;  //最新の履歴と同一
-                    if (p.Item2 == null) this.selectPostChains.Pop();  //置き換えるため削除
+                    if (post == currentPost) return;  //最新の履歴と同一
+                    if (post == null) this.selectPostChains.Pop();  //置き換えるため削除
                 }
             }
             if (count >= 2500) TrimPostChain();
-            this.selectPostChains.Push(Tuple.Create(this._curTab, this._curPost));
+            this.selectPostChains.Push((currentTab, currentPost));
         }
 
         private void TrimPostChain()
         {
             if (this.selectPostChains.Count <= 2000) return;
-            var p = new Stack<Tuple<TabPage, PostClass>>(2000);
+            var p = new Stack<(TabModel, PostClass)>(2000);
             for (int i = 0; i < 2000; i++)
             {
                 p.Push(this.selectPostChains.Pop());
@@ -7118,41 +6992,49 @@ namespace OpenTween
         private bool GoStatus(long statusId)
         {
             if (statusId == 0) return false;
-            for (int tabidx = 0; tabidx < ListTab.TabCount; tabidx++)
-            {
-                if (_statuses.Tabs[ListTab.TabPages[tabidx].Text].TabType != MyCommon.TabUsageType.DirectMessage && _statuses.Tabs[ListTab.TabPages[tabidx].Text].Contains(statusId))
-                {
-                    int idx = _statuses.Tabs[ListTab.TabPages[tabidx].Text].IndexOf(statusId);
-                    ListTab.SelectedIndex = tabidx;
-                    SelectListItem(_curList, idx);
-                    _curList.EnsureVisible(idx);
-                    return true;
-                }
-            }
-            return false;
+
+            var tab = this._statuses.Tabs
+                .Where(x => x.TabType != MyCommon.TabUsageType.DirectMessage)
+                .Where(x => x.Contains(statusId))
+                .FirstOrDefault();
+
+            if (tab == null)
+                return false;
+
+            var index = tab.IndexOf(statusId);
+
+            var tabPage = this.ListTab.TabPages.Cast<TabPage>().First(x => x.Text == tab.TabName);
+            this.ListTab.SelectedTab = tabPage;
+
+            var listView = this.CurrentListView;
+            this.SelectListItem(listView, index);
+            listView.EnsureVisible(index);
+
+            return true;
         }
 
         private bool GoDirectMessage(long statusId)
         {
             if (statusId == 0) return false;
-            for (int tabidx = 0; tabidx < ListTab.TabCount; tabidx++)
-            {
-                if (_statuses.Tabs[ListTab.TabPages[tabidx].Text].TabType == MyCommon.TabUsageType.DirectMessage && _statuses.Tabs[ListTab.TabPages[tabidx].Text].Contains(statusId))
-                {
-                    int idx = _statuses.Tabs[ListTab.TabPages[tabidx].Text].IndexOf(statusId);
-                    ListTab.SelectedIndex = tabidx;
-                    SelectListItem(_curList, idx);
-                    _curList.EnsureVisible(idx);
-                    return true;
-                }
-            }
-            return false;
+
+            var tab = this._statuses.GetTabByType<DirectMessagesTabModel>();
+            var index = tab.IndexOf(statusId);
+
+            if (index == -1)
+                return false;
+
+            var tabPage = this.ListTab.TabPages.Cast<TabPage>().First(x => x.Text == tab.TabName);
+            this.ListTab.SelectedTab = tabPage;
+
+            var listView = this.CurrentListView;
+            this.SelectListItem(listView, index);
+            listView.EnsureVisible(index);
+
+            return true;
         }
 
         private void MyList_MouseClick(object sender, MouseEventArgs e)
-        {
-            _anchorFlag = false;
-        }
+            => this._anchorFlag = false;
 
         private void StatusText_Enter(object sender, EventArgs e)
         {
@@ -7163,8 +7045,8 @@ namespace OpenTween
 
         public Color InputBackColor
         {
-            get { return _clInputBackcolor; }
-            set { _clInputBackcolor = value; }
+            get => _clInputBackcolor;
+            set => _clInputBackcolor = value;
         }
 
         private void StatusText_Leave(object sender, EventArgs e)
@@ -7176,8 +7058,7 @@ namespace OpenTween
 
         private async void StatusText_KeyDown(object sender, KeyEventArgs e)
         {
-            Task asyncTask;
-            if (CommonKeyDown(e.KeyData, FocusedControl.StatusText, out asyncTask))
+            if (CommonKeyDown(e.KeyData, FocusedControl.StatusText, out var asyncTask))
             {
                 e.Handled = true;
                 e.SuppressKeyPress = true;
@@ -7208,11 +7089,11 @@ namespace OpenTween
 
         private void SaveConfigsAtId()
         {
-            if (_ignoreConfigSave || !this._cfgCommon.UseAtIdSupplement && AtIdSupl == null) return;
+            if (_ignoreConfigSave || !SettingManager.Common.UseAtIdSupplement && AtIdSupl == null) return;
 
             ModifySettingAtId = false;
-            SettingAtIdList cfgAtId = new SettingAtIdList(AtIdSupl.GetItemList());
-            cfgAtId.Save();
+            SettingManager.AtIdList.AtIdList = this.AtIdSupl.GetItemList();
+            SettingManager.SaveAtIdList();
         }
 
         private void SaveConfigsCommon()
@@ -7222,60 +7103,48 @@ namespace OpenTween
             ModifySettingCommon = false;
             lock (_syncObject)
             {
-                _cfgCommon.UserName = tw.Username;
-                _cfgCommon.UserId = tw.UserId;
-                _cfgCommon.Token = tw.AccessToken;
-                _cfgCommon.TokenSecret = tw.AccessTokenSecret;
-
-                if (IdeographicSpaceToSpaceToolStripMenuItem != null &&
-                   IdeographicSpaceToSpaceToolStripMenuItem.IsDisposed == false)
-                {
-                    _cfgCommon.WideSpaceConvert = this.IdeographicSpaceToSpaceToolStripMenuItem.Checked;
-                }
-
-                _cfgCommon.SortOrder = (int)_statuses.SortOrder;
+                SettingManager.Common.UserName = tw.Username;
+                SettingManager.Common.UserId = tw.UserId;
+                SettingManager.Common.Token = tw.AccessToken;
+                SettingManager.Common.TokenSecret = tw.AccessTokenSecret;
+                SettingManager.Common.SortOrder = (int)_statuses.SortOrder;
                 switch (_statuses.SortMode)
                 {
                     case ComparerMode.Nickname:  //ニックネーム
-                        _cfgCommon.SortColumn = 1;
+                        SettingManager.Common.SortColumn = 1;
                         break;
                     case ComparerMode.Data:  //本文
-                        _cfgCommon.SortColumn = 2;
+                        SettingManager.Common.SortColumn = 2;
                         break;
                     case ComparerMode.Id:  //時刻=発言Id
-                        _cfgCommon.SortColumn = 3;
+                        SettingManager.Common.SortColumn = 3;
                         break;
                     case ComparerMode.Name:  //名前
-                        _cfgCommon.SortColumn = 4;
+                        SettingManager.Common.SortColumn = 4;
                         break;
                     case ComparerMode.Source:  //Source
-                        _cfgCommon.SortColumn = 7;
+                        SettingManager.Common.SortColumn = 7;
                         break;
                 }
 
-                _cfgCommon.HashTags = HashMgr.HashHistories;
+                SettingManager.Common.HashTags = HashMgr.HashHistories;
                 if (HashMgr.IsPermanent)
                 {
-                    _cfgCommon.HashSelected = HashMgr.UseHash;
+                    SettingManager.Common.HashSelected = HashMgr.UseHash;
                 }
                 else
                 {
-                    _cfgCommon.HashSelected = "";
-                }
-                _cfgCommon.HashIsHead = HashMgr.IsHead;
-                _cfgCommon.HashIsPermanent = HashMgr.IsPermanent;
-                _cfgCommon.HashIsNotAddToAtReply = HashMgr.IsNotAddToAtReply;
-                if (ToolStripFocusLockMenuItem != null &&
-                        ToolStripFocusLockMenuItem.IsDisposed == false)
-                {
-                    _cfgCommon.FocusLockToStatusText = this.ToolStripFocusLockMenuItem.Checked;
+                    SettingManager.Common.HashSelected = "";
                 }
-                _cfgCommon.TrackWord = tw.TrackWord;
-                _cfgCommon.AllAtReply = tw.AllAtReply;
-                _cfgCommon.UseImageService = ImageSelector.ServiceIndex;
-                _cfgCommon.UseImageServiceName = ImageSelector.ServiceName;
+                SettingManager.Common.HashIsHead = HashMgr.IsHead;
+                SettingManager.Common.HashIsPermanent = HashMgr.IsPermanent;
+                SettingManager.Common.HashIsNotAddToAtReply = HashMgr.IsNotAddToAtReply;
+                SettingManager.Common.TrackWord = tw.TrackWord;
+                SettingManager.Common.AllAtReply = tw.AllAtReply;
+                SettingManager.Common.UseImageService = ImageSelector.ServiceIndex;
+                SettingManager.Common.UseImageServiceName = ImageSelector.ServiceName;
 
-                _cfgCommon.Save();
+                SettingManager.SaveCommon();
             }
         }
 
@@ -7285,48 +7154,48 @@ namespace OpenTween
             lock (_syncObject)
             {
                 ModifySettingLocal = false;
-                _cfgLocal.ScaleDimension = this.CurrentAutoScaleDimensions;
-                _cfgLocal.FormSize = _mySize;
-                _cfgLocal.FormLocation = _myLoc;
-                _cfgLocal.SplitterDistance = _mySpDis;
-                _cfgLocal.PreviewDistance = _mySpDis3;
-                _cfgLocal.StatusMultiline = StatusText.Multiline;
-                _cfgLocal.StatusTextHeight = _mySpDis2;
-
-                _cfgLocal.FontUnread = _fntUnread;
-                _cfgLocal.ColorUnread = _clUnread;
-                _cfgLocal.FontRead = _fntReaded;
-                _cfgLocal.ColorRead = _clReaded;
-                _cfgLocal.FontDetail = _fntDetail;
-                _cfgLocal.ColorDetail = _clDetail;
-                _cfgLocal.ColorDetailBackcolor = _clDetailBackcolor;
-                _cfgLocal.ColorDetailLink = _clDetailLink;
-                _cfgLocal.ColorFav = _clFav;
-                _cfgLocal.ColorOWL = _clOWL;
-                _cfgLocal.ColorRetweet = _clRetweet;
-                _cfgLocal.ColorSelf = _clSelf;
-                _cfgLocal.ColorAtSelf = _clAtSelf;
-                _cfgLocal.ColorTarget = _clTarget;
-                _cfgLocal.ColorAtTarget = _clAtTarget;
-                _cfgLocal.ColorAtFromTarget = _clAtFromTarget;
-                _cfgLocal.ColorAtTo = _clAtTo;
-                _cfgLocal.ColorListBackcolor = _clListBackcolor;
-                _cfgLocal.ColorInputBackcolor = _clInputBackcolor;
-                _cfgLocal.ColorInputFont = _clInputFont;
-                _cfgLocal.FontInputFont = _fntInputFont;
+                SettingManager.Local.ScaleDimension = this.CurrentAutoScaleDimensions;
+                SettingManager.Local.FormSize = _mySize;
+                SettingManager.Local.FormLocation = _myLoc;
+                SettingManager.Local.SplitterDistance = _mySpDis;
+                SettingManager.Local.PreviewDistance = _mySpDis3;
+                SettingManager.Local.StatusMultiline = StatusText.Multiline;
+                SettingManager.Local.StatusTextHeight = _mySpDis2;
+
+                SettingManager.Local.FontUnread = _fntUnread;
+                SettingManager.Local.ColorUnread = _clUnread;
+                SettingManager.Local.FontRead = _fntReaded;
+                SettingManager.Local.ColorRead = _clReaded;
+                SettingManager.Local.FontDetail = _fntDetail;
+                SettingManager.Local.ColorDetail = _clDetail;
+                SettingManager.Local.ColorDetailBackcolor = _clDetailBackcolor;
+                SettingManager.Local.ColorDetailLink = _clDetailLink;
+                SettingManager.Local.ColorFav = _clFav;
+                SettingManager.Local.ColorOWL = _clOWL;
+                SettingManager.Local.ColorRetweet = _clRetweet;
+                SettingManager.Local.ColorSelf = _clSelf;
+                SettingManager.Local.ColorAtSelf = _clAtSelf;
+                SettingManager.Local.ColorTarget = _clTarget;
+                SettingManager.Local.ColorAtTarget = _clAtTarget;
+                SettingManager.Local.ColorAtFromTarget = _clAtFromTarget;
+                SettingManager.Local.ColorAtTo = _clAtTo;
+                SettingManager.Local.ColorListBackcolor = _clListBackcolor;
+                SettingManager.Local.ColorInputBackcolor = _clInputBackcolor;
+                SettingManager.Local.ColorInputFont = _clInputFont;
+                SettingManager.Local.FontInputFont = _fntInputFont;
 
                 if (_ignoreConfigSave) return;
-                _cfgLocal.Save();
+                SettingManager.SaveLocal();
             }
         }
 
         private void SaveConfigsTabs()
         {
-            var tabsSetting = new SettingTabs();
+            var tabSettingList = new List<SettingTabs.SettingTabItem>();
 
             var tabs = this.ListTab.TabPages.Cast<TabPage>()
                 .Select(x => this._statuses.Tabs[x.Text])
-                .Concat(new[] { this._statuses.GetTabByType(MyCommon.TabUsageType.Mute) });
+                .Append(this._statuses.GetTabByType(MyCommon.TabUsageType.Mute));
 
             foreach (var tab in tabs)
             {
@@ -7343,35 +7212,33 @@ namespace OpenTween
                     SoundFile = tab.SoundFile,
                 };
 
-                var filterTab = tab as FilterTabModel;
-                if (filterTab != null)
-                    tabSetting.FilterArray = filterTab.FilterArray;
-
-                var userTab = tab as UserTimelineTabModel;
-                if (userTab != null)
-                    tabSetting.User = userTab.ScreenName;
-
-                var searchTab = tab as PublicSearchTabModel;
-                if (searchTab != null)
+                switch (tab)
                 {
-                    tabSetting.SearchWords = searchTab.SearchWords;
-                    tabSetting.SearchLang = searchTab.SearchLang;
+                    case FilterTabModel filterTab:
+                        tabSetting.FilterArray = filterTab.FilterArray;
+                        break;
+                    case UserTimelineTabModel userTab:
+                        tabSetting.User = userTab.ScreenName;
+                        break;
+                    case PublicSearchTabModel searchTab:
+                        tabSetting.SearchWords = searchTab.SearchWords;
+                        tabSetting.SearchLang = searchTab.SearchLang;
+                        break;
+                    case ListTimelineTabModel listTab:
+                        tabSetting.ListInfo = listTab.ListInfo;
+                        break;
                 }
 
-                var listTab = tab as ListTimelineTabModel;
-                if (listTab != null)
-                    tabSetting.ListInfo = listTab.ListInfo;
-
-                tabsSetting.Tabs.Add(tabSetting);
+                tabSettingList.Add(tabSetting);
             }
 
-            tabsSetting.Save();
+            SettingManager.Tabs.Tabs = tabSettingList;
+            SettingManager.SaveTabs();
         }
 
         private async void OpenURLFileMenuItem_Click(object sender, EventArgs e)
         {
-            string inputText;
-            var ret = InputDialog.Show(this, Properties.Resources.OpenURL_InputText, Properties.Resources.OpenURL_Caption, out inputText);
+            var ret = InputDialog.Show(this, Properties.Resources.OpenURL_InputText, Properties.Resources.OpenURL_Caption, out var inputText);
             if (ret != DialogResult.OK)
                 return;
 
@@ -7390,18 +7257,20 @@ namespace OpenTween
             }
             catch (TabException ex)
             {
-                MessageBox.Show(this, ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
+                MessageBox.Show(this, ex.Message, ApplicationSettings.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Error);
             }
         }
 
         private void SaveLogMenuItem_Click(object sender, EventArgs e)
         {
+            var tab = this.CurrentTab;
+
             DialogResult rslt = MessageBox.Show(string.Format(Properties.Resources.SaveLogMenuItem_ClickText1, Environment.NewLine),
                     Properties.Resources.SaveLogMenuItem_ClickText2,
                     MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
             if (rslt == DialogResult.Cancel) return;
 
-            SaveFileDialog1.FileName = MyCommon.GetAssemblyName() + "Posts" + DateTime.Now.ToString("yyMMdd-HHmmss") + ".tsv";
+            SaveFileDialog1.FileName = $"{ApplicationSettings.AssemblyName}Posts{DateTimeUtc.Now.ToLocalTime():yyMMdd-HHmmss}.tsv";
             SaveFileDialog1.InitialDirectory = Application.ExecutablePath;
             SaveFileDialog1.Filter = Properties.Resources.SaveLogMenuItem_ClickText3;
             SaveFileDialog1.FilterIndex = 0;
@@ -7416,14 +7285,14 @@ namespace OpenTween
                     if (rslt == DialogResult.Yes)
                     {
                         //All
-                        for (int idx = 0; idx < _curList.VirtualListSize; idx++)
+                        for (int idx = 0; idx < tab.AllCount; idx++)
                         {
-                            PostClass post = _statuses.Tabs[_curTab.Text][idx];
+                            var post = tab[idx];
                             string protect = "";
                             if (post.IsProtect) protect = "Protect";
                             sw.WriteLine(post.Nickname + "\t" +
                                      "\"" + post.TextFromApi.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
-                                     post.CreatedAt + "\t" +
+                                     post.CreatedAt.ToLocalTimeString() + "\t" +
                                      post.ScreenName + "\t" +
                                      post.StatusId + "\t" +
                                      post.ImageUrl + "\t" +
@@ -7433,14 +7302,13 @@ namespace OpenTween
                     }
                     else
                     {
-                        foreach (int idx in _curList.SelectedIndices)
+                        foreach (var post in this.CurrentTab.SelectedPosts)
                         {
-                            PostClass post = _statuses.Tabs[_curTab.Text][idx];
                             string protect = "";
                             if (post.IsProtect) protect = "Protect";
                             sw.WriteLine(post.Nickname + "\t" +
                                      "\"" + post.TextFromApi.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
-                                     post.CreatedAt + "\t" +
+                                     post.CreatedAt.ToLocalTimeString() + "\t" +
                                      post.ScreenName + "\t" +
                                      post.StatusId + "\t" +
                                      post.ImageUrl + "\t" +
@@ -7450,7 +7318,7 @@ namespace OpenTween
                     }
                 }
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
         }
 
         public bool TabRename(string origTabName, out string newTabName)
@@ -7464,7 +7332,7 @@ namespace OpenTween
                 if (inputName.DialogResult == DialogResult.Cancel) return false;
                 newTabName = inputName.TabName;
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
             if (!string.IsNullOrEmpty(newTabName))
             {
                 //新タブ名存在チェック
@@ -7515,14 +7383,11 @@ namespace OpenTween
         }
 
         private void ListTab_DoubleClick(object sender, MouseEventArgs e)
-        {
-            string _;
-            TabRename(this.ListTab.SelectedTab.Text, out _);
-        }
+            => this.TabRename(this.CurrentTabName, out var _);
 
         private void ListTab_MouseDown(object sender, MouseEventArgs e)
         {
-            if (this._cfgCommon.TabMouseLock) return;
+            if (SettingManager.Common.TabMouseLock) return;
             if (e.Button == MouseButtons.Left)
             {
                 for (int i = 0; i < ListTab.TabPages.Count; i++)
@@ -7601,16 +7466,18 @@ namespace OpenTween
 
             using (ControlTransaction.Layout(this.ListTab))
             {
-                var mTp = this.ListTab.TabPages[targetIndex];
-                this.ListTab.TabPages.Remove(mTp);
+                var tab = this._statuses.Tabs[targetIndex];
+                var tabPage = this.ListTab.TabPages[targetIndex];
+                this.ListTab.TabPages.Remove(tabPage);
 
                 if (targetIndex < baseIndex)
                     baseIndex--;
 
-                if (isBeforeBaseTab)
-                    ListTab.TabPages.Insert(baseIndex, mTp);
-                else
-                    ListTab.TabPages.Insert(baseIndex + 1, mTp);
+                if (!isBeforeBaseTab)
+                    baseIndex++;
+
+                this._statuses.MoveTab(baseIndex, tab);
+                ListTab.TabPages.Insert(baseIndex, tabPage);
             }
 
             SaveConfigsTabs();
@@ -7621,40 +7488,42 @@ namespace OpenTween
             //isAuto:true=先頭に挿入、false=カーソル位置に挿入
             //isReply:true=@,false=DM
             if (!StatusText.Enabled) return;
-            if (_curList == null) return;
-            if (_curTab == null) return;
             if (!this.ExistCurrentPost) return;
 
+            var tab = this.CurrentTab;
+            var selectedPosts = tab.SelectedPosts;
+
             // 複数あてリプライはReplyではなく通常ポスト
             //↑仕様変更で全部リプライ扱いでOK(先頭ドット付加しない)
             //090403暫定でドットを付加しないようにだけ修正。単独と複数の処理は統合できると思われる。
             //090513 all @ replies 廃止の仕様変更によりドット付加に戻し(syo68k)
 
-            if (_curList.SelectedIndices.Count > 0)
+            if (selectedPosts.Length > 0)
             {
                 // アイテムが1件以上選択されている
-                if (_curList.SelectedIndices.Count == 1 && !isAll && this.ExistCurrentPost)
+                if (selectedPosts.Length == 1 && !isAll && this.ExistCurrentPost)
                 {
+                    var post = selectedPosts.Single();
+
                     // 単独ユーザー宛リプライまたはDM
-                    if ((_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.DirectMessage && isAuto) || (!isAuto && !isReply))
+                    if ((tab.TabType == MyCommon.TabUsageType.DirectMessage && isAuto) || (!isAuto && !isReply))
                     {
                         // ダイレクトメッセージ
-                        StatusText.Text = "D " + _curPost.ScreenName + " " + StatusText.Text;
+                        this.inReplyTo = null;
+                        StatusText.Text = "D " + post.ScreenName + " " + StatusText.Text;
                         StatusText.SelectionStart = StatusText.Text.Length;
                         StatusText.Focus();
-                        this.inReplyTo = null;
                         return;
                     }
                     if (string.IsNullOrEmpty(StatusText.Text))
                     {
                         //空の場合
+                        var inReplyToStatusId = post.RetweetedId ?? post.StatusId;
+                        var inReplyToScreenName = post.ScreenName;
+                        this.inReplyTo = (inReplyToStatusId, inReplyToScreenName);
 
                         // ステータステキストが入力されていない場合先頭に@ユーザー名を追加する
-                        StatusText.Text = "@" + _curPost.ScreenName + " ";
-
-                        var inReplyToStatusId = this._curPost.RetweetedId ?? this._curPost.StatusId;
-                        var inReplyToScreenName = this._curPost.ScreenName;
-                        this.inReplyTo = Tuple.Create(inReplyToStatusId, inReplyToScreenName);
+                        StatusText.Text = "@" + post.ScreenName + " ";
                     }
                     else
                     {
@@ -7663,14 +7532,14 @@ namespace OpenTween
                         if (isAuto)
                         {
                             //1件選んでEnter or DoubleClick
-                            if (StatusText.Text.Contains("@" + _curPost.ScreenName + " "))
+                            if (StatusText.Text.Contains("@" + post.ScreenName + " "))
                             {
-                                if (this.inReplyTo?.Item2 == _curPost.ScreenName)
+                                if (this.inReplyTo?.ScreenName == post.ScreenName)
                                 {
                                     //返信先書き換え
-                                    var inReplyToStatusId = this._curPost.RetweetedId ?? this._curPost.StatusId;
-                                    var inReplyToScreenName = this._curPost.ScreenName;
-                                    this.inReplyTo = Tuple.Create(inReplyToStatusId, inReplyToScreenName);
+                                    var inReplyToStatusId = post.RetweetedId ?? post.StatusId;
+                                    var inReplyToScreenName = post.ScreenName;
+                                    this.inReplyTo = (inReplyToStatusId, inReplyToScreenName);
                                 }
                                 return;
                             }
@@ -7680,32 +7549,31 @@ namespace OpenTween
                                 if (StatusText.Text.StartsWith(". ", StringComparison.Ordinal))
                                 {
                                     // 複数リプライ
-                                    StatusText.Text = StatusText.Text.Insert(2, "@" + _curPost.ScreenName + " ");
                                     this.inReplyTo = null;
+                                    StatusText.Text = StatusText.Text.Insert(2, "@" + post.ScreenName + " ");
                                 }
                                 else
                                 {
                                     // 単独リプライ
-                                    StatusText.Text = "@" + _curPost.ScreenName + " " + StatusText.Text;
-                                    var inReplyToStatusId = this._curPost.RetweetedId ?? this._curPost.StatusId;
-                                    var inReplyToScreenName = this._curPost.ScreenName;
-                                    this.inReplyTo = Tuple.Create(inReplyToStatusId, inReplyToScreenName);
+                                    var inReplyToStatusId = post.RetweetedId ?? post.StatusId;
+                                    var inReplyToScreenName = post.ScreenName;
+                                    this.inReplyTo = (inReplyToStatusId, inReplyToScreenName);
+                                    StatusText.Text = "@" + post.ScreenName + " " + StatusText.Text;
                                 }
                             }
                             else
                             {
                                 //文頭@
                                 // 複数リプライ
-                                StatusText.Text = ". @" + _curPost.ScreenName + " " + StatusText.Text;
-                                //StatusText.Text = "@" + _curPost.ScreenName + " " + StatusText.Text;
                                 this.inReplyTo = null;
+                                StatusText.Text = ". @" + post.ScreenName + " " + StatusText.Text;
                             }
                         }
                         else
                         {
                             //1件選んでCtrl-Rの場合(返信先操作せず)
                             int sidx = StatusText.SelectionStart;
-                            string id = "@" + _curPost.ScreenName + " ";
+                            string id = "@" + post.ScreenName + " ";
                             if (sidx > 0)
                             {
                                 if (StatusText.Text.Substring(sidx - 1, 1) != " ")
@@ -7752,9 +7620,8 @@ namespace OpenTween
                             sTxt = ". " + sTxt;
                             this.inReplyTo = null;
                         }
-                        for (int cnt = 0; cnt < _curList.SelectedIndices.Count; cnt++)
+                        foreach (var post in selectedPosts)
                         {
-                            PostClass post = _statuses.Tabs[_curTab.Text][_curList.SelectedIndices[cnt]];
                             if (!sTxt.Contains("@" + post.ScreenName + " "))
                             {
                                 sTxt = sTxt.Insert(2, "@" + post.ScreenName + " ");
@@ -7766,32 +7633,31 @@ namespace OpenTween
                     else
                     {
                         //C-S-r or C-r
-                        if (_curList.SelectedIndices.Count > 1)
+
+                        if (selectedPosts.Length > 1)
                         {
                             //複数ポスト選択
 
                             string ids = "";
                             int sidx = StatusText.SelectionStart;
-                            for (int cnt = 0; cnt < _curList.SelectedIndices.Count; cnt++)
+                            foreach (var post in selectedPosts)
                             {
-                                PostClass post = _statuses.Tabs[_curTab.Text][_curList.SelectedIndices[cnt]];
-                                if (!ids.Contains("@" + post.ScreenName + " ") &&
-                                    !post.ScreenName.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
+                                if (!ids.Contains("@" + post.ScreenName + " ") && post.UserId != tw.UserId)
                                 {
                                     ids += "@" + post.ScreenName + " ";
                                 }
                                 if (isAll)
                                 {
-                                    foreach (string nm in post.ReplyToList)
+                                    foreach (var (_, screenName) in post.ReplyToList)
                                     {
-                                        if (!ids.Contains("@" + nm + " ") &&
-                                            !nm.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
+                                        if (!ids.Contains("@" + screenName + " ") &&
+                                            !screenName.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
                                         {
-                                            Match m = Regex.Match(post.TextFromApi, "[@@](?<id>" + nm + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase);
+                                            Match m = Regex.Match(post.TextFromApi, "[@@](?<id>" + screenName + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase);
                                             if (m.Success)
                                                 ids += "@" + m.Result("${id}") + " ";
                                             else
-                                                ids += "@" + nm + " ";
+                                                ids += "@" + screenName + " ";
                                         }
                                     }
                                 }
@@ -7799,9 +7665,9 @@ namespace OpenTween
                             if (ids.Length == 0) return;
                             if (!StatusText.Text.StartsWith(". ", StringComparison.Ordinal))
                             {
+                                this.inReplyTo = null;
                                 StatusText.Text = ". " + StatusText.Text;
                                 sidx += 2;
-                                this.inReplyTo = null;
                             }
                             if (sidx > 0)
                             {
@@ -7832,28 +7698,26 @@ namespace OpenTween
 
                             string ids = "";
                             int sidx = StatusText.SelectionStart;
-                            PostClass post = _curPost;
-                            if (!ids.Contains("@" + post.ScreenName + " ") &&
-                                !post.ScreenName.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
+                            var post = selectedPosts.Single();
+                            if (!ids.Contains("@" + post.ScreenName + " ") && post.UserId != tw.UserId)
                             {
                                 ids += "@" + post.ScreenName + " ";
                             }
-                            foreach (string nm in post.ReplyToList)
+                            foreach (var (_, screenName) in post.ReplyToList)
                             {
-                                if (!ids.Contains("@" + nm + " ") &&
-                                    !nm.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
+                                if (!ids.Contains("@" + screenName + " ") &&
+                                    !screenName.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
                                 {
-                                    Match m = Regex.Match(post.TextFromApi, "[@@](?<id>" + nm + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase);
+                                    Match m = Regex.Match(post.TextFromApi, "[@@](?<id>" + screenName + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase);
                                     if (m.Success)
                                         ids += "@" + m.Result("${id}") + " ";
                                     else
-                                        ids += "@" + nm + " ";
+                                        ids += "@" + screenName + " ";
                                 }
                             }
                             if (!string.IsNullOrEmpty(post.RetweetedBy))
                             {
-                                if (!ids.Contains("@" + post.RetweetedBy + " ") &&
-                                   !post.RetweetedBy.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
+                                if (!ids.Contains("@" + post.RetweetedBy + " ") && post.RetweetedByUserId != tw.UserId)
                                 {
                                     ids += "@" + post.RetweetedBy + " ";
                                 }
@@ -7862,13 +7726,13 @@ namespace OpenTween
                             if (string.IsNullOrEmpty(StatusText.Text))
                             {
                                 //未入力の場合のみ返信先付加
+                                var inReplyToStatusId = post.RetweetedId ?? post.StatusId;
+                                var inReplyToScreenName = post.ScreenName;
+                                this.inReplyTo = (inReplyToStatusId, inReplyToScreenName);
+
                                 StatusText.Text = ids;
                                 StatusText.SelectionStart = ids.Length;
                                 StatusText.Focus();
-
-                                var inReplyToStatusId = this._curPost.RetweetedId ?? this._curPost.StatusId;
-                                var inReplyToScreenName = this._curPost.ScreenName;
-                                this.inReplyTo = Tuple.Create(inReplyToStatusId, inReplyToScreenName);
                                 return;
                             }
 
@@ -7893,9 +7757,7 @@ namespace OpenTween
         }
 
         private void ListTab_MouseUp(object sender, MouseEventArgs e)
-        {
-            _tabDrag = false;
-        }
+            => this._tabDrag = false;
 
         private static int iconCnt = 0;
         private static int blinkCnt = 0;
@@ -7955,11 +7817,11 @@ namespace OpenTween
             }
 
             TabModel tb = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
-            if (this._cfgCommon.ReplyIconState != MyCommon.REPLY_ICONSTATE.None && tb != null && tb.UnreadCount > 0)
+            if (SettingManager.Common.ReplyIconState != MyCommon.REPLY_ICONSTATE.None && tb != null && tb.UnreadCount > 0)
             {
                 if (blinkCnt > 0) return;
                 blink = !blink;
-                if (blink || this._cfgCommon.ReplyIconState == MyCommon.REPLY_ICONSTATE.StaticIcon)
+                if (blink || SettingManager.Common.ReplyIconState == MyCommon.REPLY_ICONSTATE.StaticIcon)
                 {
                     NotifyIcon1.Icon = ReplyIcon;
                 }
@@ -7991,27 +7853,18 @@ namespace OpenTween
         }
 
         private async void TimerRefreshIcon_Tick(object sender, EventArgs e)
-        {
-            //200ms
-            await this.RefreshTasktrayIcon();
-        }
+            => await this.RefreshTasktrayIcon(); // 200ms
 
         private void ContextMenuTabProperty_Opening(object sender, CancelEventArgs e)
         {
             //右クリックの場合はタブ名が設定済。アプリケーションキーの場合は現在のタブを対象とする
             if (string.IsNullOrEmpty(_rclickTabName) || sender != ContextMenuTabProperty)
-            {
-                if (ListTab != null && ListTab.SelectedTab != null)
-                    _rclickTabName = ListTab.SelectedTab.Text;
-                else
-                    return;
-            }
+                _rclickTabName = this.CurrentTabName;
 
             if (_statuses == null) return;
             if (_statuses.Tabs == null) return;
 
-            TabModel tb;
-            if (!this._statuses.Tabs.TryGetValue(this._rclickTabName, out tb))
+            if (!this._statuses.Tabs.TryGetValue(this._rclickTabName, out var tb))
                 return;
 
             NotifyDispMenuItem.Checked = tb.Notify;
@@ -8113,7 +7966,7 @@ namespace OpenTween
                 return;
 
             _statuses.Tabs[tabName].UnreadManage = isManage;
-            if (this._cfgCommon.TabIconDisp)
+            if (SettingManager.Common.TabIconDisp)
             {
                 if (_statuses.Tabs[tabName].UnreadCount > 0)
                     ListTab.TabPages[idx].ImageIndex = 0;
@@ -8121,15 +7974,15 @@ namespace OpenTween
                     ListTab.TabPages[idx].ImageIndex = -1;
             }
 
-            if (_curTab.Text == tabName)
+            if (this.CurrentTabName == tabName)
             {
                 this.PurgeListViewItemCache();
-                _curList.Refresh();
+                this.CurrentListView.Refresh();
             }
 
             SetMainWindowTitle();
             SetStatusLabelUrl();
-            if (!this._cfgCommon.TabIconDisp) ListTab.Refresh();
+            if (!SettingManager.Common.TabIconDisp) ListTab.Refresh();
         }
 
         private void NotifyDispMenuItem_Click(object sender, EventArgs e)
@@ -8155,7 +8008,8 @@ namespace OpenTween
 
         private void DeleteTabMenuItem_Click(object sender, EventArgs e)
         {
-            if (string.IsNullOrEmpty(_rclickTabName) || sender == this.DeleteTbMenuItem) _rclickTabName = ListTab.SelectedTab.Text;
+            if (string.IsNullOrEmpty(_rclickTabName) || sender == this.DeleteTbMenuItem)
+                _rclickTabName = this.CurrentTabName;
 
             RemoveSpecifiedTab(_rclickTabName, true);
             SaveConfigsTabs();
@@ -8171,13 +8025,13 @@ namespace OpenTween
                 fltDialog.SetCurrent(_rclickTabName);
                 fltDialog.ShowDialog(this);
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
 
             this.ApplyPostFilters();
             SaveConfigsTabs();
         }
 
-        private void AddTabMenuItem_Click(object sender, EventArgs e)
+        private async void AddTabMenuItem_Click(object sender, EventArgs e)
         {
             string tabName = null;
             MyCommon.TabUsageType tabUsage;
@@ -8190,7 +8044,7 @@ namespace OpenTween
                 tabName = inputName.TabName;
                 tabUsage = inputName.Usage;
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
             if (!string.IsNullOrEmpty(tabName))
             {
                 //List対応
@@ -8238,8 +8092,7 @@ namespace OpenTween
                     if (tabUsage == MyCommon.TabUsageType.Lists)
                     {
                         ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
-                        var listTab = (ListTimelineTabModel)this._statuses.Tabs[this._curTab.Text];
-                        this.GetListTimelineAsync(listTab);
+                        await this.RefreshTabAsync(this.CurrentTab);
                     }
                 }
             }
@@ -8252,33 +8105,28 @@ namespace OpenTween
                 fltDialog.Owner = this;
 
                 //選択発言を元にフィルタ追加
-                foreach (int idx in _curList.SelectedIndices)
+                foreach (var post in this.CurrentTab.SelectedPosts)
                 {
-                    string tabName;
                     //タブ選択(or追加)
-                    if (!SelectTab(out tabName)) return;
+                    if (!SelectTab(out var tabName)) return;
 
                     fltDialog.SetCurrent(tabName);
-                    if (_statuses.Tabs[_curTab.Text][idx].RetweetedId == null)
+
+                    if (post.RetweetedId == null)
                     {
-                        fltDialog.AddNewFilter(_statuses.Tabs[_curTab.Text][idx].ScreenName, _statuses.Tabs[_curTab.Text][idx].TextFromApi);
+                        fltDialog.AddNewFilter(post.ScreenName, post.TextFromApi);
                     }
                     else
                     {
-                        fltDialog.AddNewFilter(_statuses.Tabs[_curTab.Text][idx].RetweetedBy, _statuses.Tabs[_curTab.Text][idx].TextFromApi);
+                        fltDialog.AddNewFilter(post.RetweetedBy, post.TextFromApi);
                     }
                     fltDialog.ShowDialog(this);
-                    this.TopMost = this._cfgCommon.AlwaysTop;
+                    this.TopMost = SettingManager.Common.AlwaysTop;
                 }
             }
 
             this.ApplyPostFilters();
             SaveConfigsTabs();
-            if (this.ListTab.SelectedTab != null &&
-                ((DetailsListView)this.ListTab.SelectedTab.Tag).SelectedIndices.Count > 0)
-            {
-                _curPost = _statuses.Tabs[this.ListTab.SelectedTab.Text][((DetailsListView)this.ListTab.SelectedTab.Tag).SelectedIndices[0]];
-            }
         }
 
         protected override bool ProcessDialogKey(Keys keyData)
@@ -8291,7 +8139,7 @@ namespace OpenTween
                     bool _NewLine = false;
                     bool _Post = false;
 
-                    if (this._cfgCommon.PostCtrlEnter) //Ctrl+Enter投稿時
+                    if (SettingManager.Common.PostCtrlEnter) //Ctrl+Enter投稿時
                     {
                         if (StatusText.Multiline)
                         {
@@ -8305,7 +8153,7 @@ namespace OpenTween
                         }
 
                     }
-                    else if (this._cfgCommon.PostShiftEnter) //SHift+Enter投稿時
+                    else if (SettingManager.Common.PostShiftEnter) //SHift+Enter投稿時
                     {
                         if (StatusText.Multiline)
                         {
@@ -8353,12 +8201,19 @@ namespace OpenTween
                         return true;
                     }
                 }
-                else if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch &&
-                         (ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focused ||
-                         ListTab.SelectedTab.Controls["panelSearch"].Controls["comboLang"].Focused))
+                else
                 {
-                    this.SearchButton_Click(ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"], null);
-                    return true;
+                    var tab = this.CurrentTab;
+                    if (tab.TabType == MyCommon.TabUsageType.PublicSearch)
+                    {
+                        var tabPage = this.CurrentTabPage;
+                        if (tabPage.Controls["panelSearch"].Controls["comboSearch"].Focused ||
+                            tabPage.Controls["panelSearch"].Controls["comboLang"].Focused)
+                        {
+                            this.SearchButton_Click(tabPage.Controls["panelSearch"].Controls["comboSearch"], null);
+                            return true;
+                        }
+                    }
                 }
             }
 
@@ -8366,18 +8221,18 @@ namespace OpenTween
         }
 
         private void ReplyAllStripMenuItem_Click(object sender, EventArgs e)
-        {
-            MakeReplyOrDirectStatus(false, true, true);
-        }
+            => this.MakeReplyOrDirectStatus(false, true, true);
 
         private void IDRuleMenuItem_Click(object sender, EventArgs e)
         {
-            //未選択なら処理終了
-            if (_curList.SelectedIndices.Count == 0) return;
+            var tab = this.CurrentTab;
+            var selectedPosts = tab.SelectedPosts;
+
+            // 未選択なら処理終了
+            if (selectedPosts.Length == 0)
+                return;
 
-            var tab = this._statuses.Tabs[this._curTab.Text];
-            var screenNameArray = this._curList.SelectedIndices.Cast<int>()
-                .Select(x => tab[x])
+            var screenNameArray = selectedPosts
                 .Select(x => x.RetweetedId != null ? x.RetweetedBy : x.ScreenName)
                 .ToArray();
 
@@ -8398,12 +8253,13 @@ namespace OpenTween
 
         private void SourceRuleMenuItem_Click(object sender, EventArgs e)
         {
-            if (this._curList.SelectedIndices.Count == 0)
+            var tab = this.CurrentTab;
+            var selectedPosts = tab.SelectedPosts;
+
+            if (selectedPosts.Length == 0)
                 return;
 
-            var tab = this._statuses.Tabs[this._curTab.Text];
-            var sourceArray = this._curList.SelectedIndices.Cast<int>()
-                .Select(x => tab[x].Source).ToArray();
+            var sourceArray = selectedPosts.Select(x => x.Source).ToArray();
 
             this.AddFilterRuleBySource(sourceArray);
         }
@@ -8411,8 +8267,7 @@ namespace OpenTween
         public void AddFilterRuleByScreenName(params string[] screenNameArray)
         {
             //タブ選択(or追加)
-            string tabName;
-            if (!SelectTab(out tabName)) return;
+            if (!SelectTab(out var tabName)) return;
 
             var tab = (FilterTabModel)this._statuses.Tabs[tabName];
 
@@ -8449,8 +8304,7 @@ namespace OpenTween
         public void AddFilterRuleBySource(params string[] sourceArray)
         {
             // タブ選択ダイアログを表示(or追加)
-            string tabName;
-            if (!this.SelectTab(out tabName))
+            if (!this.SelectTab(out var tabName))
                 return;
 
             var filterTab = (FilterTabModel)this._statuses.Tabs[tabName];
@@ -8497,8 +8351,7 @@ namespace OpenTween
                 {
                     if (dialog.ShowDialog(this) == DialogResult.Cancel) return false;
 
-                    var selectedTab = dialog.SelectedTab;
-                    tabName = selectedTab == null ? null : selectedTab.TabName;
+                    tabName = dialog.SelectedTab?.TabName;
                 }
 
                 ListTab.SelectedTab.Focus();
@@ -8512,7 +8365,7 @@ namespace OpenTween
                         if (inputName.DialogResult == DialogResult.Cancel) return false;
                         tabName = inputName.TabName;
                     }
-                    this.TopMost = this._cfgCommon.AlwaysTop;
+                    this.TopMost = SettingManager.Common.AlwaysTop;
                     if (!string.IsNullOrEmpty(tabName))
                     {
                         var tab = new FilterTabModel(tabName);
@@ -8561,15 +8414,12 @@ namespace OpenTween
                 mark = false;
             }
         }
+
         private void CopySTOTMenuItem_Click(object sender, EventArgs e)
-        {
-            this.CopyStot();
-        }
+            => this.CopyStot();
 
         private void CopyURLMenuItem_Click(object sender, EventArgs e)
-        {
-            this.CopyIdUri();
-        }
+            => this.CopyIdUri();
 
         private void SelectAllMenuItem_Click(object sender, EventArgs e)
         {
@@ -8581,7 +8431,7 @@ namespace OpenTween
             else
             {
                 // ListView上でのCtrl+A
-                NativeMethods.SelectAllItems(this._curList);
+                NativeMethods.SelectAllItems(this.CurrentListView);
             }
         }
 
@@ -8591,27 +8441,28 @@ namespace OpenTween
             int idx1;
             int idx2;
 
-            if (_curList.SelectedIndices.Count == 0) return;
+            var listView = this.CurrentListView;
+            if (listView.SelectedIndices.Count == 0) return;
 
-            int idx = _curList.SelectedIndices[0];
+            int idx = listView.SelectedIndices[0];
 
-            _item = _curList.GetItemAt(0, 25);
+            _item = listView.GetItemAt(0, 25);
             if (_item == null)
                 idx1 = 0;
             else
                 idx1 = _item.Index;
 
-            _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);
+            _item = listView.GetItemAt(0, listView.ClientSize.Height - 1);
             if (_item == null)
-                idx2 = _curList.VirtualListSize - 1;
+                idx2 = listView.VirtualListSize - 1;
             else
                 idx2 = _item.Index;
 
             idx -= Math.Abs(idx1 - idx2) / 2;
             if (idx < 0) idx = 0;
 
-            _curList.EnsureVisible(_curList.VirtualListSize - 1);
-            _curList.EnsureVisible(idx);
+            listView.EnsureVisible(listView.VirtualListSize - 1);
+            listView.EnsureVisible(idx);
         }
 
         private async void OpenURLMenuItem_Click(object sender, EventArgs e)
@@ -8692,7 +8543,7 @@ namespace OpenTween
                     {
                         return;
                     }
-                    this.TopMost = this._cfgCommon.AlwaysTop;
+                    this.TopMost = SettingManager.Common.AlwaysTop;
                 }
             }
         }
@@ -8715,13 +8566,11 @@ namespace OpenTween
             }
 
             _statuses.ClearTabIds(tabName);
-            if (ListTab.SelectedTab.Text == tabName)
+            if (this.CurrentTabName == tabName)
             {
                 _anchorPost = null;
                 _anchorFlag = false;
                 this.PurgeListViewItemCache();
-                _curItemIndex = -1;
-                _curPost = null;
             }
             foreach (TabPage tb in ListTab.TabPages)
             {
@@ -8732,7 +8581,7 @@ namespace OpenTween
                     break;
                 }
             }
-            if (!this._cfgCommon.TabIconDisp) ListTab.Refresh();
+            if (!SettingManager.Common.TabIconDisp) ListTab.Refresh();
 
             SetMainWindowTitle();
             SetStatusLabelUrl();
@@ -8746,22 +8595,22 @@ namespace OpenTween
             StringBuilder ttl = new StringBuilder(256);
             int ur = 0;
             int al = 0;
-            if (this._cfgCommon.DispLatestPost != MyCommon.DispTitleEnum.None &&
-                this._cfgCommon.DispLatestPost != MyCommon.DispTitleEnum.Post &&
-                this._cfgCommon.DispLatestPost != MyCommon.DispTitleEnum.Ver &&
-                this._cfgCommon.DispLatestPost != MyCommon.DispTitleEnum.OwnStatus)
+            if (SettingManager.Common.DispLatestPost != MyCommon.DispTitleEnum.None &&
+                SettingManager.Common.DispLatestPost != MyCommon.DispTitleEnum.Post &&
+                SettingManager.Common.DispLatestPost != MyCommon.DispTitleEnum.Ver &&
+                SettingManager.Common.DispLatestPost != MyCommon.DispTitleEnum.OwnStatus)
             {
-                foreach (var tab in _statuses.Tabs.Values)
+                foreach (var tab in _statuses.Tabs)
                 {
                     ur += tab.UnreadCount;
                     al += tab.AllCount;
                 }
             }
 
-            if (this._cfgCommon.DispUsername) ttl.Append(tw.Username).Append(" - ");
-            ttl.Append(Application.ProductName);
+            if (SettingManager.Common.DispUsername) ttl.Append(tw.Username).Append(" - ");
+            ttl.Append(ApplicationSettings.ApplicationName);
             ttl.Append("  ");
-            switch (this._cfgCommon.DispLatestPost)
+            switch (SettingManager.Common.DispLatestPost)
             {
                 case MyCommon.DispTitleEnum.Ver:
                     ttl.Append("Ver:").Append(MyCommon.GetReadableVersion());
@@ -8814,11 +8663,11 @@ namespace OpenTween
             StringBuilder slbl = new StringBuilder(256);
             try
             {
-                foreach (var tab in _statuses.Tabs.Values)
+                foreach (var tab in _statuses.Tabs)
                 {
                     ur += tab.UnreadCount;
                     al += tab.AllCount;
-                    if (_curTab != null && tab.TabName.Equals(_curTab.Text))
+                    if (tab.TabName == this.CurrentTabName)
                     {
                         tur = tab.UnreadCount;
                         tal = tab.AllCount;
@@ -8836,13 +8685,13 @@ namespace OpenTween
             var homeTab = this._statuses.GetTabByType<HomeTabModel>();
 
             slbl.AppendFormat(Properties.Resources.SetStatusLabelText1, tur, tal, ur, al, urat, _postTimestamps.Count, _favTimestamps.Count, homeTab.TweetsPerHour);
-            if (this._cfgCommon.TimelinePeriod == 0)
+            if (SettingManager.Common.TimelinePeriod == 0)
             {
                 slbl.Append(Properties.Resources.SetStatusLabelText2);
             }
             else
             {
-                slbl.Append(this._cfgCommon.TimelinePeriod + Properties.Resources.SetStatusLabelText3);
+                slbl.Append(SettingManager.Common.TimelinePeriod + Properties.Resources.SetStatusLabelText3);
             }
             return slbl.ToString();
         }
@@ -8873,119 +8722,108 @@ namespace OpenTween
 
         private void SetApiStatusLabel(string endpointName = null)
         {
-            if (_curTab == null)
-            {
-                this.toolStripApiGauge.ApiEndpoint = null;
-            }
-            else
-            {
-                var tabType = _statuses.Tabs[_curTab.Text].TabType;
+            var tabType = this.CurrentTab.TabType;
 
-                if (endpointName == null)
+            if (endpointName == null)
+            {
+                // 表示中のタブに応じて更新
+                switch (tabType)
                 {
-                    // 表示中のタブに応じて更新
-                    switch (tabType)
-                    {
-                        case MyCommon.TabUsageType.Home:
-                        case MyCommon.TabUsageType.UserDefined:
-                            endpointName = "/statuses/home_timeline";
-                            break;
+                    case MyCommon.TabUsageType.Home:
+                    case MyCommon.TabUsageType.UserDefined:
+                        endpointName = "/statuses/home_timeline";
+                        break;
+
+                    case MyCommon.TabUsageType.Mentions:
+                        endpointName = "/statuses/mentions_timeline";
+                        break;
 
-                        case MyCommon.TabUsageType.Mentions:
-                            endpointName = "/statuses/mentions_timeline";
-                            break;
+                    case MyCommon.TabUsageType.Favorites:
+                        endpointName = "/favorites/list";
+                        break;
 
-                        case MyCommon.TabUsageType.Favorites:
-                            endpointName = "/favorites/list";
-                            break;
+                    case MyCommon.TabUsageType.DirectMessage:
+                        endpointName = "/direct_messages/events/list";
+                        break;
 
-                        case MyCommon.TabUsageType.DirectMessage:
-                            endpointName = "/direct_messages";
-                            break;
+                    case MyCommon.TabUsageType.UserTimeline:
+                        endpointName = "/statuses/user_timeline";
+                        break;
 
-                        case MyCommon.TabUsageType.UserTimeline:
-                            endpointName = "/statuses/user_timeline";
-                            break;
+                    case MyCommon.TabUsageType.Lists:
+                        endpointName = "/lists/statuses";
+                        break;
 
-                        case MyCommon.TabUsageType.Lists:
-                            endpointName = "/lists/statuses";
-                            break;
+                    case MyCommon.TabUsageType.PublicSearch:
+                        endpointName = "/search/tweets";
+                        break;
 
-                        case MyCommon.TabUsageType.PublicSearch:
-                            endpointName = "/search/tweets";
-                            break;
+                    case MyCommon.TabUsageType.Related:
+                        endpointName = "/statuses/show/:id";
+                        break;
 
-                        case MyCommon.TabUsageType.Related:
-                            endpointName = "/statuses/show/:id";
-                            break;
+                    default:
+                        break;
+                }
 
-                        default:
-                            break;
-                    }
+                this.toolStripApiGauge.ApiEndpoint = endpointName;
+            }
+            else
+            {
+                // 表示中のタブに関連する endpoint であれば更新
+                var update = false;
 
-                    this.toolStripApiGauge.ApiEndpoint = endpointName;
-                }
-                else
+                switch (endpointName)
                 {
-                    // 表示中のタブに関連する endpoint であれば更新
-                    var update = false;
-
-                    switch (endpointName)
-                    {
-                        case "/statuses/home_timeline":
-                            update = tabType == MyCommon.TabUsageType.Home ||
-                                     tabType == MyCommon.TabUsageType.UserDefined;
-                            break;
+                    case "/statuses/home_timeline":
+                        update = tabType == MyCommon.TabUsageType.Home ||
+                                 tabType == MyCommon.TabUsageType.UserDefined;
+                        break;
 
-                        case "/statuses/mentions_timeline":
-                            update = tabType == MyCommon.TabUsageType.Mentions;
-                            break;
+                    case "/statuses/mentions_timeline":
+                        update = tabType == MyCommon.TabUsageType.Mentions;
+                        break;
 
-                        case "/favorites/list":
-                            update = tabType == MyCommon.TabUsageType.Favorites;
-                            break;
+                    case "/favorites/list":
+                        update = tabType == MyCommon.TabUsageType.Favorites;
+                        break;
 
-                        case "/direct_messages:":
-                            update = tabType == MyCommon.TabUsageType.DirectMessage;
-                            break;
+                    case "/direct_messages/events/list":
+                        update = tabType == MyCommon.TabUsageType.DirectMessage;
+                        break;
 
-                        case "/statuses/user_timeline":
-                            update = tabType == MyCommon.TabUsageType.UserTimeline;
-                            break;
+                    case "/statuses/user_timeline":
+                        update = tabType == MyCommon.TabUsageType.UserTimeline;
+                        break;
 
-                        case "/lists/statuses":
-                            update = tabType == MyCommon.TabUsageType.Lists;
-                            break;
+                    case "/lists/statuses":
+                        update = tabType == MyCommon.TabUsageType.Lists;
+                        break;
 
-                        case "/search/tweets":
-                            update = tabType == MyCommon.TabUsageType.PublicSearch;
-                            break;
+                    case "/search/tweets":
+                        update = tabType == MyCommon.TabUsageType.PublicSearch;
+                        break;
 
-                        case "/statuses/show/:id":
-                            update = tabType == MyCommon.TabUsageType.Related;
-                            break;
+                    case "/statuses/show/:id":
+                        update = tabType == MyCommon.TabUsageType.Related;
+                        break;
 
-                        default:
-                            break;
-                    }
+                    default:
+                        break;
+                }
 
-                    if (update)
-                    {
-                        this.toolStripApiGauge.ApiEndpoint = endpointName;
-                    }
+                if (update)
+                {
+                    this.toolStripApiGauge.ApiEndpoint = endpointName;
                 }
             }
         }
 
         private void SetStatusLabelUrl()
-        {
-            StatusLabelUrl.Text = GetStatusLabelText();
-        }
+            => this.StatusLabelUrl.Text = this.GetStatusLabelText();
 
         public void SetStatusLabel(string text)
-        {
-            StatusLabel.Text = text;
-        }
+            => this.StatusLabel.Text = text;
 
         private void SetNotifyIconText()
         {
@@ -8994,12 +8832,12 @@ namespace OpenTween
             // タスクトレイアイコンのツールチップテキスト書き換え
             // Tween [未読/@]
             ur.Remove(0, ur.Length);
-            if (this._cfgCommon.DispUsername)
+            if (SettingManager.Common.DispUsername)
             {
                 ur.Append(tw.Username);
                 ur.Append(" - ");
             }
-            ur.Append(Application.ProductName);
+            ur.Append(ApplicationSettings.ApplicationName);
 #if DEBUG
             ur.Append("(Debug Build)");
 #endif
@@ -9037,7 +8875,7 @@ namespace OpenTween
             // 本当にリプライ先指定すべきかどうかの判定
             m = Regex.Matches(StatusText, "(^|[ -/:-@[-^`{-~])(?<id>@[a-zA-Z0-9_]+)");
 
-            if (this._cfgCommon.UseAtIdSupplement)
+            if (SettingManager.Common.UseAtIdSupplement)
             {
                 int bCnt = AtIdSupl.ItemCount;
                 foreach (Match mid in m)
@@ -9059,7 +8897,7 @@ namespace OpenTween
 
             if (m != null)
             {
-                var inReplyToScreenName = this.inReplyTo.Item2;
+                var inReplyToScreenName = this.inReplyTo.Value.ScreenName;
                 if (StatusText.StartsWith("@", StringComparison.Ordinal))
                 {
                     if (StatusText.StartsWith("@" + inReplyToScreenName, StringComparison.Ordinal)) return;
@@ -9078,22 +8916,19 @@ namespace OpenTween
 
         private void TweenMain_Resize(object sender, EventArgs e)
         {
-            if (!_initialLayout && this._cfgCommon.MinimizeToTray && WindowState == FormWindowState.Minimized)
+            if (!_initialLayout && SettingManager.Common.MinimizeToTray && WindowState == FormWindowState.Minimized)
             {
                 this.Visible = false;
             }
-            if (_initialLayout && _cfgLocal != null && this.WindowState == FormWindowState.Normal && this.Visible)
+            if (_initialLayout && SettingManager.Local != null && this.WindowState == FormWindowState.Normal && this.Visible)
             {
                 // 現在の DPI と設定保存時の DPI との比を取得する
-                var configScaleFactor = this._cfgLocal.GetConfigScaleFactor(this.CurrentAutoScaleDimensions);
+                var configScaleFactor = SettingManager.Local.GetConfigScaleFactor(this.CurrentAutoScaleDimensions);
 
-                this.ClientSize = ScaleBy(configScaleFactor, _cfgLocal.FormSize);
-                //_mySize = this.ClientSize;                     //サイズ保持(最小化・最大化されたまま終了した場合の対応用)
-                this.DesktopLocation = _cfgLocal.FormLocation;
-                //_myLoc = this.DesktopLocation;                        //位置保持(最小化・最大化されたまま終了した場合の対応用)
+                this.ClientSize = ScaleBy(configScaleFactor, SettingManager.Local.FormSize);
 
                 // Splitterの位置設定
-                var splitterDistance = ScaleBy(configScaleFactor.Height, _cfgLocal.SplitterDistance);
+                var splitterDistance = ScaleBy(configScaleFactor.Height, SettingManager.Local.SplitterDistance);
                 if (splitterDistance > this.SplitContainer1.Panel1MinSize &&
                     splitterDistance < this.SplitContainer1.Height - this.SplitContainer1.Panel2MinSize - this.SplitContainer1.SplitterWidth)
                 {
@@ -9101,10 +8936,10 @@ namespace OpenTween
                 }
 
                 //発言欄複数行
-                StatusText.Multiline = _cfgLocal.StatusMultiline;
+                StatusText.Multiline = SettingManager.Local.StatusMultiline;
                 if (StatusText.Multiline)
                 {
-                    var statusTextHeight = ScaleBy(configScaleFactor.Height, _cfgLocal.StatusTextHeight);
+                    var statusTextHeight = ScaleBy(configScaleFactor.Height, SettingManager.Local.StatusTextHeight);
                     int dis = SplitContainer2.Height - statusTextHeight - SplitContainer2.SplitterWidth;
                     if (dis > SplitContainer2.Panel1MinSize && dis < SplitContainer2.Height - SplitContainer2.Panel2MinSize - SplitContainer2.SplitterWidth)
                     {
@@ -9120,7 +8955,7 @@ namespace OpenTween
                     }
                 }
 
-                var previewDistance = ScaleBy(configScaleFactor.Width, _cfgLocal.PreviewDistance);
+                var previewDistance = ScaleBy(configScaleFactor.Width, SettingManager.Local.PreviewDistance);
                 if (previewDistance > this.SplitContainer3.Panel1MinSize && previewDistance < this.SplitContainer3.Width - this.SplitContainer3.Panel2MinSize - this.SplitContainer3.SplitterWidth)
                 {
                     this.SplitContainer3.SplitterDistance = previewDistance;
@@ -9143,11 +8978,11 @@ namespace OpenTween
             this.PlaySoundFileMenuItem.Checked = PlaySoundMenuItem.Checked;
             if (PlaySoundMenuItem.Checked)
             {
-                this._cfgCommon.PlaySound = true;
+                SettingManager.Common.PlaySound = true;
             }
             else
             {
-                this._cfgCommon.PlaySound = false;
+                SettingManager.Common.PlaySound = false;
             }
             ModifySettingCommon = true;
         }
@@ -9179,44 +9014,46 @@ namespace OpenTween
 
         private async Task doRepliedStatusOpen()
         {
-            if (this.ExistCurrentPost && _curPost.InReplyToUser != null && _curPost.InReplyToStatusId != null)
+            var currentPost = this.CurrentPost;
+            if (this.ExistCurrentPost && currentPost.InReplyToUser != null && currentPost.InReplyToStatusId != null)
             {
                 if (MyCommon.IsKeyDown(Keys.Shift))
                 {
-                    await this.OpenUriInBrowserAsync(MyCommon.GetStatusUrl(_curPost.InReplyToUser, _curPost.InReplyToStatusId.Value));
+                    await this.OpenUriInBrowserAsync(MyCommon.GetStatusUrl(currentPost.InReplyToUser, currentPost.InReplyToStatusId.Value));
                     return;
                 }
-                if (_statuses.ContainsKey(_curPost.InReplyToStatusId.Value))
+                if (_statuses.ContainsKey(currentPost.InReplyToStatusId.Value))
                 {
-                    PostClass repPost = _statuses[_curPost.InReplyToStatusId.Value];
-                    MessageBox.Show($"{repPost.ScreenName} / {repPost.Nickname}   ({repPost.CreatedAt})" + Environment.NewLine + repPost.TextFromApi);
+                    PostClass repPost = _statuses[currentPost.InReplyToStatusId.Value];
+                    MessageBox.Show($"{repPost.ScreenName} / {repPost.Nickname}   ({repPost.CreatedAt.ToLocalTimeString()})" + Environment.NewLine + repPost.TextFromApi);
                 }
                 else
                 {
                     foreach (TabModel tb in _statuses.GetTabsByType(MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.PublicSearch))
                     {
-                        if (tb == null || !tb.Contains(_curPost.InReplyToStatusId.Value)) break;
-                        PostClass repPost = _statuses[_curPost.InReplyToStatusId.Value];
-                        MessageBox.Show($"{repPost.ScreenName} / {repPost.Nickname}   ({repPost.CreatedAt})" + Environment.NewLine + repPost.TextFromApi);
+                        if (tb == null || !tb.Contains(currentPost.InReplyToStatusId.Value)) break;
+                        PostClass repPost = _statuses[currentPost.InReplyToStatusId.Value];
+                        MessageBox.Show($"{repPost.ScreenName} / {repPost.Nickname}   ({repPost.CreatedAt.ToLocalTimeString()})" + Environment.NewLine + repPost.TextFromApi);
                         return;
                     }
-                    await this.OpenUriInBrowserAsync(MyCommon.GetStatusUrl(_curPost.InReplyToUser, _curPost.InReplyToStatusId.Value));
+                    await this.OpenUriInBrowserAsync(MyCommon.GetStatusUrl(currentPost.InReplyToUser, currentPost.InReplyToStatusId.Value));
                 }
             }
         }
 
         private async void RepliedStatusOpenMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.doRepliedStatusOpen();
-        }
+            => await this.doRepliedStatusOpen();
 
         private void SplitContainer2_Panel2_Resize(object sender, EventArgs e)
         {
+            if (this._initialLayout)
+                return; // SettingLocal の反映が完了するまで multiline の判定を行わない
+
             var multiline = this.SplitContainer2.Panel2.Height > this.SplitContainer2.Panel2MinSize + 2;
             if (multiline != this.StatusText.Multiline)
             {
                 this.StatusText.Multiline = multiline;
-                MultiLineMenuItem.Checked = multiline;
+                SettingManager.Local.StatusMultiline = multiline;
                 ModifySettingLocal = true;
             }
         }
@@ -9234,9 +9071,10 @@ namespace OpenTween
         private void MultiLineMenuItem_Click(object sender, EventArgs e)
         {
             //発言欄複数行
-            StatusText.Multiline = MultiLineMenuItem.Checked;
-            _cfgLocal.StatusMultiline = MultiLineMenuItem.Checked;
-            if (MultiLineMenuItem.Checked)
+            var menuItemChecked = ((ToolStripMenuItem)sender).Checked;
+            StatusText.Multiline = menuItemChecked;
+            SettingManager.Local.StatusMultiline = menuItemChecked;
+            if (menuItemChecked)
             {
                 if (SplitContainer2.Height - _mySpDis2 - SplitContainer2.SplitterWidth < 0)
                     SplitContainer2.SplitterDistance = 0;
@@ -9252,6 +9090,17 @@ namespace OpenTween
 
         private async Task<bool> UrlConvertAsync(MyCommon.UrlConverter Converter_Type)
         {
+            if (Converter_Type == MyCommon.UrlConverter.Bitly || Converter_Type == MyCommon.UrlConverter.Jmp)
+            {
+                // OAuth2 アクセストークンまたは API キー (旧方式) のいずれも設定されていなければ短縮しない
+                if (string.IsNullOrEmpty(SettingManager.Common.BitlyAccessToken) &&
+                    (string.IsNullOrEmpty(SettingManager.Common.BilyUser) || string.IsNullOrEmpty(SettingManager.Common.BitlyPwd)))
+                {
+                    MessageBox.Show(this, Properties.Resources.UrlConvert_BitlyAuthRequired, ApplicationSettings.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
+                    return false;
+                }
+            }
+
             //t.coで投稿時自動短縮する場合は、外部サービスでの短縮禁止
             //if (SettingDialog.UrlConvertAuto && SettingDialog.ShortenTco) return;
 
@@ -9273,7 +9122,7 @@ namespace OpenTween
                     // 文字列が選択されている場合はその文字列について処理
 
                     //nico.ms使用、nicovideoにマッチしたら変換
-                    if (this._cfgCommon.Nicoms && Regex.IsMatch(tmp, nico))
+                    if (SettingManager.Common.Nicoms && Regex.IsMatch(tmp, nico))
                     {
                         result = nicoms.Shorten(tmp);
                     }
@@ -9306,7 +9155,12 @@ namespace OpenTween
                     {
                         urlUndo undotmp = new urlUndo();
 
-                        StatusText.Select(StatusText.Text.IndexOf(tmp, StringComparison.Ordinal), tmp.Length);
+                        // 短縮 URL が生成されるまでの間に投稿欄から元の URL が削除されていたら中断する
+                        var origUrlIndex = this.StatusText.Text.IndexOf(tmp, StringComparison.Ordinal);
+                        if (origUrlIndex == -1)
+                            return false;
+
+                        StatusText.Select(origUrlIndex, tmp.Length);
                         StatusText.SelectedText = result;
 
                         //undoバッファにセット
@@ -9342,7 +9196,7 @@ namespace OpenTween
                     StatusText.Select(StatusText.Text.IndexOf(mt.Result("${url}"), StringComparison.Ordinal), mt.Result("${url}").Length);
 
                     //nico.ms使用、nicovideoにマッチしたら変換
-                    if (this._cfgCommon.Nicoms && Regex.IsMatch(tmp, nico))
+                    if (SettingManager.Common.Nicoms && Regex.IsMatch(tmp, nico))
                     {
                         result = nicoms.Shorten(tmp);
                     }
@@ -9382,7 +9236,12 @@ namespace OpenTween
 
                     if (!string.IsNullOrEmpty(result))
                     {
-                        StatusText.Select(StatusText.Text.IndexOf(mt.Result("${url}"), StringComparison.Ordinal), mt.Result("${url}").Length);
+                        // 短縮 URL が生成されるまでの間に投稿欄から元の URL が削除されていたら中断する
+                        var origUrlIndex = this.StatusText.Text.IndexOf(mt.Result("${url}"), StringComparison.Ordinal);
+                        if (origUrlIndex == -1)
+                            return false;
+
+                        StatusText.Select(origUrlIndex, mt.Result("${url}").Length);
                         StatusText.SelectedText = result;
                         //undoバッファにセット
                         undotmp.Before = mt.Result("${url}");
@@ -9420,51 +9279,38 @@ namespace OpenTween
         }
 
         private async void TinyURLToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await UrlConvertAsync(MyCommon.UrlConverter.TinyUrl);
-        }
+            => await this.UrlConvertAsync(MyCommon.UrlConverter.TinyUrl);
 
         private async void IsgdToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await UrlConvertAsync(MyCommon.UrlConverter.Isgd);
-        }
-
-        private async void TwurlnlToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await UrlConvertAsync(MyCommon.UrlConverter.Twurl);
-        }
+            => await this.UrlConvertAsync(MyCommon.UrlConverter.Isgd);
 
         private async void UxnuMenuItem_Click(object sender, EventArgs e)
-        {
-            await UrlConvertAsync(MyCommon.UrlConverter.Uxnu);
-        }
+            => await this.UrlConvertAsync(MyCommon.UrlConverter.Uxnu);
 
         private async void UrlConvertAutoToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            if (!await UrlConvertAsync(this._cfgCommon.AutoShortUrlFirst))
+            if (!await UrlConvertAsync(SettingManager.Common.AutoShortUrlFirst))
             {
-                MyCommon.UrlConverter svc = this._cfgCommon.AutoShortUrlFirst;
+                MyCommon.UrlConverter svc = SettingManager.Common.AutoShortUrlFirst;
                 Random rnd = new Random();
                 // 前回使用した短縮URLサービス以外を選択する
                 do
                 {
                     svc = (MyCommon.UrlConverter)rnd.Next(System.Enum.GetNames(typeof(MyCommon.UrlConverter)).Length);
                 }
-                while (svc == this._cfgCommon.AutoShortUrlFirst || svc == MyCommon.UrlConverter.Nicoms || svc == MyCommon.UrlConverter.Unu);
+                while (svc == SettingManager.Common.AutoShortUrlFirst || svc == MyCommon.UrlConverter.Nicoms || svc == MyCommon.UrlConverter.Unu);
                 await UrlConvertAsync(svc);
             }
         }
 
         private void UrlUndoToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            doUrlUndo();
-        }
+            => this.doUrlUndo();
 
         private void NewPostPopMenuItem_CheckStateChanged(object sender, EventArgs e)
         {
             this.NotifyFileMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
             this.NewPostPopMenuItem.Checked = this.NotifyFileMenuItem.Checked;
-            _cfgCommon.NewAllPop = NewPostPopMenuItem.Checked;
+            SettingManager.Common.NewAllPop = NewPostPopMenuItem.Checked;
             ModifySettingCommon = true;
         }
 
@@ -9472,7 +9318,7 @@ namespace OpenTween
         {
             ListLockMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
             this.LockListFileMenuItem.Checked = ListLockMenuItem.Checked;
-            _cfgCommon.ListLock = ListLockMenuItem.Checked;
+            SettingManager.Common.ListLock = ListLockMenuItem.Checked;
             ModifySettingCommon = true;
         }
 
@@ -9507,12 +9353,12 @@ namespace OpenTween
         private void MyList_ColumnReordered(object sender, ColumnReorderedEventArgs e)
         {
             DetailsListView lst = (DetailsListView)sender;
-            if (_cfgLocal == null) return;
+            if (SettingManager.Local == null) return;
 
             if (_iconCol)
             {
-                _cfgLocal.Width1 = lst.Columns[0].Width;
-                _cfgLocal.Width3 = lst.Columns[1].Width;
+                SettingManager.Local.Width1 = lst.Columns[0].Width;
+                SettingManager.Local.Width3 = lst.Columns[1].Width;
             }
             else
             {
@@ -9528,39 +9374,39 @@ namespace OpenTween
                     switch (darr[i])
                     {
                         case 0:
-                            _cfgLocal.DisplayIndex1 = i;
+                            SettingManager.Local.DisplayIndex1 = i;
                             break;
                         case 1:
-                            _cfgLocal.DisplayIndex2 = i;
+                            SettingManager.Local.DisplayIndex2 = i;
                             break;
                         case 2:
-                            _cfgLocal.DisplayIndex3 = i;
+                            SettingManager.Local.DisplayIndex3 = i;
                             break;
                         case 3:
-                            _cfgLocal.DisplayIndex4 = i;
+                            SettingManager.Local.DisplayIndex4 = i;
                             break;
                         case 4:
-                            _cfgLocal.DisplayIndex5 = i;
+                            SettingManager.Local.DisplayIndex5 = i;
                             break;
                         case 5:
-                            _cfgLocal.DisplayIndex6 = i;
+                            SettingManager.Local.DisplayIndex6 = i;
                             break;
                         case 6:
-                            _cfgLocal.DisplayIndex7 = i;
+                            SettingManager.Local.DisplayIndex7 = i;
                             break;
                         case 7:
-                            _cfgLocal.DisplayIndex8 = i;
+                            SettingManager.Local.DisplayIndex8 = i;
                             break;
                     }
                 }
-                _cfgLocal.Width1 = lst.Columns[0].Width;
-                _cfgLocal.Width2 = lst.Columns[1].Width;
-                _cfgLocal.Width3 = lst.Columns[2].Width;
-                _cfgLocal.Width4 = lst.Columns[3].Width;
-                _cfgLocal.Width5 = lst.Columns[4].Width;
-                _cfgLocal.Width6 = lst.Columns[5].Width;
-                _cfgLocal.Width7 = lst.Columns[6].Width;
-                _cfgLocal.Width8 = lst.Columns[7].Width;
+                SettingManager.Local.Width1 = lst.Columns[0].Width;
+                SettingManager.Local.Width2 = lst.Columns[1].Width;
+                SettingManager.Local.Width3 = lst.Columns[2].Width;
+                SettingManager.Local.Width4 = lst.Columns[3].Width;
+                SettingManager.Local.Width5 = lst.Columns[4].Width;
+                SettingManager.Local.Width6 = lst.Columns[5].Width;
+                SettingManager.Local.Width7 = lst.Columns[6].Width;
+                SettingManager.Local.Width8 = lst.Columns[7].Width;
             }
             ModifySettingLocal = true;
             _isColumnChanged = true;
@@ -9569,69 +9415,69 @@ namespace OpenTween
         private void MyList_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
         {
             DetailsListView lst = (DetailsListView)sender;
-            if (_cfgLocal == null) return;
+            if (SettingManager.Local == null) return;
             if (_iconCol)
             {
-                if (_cfgLocal.Width1 != lst.Columns[0].Width)
+                if (SettingManager.Local.Width1 != lst.Columns[0].Width)
                 {
-                    _cfgLocal.Width1 = lst.Columns[0].Width;
+                    SettingManager.Local.Width1 = lst.Columns[0].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
-                if (_cfgLocal.Width3 != lst.Columns[1].Width)
+                if (SettingManager.Local.Width3 != lst.Columns[1].Width)
                 {
-                    _cfgLocal.Width3 = lst.Columns[1].Width;
+                    SettingManager.Local.Width3 = lst.Columns[1].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
             }
             else
             {
-                if (_cfgLocal.Width1 != lst.Columns[0].Width)
+                if (SettingManager.Local.Width1 != lst.Columns[0].Width)
                 {
-                    _cfgLocal.Width1 = lst.Columns[0].Width;
+                    SettingManager.Local.Width1 = lst.Columns[0].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
-                if (_cfgLocal.Width2 != lst.Columns[1].Width)
+                if (SettingManager.Local.Width2 != lst.Columns[1].Width)
                 {
-                    _cfgLocal.Width2 = lst.Columns[1].Width;
+                    SettingManager.Local.Width2 = lst.Columns[1].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
-                if (_cfgLocal.Width3 != lst.Columns[2].Width)
+                if (SettingManager.Local.Width3 != lst.Columns[2].Width)
                 {
-                    _cfgLocal.Width3 = lst.Columns[2].Width;
+                    SettingManager.Local.Width3 = lst.Columns[2].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
-                if (_cfgLocal.Width4 != lst.Columns[3].Width)
+                if (SettingManager.Local.Width4 != lst.Columns[3].Width)
                 {
-                    _cfgLocal.Width4 = lst.Columns[3].Width;
+                    SettingManager.Local.Width4 = lst.Columns[3].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
-                if (_cfgLocal.Width5 != lst.Columns[4].Width)
+                if (SettingManager.Local.Width5 != lst.Columns[4].Width)
                 {
-                    _cfgLocal.Width5 = lst.Columns[4].Width;
+                    SettingManager.Local.Width5 = lst.Columns[4].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
-                if (_cfgLocal.Width6 != lst.Columns[5].Width)
+                if (SettingManager.Local.Width6 != lst.Columns[5].Width)
                 {
-                    _cfgLocal.Width6 = lst.Columns[5].Width;
+                    SettingManager.Local.Width6 = lst.Columns[5].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
-                if (_cfgLocal.Width7 != lst.Columns[6].Width)
+                if (SettingManager.Local.Width7 != lst.Columns[6].Width)
                 {
-                    _cfgLocal.Width7 = lst.Columns[6].Width;
+                    SettingManager.Local.Width7 = lst.Columns[6].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
-                if (_cfgLocal.Width8 != lst.Columns[7].Width)
+                if (SettingManager.Local.Width8 != lst.Columns[7].Width)
                 {
-                    _cfgLocal.Width8 = lst.Columns[7].Width;
+                    SettingManager.Local.Width8 = lst.Columns[7].Width;
                     ModifySettingLocal = true;
                     _isColumnChanged = true;
                 }
@@ -9660,13 +9506,13 @@ namespace OpenTween
             }
             else if (e.Data.GetDataPresent("UniformResourceLocatorW"))
             {
-                var url = GetUrlFromDataObject(e.Data);
+                var (url, title) = GetUrlFromDataObject(e.Data);
 
                 string appendText;
-                if (url.Item2 == null)
-                    appendText = url.Item1;
+                if (title == null)
+                    appendText = url;
                 else
-                    appendText = url.Item2 + " " + url.Item1;
+                    appendText = title + " " + url;
 
                 if (this.StatusText.TextLength == 0)
                     this.StatusText.Text = appendText;
@@ -9694,7 +9540,7 @@ namespace OpenTween
         /// </remarks>
         /// <exception cref="ArgumentException">不正なフォーマットが入力された場合</exception>
         /// <exception cref="NotSupportedException">サポートされていないデータが入力された場合</exception>
-        internal static Tuple<string, string> GetUrlFromDataObject(IDataObject data)
+        internal static (string Url, string Title) GetUrlFromDataObject(IDataObject data)
         {
             if (data.GetDataPresent("text/x-moz-url"))
             {
@@ -9707,7 +9553,7 @@ namespace OpenTween
                     if (lines.Length < 2)
                         throw new ArgumentException("不正な text/x-moz-url フォーマットです", nameof(data));
 
-                    return new Tuple<string, string>(lines[0], lines[1]);
+                    return (lines[0], lines[1]);
                 }
             }
             else if (data.GetDataPresent("IESiteModeToUrl"))
@@ -9721,7 +9567,7 @@ namespace OpenTween
                     if (lines.Length < 2)
                         throw new ArgumentException("不正な IESiteModeToUrl フォーマットです", nameof(data));
 
-                    return new Tuple<string, string>(lines[0], lines[1]);
+                    return (lines[0], lines[1]);
                 }
             }
             else if (data.GetDataPresent("UniformResourceLocatorW"))
@@ -9731,7 +9577,7 @@ namespace OpenTween
                 using (var stream = (MemoryStream)data.GetData("UniformResourceLocatorW"))
                 {
                     var url = Encoding.Unicode.GetString(stream.ToArray()).TrimEnd('\0');
-                    return new Tuple<string, string>(url, null);
+                    return (url, null);
                 }
             }
 
@@ -9807,8 +9653,8 @@ namespace OpenTween
 
             // ユーザープロフィールURL
             // フラグが立っている場合は設定と逆の動作をする
-            if( this._cfgCommon.OpenUserTimeline && !isReverseSettings ||
-                !this._cfgCommon.OpenUserTimeline && isReverseSettings )
+            if( SettingManager.Common.OpenUserTimeline && !isReverseSettings ||
+                !SettingManager.Common.OpenUserTimeline && isReverseSettings )
             {
                 var userUriMatch = Regex.Match(uriStr, "^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)$");
                 if (userUriMatch.Success)
@@ -9816,7 +9662,7 @@ namespace OpenTween
                     var screenName = userUriMatch.Groups["ScreenName"].Value;
                     if (this.IsTwitterId(screenName))
                     {
-                        this.AddNewTabForUserTimeline(screenName);
+                        await this.AddNewTabForUserTimeline(screenName);
                         return;
                     }
                 }
@@ -9849,7 +9695,7 @@ namespace OpenTween
 
                 try
                 {
-                    var configBrowserPath = this._cfgLocal.BrowserPath;
+                    var configBrowserPath = SettingManager.Local.BrowserPath;
                     if (!string.IsNullOrEmpty(configBrowserPath))
                     {
                         if (configBrowserPath.StartsWith("\"", StringComparison.Ordinal) && configBrowserPath.Length > 2 && configBrowserPath.IndexOf("\"", 2, StringComparison.Ordinal) > -1)
@@ -9887,40 +9733,28 @@ namespace OpenTween
 
             this.PurgeListViewItemCache();
 
-            _curTab = _tab;
-            _curList = (DetailsListView)_tab.Tag;
+            this._statuses.SelectTab(_tab.Text);
 
-            if (_curList.SelectedIndices.Count > 0)
-            {
-                _curItemIndex = _curList.SelectedIndices[0];
-                _curPost = GetCurTabPost(_curItemIndex);
-            }
-            else
-            {
-                _curItemIndex = -1;
-                _curPost = null;
-            }
+            var listView = this.CurrentListView;
 
             _anchorPost = null;
             _anchorFlag = false;
 
             if (_iconCol)
             {
-                ((DetailsListView)_tab.Tag).Columns[1].Text = ColumnText[2];
+                listView.Columns[1].Text = ColumnText[2];
             }
             else
             {
-                for (int i = 0; i < _curList.Columns.Count; i++)
+                for (int i = 0; i < listView.Columns.Count; i++)
                 {
-                    ((DetailsListView)_tab.Tag).Columns[i].Text = ColumnText[i];
+                    listView.Columns[i].Text = ColumnText[i];
                 }
             }
         }
 
         private void ListTab_Selecting(object sender, TabControlCancelEventArgs e)
-        {
-            ListTabSelect(e.TabPage);
-        }
+            => this.ListTabSelect(e.TabPage);
 
         private void SelectListItem(DetailsListView LView, int Index)
         {
@@ -9993,7 +9827,7 @@ namespace OpenTween
 
             this.RefreshUserStreamsMenu();
 
-            if (this._cfgCommon.UserstreamStartup)
+            if (SettingManager.Common.UserstreamStartup)
                 tw.StartUserStream();
         }
 
@@ -10011,19 +9845,19 @@ namespace OpenTween
                     this.RefreshBlockIdsAsync(),
                     this.RefreshNoRetweetIdsAsync(),
                     this.RefreshTwitterConfigurationAsync(),
-                    this.GetHomeTimelineAsync(),
-                    this.GetReplyAsync(),
-                    this.GetDirectMessagesAsync(),
-                    this.GetPublicSearchAllAsync(),
-                    this.GetUserTimelineAllAsync(),
-                    this.GetListTimelineAllAsync(),
+                    this.RefreshTabAsync<HomeTabModel>(),
+                    this.RefreshTabAsync<MentionsTabModel>(),
+                    this.RefreshTabAsync<DirectMessagesTabModel>(),
+                    this.RefreshTabAsync<PublicSearchTabModel>(),
+                    this.RefreshTabAsync<UserTimelineTabModel>(),
+                    this.RefreshTabAsync<ListTimelineTabModel>(),
                 };
 
-                if (this._cfgCommon.StartupFollowers)
+                if (SettingManager.Common.StartupFollowers)
                     loadTasks.Add(this.RefreshFollowerIdsAsync());
 
-                if (this._cfgCommon.GetFav)
-                    loadTasks.Add(this.GetFavoritesAsync());
+                if (SettingManager.Common.GetFav)
+                    loadTasks.Add(this.RefreshTabAsync<FavoritesTabModel>());
 
                 var allTasks = Task.WhenAll(loadTasks);
 
@@ -10046,7 +9880,7 @@ namespace OpenTween
                 if (ApplicationSettings.VersionInfoUrl != null)
                 {
                     //バージョンチェック(引数:起動時チェックの場合はtrue・・・チェック結果のメッセージを表示しない)
-                    if (this._cfgCommon.StartupVersion)
+                    if (SettingManager.Common.StartupVersion)
                         await this.CheckNewVersion(true);
                 }
                 else
@@ -10067,7 +9901,7 @@ namespace OpenTween
                 // 取得失敗の場合は再試行する
                 var reloadTasks = new List<Task>();
 
-                if (!tw.GetFollowersSuccess && this._cfgCommon.StartupFollowers)
+                if (!tw.GetFollowersSuccess && SettingManager.Common.StartupFollowers)
                     reloadTasks.Add(this.RefreshFollowerIdsAsync());
 
                 if (!tw.GetNoRetweetSuccess)
@@ -10091,35 +9925,34 @@ namespace OpenTween
         }
 
         private async void GetFollowersAllToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.doGetFollowersMenu();
-        }
+            => await this.doGetFollowersMenu();
 
         private void ReTweetUnofficialStripMenuItem_Click(object sender, EventArgs e)
-        {
-            doReTweetUnofficial();
-        }
+            => this.doReTweetUnofficial();
 
         private async Task doReTweetOfficial(bool isConfirm)
         {
             //公式RT
             if (this.ExistCurrentPost)
             {
-                if (!_curPost.CanRetweetBy(this.twitterApi.CurrentUserId))
+                var selectedPosts = this.CurrentTab.SelectedPosts;
+
+                if (selectedPosts.Any(x => !x.CanRetweetBy(this.twitterApi.CurrentUserId)))
                 {
-                    if (this._curPost.IsProtect)
+                    if (selectedPosts.Any(x => x.IsProtect))
                         MessageBox.Show("Protected.");
 
                     _DoFavRetweetFlags = false;
                     return;
                 }
-                if (_curList.SelectedIndices.Count > 15)
+
+                if (selectedPosts.Length > 15)
                 {
                     MessageBox.Show(Properties.Resources.RetweetLimitText);
                     _DoFavRetweetFlags = false;
                     return;
                 }
-                else if (_curList.SelectedIndices.Count > 1)
+                else if (selectedPosts.Length > 1)
                 {
                     string QuestionText = Properties.Resources.RetweetQuestion2;
                     if (_DoFavRetweetFlags) QuestionText = Properties.Resources.FavoriteRetweetQuestionText1;
@@ -10133,7 +9966,7 @@ namespace OpenTween
                 }
                 else
                 {
-                    if (!this._cfgCommon.RetweetNoConfirm)
+                    if (!SettingManager.Common.RetweetNoConfirm)
                     {
                         string Questiontext = Properties.Resources.RetweetQuestion1;
                         if (_DoFavRetweetFlags) Questiontext = Properties.Resources.FavoritesRetweetQuestionText2;
@@ -10145,22 +9978,14 @@ namespace OpenTween
                     }
                 }
 
-                var statusIds = new List<long>();
-                foreach (int idx in _curList.SelectedIndices)
-                {
-                    PostClass post = GetCurTabPost(idx);
-                    if (post.CanRetweetBy(this.twitterApi.CurrentUserId))
-                        statusIds.Add(post.StatusId);
-                }
+                var statusIds = selectedPosts.Select(x => x.StatusId).ToList();
 
                 await this.RetweetAsync(statusIds);
             }
         }
 
         private async void ReTweetStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.doReTweetOfficial(true);
-        }
+            => await this.doReTweetOfficial(true);
 
         private async Task FavoritesRetweetOfficial()
         {
@@ -10182,11 +10007,12 @@ namespace OpenTween
 
         private async Task FavoritesRetweetUnofficial()
         {
-            if (this.ExistCurrentPost && !_curPost.IsDm)
+            var post = this.CurrentPost;
+            if (this.ExistCurrentPost && !post.IsDm)
             {
                 _DoFavRetweetFlags = true;
                 var favoriteTask = this.FavoriteChange(true);
-                if (!_curPost.IsProtect && _DoFavRetweetFlags)
+                if (!post.IsProtect && _DoFavRetweetFlags)
                 {
                     _DoFavRetweetFlags = false;
                     doReTweetUnofficial();
@@ -10212,6 +10038,8 @@ namespace OpenTween
             statusHtml = Regex.Replace(statusHtml, "<a class=\"mention\" href=\"(?<href>.+?)\">(?<text>.+?)</a>", "${text}");
             // ハッシュタグ
             statusHtml = Regex.Replace(statusHtml, "<a class=\"hashtag\" href=\"(?<href>.+?)\">(?<text>.+?)</a>", "${text}");
+            // 絵文字
+            statusHtml = Regex.Replace(statusHtml, "<img class=\"emoji\" src=\".+?\" alt=\"(?<text>.+?)\" />", "${text}");
 
             // <br> 除去
             if (multiline)
@@ -10230,7 +10058,7 @@ namespace OpenTween
         {
             this.tweetDetailsView.DumpPostClass = this.DumpPostClassToolStripMenuItem.Checked;
 
-            if (_curPost != null)
+            if (this.CurrentPost != null)
                 await this.DispSelectedPost(true);
         }
 
@@ -10242,14 +10070,45 @@ namespace OpenTween
                 DebugModeToolStripMenuItem.Visible = false;
         }
 
-        private void ToolStripMenuItemUrlAutoShorten_CheckedChanged(object sender, EventArgs e)
+        private void UrlMultibyteSplitMenuItem_CheckedChanged(object sender, EventArgs e)
+            => this.urlMultibyteSplit = ((ToolStripMenuItem)sender).Checked;
+
+        private void PreventSmsCommandMenuItem_CheckedChanged(object sender, EventArgs e)
+            => this.preventSmsCommand = ((ToolStripMenuItem)sender).Checked;
+
+        private void UrlAutoShortenMenuItem_CheckedChanged(object sender, EventArgs e)
+            => SettingManager.Common.UrlConvertAuto = ((ToolStripMenuItem)sender).Checked;
+
+        private void IdeographicSpaceToSpaceMenuItem_Click(object sender, EventArgs e)
+        {
+            SettingManager.Common.WideSpaceConvert = ((ToolStripMenuItem)sender).Checked;
+            ModifySettingCommon = true;
+        }
+
+        private void FocusLockMenuItem_CheckedChanged(object sender, EventArgs e)
+        {
+            SettingManager.Common.FocusLockToStatusText = ((ToolStripMenuItem)sender).Checked;
+            ModifySettingCommon = true;
+        }
+
+        private void PostModeMenuItem_DropDownOpening(object sender, EventArgs e)
         {
-            this._cfgCommon.UrlConvertAuto = ToolStripMenuItemUrlAutoShorten.Checked;
+            UrlMultibyteSplitMenuItem.Checked = this.urlMultibyteSplit;
+            PreventSmsCommandMenuItem.Checked = this.preventSmsCommand;
+            UrlAutoShortenMenuItem.Checked = SettingManager.Common.UrlConvertAuto;
+            IdeographicSpaceToSpaceMenuItem.Checked = SettingManager.Common.WideSpaceConvert;
+            MultiLineMenuItem.Checked = SettingManager.Local.StatusMultiline;
+            FocusLockMenuItem.Checked = SettingManager.Common.FocusLockToStatusText;
         }
 
         private void ContextMenuPostMode_Opening(object sender, CancelEventArgs e)
         {
-            ToolStripMenuItemUrlAutoShorten.Checked = this._cfgCommon.UrlConvertAuto;
+            UrlMultibyteSplitPullDownMenuItem.Checked = this.urlMultibyteSplit;
+            PreventSmsCommandPullDownMenuItem.Checked = this.preventSmsCommand;
+            UrlAutoShortenPullDownMenuItem.Checked = SettingManager.Common.UrlConvertAuto;
+            IdeographicSpaceToSpacePullDownMenuItem.Checked = SettingManager.Common.WideSpaceConvert;
+            MultiLinePullDownMenuItem.Checked = SettingManager.Local.StatusMultiline;
+            FocusLockPullDownMenuItem.Checked = SettingManager.Common.FocusLockToStatusText;
         }
 
         private void TraceOutToolStripMenuItem_Click(object sender, EventArgs e)
@@ -10261,28 +10120,20 @@ namespace OpenTween
         }
 
         private void TweenMain_Deactivate(object sender, EventArgs e)
-        {
-            //画面が非アクティブになったら、発言欄の背景色をデフォルトへ
-            this.StatusText_Leave(StatusText, System.EventArgs.Empty);
-        }
+            => this.StatusText_Leave(StatusText, EventArgs.Empty); // 画面が非アクティブになったら、発言欄の背景色をデフォルトへ
 
         private void TabRenameMenuItem_Click(object sender, EventArgs e)
         {
             if (string.IsNullOrEmpty(_rclickTabName)) return;
 
-            string _;
-            TabRename(_rclickTabName, out _);
+            TabRename(_rclickTabName, out var _);
         }
 
         private async void BitlyToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await UrlConvertAsync(MyCommon.UrlConverter.Bitly);
-        }
+            => await this.UrlConvertAsync(MyCommon.UrlConverter.Bitly);
 
         private async void JmpToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await UrlConvertAsync(MyCommon.UrlConverter.Jmp);
-        }
+            => await this.UrlConvertAsync(MyCommon.UrlConverter.Jmp);
 
         private async void ApiUsageInfoMenuItem_Click(object sender, EventArgs e)
         {
@@ -10320,7 +10171,7 @@ namespace OpenTween
 
         private async void FollowCommandMenuItem_Click(object sender, EventArgs e)
         {
-            var id = _curPost?.ScreenName ?? "";
+            var id = this.CurrentPost?.ScreenName ?? "";
 
             await this.FollowCommand(id);
         }
@@ -10345,7 +10196,7 @@ namespace OpenTween
             {
                 try
                 {
-                    var task = this.twitterApi.FriendshipsCreate(id);
+                    var task = this.twitterApi.FriendshipsCreate(id).IgnoreResponse();
                     await dialog.WaitForAsync(this, task);
                 }
                 catch (WebApiException ex)
@@ -10360,7 +10211,7 @@ namespace OpenTween
 
         private async void RemoveCommandMenuItem_Click(object sender, EventArgs e)
         {
-            var id = _curPost?.ScreenName ?? "";
+            var id = this.CurrentPost?.ScreenName ?? "";
 
             await this.RemoveCommand(id, false);
         }
@@ -10388,7 +10239,7 @@ namespace OpenTween
             {
                 try
                 {
-                    var task = this.twitterApi.FriendshipsDestroy(id);
+                    var task = this.twitterApi.FriendshipsDestroy(id).IgnoreResponse();
                     await dialog.WaitForAsync(this, task);
                 }
                 catch (WebApiException ex)
@@ -10403,7 +10254,7 @@ namespace OpenTween
 
         private async void FriendshipMenuItem_Click(object sender, EventArgs e)
         {
-            var id = _curPost?.ScreenName ?? "";
+            var id = this.CurrentPost?.ScreenName ?? "";
 
             await this.ShowFriendship(id);
         }
@@ -10541,18 +10392,7 @@ namespace OpenTween
         }
 
         private async void OwnStatusMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.doShowUserStatus(tw.Username, false);
-            //if (!string.IsNullOrEmpty(tw.UserInfoXml))
-            //{
-            //    doShowUserStatus(tw.Username, false);
-            //}
-            //else
-            //{
-            //    MessageBox.Show(Properties.Resources.ShowYourProfileText1, "Your status", MessageBoxButtons.OK, MessageBoxIcon.Information);
-            //    return;
-            //}
-        }
+            => await this.doShowUserStatus(tw.Username, false);
 
         // TwitterIDでない固定文字列を調べる(文字列検証のみ 実際に取得はしない)
         // URLから切り出した文字列を渡す
@@ -10562,37 +10402,30 @@ namespace OpenTween
             if (this.tw.Configuration.NonUsernamePaths == null || this.tw.Configuration.NonUsernamePaths.Length == 0)
                 return !Regex.Match(name, @"^(about|jobs|tos|privacy|who_to_follow|download|messages)$", RegexOptions.IgnoreCase).Success;
             else
-                return !this.tw.Configuration.NonUsernamePaths.Contains(name.ToLowerInvariant());
-        }
-
-        private void IdeographicSpaceToSpaceToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            ModifySettingCommon = true;
-        }
-
-        private void ToolStripFocusLockMenuItem_CheckedChanged(object sender, EventArgs e)
-        {
-            ModifySettingCommon = true;
+                return !this.tw.Configuration.NonUsernamePaths.Contains(name, StringComparer.InvariantCultureIgnoreCase);
         }
 
         private void doQuoteOfficial()
         {
             if (this.ExistCurrentPost)
             {
-                if (_curPost.IsDm ||
-                    !StatusText.Enabled) return;
+                var post = this.CurrentPost;
+                if (post.IsDm || !StatusText.Enabled)
+                    return;
 
-                if (_curPost.IsProtect)
+                if (post.IsProtect)
                 {
                     MessageBox.Show("Protected.");
                     return;
                 }
 
-                StatusText.Text = " " + MyCommon.GetStatusUrl(_curPost);
+                var selection = (this.StatusText.SelectionStart, this.StatusText.SelectionLength);
 
                 this.inReplyTo = null;
 
-                StatusText.SelectionStart = 0;
+                StatusText.Text += " " + MyCommon.GetStatusUrl(post);
+
+                (this.StatusText.SelectionStart, this.StatusText.SelectionLength) = selection;
                 StatusText.Focus();
             }
         }
@@ -10602,35 +10435,36 @@ namespace OpenTween
             //RT @id:内容
             if (this.ExistCurrentPost)
             {
-                if (_curPost.IsDm || !StatusText.Enabled)
+                var post = this.CurrentPost;
+                if (post.IsDm || !StatusText.Enabled)
                     return;
 
-                if (_curPost.IsProtect)
+                if (post.IsProtect)
                 {
                     MessageBox.Show("Protected.");
                     return;
                 }
-                string rtdata = _curPost.Text;
+                string rtdata = post.Text;
                 rtdata = CreateRetweetUnofficial(rtdata, this.StatusText.Multiline);
 
-                StatusText.Text = " RT @" + _curPost.ScreenName + ": " + rtdata;
+                var selection = (this.StatusText.SelectionStart, this.StatusText.SelectionLength);
 
                 // 投稿時に in_reply_to_status_id を付加する
-                var inReplyToStatusId = this._curPost.RetweetedId ?? this._curPost.StatusId;
-                var inReplyToScreenName = this._curPost.ScreenName;
-                this.inReplyTo = Tuple.Create(inReplyToStatusId, inReplyToScreenName);
+                var inReplyToStatusId = post.RetweetedId ?? post.StatusId;
+                var inReplyToScreenName = post.ScreenName;
+                this.inReplyTo = (inReplyToStatusId, inReplyToScreenName);
 
-                StatusText.SelectionStart = 0;
+                StatusText.Text += " RT @" + post.ScreenName + ": " + rtdata;
+
+                (this.StatusText.SelectionStart, this.StatusText.SelectionLength) = selection;
                 StatusText.Focus();
             }
         }
 
-        private void QuoteStripMenuItem_Click(object sender, EventArgs e) // Handles QuoteStripMenuItem.Click, QtOpMenuItem.Click
-        {
-            doQuoteOfficial();
-        }
+        private void QuoteStripMenuItem_Click(object sender, EventArgs e)
+            => this.doQuoteOfficial();
 
-        private void SearchButton_Click(object sender, EventArgs e)
+        private async void SearchButton_Click(object sender, EventArgs e)
         {
             //公式検索
             Control pnl = ((Control)sender).Parent;
@@ -10693,15 +10527,12 @@ namespace OpenTween
                 SaveConfigsTabs();   //検索条件の保存
             }
 
-            this.GetPublicSearchAsync(tb);
             listView.Focus();
+            await this.RefreshTabAsync(tb);
         }
 
         private async void RefreshMoreStripMenuItem_Click(object sender, EventArgs e)
-        {
-            //もっと前を取得
-            await this.DoRefreshMore();
-        }
+            => await this.DoRefreshMore(); // もっと前を取得
 
         /// <summary>
         /// 指定されたタブのListTabにおける位置を返します
@@ -10743,7 +10574,8 @@ namespace OpenTween
                         // 関連発言なら既存のタブを置き換える
                         tb.TabName = relatedTab.TabName;
                         this.ClearTab(tb.TabName, false);
-                        _statuses.Tabs[tb.TabName] = tb;
+
+                        this._statuses.ReplaceTab(tb);
 
                         for (int i = 0; i < ListTab.TabPages.Count; i++)
                         {
@@ -10806,24 +10638,17 @@ namespace OpenTween
 
         private async Task doMoveToRTHome()
         {
-            if (_curList.SelectedIndices.Count > 0)
-            {
-                PostClass post = GetCurTabPost(_curList.SelectedIndices[0]);
-                if (post.RetweetedId != null)
-                {
-                    await this.OpenUriInBrowserAsync("https://twitter.com/" + GetCurTabPost(_curList.SelectedIndices[0]).RetweetedBy);
-                }
-            }
+            var post = this.CurrentPost;
+            if (post != null && post.RetweetedId != null)
+                await this.OpenUriInBrowserAsync("https://twitter.com/" + post.RetweetedBy);
         }
 
         private async void MoveToRTHomeMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.doMoveToRTHome();
-        }
+            => await this.doMoveToRTHome();
 
         private void ListManageUserContextToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            var screenName = this._curPost?.ScreenName;
+            var screenName = this.CurrentPost?.ScreenName;
             if (screenName != null)
                 this.ListManageUserContext(screenName);
         }
@@ -10856,17 +10681,13 @@ namespace OpenTween
 
         private void PublicSearchQueryMenuItem_Click(object sender, EventArgs e)
         {
-            if (ListTab.SelectedTab != null)
-            {
-                if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType != MyCommon.TabUsageType.PublicSearch) return;
-                ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focus();
-            }
+            var tab = this.CurrentTab;
+            if (tab.TabType != MyCommon.TabUsageType.PublicSearch) return;
+            this.CurrentTabPage.Controls["panelSearch"].Controls["comboSearch"].Focus();
         }
 
         private void StatusLabel_DoubleClick(object sender, EventArgs e)
-        {
-            MessageBox.Show(StatusLabel.TextHistory, "Logs", MessageBoxButtons.OK, MessageBoxIcon.None);
-        }
+            => MessageBox.Show(StatusLabel.TextHistory, "Logs", MessageBoxButtons.OK, MessageBoxIcon.None);
 
         private void HashManageMenuItem_Click(object sender, EventArgs e)
         {
@@ -10879,19 +10700,19 @@ namespace OpenTween
             {
                 return;
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
             if (rslt == DialogResult.Cancel) return;
             if (!string.IsNullOrEmpty(HashMgr.UseHash))
             {
                 HashStripSplitButton.Text = HashMgr.UseHash;
+                HashTogglePullDownMenuItem.Checked = true;
                 HashToggleMenuItem.Checked = true;
-                HashToggleToolStripMenuItem.Checked = true;
             }
             else
             {
                 HashStripSplitButton.Text = "#[-]";
+                HashTogglePullDownMenuItem.Checked = false;
                 HashToggleMenuItem.Checked = false;
-                HashToggleToolStripMenuItem.Checked = false;
             }
             //if (HashMgr.IsInsert && HashMgr.UseHash != "")
             //{
@@ -10918,37 +10739,33 @@ namespace OpenTween
             {
                 HashStripSplitButton.Text = HashMgr.UseHash;
                 HashToggleMenuItem.Checked = true;
-                HashToggleToolStripMenuItem.Checked = true;
+                HashTogglePullDownMenuItem.Checked = true;
             }
             else
             {
                 HashStripSplitButton.Text = "#[-]";
                 HashToggleMenuItem.Checked = false;
-                HashToggleToolStripMenuItem.Checked = false;
+                HashTogglePullDownMenuItem.Checked = false;
             }
             ModifySettingCommon = true;
             this.StatusText_TextChanged(null, null);
         }
 
         private void HashStripSplitButton_ButtonClick(object sender, EventArgs e)
-        {
-            HashToggleMenuItem_Click(null, null);
-        }
+            => this.HashToggleMenuItem_Click(null, null);
 
         public void SetPermanentHashtag(string hashtag)
         {
             HashMgr.SetPermanentHash("#" + hashtag);
             HashStripSplitButton.Text = HashMgr.UseHash;
+            HashTogglePullDownMenuItem.Checked = true;
             HashToggleMenuItem.Checked = true;
-            HashToggleToolStripMenuItem.Checked = true;
             //使用ハッシュタグとして設定
             ModifySettingCommon = true;
         }
 
         private void MenuItemOperate_DropDownOpening(object sender, EventArgs e)
         {
-            if (ListTab.SelectedTab == null) return;
-            if (_statuses == null || _statuses.Tabs == null || !_statuses.Tabs.ContainsKey(ListTab.SelectedTab.Text)) return;
             if (!this.ExistCurrentPost)
             {
                 this.ReplyOpMenuItem.Enabled = false;
@@ -10980,12 +10797,13 @@ namespace OpenTween
                 this.UnreadOpMenuItem.Enabled = true;
             }
 
-            if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || _curPost.IsDm)
+            var tab = this.CurrentTab;
+            var post = this.CurrentPost;
+            if (tab.TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || post.IsDm)
             {
                 this.FavOpMenuItem.Enabled = false;
                 this.UnFavOpMenuItem.Enabled = false;
                 this.OpenStatusOpMenuItem.Enabled = false;
-                this.OpenFavotterOpMenuItem.Enabled = false;
                 this.ShowRelatedStatusesMenuItem2.Enabled = false;
                 this.RtOpMenuItem.Enabled = false;
                 this.RtUnOpMenuItem.Enabled = false;
@@ -10998,10 +10816,9 @@ namespace OpenTween
                 this.FavOpMenuItem.Enabled = true;
                 this.UnFavOpMenuItem.Enabled = true;
                 this.OpenStatusOpMenuItem.Enabled = true;
-                this.OpenFavotterOpMenuItem.Enabled = true;
                 this.ShowRelatedStatusesMenuItem2.Enabled = true;  //PublicSearchの時問題出るかも
 
-                if (!_curPost.CanRetweetBy(this.twitterApi.CurrentUserId))
+                if (!post.CanRetweetBy(this.twitterApi.CurrentUserId))
                 {
                     this.RtOpMenuItem.Enabled = false;
                     this.RtUnOpMenuItem.Enabled = false;
@@ -11019,7 +10836,7 @@ namespace OpenTween
                 }
             }
 
-            if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType != MyCommon.TabUsageType.Favorites)
+            if (tab.TabType != MyCommon.TabUsageType.Favorites)
             {
                 this.RefreshPrevOpMenuItem.Enabled = true;
             }
@@ -11027,8 +10844,7 @@ namespace OpenTween
             {
                 this.RefreshPrevOpMenuItem.Enabled = false;
             }
-            if (!this.ExistCurrentPost
-                || _curPost.InReplyToStatusId == null)
+            if (!this.ExistCurrentPost || post.InReplyToStatusId == null)
             {
                 OpenRepSourceOpMenuItem.Enabled = false;
             }
@@ -11036,7 +10852,7 @@ namespace OpenTween
             {
                 OpenRepSourceOpMenuItem.Enabled = true;
             }
-            if (!this.ExistCurrentPost || string.IsNullOrEmpty(_curPost.RetweetedBy))
+            if (!this.ExistCurrentPost || string.IsNullOrEmpty(post.RetweetedBy))
             {
                 OpenRterHomeMenuItem.Enabled = false;
             }
@@ -11047,19 +10863,15 @@ namespace OpenTween
 
             if (this.ExistCurrentPost)
             {
-                this.DelOpMenuItem.Enabled = this._curPost.CanDeleteBy(this.tw.UserId);
+                this.DelOpMenuItem.Enabled = post.CanDeleteBy(this.tw.UserId);
             }
         }
 
         private void MenuItemTab_DropDownOpening(object sender, EventArgs e)
-        {
-            ContextMenuTabProperty_Opening(sender, null);
-        }
+            => this.ContextMenuTabProperty_Opening(sender, null);
 
         public Twitter TwitterInstance
-        {
-            get { return tw; }
-        }
+            => this.tw;
 
         private void SplitContainer3_SplitterMoved(object sender, SplitterEventArgs e)
         {
@@ -11096,17 +10908,12 @@ namespace OpenTween
             {
                 UndoRemoveTabMenuItem.Enabled = true;
             }
-            if (ListTab.SelectedTab != null)
-            {
-                if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch)
-                    PublicSearchQueryMenuItem.Enabled = true;
-                else
-                    PublicSearchQueryMenuItem.Enabled = false;
-            }
+
+            if (this.CurrentTab.TabType == MyCommon.TabUsageType.PublicSearch)
+                PublicSearchQueryMenuItem.Enabled = true;
             else
-            {
                 PublicSearchQueryMenuItem.Enabled = false;
-            }
+
             if (!this.ExistCurrentPost)
             {
                 this.CopySTOTMenuItem.Enabled = false;
@@ -11118,22 +10925,18 @@ namespace OpenTween
                 this.CopySTOTMenuItem.Enabled = true;
                 this.CopyURLMenuItem.Enabled = true;
                 this.CopyUserIdStripMenuItem.Enabled = true;
-                if (_curPost.IsDm) this.CopyURLMenuItem.Enabled = false;
-                if (_curPost.IsProtect) this.CopySTOTMenuItem.Enabled = false;
+
+                var post = this.CurrentPost;
+                if (post.IsDm) this.CopyURLMenuItem.Enabled = false;
+                if (post.IsProtect) this.CopySTOTMenuItem.Enabled = false;
             }
         }
 
         private void NotifyIcon1_MouseMove(object sender, MouseEventArgs e)
-        {
-            SetNotifyIconText();
-        }
+            => this.SetNotifyIconText();
 
         private async void UserStatusToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            var id = _curPost?.ScreenName ?? "";
-
-            await this.ShowUserStatus(id);
-        }
+            => await this.ShowUserStatus(this.CurrentPost?.ScreenName ?? "");
 
         private async Task doShowUserStatus(string id, bool ShowInputDialog)
         {
@@ -11195,20 +10998,17 @@ namespace OpenTween
         }
 
         internal Task ShowUserStatus(string id, bool ShowInputDialog)
-        {
-            return this.doShowUserStatus(id, ShowInputDialog);
-        }
+            => this.doShowUserStatus(id, ShowInputDialog);
 
         internal Task ShowUserStatus(string id)
-        {
-            return this.doShowUserStatus(id, true);
-        }
+            => this.doShowUserStatus(id, true);
 
         private async void ShowProfileMenuItem_Click(object sender, EventArgs e)
         {
-            if (_curPost != null)
+            var post = this.CurrentPost;
+            if (post != null)
             {
-                await this.ShowUserStatus(_curPost.ScreenName, false);
+                await this.ShowUserStatus(post.ScreenName, false);
             }
         }
 
@@ -11217,7 +11017,8 @@ namespace OpenTween
             if (!this.ExistCurrentPost)
                 return;
 
-            var statusId = this._curPost.RetweetedId ?? this._curPost.StatusId;
+            var post = this.CurrentPost;
+            var statusId = post.RetweetedId ?? post.StatusId;
             TwitterStatus status;
 
             using (var dialog = new WaitingDialog(Properties.Resources.RtCountMenuItem_ClickText1))
@@ -11296,14 +11097,7 @@ namespace OpenTween
         }
 
         private void SplitContainer2_MouseDoubleClick(object sender, MouseEventArgs e)
-        {
-            this.MultiLineMenuItem.PerformClick();
-        }
-
-        public PostClass CurPost
-        {
-            get { return _curPost; }
-        }
+            => this.MultiLinePullDownMenuItem.PerformClick();
 
 #region "画像投稿"
         private void ImageSelectMenuItem_Click(object sender, EventArgs e)
@@ -11342,18 +11136,14 @@ namespace OpenTween
         {
             TimelinePanel.Visible = true;
             TimelinePanel.Enabled = true;
-            ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
+            this.CurrentListView.Focus();
         }
 
         private void ImageSelector_FilePickDialogOpening(object sender, EventArgs e)
-        {
-            this.AllowDrop = false;
-        }
+            => this.AllowDrop = false;
 
         private void ImageSelector_FilePickDialogClosed(object sender, EventArgs e)
-        {
-            this.AllowDrop = true;
-        }
+            => this.AllowDrop = true;
 
         private void ImageSelector_SelectedServiceChanged(object sender, EventArgs e)
         {
@@ -11367,9 +11157,7 @@ namespace OpenTween
         }
 
         private void ImageSelector_VisibleChanged(object sender, EventArgs e)
-        {
-            this.StatusText_TextChanged(null, null);
-        }
+            => this.StatusText_TextChanged(null, null);
 
         /// <summary>
         /// StatusTextでCtrl+Vが押下された時の処理
@@ -11422,7 +11210,8 @@ namespace OpenTween
 
         private void MenuItemCommand_DropDownOpening(object sender, EventArgs e)
         {
-            if (this.ExistCurrentPost && !_curPost.IsDm)
+            var post = this.CurrentPost;
+            if (this.ExistCurrentPost && !post.IsDm)
                 RtCountMenuItem.Enabled = true;
             else
                 RtCountMenuItem.Enabled = false;
@@ -11434,14 +11223,13 @@ namespace OpenTween
         }
 
         private void CopyUserIdStripMenuItem_Click(object sender, EventArgs e)
-        {
-            CopyUserId();
-        }
+            => this.CopyUserId();
 
         private void CopyUserId()
         {
-            if (_curPost == null) return;
-            string clstr = _curPost.ScreenName;
+            var post = this.CurrentPost;
+            if (post == null) return;
+            var clstr = post.ScreenName;
             try
             {
                 Clipboard.SetDataObject(clstr, false, 5, 100);
@@ -11454,15 +11242,16 @@ namespace OpenTween
 
         private async void ShowRelatedStatusesMenuItem_Click(object sender, EventArgs e)
         {
-            if (this.ExistCurrentPost && !_curPost.IsDm)
+            var post = this.CurrentPost;
+            if (this.ExistCurrentPost && !post.IsDm)
             {
                 try
                 {
-                    await this.OpenRelatedTab(this._curPost);
+                    await this.OpenRelatedTab(post);
                 }
                 catch (TabException ex)
                 {
-                    MessageBox.Show(this, ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
+                    MessageBox.Show(this, ex.Message, ApplicationSettings.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                 }
             }
         }
@@ -11472,7 +11261,7 @@ namespace OpenTween
         /// </summary>
         /// <param name="statusId">表示するツイートのID</param>
         /// <exception cref="TabException">名前の重複が多すぎてタブを作成できない場合</exception>
-        private async Task OpenRelatedTab(long statusId)
+        public async Task OpenRelatedTab(long statusId)
         {
             var post = this._statuses[statusId];
             if (post == null)
@@ -11506,9 +11295,11 @@ namespace OpenTween
 
             var tabName = this._statuses.MakeTabName("Related Tweets");
 
-            tabRelated = new RelatedPostsTabModel(tabName, post);
-            tabRelated.UnreadManage = false;
-            tabRelated.Notify = false;
+            tabRelated = new RelatedPostsTabModel(tabName, post)
+            {
+                UnreadManage = false,
+                Notify = false,
+            };
 
             this._statuses.AddTab(tabRelated);
             this.AddNewTab(tabRelated, startup: false);
@@ -11524,7 +11315,7 @@ namespace OpenTween
                 }
             }
 
-            await this.GetRelatedTweetsAsync(tabRelated);
+            await this.RefreshTabAsync(tabRelated);
 
             tabPage = this.ListTab.TabPages.Cast<TabPage>()
                 .FirstOrDefault(x => x.Text == tabRelated.TabName);
@@ -11556,9 +11347,7 @@ namespace OpenTween
         }
 
         private void tw_UserIdChanged()
-        {
-            this.ModifySettingCommon = true;
-        }
+            => this.ModifySettingCommon = true;
 
 #region "Userstream"
         private async void tw_PostDeleted(object sender, PostDeletedEventArgs e)
@@ -11570,11 +11359,12 @@ namespace OpenTween
                     await this.InvokeAsync(async () =>
                     {
                         this._statuses.RemovePostFromAllTabs(e.StatusId, setIsDeleted: true);
-                        if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(e.StatusId))
+                        if (this.CurrentTab.Contains(e.StatusId))
                         {
                             this.PurgeListViewItemCache();
-                            ((DetailsListView)_curTab.Tag).Update();
-                            if (_curPost != null && _curPost.StatusId == e.StatusId)
+                            this.CurrentListView.Update();
+                            var post = this.CurrentPost;
+                            if (post != null && post.StatusId == e.StatusId)
                                 await this.DispSelectedPost(true);
                         }
                     });
@@ -11591,32 +11381,16 @@ namespace OpenTween
             }
         }
 
-        private int userStreamsRefreshing = 0;
-
-        private async void tw_NewPostFromStream(object sender, EventArgs e)
+        private void tw_NewPostFromStream(object sender, EventArgs e)
         {
-            if (this._cfgCommon.ReadOldPosts)
+            if (SettingManager.Common.ReadOldPosts)
             {
                 _statuses.SetReadHomeTab(); //新着時未読クリア
             }
 
             this._statuses.DistributePosts();
 
-            if (this._cfgCommon.UserstreamPeriod > 0) return;
-
-            // userStreamsRefreshing が 0 (インクリメント後は1) であれば RefreshTimeline を実行
-            if (Interlocked.Increment(ref this.userStreamsRefreshing) == 1)
-            {
-                try
-                {
-                    await this.InvokeAsync(() => this.RefreshTimeline())
-                        .ConfigureAwait(false);
-                }
-                finally
-                {
-                    Interlocked.Exchange(ref this.userStreamsRefreshing, 0);
-                }
-            }
+            this.RefreshThrottlingTimer.Invoke();
         }
 
         private async void tw_UserStreamStarted(object sender, EventArgs e)
@@ -11710,12 +11484,12 @@ namespace OpenTween
             NotifyEvent(ev);
             if (ev.Event == "favorite" || ev.Event == "unfavorite")
             {
-                if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(ev.Id))
+                if (this.CurrentTab.Contains(ev.Id))
                 {
                     this.PurgeListViewItemCache();
-                    ((DetailsListView)_curTab.Tag).Update();
+                    this.CurrentListView.Update();
                 }
-                if (ev.Event == "unfavorite" && ev.Username.ToLowerInvariant().Equals(tw.Username.ToLowerInvariant()))
+                if (ev.Event == "unfavorite" && ev.Username.Equals(tw.Username, StringComparison.InvariantCultureIgnoreCase))
                 {
                     var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites);
                     favTab.EnqueueRemovePost(ev.Id, setIsDeleted: false);
@@ -11732,7 +11506,7 @@ namespace OpenTween
                 //if (SettingDialog.DispUsername) NotifyIcon1.BalloonTipTitle = tw.Username + " - "; else NotifyIcon1.BalloonTipTitle = "";
                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [" + ev.Event.ToUpper() + "] by " + ((string)(!string.IsNullOrEmpty(ev.Username) ? ev.Username : ""), string);
                 StringBuilder title = new StringBuilder();
-                if (this._cfgCommon.DispUsername)
+                if (SettingManager.Common.DispUsername)
                 {
                     title.Append(tw.Username);
                     title.Append(" - ");
@@ -11741,7 +11515,7 @@ namespace OpenTween
                 {
                     //title.Clear();
                 }
-                title.Append(Application.ProductName);
+                title.Append(ApplicationSettings.ApplicationName);
                 title.Append(" [");
                 title.Append(ev.Event.ToUpper(CultureInfo.CurrentCulture));
                 title.Append("] by ");
@@ -11765,7 +11539,7 @@ namespace OpenTween
                     text = " ";
                 }
                 //NotifyIcon1.ShowBalloonTip(500);
-                if (this._cfgCommon.IsUseNotifyGrowl)
+                if (SettingManager.Common.IsUseNotifyGrowl)
                 {
                     gh.Notify(GrowlHelper.NotifyType.UserStreamEvent,
                               ev.Id.ToString(), title.ToString(), text);
@@ -11780,10 +11554,10 @@ namespace OpenTween
             }
 
             //サウンド再生
-            string snd = this._cfgCommon.EventSoundFile;
-            if (!_initial && this._cfgCommon.PlaySound && !string.IsNullOrEmpty(snd))
+            string snd = SettingManager.Common.EventSoundFile;
+            if (!_initial && SettingManager.Common.PlaySound && !string.IsNullOrEmpty(snd))
             {
-                if ((ev.Eventtype & this._cfgCommon.EventNotifyFlag) != 0 && IsMyEventNotityAsEventType(ev))
+                if ((ev.Eventtype & SettingManager.Common.EventNotifyFlag) != 0 && IsMyEventNotityAsEventType(ev))
                 {
                     try
                     {
@@ -11867,14 +11641,17 @@ namespace OpenTween
         {
             if (evtDialog == null || evtDialog.IsDisposed)
             {
-                evtDialog = null;
-                evtDialog = new EventViewerDialog();
-                evtDialog.Owner = this;
+                this.evtDialog = new EventViewerDialog
+                {
+                    Owner = this,
+                };
+
                 //親の中央に表示
-                Point pos = evtDialog.Location;
-                pos.X = Convert.ToInt32(this.Location.X + this.Size.Width / 2 - evtDialog.Size.Width / 2);
-                pos.Y = Convert.ToInt32(this.Location.Y + this.Size.Height / 2 - evtDialog.Size.Height / 2);
-                evtDialog.Location = pos;
+                this.evtDialog.Location = new Point
+                {
+                    X = Convert.ToInt32(this.Location.X + this.Size.Width / 2 - evtDialog.Size.Width / 2),
+                    Y = Convert.ToInt32(this.Location.Y + this.Size.Height / 2 - evtDialog.Size.Height / 2),
+                };
             }
             evtDialog.EventSource = tw.StoredEvent;
             if (!evtDialog.Visible)
@@ -11885,7 +11662,7 @@ namespace OpenTween
             {
                 evtDialog.Activate();
             }
-            this.TopMost = this._cfgCommon.AlwaysTop;
+            this.TopMost = SettingManager.Common.AlwaysTop;
         }
 #endregion
 
@@ -11899,39 +11676,28 @@ namespace OpenTween
             }
             catch (Exception)
             {
-                MessageBox.Show("Failed to restart. Please run " + Application.ProductName + " manually.");
+                MessageBox.Show("Failed to restart. Please run " + ApplicationSettings.ApplicationName + " manually.");
             }
         }
 
-        private async void OpenOwnFavedMenuItem_Click(object sender, EventArgs e)
-        {
-            if (!string.IsNullOrEmpty(tw.Username))
-                await this.OpenUriInBrowserAsync(Properties.Resources.FavstarUrl + "users/" + tw.Username + "/recent");
-        }
-
         private async void OpenOwnHomeMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.OpenUriInBrowserAsync(MyCommon.TwitterUrl + tw.Username);
-        }
+            => await this.OpenUriInBrowserAsync(MyCommon.TwitterUrl + tw.Username);
 
         private bool ExistCurrentPost
         {
             get
             {
-                if (_curPost == null) return false;
-                if (_curPost.IsDeleted) return false;
-                return true;
+                var post = this.CurrentPost;
+                return post != null && !post.IsDeleted;
             }
         }
 
-        private void ShowUserTimelineToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            ShowUserTimeline();
-        }
+        private async void ShowUserTimelineToolStripMenuItem_Click(object sender, EventArgs e)
+            => await this.ShowUserTimeline();
 
         private string GetUserIdFromCurPostOrInput(string caption)
         {
-            var id = _curPost?.ScreenName ?? "";
+            var id = this.CurrentPost?.ScreenName ?? "";
 
             using (InputTabName inputName = new InputTabName())
             {
@@ -11951,27 +11717,36 @@ namespace OpenTween
             return id;
         }
 
-        private void UserTimelineToolStripMenuItem_Click(object sender, EventArgs e)
+        private async void UserTimelineToolStripMenuItem_Click(object sender, EventArgs e)
         {
             string id = GetUserIdFromCurPostOrInput("Show UserTimeline");
             if (!string.IsNullOrEmpty(id))
             {
-                AddNewTabForUserTimeline(id);
+                await this.AddNewTabForUserTimeline(id);
             }
         }
 
-        private async void UserFavorareToolStripMenuItem_Click(object sender, EventArgs e)
+        private void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e)
         {
-            string id = GetUserIdFromCurPostOrInput("Show Favstar");
-            if (!string.IsNullOrEmpty(id))
-            {
-                await this.OpenUriInBrowserAsync(Properties.Resources.FavstarUrl + "users/" + id + "/recent");
-            }
+            if (e.Mode == Microsoft.Win32.PowerModes.Resume) osResumed = true;
         }
 
-        private void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e)
+        private async void SystemEvents_TimeChanged(object sender, EventArgs e)
         {
-            if (e.Mode == Microsoft.Win32.PowerModes.Resume) osResumed = true;
+            var prevTimeOffset = TimeZoneInfo.Local.BaseUtcOffset;
+
+            TimeZoneInfo.ClearCachedData();
+
+            var curTimeOffset = TimeZoneInfo.Local.BaseUtcOffset;
+
+            if (curTimeOffset != prevTimeOffset)
+            {
+                // タイムゾーンの変更を反映
+                this.PurgeListViewItemCache();
+                this.CurrentListView.Refresh();
+
+                await this.DispSelectedPost(forceupdate: true);
+            }
         }
 
         private void TimelineRefreshEnableChange(bool isEnable)
@@ -11988,22 +11763,21 @@ namespace OpenTween
         }
 
         private void StopRefreshAllMenuItem_CheckedChanged(object sender, EventArgs e)
-        {
-            TimelineRefreshEnableChange(!StopRefreshAllMenuItem.Checked);
-        }
+            => this.TimelineRefreshEnableChange(!StopRefreshAllMenuItem.Checked);
 
         private async Task OpenUserAppointUrl()
         {
-            if (this._cfgCommon.UserAppointUrl != null)
+            if (SettingManager.Common.UserAppointUrl != null)
             {
-                if (this._cfgCommon.UserAppointUrl.Contains("{ID}") || this._cfgCommon.UserAppointUrl.Contains("{STATUS}"))
+                if (SettingManager.Common.UserAppointUrl.Contains("{ID}") || SettingManager.Common.UserAppointUrl.Contains("{STATUS}"))
                 {
-                    if (_curPost != null)
+                    var post = this.CurrentPost;
+                    if (post != null)
                     {
-                        string xUrl = this._cfgCommon.UserAppointUrl;
-                        xUrl = xUrl.Replace("{ID}", _curPost.ScreenName);
+                        string xUrl = SettingManager.Common.UserAppointUrl;
+                        xUrl = xUrl.Replace("{ID}", post.ScreenName);
 
-                        var statusId = _curPost.RetweetedId ?? _curPost.StatusId;
+                        var statusId = post.RetweetedId ?? post.StatusId;
                         xUrl = xUrl.Replace("{STATUS}", statusId.ToString());
 
                         await this.OpenUriInBrowserAsync(xUrl);
@@ -12011,15 +11785,13 @@ namespace OpenTween
                 }
                 else
                 {
-                    await this.OpenUriInBrowserAsync(this._cfgCommon.UserAppointUrl);
+                    await this.OpenUriInBrowserAsync(SettingManager.Common.UserAppointUrl);
                 }
             }
         }
 
         private async void OpenUserSpecifiedUrlMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.OpenUserAppointUrl();
-        }
+            => await this.OpenUserAppointUrl();
 
         private async void GrowlHelper_Callback(object sender, GrowlHelper.NotifyCallbackEventArgs e)
         {
@@ -12050,19 +11822,13 @@ namespace OpenTween
         }
 
         private void tweetThumbnail1_ThumbnailLoading(object sender, EventArgs e)
-        {
-            this.SplitContainer3.Panel2Collapsed = false;
-        }
+            => this.SplitContainer3.Panel2Collapsed = false;
 
         private async void tweetThumbnail1_ThumbnailDoubleClick(object sender, ThumbnailDoubleClickEventArgs e)
-        {
-            await this.OpenThumbnailPicture(e.Thumbnail);
-        }
+            => await this.OpenThumbnailPicture(e.Thumbnail);
 
         private async void tweetThumbnail1_ThumbnailImageSearchClick(object sender, ThumbnailImageSearchEventArgs e)
-        {
-            await this.OpenUriInBrowserAsync(e.ImageUrl);
-        }
+            => await this.OpenUriInBrowserAsync(e.ImageUrl);
 
         private async Task OpenThumbnailPicture(ThumbnailInfo thumbnail)
         {
@@ -12072,9 +11838,7 @@ namespace OpenTween
         }
 
         private async void TwitterApiStatusToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            await this.OpenUriInBrowserAsync(Twitter.ServiceAvailabilityStatusUrl);
-        }
+            => await this.OpenUriInBrowserAsync(Twitter.ServiceAvailabilityStatusUrl);
 
         private void PostButton_KeyDown(object sender, KeyEventArgs e)
         {
@@ -12088,47 +11852,37 @@ namespace OpenTween
 
         private void ContextMenuColumnHeader_Opening(object sender, CancelEventArgs e)
         {
-            this.IconSizeNoneToolStripMenuItem.Checked = this._cfgCommon.IconSize == MyCommon.IconSizes.IconNone;
-            this.IconSize16ToolStripMenuItem.Checked = this._cfgCommon.IconSize == MyCommon.IconSizes.Icon16;
-            this.IconSize24ToolStripMenuItem.Checked = this._cfgCommon.IconSize == MyCommon.IconSizes.Icon24;
-            this.IconSize48ToolStripMenuItem.Checked = this._cfgCommon.IconSize == MyCommon.IconSizes.Icon48;
-            this.IconSize48_2ToolStripMenuItem.Checked = this._cfgCommon.IconSize == MyCommon.IconSizes.Icon48_2;
+            this.IconSizeNoneToolStripMenuItem.Checked = SettingManager.Common.IconSize == MyCommon.IconSizes.IconNone;
+            this.IconSize16ToolStripMenuItem.Checked = SettingManager.Common.IconSize == MyCommon.IconSizes.Icon16;
+            this.IconSize24ToolStripMenuItem.Checked = SettingManager.Common.IconSize == MyCommon.IconSizes.Icon24;
+            this.IconSize48ToolStripMenuItem.Checked = SettingManager.Common.IconSize == MyCommon.IconSizes.Icon48;
+            this.IconSize48_2ToolStripMenuItem.Checked = SettingManager.Common.IconSize == MyCommon.IconSizes.Icon48_2;
 
-            this.LockListSortOrderToolStripMenuItem.Checked = this._cfgCommon.SortOrderLock;
+            this.LockListSortOrderToolStripMenuItem.Checked = SettingManager.Common.SortOrderLock;
         }
 
         private void IconSizeNoneToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            ChangeListViewIconSize(MyCommon.IconSizes.IconNone);
-        }
+            => this.ChangeListViewIconSize(MyCommon.IconSizes.IconNone);
 
         private void IconSize16ToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            ChangeListViewIconSize(MyCommon.IconSizes.Icon16);
-        }
+            => this.ChangeListViewIconSize(MyCommon.IconSizes.Icon16);
 
         private void IconSize24ToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            ChangeListViewIconSize(MyCommon.IconSizes.Icon24);
-        }
+            => this.ChangeListViewIconSize(MyCommon.IconSizes.Icon24);
 
         private void IconSize48ToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            ChangeListViewIconSize(MyCommon.IconSizes.Icon48);
-        }
+            => this.ChangeListViewIconSize(MyCommon.IconSizes.Icon48);
 
         private void IconSize48_2ToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            ChangeListViewIconSize(MyCommon.IconSizes.Icon48_2);
-        }
+            => this.ChangeListViewIconSize(MyCommon.IconSizes.Icon48_2);
 
         private void ChangeListViewIconSize(MyCommon.IconSizes iconSize)
         {
-            if (this._cfgCommon.IconSize == iconSize) return;
+            if (SettingManager.Common.IconSize == iconSize) return;
 
             var oldIconCol = _iconCol;
 
-            this._cfgCommon.IconSize = iconSize;
+            SettingManager.Common.IconSize = iconSize;
             ApplyListViewIconSize(iconSize);
 
             if (_iconCol != oldIconCol)
@@ -12139,7 +11893,7 @@ namespace OpenTween
                 }
             }
 
-            _curList?.Refresh();
+            this.CurrentListView.Refresh();
 
             ModifySettingCommon = true;
         }
@@ -12147,9 +11901,9 @@ namespace OpenTween
         private void LockListSortToolStripMenuItem_Click(object sender, EventArgs e)
         {
             var state = this.LockListSortOrderToolStripMenuItem.Checked;
-            if (this._cfgCommon.SortOrderLock == state) return;
+            if (SettingManager.Common.SortOrderLock == state) return;
 
-            this._cfgCommon.SortOrderLock = state;
+            SettingManager.Common.SortOrderLock = state;
 
             ModifySettingCommon = true;
         }