OSDN Git Service

プロフィール画面へのD&Dによるアイコン変更時に確認ダイアログを表示するように変更
[opentween/open-tween.git] / OpenTween / UserInfoDialog.cs
index c46e5fc..e84e921 100644 (file)
@@ -31,6 +31,7 @@ using System.Data;
 using System.Drawing;
 using System.Linq;
 using System.Text;
+using System.Threading;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using System.Text.RegularExpressions;
@@ -45,6 +46,7 @@ namespace OpenTween
     public partial class UserInfoDialog : OTBaseForm
     {
         private TwitterUser _displayUser;
+        private CancellationTokenSource cancellationTokenSource = null;
 
         private readonly TweenMain mainForm;
         private readonly Twitter twitter;
@@ -60,16 +62,32 @@ namespace OpenTween
             this.LabelScreenName.Font = this.ReplaceToGlobalFont(this.LabelScreenName.Font);
         }
 
+        private void CancelLoading()
+        {
+            var newTokenSource = new CancellationTokenSource();
+            var oldTokenSource = Interlocked.Exchange(ref this.cancellationTokenSource, newTokenSource);
+
+            if (oldTokenSource != null)
+            {
+                oldTokenSource.Cancel();
+                oldTokenSource.Dispose();
+            }
+        }
+
         public async Task ShowUserAsync(TwitterUser user)
         {
             if (user == null || user == this._displayUser)
                 return;
 
+            this.CancelLoading();
+
+            var cancellationToken = this.cancellationTokenSource.Token;
+
             this._displayUser = user;
 
             this.LabelId.Text = user.IdStr;
             this.LabelScreenName.Text = user.ScreenName;
-            this.LabelName.Text = WebUtility.HtmlDecode(user.Name);
+            this.LabelName.Text = user.Name;
             this.LabelLocation.Text = user.Location ?? "";
             this.LabelCreatedAt.Text = MyCommon.DateTimeParse(user.CreatedAt).ToString();
 
@@ -122,24 +140,30 @@ namespace OpenTween
 
             await Task.WhenAll(new[]
             {
-                this.SetDescriptionAsync(user.Description),
-                this.SetRecentStatusAsync(user.Status),
-                this.SetLinkLabelWebAsync(user.Url),
-                this.SetUserImageAsync(user.ProfileImageUrlHttps),
-                this.LoadFriendshipAsync(user.ScreenName),
+                this.SetDescriptionAsync(user.Description, cancellationToken),
+                this.SetRecentStatusAsync(user.Status, cancellationToken),
+                this.SetLinkLabelWebAsync(user.Url, cancellationToken),
+                this.SetUserImageAsync(user.ProfileImageUrlHttps, cancellationToken),
+                this.LoadFriendshipAsync(user.ScreenName, cancellationToken),
             });
         }
 
-        private async Task SetDescriptionAsync(string descriptionText)
+        private async Task SetDescriptionAsync(string descriptionText, CancellationToken cancellationToken)
         {
             if (descriptionText != null)
             {
                 var atlist = new List<string>();
 
-                var html = WebUtility.HtmlEncode(descriptionText);
+                // description に含まれる < > " の記号のみエスケープを一旦解除する
+                var decodedText = descriptionText.Replace("&lt;", "<").Replace("&gt;", ">").Replace("&quot;", "\"");
+
+                var html = WebUtility.HtmlEncode(decodedText);
                 html = await this.twitter.CreateHtmlAnchorAsync(html, atlist, null);
                 html = this.mainForm.createDetailHtml(html);
 
+                if (cancellationToken.IsCancellationRequested)
+                    return;
+
                 this.DescriptionBrowser.DocumentText = html;
             }
             else
@@ -148,7 +172,7 @@ namespace OpenTween
             }
         }
 
-        private async Task SetUserImageAsync(string imageUri)
+        private async Task SetUserImageAsync(string imageUri, CancellationToken cancellationToken)
         {
             var oldImage = this.UserPicture.Image;
             if (oldImage != null)
@@ -166,20 +190,31 @@ namespace OpenTween
             {
                 var uri = imageUri.Replace("_normal", "_bigger");
 
-                var imageStream = await Networking.Http.GetStreamAsync(uri)
-                    .ConfigureAwait(false);
+                using (var imageStream = await Networking.Http.GetStreamAsync(uri).ConfigureAwait(false))
+                {
+                    var image = await MemoryImage.CopyFromStreamAsync(imageStream)
+                        .ConfigureAwait(false);
 
-                return await MemoryImage.CopyFromStreamAsync(imageStream)
-                    .ConfigureAwait(false);
+                    if (cancellationToken.IsCancellationRequested)
+                    {
+                        image.Dispose();
+                        throw new OperationCanceledException(cancellationToken);
+                    }
+
+                    return image;
+                }
             });
         }
 
-        private async Task SetLinkLabelWebAsync(string uri)
+        private async Task SetLinkLabelWebAsync(string uri, CancellationToken cancellationToken)
         {
             if (uri != null)
             {
                 var expandedUrl = await ShortUrl.Instance.ExpandUrlAsync(uri);
 
+                if (cancellationToken.IsCancellationRequested)
+                    return;
+
                 this.LinkLabelWeb.Text = uri;
                 this.LinkLabelWeb.Tag = expandedUrl;
                 this.ToolTip1.SetToolTip(this.LinkLabelWeb, expandedUrl);
@@ -192,7 +227,7 @@ namespace OpenTween
             }
         }
 
-        private async Task SetRecentStatusAsync(TwitterStatus status)
+        private async Task SetRecentStatusAsync(TwitterStatus status, CancellationToken cancellationToken)
         {
             var atlist = new List<string>();
 
@@ -203,6 +238,9 @@ namespace OpenTween
                     " Posted at " + MyCommon.DateTimeParse(status.CreatedAt) +
                     " via " + status.Source);
 
+                if (cancellationToken.IsCancellationRequested)
+                    return;
+
                 this.RecentPostBrowser.DocumentText = html;
             }
             else
@@ -211,7 +249,7 @@ namespace OpenTween
             }
         }
 
-        private async Task LoadFriendshipAsync(string screenName)
+        private async Task LoadFriendshipAsync(string screenName, CancellationToken cancellationToken)
         {
             this.LabelIsFollowing.Text = "";
             this.LabelIsFollowed.Text = "";
@@ -233,6 +271,9 @@ namespace OpenTween
                 return new { IsFollowing, IsFollowedBy };
             });
 
+            if (cancellationToken.IsCancellationRequested)
+                return;
+
             if (friendship == null)
             {
                 LabelIsFollowed.Text = Properties.Resources.GetFriendshipInfo6;
@@ -674,6 +715,11 @@ namespace OpenTween
         {
             if (e.Data.GetDataPresent(DataFormats.FileDrop))
             {
+                var ret = MessageBox.Show(this, Properties.Resources.ChangeIconToolStripMenuItem_Confirm,
+                    Application.ProductName, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
+                if (ret != DialogResult.OK)
+                    return;
+
                 string filename = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
                 await this.DoChangeIcon(filename);
             }
@@ -683,6 +729,10 @@ namespace OpenTween
         {
             if (disposing)
             {
+                var cts = this.cancellationTokenSource;
+                cts.Cancel();
+                cts.Dispose();
+
                 var oldImage = this.UserPicture.Image;
                 if (oldImage != null)
                 {