OSDN Git Service

鍵垢であっても自分自身のツイートを公式RTできるように修正
[opentween/open-tween.git] / OpenTween / Tween.cs
index f97089e..5f678a1 100644 (file)
@@ -41,6 +41,7 @@ using System.Media;
 using System.Net;
 using System.Net.Http;
 using System.Reflection;
+using System.Runtime.InteropServices;
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Threading;
@@ -1424,22 +1425,21 @@ namespace OpenTween
 
             if (MyCommon._endingFlag) return;
 
-            try
+            if (addCount > 0)
             {
-                foreach (TabPage tab in ListTab.TabPages)
+                if (this._cfgCommon.TabIconDisp)
                 {
-                    TabModel tabInfo = _statuses.Tabs[tab.Text];
-
-                    if (tabInfo.UnreadCount > 0)
-                        if (this._cfgCommon.TabIconDisp)
-                            if (tab.ImageIndex == -1) tab.ImageIndex = 0; //タブアイコン
+                    foreach (var tabPage in this.ListTab.TabPages.Cast<TabPage>())
+                    {
+                        var tabModel = this._statuses.Tabs[tabPage.Text];
+                        if (tabModel.UnreadCount > 0 && tabPage.ImageIndex != 0)
+                            tabPage.ImageIndex = 0; // 未読アイコン
+                    }
+                }
+                else
+                {
+                    this.ListTab.Refresh();
                 }
-                if (!this._cfgCommon.TabIconDisp) ListTab.Refresh();
-            }
-            catch (Exception)
-            {
-                //ex.Data["Msg"] = "Ref1, UseAPI=" + SettingDialog.UseAPI.ToString();
-                //throw;
             }
 
             // リストに反映&選択状態復元
@@ -2769,6 +2769,13 @@ namespace OpenTween
                 p.Report(errMsg);
                 this._myStatusError = true;
             }
+            catch (UnauthorizedAccessException ex)
+            {
+                // アップロード対象のファイルが開けなかった場合など
+                errMsg = $"Err:{ex.Message}(PostMessage)";
+                p.Report(errMsg);
+                this._myStatusError = true;
+            }
             finally
             {
                 // 使い終わった MediaItem は破棄する
@@ -2788,13 +2795,10 @@ namespace OpenTween
                 !errMsg.StartsWith("OK:", StringComparison.Ordinal) &&
                 !errMsg.StartsWith("Warn:", StringComparison.Ordinal))
             {
+                var message = string.Format(Properties.Resources.StatusUpdateFailed, errMsg, status.status);
+
                 var ret = MessageBox.Show(
-                    string.Format(
-                        "{0}   --->   [ " + errMsg + " ]" + Environment.NewLine +
-                        "\"" + status.status + "\"" + Environment.NewLine +
-                        "{1}",
-                        Properties.Resources.StatusUpdateFailed1,
-                        Properties.Resources.StatusUpdateFailed2),
+                    message,
                     "Failed to update status",
                     MessageBoxButtons.RetryCancel,
                     MessageBoxIcon.Question);
@@ -2880,11 +2884,10 @@ namespace OpenTween
 
             p.Report("Posting...");
 
-            var retweetTasks = from statusId in statusIds
-                               select this.tw.PostRetweet(statusId, read);
-
-            await Task.WhenAll(retweetTasks)
-                .ConfigureAwait(false);
+            foreach (var statusId in statusIds)
+            {
+                await this.tw.PostRetweet(statusId, read).ConfigureAwait(false);
+            }
 
             if (ct.IsCancellationRequested)
                 return;
@@ -3365,7 +3368,7 @@ namespace OpenTween
                 FavorareMenuItem.Enabled = true;
                 ShowRelatedStatusesMenuItem.Enabled = true;  //PublicSearchの時問題出るかも
 
-                if (_curPost.IsProtect)
+                if (!_curPost.CanRetweetBy(this.twitterApi.CurrentUserId))
                 {
                     ReTweetStripMenuItem.Enabled = false;
                     ReTweetUnofficialStripMenuItem.Enabled = false;
@@ -3471,14 +3474,25 @@ namespace OpenTween
                         }
                         else
                         {
-                            if (post.RetweetedId != null && post.UserId == this.tw.UserId)
-                                // 他人に RT された自分のツイート
-                                await this.twitterApi.StatusesDestroy(post.RetweetedId.Value)
-                                    .IgnoreResponse();
-                            else
-                                // 自分のツイート or 自分が RT したツイート
+                            if (post.RetweetedByUserId == this.tw.UserId)
+                                // 自分が RT したツイート (自分が RT した自分のツイートも含む)
+                                //   => RT を取り消し
                                 await this.twitterApi.StatusesDestroy(post.StatusId)
                                     .IgnoreResponse();
+
+                            if (post.UserId == this.tw.UserId)
+                            {
+                                if (post.RetweetedId != null)
+                                    // 他人に RT された自分のツイート
+                                    //   => RT 元の自分のツイートを削除
+                                    await this.twitterApi.StatusesDestroy(post.RetweetedId.Value)
+                                        .IgnoreResponse();
+                                else
+                                    // 自分のツイート
+                                    //   => ツイートを削除
+                                    await this.twitterApi.StatusesDestroy(post.StatusId)
+                                        .IgnoreResponse();
+                            }
                         }
                     }
                     catch (WebApiException ex)
@@ -4802,9 +4816,11 @@ namespace OpenTween
             //文字数カウント
             var remainCount = this.tw.GetTextLengthRemain(statusText);
 
-            if (this.ImageSelector.Visible && !string.IsNullOrEmpty(this.ImageSelector.ServiceName))
+            var uploadService = this.ImageSelector.SelectedService;
+            if (this.ImageSelector.Visible && uploadService != null)
             {
-                remainCount -= this.tw.Configuration.CharactersReservedPerMedia;
+                // TODO: ImageSelector で選択中の画像の枚数が mediaCount 引数に渡るようにする
+                remainCount -= uploadService.GetReservedTextLength(1);
             }
 
             return remainCount;
@@ -4816,7 +4832,7 @@ namespace OpenTween
                 return;
 
             var listCache = this._listItemCache;
-            if (listCache != null && listCache.IsSupersetOf(e.StartIndex, e.EndIndex))
+            if (listCache?.TargetList == sender && listCache.IsSupersetOf(e.StartIndex, e.EndIndex))
             {
                 // If the newly requested cache is a subset of the old cache,
                 // no need to rebuild everything, so do nothing.
@@ -4830,7 +4846,7 @@ namespace OpenTween
         private void MyList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
         {
             var listCache = this._listItemCache;
-            if (listCache != null && listCache.TargetList == sender)
+            if (listCache?.TargetList == sender)
             {
                 ListViewItem item;
                 PostClass cacheItemPost;
@@ -5464,74 +5480,89 @@ namespace OpenTween
         private void JumpUnreadMenuItem_Click(object sender, EventArgs e)
         {
             int bgnIdx = ListTab.TabPages.IndexOf(_curTab);
-            int idx = -1;
-            DetailsListView lst = null;
 
             if (ImageSelector.Enabled)
                 return;
 
+            TabModel foundTab = null;
+            int foundIndex = 0;
+
+            DetailsListView lst = null;
+
             //現在タブから最終タブまで探索
             for (int i = bgnIdx; i < ListTab.TabPages.Count; i++)
             {
-                //未読Index取得
-                idx = _statuses.Tabs[ListTab.TabPages[i].Text].NextUnreadIndex;
-                if (idx > -1)
+                var tabPage = this.ListTab.TabPages[i];
+                var tab = this._statuses.Tabs[tabPage.Text];
+                var unreadIndex = tab.NextUnreadIndex;
+
+                if (unreadIndex != -1)
                 {
                     ListTab.SelectedIndex = i;
-                    lst = (DetailsListView)ListTab.TabPages[i].Tag;
-                    //_curTab = ListTab.TabPages[i];
+                    foundTab = tab;
+                    foundIndex = unreadIndex;
+                    lst = (DetailsListView)tabPage.Tag;
                     break;
                 }
             }
 
             //未読みつからず&現在タブが先頭ではなかったら、先頭タブから現在タブの手前まで探索
-            if (idx == -1 && bgnIdx > 0)
+            if (foundTab == null && bgnIdx > 0)
             {
                 for (int i = 0; i < bgnIdx; i++)
                 {
-                    idx = _statuses.Tabs[ListTab.TabPages[i].Text].NextUnreadIndex;
-                    if (idx > -1)
+                    var tabPage = this.ListTab.TabPages[i];
+                    var tab = this._statuses.Tabs[tabPage.Text];
+                    var unreadIndex = tab.NextUnreadIndex;
+
+                    if (unreadIndex != -1)
                     {
                         ListTab.SelectedIndex = i;
-                        lst = (DetailsListView)ListTab.TabPages[i].Tag;
-                        //_curTab = ListTab.TabPages[i];
+                        foundTab = tab;
+                        foundIndex = unreadIndex;
+                        lst = (DetailsListView)tabPage.Tag;
                         break;
                     }
                 }
             }
 
-            //全部調べたが未読見つからず→先頭タブの最新発言へ
-            if (idx == -1)
+            if (foundTab == null)
             {
+                //全部調べたが未読見つからず→先頭タブの最新発言へ
                 ListTab.SelectedIndex = 0;
-                lst = (DetailsListView)ListTab.TabPages[0].Tag;
-                //_curTab = ListTab.TabPages[0];
+                var tabPage = this.ListTab.TabPages[0];
+                var tab = this._statuses.Tabs[tabPage.Text];
+
+                if (tab.AllCount == 0)
+                    return;
+
                 if (_statuses.SortOrder == SortOrder.Ascending)
-                    idx = lst.VirtualListSize - 1;
+                    foundIndex = tab.AllCount - 1;
                 else
-                    idx = 0;
+                    foundIndex = 0;
+
+                lst = (DetailsListView)tabPage.Tag;
             }
 
-            if (lst.VirtualListSize > 0 && idx > -1 && lst.VirtualListSize > idx)
+            SelectListItem(lst, foundIndex);
+
+            if (_statuses.SortMode == ComparerMode.Id)
             {
-                SelectListItem(lst, idx);
-                if (_statuses.SortMode == ComparerMode.Id)
+                if (_statuses.SortOrder == SortOrder.Ascending && lst.Items[foundIndex].Position.Y > lst.ClientSize.Height - _iconSz - 10 ||
+                    _statuses.SortOrder == SortOrder.Descending && lst.Items[foundIndex].Position.Y < _iconSz + 10)
                 {
-                    if (_statuses.SortOrder == SortOrder.Ascending && lst.Items[idx].Position.Y > lst.ClientSize.Height - _iconSz - 10 ||
-                       _statuses.SortOrder == SortOrder.Descending && lst.Items[idx].Position.Y < _iconSz + 10)
-                    {
-                        MoveTop();
-                    }
-                    else
-                    {
-                        lst.EnsureVisible(idx);
-                    }
+                    MoveTop();
                 }
                 else
                 {
-                    lst.EnsureVisible(idx);
+                    lst.EnsureVisible(foundIndex);
                 }
             }
+            else
+            {
+                lst.EnsureVisible(foundIndex);
+            }
+
             lst.Focus();
         }
 
@@ -6393,11 +6424,6 @@ namespace OpenTween
             foreach (int idx in _curList.SelectedIndices)
             {
                 PostClass post = _statuses.Tabs[_curTab.Text][idx];
-                if (post.IsProtect)
-                {
-                    IsProtected = true;
-                    continue;
-                }
                 if (post.IsDeleted) continue;
                 if (!isDm)
                 {
@@ -6431,28 +6457,30 @@ namespace OpenTween
 
         private void CopyIdUri()
         {
-            string clstr = "";
-            StringBuilder sb = new StringBuilder();
-            if (this._curTab == null) return;
-            if (this._statuses.GetTabByName(this._curTab.Text) == null) return;
-            if (this._statuses.GetTabByName(this._curTab.Text).TabType == MyCommon.TabUsageType.DirectMessage) return;
+            if (this._curTab == null)
+                return;
+
+            var tab = this._statuses.GetTabByName(this._curTab.Text);
+            if (tab == null || tab is DirectMessagesTabModel)
+                return;
+
+            var copyUrls = new List<string>();
             foreach (int idx in _curList.SelectedIndices)
             {
-                var post = _statuses.Tabs[_curTab.Text][idx];
-                sb.Append(MyCommon.GetStatusUrl(post));
-                sb.Append(Environment.NewLine);
+                var post = tab[idx];
+                copyUrls.Add(MyCommon.GetStatusUrl(post));
             }
-            if (sb.Length > 0)
+
+            if (copyUrls.Count == 0)
+                return;
+
+            try
             {
-                clstr = sb.ToString();
-                try
-                {
-                    Clipboard.SetDataObject(clstr, false, 5, 100);
-                }
-                catch (Exception ex)
-                {
-                    MessageBox.Show(ex.Message);
-                }
+                Clipboard.SetDataObject(string.Join(Environment.NewLine, copyUrls), false, 5, 100);
+            }
+            catch (ExternalException ex)
+            {
+                MessageBox.Show(ex.Message);
             }
         }
 
@@ -6505,16 +6533,19 @@ namespace OpenTween
 
         private void GoSamePostToAnotherTab(bool left)
         {
-            if (_curList.VirtualListSize == 0) return;
-            int fIdx = 0;
-            int toIdx = 0;
-            int stp = 1;
-            long targetId = 0;
+            if (this._curList.SelectedIndices.Count == 0)
+                return;
 
-            if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage) return; // Directタブは対象外(見つかるはずがない)
-            if (_curList.SelectedIndices.Count == 0) return; //未選択も処理しない
+            var tab = this._statuses.Tabs[this._curTab.Text];
+
+            // Directタブは対象外(見つかるはずがない)
+            if (tab.TabType == MyCommon.TabUsageType.DirectMessage)
+                return;
 
-            targetId = GetCurTabPost(_curList.SelectedIndices[0]).StatusId;
+            var selectedIndex = this._curList.SelectedIndices[0];
+            var selectedStatusId = tab.GetStatusIdAt(selectedIndex);
+
+            int fIdx, toIdx, stp;
 
             if (left)
             {
@@ -6545,42 +6576,45 @@ namespace OpenTween
                 stp = 1;
             }
 
-            bool found = false;
             for (int tabidx = fIdx; tabidx != toIdx; tabidx += stp)
             {
-                if (_statuses.Tabs[ListTab.TabPages[tabidx].Text].TabType == MyCommon.TabUsageType.DirectMessage) continue; // Directタブは対象外
-                for (int idx = 0; idx < ((DetailsListView)ListTab.TabPages[tabidx].Tag).VirtualListSize; idx++)
+                var targetTab = this._statuses.Tabs[this.ListTab.TabPages[tabidx].Text];
+
+                // Directタブは対象外
+                if (targetTab.TabType == MyCommon.TabUsageType.DirectMessage)
+                    continue;
+
+                var foundIndex = targetTab.IndexOf(selectedStatusId);
+                if (foundIndex != -1)
                 {
-                    if (_statuses.Tabs[ListTab.TabPages[tabidx].Text][idx].StatusId == targetId)
-                    {
-                        ListTab.SelectedIndex = tabidx;
-                        SelectListItem(_curList, idx);
-                        _curList.EnsureVisible(idx);
-                        found = true;
-                        break;
-                    }
+                    ListTab.SelectedIndex = tabidx;
+                    SelectListItem(_curList, foundIndex);
+                    _curList.EnsureVisible(foundIndex);
+                    return;
                 }
-                if (found) break;
             }
         }
 
         private void GoPost(bool forward)
         {
-            if (_curList.SelectedIndices.Count == 0 || _curPost == null) return;
-            int fIdx = 0;
-            int toIdx = 0;
-            int stp = 1;
+            if (_curList.SelectedIndices.Count == 0 || _curPost == null)
+                return;
+
+            var tab = this._statuses.Tabs[this._curTab.Text];
+            var selectedIndex = this._curList.SelectedIndices[0];
+
+            int fIdx, toIdx, stp;
 
             if (forward)
             {
-                fIdx = _curList.SelectedIndices[0] + 1;
-                if (fIdx > _curList.VirtualListSize - 1) return;
-                toIdx = _curList.VirtualListSize;
+                fIdx = selectedIndex + 1;
+                if (fIdx > tab.AllCount - 1) return;
+                toIdx = tab.AllCount;
                 stp = 1;
             }
             else
             {
-                fIdx = _curList.SelectedIndices[0] - 1;
+                fIdx = selectedIndex - 1;
                 if (fIdx < 0) return;
                 toIdx = -1;
                 stp = -1;
@@ -6597,9 +6631,10 @@ namespace OpenTween
             }
             for (int idx = fIdx; idx != toIdx; idx += stp)
             {
-                if (_statuses.Tabs[_curTab.Text][idx].RetweetedId == null)
+                var post = tab[idx];
+                if (post.RetweetedId == null)
                 {
-                    if (_statuses.Tabs[_curTab.Text][idx].ScreenName == name)
+                    if (post.ScreenName == name)
                     {
                         SelectListItem(_curList, idx);
                         _curList.EnsureVisible(idx);
@@ -6608,7 +6643,7 @@ namespace OpenTween
                 }
                 else
                 {
-                    if (_statuses.Tabs[_curTab.Text][idx].RetweetedBy == name)
+                    if (post.RetweetedBy == name)
                     {
                         SelectListItem(_curList, idx);
                         _curList.EnsureVisible(idx);
@@ -6620,21 +6655,24 @@ namespace OpenTween
 
         private void GoRelPost(bool forward)
         {
-            if (_curList.SelectedIndices.Count == 0) return;
+            if (this._curList.SelectedIndices.Count == 0)
+                return;
+
+            var tab = this._statuses.Tabs[this._curTab.Text];
+            var selectedIndex = this._curList.SelectedIndices[0];
+
+            int fIdx, toIdx, stp;
 
-            int fIdx = 0;
-            int toIdx = 0;
-            int stp = 1;
             if (forward)
             {
-                fIdx = _curList.SelectedIndices[0] + 1;
-                if (fIdx > _curList.VirtualListSize - 1) return;
-                toIdx = _curList.VirtualListSize;
+                fIdx = selectedIndex + 1;
+                if (fIdx > tab.AllCount - 1) return;
+                toIdx = tab.AllCount;
                 stp = 1;
             }
             else
             {
-                fIdx = _curList.SelectedIndices[0] - 1;
+                fIdx = selectedIndex - 1;
                 if (fIdx < 0) return;
                 toIdx = -1;
                 stp = -1;
@@ -6653,7 +6691,7 @@ namespace OpenTween
 
             for (int idx = fIdx; idx != toIdx; idx += stp)
             {
-                PostClass post = _statuses.Tabs[_curTab.Text][idx];
+                var post = tab[idx];
                 if (post.ScreenName == _anchorPost.ScreenName ||
                     post.RetweetedBy == _anchorPost.ScreenName ||
                     post.ScreenName == _anchorPost.RetweetedBy ||
@@ -7389,45 +7427,55 @@ namespace OpenTween
             this.TopMost = this._cfgCommon.AlwaysTop;
         }
 
-        public bool TabRename(ref string tabName)
+        public bool TabRename(string origTabName, out string newTabName)
         {
             //タブ名変更
-            string newTabText = null;
+            newTabName = null;
             using (InputTabName inputName = new InputTabName())
             {
-                inputName.TabName = tabName;
+                inputName.TabName = origTabName;
                 inputName.ShowDialog();
                 if (inputName.DialogResult == DialogResult.Cancel) return false;
-                newTabText = inputName.TabName;
+                newTabName = inputName.TabName;
             }
             this.TopMost = this._cfgCommon.AlwaysTop;
-            if (!string.IsNullOrEmpty(newTabText))
+            if (!string.IsNullOrEmpty(newTabName))
             {
                 //新タブ名存在チェック
                 for (int i = 0; i < ListTab.TabCount; i++)
                 {
-                    if (ListTab.TabPages[i].Text == newTabText)
+                    if (ListTab.TabPages[i].Text == newTabName)
                     {
-                        string tmp = string.Format(Properties.Resources.Tabs_DoubleClickText1, newTabText);
+                        string tmp = string.Format(Properties.Resources.Tabs_DoubleClickText1, newTabName);
                         MessageBox.Show(tmp, Properties.Resources.Tabs_DoubleClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                         return false;
                     }
                 }
-                //タブ名を変更
-                for (int i = 0; i < ListTab.TabCount; i++)
+
+                var tabPage = this.ListTab.TabPages.Cast<TabPage>()
+                    .First(x => x.Text == origTabName);
+
+                ListViewScroll scrollInfo;
+                if (this.listViewScroll.TryGetValue(origTabName, out scrollInfo))
                 {
-                    if (ListTab.TabPages[i].Text == tabName)
-                    {
-                        ListTab.TabPages[i].Text = newTabText;
-                        break;
-                    }
+                    this.listViewScroll.Remove(origTabName);
+                    this.listViewScroll[newTabName] = scrollInfo;
+                }
+
+                ListViewSelection selectionInfo;
+                if (this.listViewSelection.TryGetValue(origTabName, out selectionInfo))
+                {
+                    this.listViewSelection.Remove(origTabName);
+                    this.listViewSelection[newTabName] = selectionInfo;
                 }
-                _statuses.RenameTab(tabName, newTabText);
+
+                //タブ名を変更
+                tabPage.Text = newTabName;
+                _statuses.RenameTab(origTabName, newTabName);
 
                 SaveConfigsCommon();
                 SaveConfigsTabs();
-                _rclickTabName = newTabText;
-                tabName = newTabText;
+                _rclickTabName = newTabName;
                 return true;
             }
             else
@@ -7454,8 +7502,8 @@ namespace OpenTween
 
         private void ListTab_DoubleClick(object sender, MouseEventArgs e)
         {
-            string tn = ListTab.SelectedTab.Text;
-            TabRename(ref tn);
+            string _;
+            TabRename(this.ListTab.SelectedTab.Text, out _);
         }
 
         private void ListTab_MouseDown(object sender, MouseEventArgs e)
@@ -7948,8 +7996,9 @@ namespace OpenTween
             if (_statuses == null) return;
             if (_statuses.Tabs == null) return;
 
-            TabModel tb = _statuses.Tabs[_rclickTabName];
-            if (tb == null) return;
+            TabModel tb;
+            if (!this._statuses.Tabs.TryGetValue(this._rclickTabName, out tb))
+                return;
 
             NotifyDispMenuItem.Checked = tb.Notify;
             this.NotifyTbMenuItem.Checked = tb.Notify;
@@ -8664,8 +8713,8 @@ namespace OpenTween
             {
                 if (tb.Text == tabName)
                 {
-                    tb.ImageIndex = -1;
                     ((DetailsListView)tb.Tag).VirtualListSize = 0;
+                    tb.ImageIndex = -1;
                     break;
                 }
             }
@@ -10066,9 +10115,11 @@ namespace OpenTween
             //公式RT
             if (this.ExistCurrentPost)
             {
-                if (_curPost.IsProtect)
+                if (!_curPost.CanRetweetBy(this.twitterApi.CurrentUserId))
                 {
-                    MessageBox.Show("Protected.");
+                    if (this._curPost.IsProtect)
+                        MessageBox.Show("Protected.");
+
                     _DoFavRetweetFlags = false;
                     return;
                 }
@@ -10092,11 +10143,6 @@ namespace OpenTween
                 }
                 else
                 {
-                    if (_curPost.IsDm)
-                    {
-                        _DoFavRetweetFlags = false;
-                        return;
-                    }
                     if (!this._cfgCommon.RetweetNoConfirm)
                     {
                         string Questiontext = Properties.Resources.RetweetQuestion1;
@@ -10113,7 +10159,7 @@ namespace OpenTween
                 foreach (int idx in _curList.SelectedIndices)
                 {
                     PostClass post = GetCurTabPost(idx);
-                    if (!post.IsProtect && !post.IsDm)
+                    if (post.CanRetweetBy(this.twitterApi.CurrentUserId))
                         statusIds.Add(post.StatusId);
                 }
 
@@ -10233,7 +10279,9 @@ namespace OpenTween
         private void TabRenameMenuItem_Click(object sender, EventArgs e)
         {
             if (string.IsNullOrEmpty(_rclickTabName)) return;
-            TabRename(ref _rclickTabName);
+
+            string _;
+            TabRename(_rclickTabName, out _);
         }
 
         private async void BitlyToolStripMenuItem_Click(object sender, EventArgs e)
@@ -10783,38 +10831,16 @@ namespace OpenTween
             await this.doMoveToRTHome();
         }
 
-        private async void ListManageUserContextToolStripMenuItem_Click(object sender, EventArgs e)
+        private void ListManageUserContextToolStripMenuItem_Click(object sender, EventArgs e)
         {
             var screenName = this._curPost?.ScreenName;
             if (screenName != null)
-                await this.ListManageUserContext(screenName);
+                this.ListManageUserContext(screenName);
         }
 
-        public async Task ListManageUserContext(string screenName)
+        public void ListManageUserContext(string screenName)
         {
-            if (this._statuses.SubscribableLists.Count == 0)
-            {
-                try
-                {
-                    using (var dialog = new WaitingDialog(Properties.Resources.ListsGetting))
-                    {
-                        var cancellationToken = dialog.EnableCancellation();
-
-                        var task = this.tw.GetListsApi();
-                        await dialog.WaitForAsync(this, task);
-
-                        cancellationToken.ThrowIfCancellationRequested();
-                    }
-                }
-                catch (OperationCanceledException) { return; }
-                catch (WebApiException ex)
-                {
-                    MessageBox.Show("Failed to get lists. (" + ex.Message + ")");
-                    return;
-                }
-            }
-
-            using (MyLists listSelectForm = new MyLists(screenName, this.tw))
+            using (var listSelectForm = new MyLists(screenName, this.twitterApi))
             {
                 listSelectForm.ShowDialog(this);
             }
@@ -10985,7 +11011,7 @@ namespace OpenTween
                 this.OpenFavotterOpMenuItem.Enabled = true;
                 this.ShowRelatedStatusesMenuItem2.Enabled = true;  //PublicSearchの時問題出るかも
 
-                if (_curPost.IsProtect)
+                if (!_curPost.CanRetweetBy(this.twitterApi.CurrentUserId))
                 {
                     this.RtOpMenuItem.Enabled = false;
                     this.RtUnOpMenuItem.Enabled = false;
@@ -11346,8 +11372,7 @@ namespace OpenTween
                 ModifySettingCommon = true;
                 SaveConfigsAll(true);
 
-                if (ImageSelector.ServiceName.Equals("Twitter"))
-                    this.StatusText_TextChanged(null, null);
+                this.StatusText_TextChanged(null, null);
             }
         }
 
@@ -11361,28 +11386,35 @@ namespace OpenTween
         /// </summary>
         private void ProcClipboardFromStatusTextWhenCtrlPlusV()
         {
-            if (Clipboard.ContainsText())
-            {
-                // clipboardにテキストがある場合は貼り付け処理
-                this.StatusText.Paste(Clipboard.GetText());
-            }
-            else if (Clipboard.ContainsImage())
+            try
             {
-                // 画像があるので投稿処理を行う
-                if (MessageBox.Show(Properties.Resources.PostPictureConfirm3,
-                                   Properties.Resources.PostPictureWarn4,
-                                   MessageBoxButtons.OKCancel,
-                                   MessageBoxIcon.Question,
-                                   MessageBoxDefaultButton.Button2)
-                               == DialogResult.OK)
+                if (Clipboard.ContainsText())
+                {
+                    // clipboardにテキストがある場合は貼り付け処理
+                    this.StatusText.Paste(Clipboard.GetText());
+                }
+                else if (Clipboard.ContainsImage())
                 {
-                    // clipboardから画像を取得
-                    using (var image = Clipboard.GetImage())
+                    // 画像があるので投稿処理を行う
+                    if (MessageBox.Show(Properties.Resources.PostPictureConfirm3,
+                                       Properties.Resources.PostPictureWarn4,
+                                       MessageBoxButtons.OKCancel,
+                                       MessageBoxIcon.Question,
+                                       MessageBoxDefaultButton.Button2)
+                                   == DialogResult.OK)
                     {
-                        this.ImageSelector.BeginSelection(image);
+                        // clipboardから画像を取得
+                        using (var image = Clipboard.GetImage())
+                        {
+                            this.ImageSelector.BeginSelection(image);
+                        }
                     }
                 }
             }
+            catch (ExternalException ex)
+            {
+                MessageBox.Show(ex.Message);
+            }
         }
 #endregion
 
@@ -11539,23 +11571,23 @@ namespace OpenTween
         }
 
 #region "Userstream"
-        private void tw_PostDeleted(object sender, PostDeletedEventArgs e)
+        private async void tw_PostDeleted(object sender, PostDeletedEventArgs e)
         {
             try
             {
                 if (InvokeRequired && !IsDisposed)
                 {
-                    Invoke((Action) (async () =>
-                           {
-                               this._statuses.RemovePostFromAllTabs(e.StatusId, setIsDeleted: true);
-                               if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(e.StatusId))
-                               {
-                                   this.PurgeListViewItemCache();
-                                   ((DetailsListView)_curTab.Tag).Update();
-                                   if (_curPost != null && _curPost.StatusId == e.StatusId)
-                                       await this.DispSelectedPost(true);
-                               }
-                           }));
+                    await this.InvokeAsync(async () =>
+                    {
+                        this._statuses.RemovePostFromAllTabs(e.StatusId, setIsDeleted: true);
+                        if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(e.StatusId))
+                        {
+                            this.PurgeListViewItemCache();
+                            ((DetailsListView)_curTab.Tag).Update();
+                            if (_curPost != null && _curPost.StatusId == e.StatusId)
+                                await this.DispSelectedPost(true);
+                        }
+                    });
                     return;
                 }
             }
@@ -11597,13 +11629,13 @@ namespace OpenTween
             }
         }
 
-        private void tw_UserStreamStarted(object sender, EventArgs e)
+        private async void tw_UserStreamStarted(object sender, EventArgs e)
         {
             try
             {
                 if (InvokeRequired && !IsDisposed)
                 {
-                    Invoke((Action)(() => this.tw_UserStreamStarted(sender, e)));
+                    await this.InvokeAsync(() => this.tw_UserStreamStarted(sender, e));
                     return;
                 }
             }
@@ -11622,13 +11654,13 @@ namespace OpenTween
             StatusLabel.Text = "UserStream Started.";
         }
 
-        private void tw_UserStreamStopped(object sender, EventArgs e)
+        private async void tw_UserStreamStopped(object sender, EventArgs e)
         {
             try
             {
                 if (InvokeRequired && !IsDisposed)
                 {
-                    Invoke((Action)(() => this.tw_UserStreamStopped(sender, e)));
+                    await this.InvokeAsync(() => this.tw_UserStreamStopped(sender, e));
                     return;
                 }
             }
@@ -11661,13 +11693,13 @@ namespace OpenTween
             }
         }
 
-        private void tw_UserStreamEventArrived(object sender, UserStreamEventReceivedEventArgs e)
+        private async void tw_UserStreamEventArrived(object sender, UserStreamEventReceivedEventArgs e)
         {
             try
             {
                 if (InvokeRequired && !IsDisposed)
                 {
-                    Invoke((Action)(() => this.tw_UserStreamEventArrived(sender, e)));
+                    await this.InvokeAsync(() => this.tw_UserStreamEventArrived(sender, e));
                     return;
                 }
             }
@@ -11999,11 +12031,11 @@ namespace OpenTween
             await this.OpenUserAppointUrl();
         }
 
-        private void GrowlHelper_Callback(object sender, GrowlHelper.NotifyCallbackEventArgs e)
+        private async void GrowlHelper_Callback(object sender, GrowlHelper.NotifyCallbackEventArgs e)
         {
             if (Form.ActiveForm == null)
             {
-                this.BeginInvoke((Action) (() =>
+                await this.InvokeAsync(() =>
                 {
                     this.Visible = true;
                     if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal;
@@ -12017,7 +12049,7 @@ namespace OpenTween
                     {
                         if (!this.GoStatus(e.StatusId)) this.StatusText.Focus();
                     }
-                }));
+                });
             }
         }