OSDN Git Service

UserInfoDialog.SetUserImageAsync() メソッドに null が渡される可能性を考慮 (thx @kamiari!)
[opentween/open-tween.git] / OpenTween / UserInfoDialog.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 //           (c) 2008-2011 Moz (@syo68k)
4 //           (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 //           (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 //           (c) 2011      kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
8 // All rights reserved.
9 // 
10 // This file is part of OpenTween.
11 // 
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
15 // any later version.
16 // 
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 // for more details. 
21 // 
22 // You should have received a copy of the GNU General Public License along
23 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
26
27 using System;
28 using System.Collections.Generic;
29 using System.ComponentModel;
30 using System.Data;
31 using System.Drawing;
32 using System.Linq;
33 using System.Text;
34 using System.Threading.Tasks;
35 using System.Windows.Forms;
36 using System.Text.RegularExpressions;
37 using System.Web;
38 using System.IO;
39 using System.Net;
40 using OpenTween.Api;
41
42 namespace OpenTween
43 {
44     public partial class UserInfoDialog : OTBaseForm
45     {
46         private TwitterUser _displayUser;
47         public TwitterUser DisplayUser
48         {
49             get { return this._displayUser; }
50             set
51             {
52                 if (this._displayUser != value)
53                 {
54                     this._displayUser = value;
55                     this.OnDisplayUserChanged();
56                 }
57             }
58         }
59
60         private new TweenMain Owner
61         {
62             get { return (TweenMain)base.Owner; }
63         }
64
65         private Twitter Twitter
66         {
67             get { return this.Owner.TwitterInstance; }
68         }
69
70         public UserInfoDialog()
71         {
72             InitializeComponent();
73
74             // LabelScreenName のフォントを OTBaseForm.GlobalFont に変更
75             this.LabelScreenName.Font = this.ReplaceToGlobalFont(this.LabelScreenName.Font);
76         }
77
78         protected virtual async void OnDisplayUserChanged()
79         {
80             if (this._displayUser == null)
81                 return;
82
83             var user = this._displayUser;
84
85             this.LabelId.Text = user.IdStr;
86             this.LabelScreenName.Text = user.ScreenName;
87             this.LabelName.Text = WebUtility.HtmlDecode(user.Name);
88             this.LabelLocation.Text = user.Location ?? "";
89             this.LabelCreatedAt.Text = MyCommon.DateTimeParse(user.CreatedAt).ToString();
90
91             if (user.Protected)
92                 this.LabelIsProtected.Text = Properties.Resources.Yes;
93             else
94                 this.LabelIsProtected.Text = Properties.Resources.No;
95
96             if (user.Verified)
97                 this.LabelIsVerified.Text = Properties.Resources.Yes;
98             else
99                 this.LabelIsVerified.Text = Properties.Resources.No;
100
101             var followingUrl = "https://twitter.com/" + user.ScreenName + "/following";
102             this.LinkLabelFollowing.Text = user.FriendsCount.ToString();
103             this.LinkLabelFollowing.Tag = followingUrl;
104             this.ToolTip1.SetToolTip(this.LinkLabelFollowing, followingUrl);
105
106             var followersUrl = "https://twitter.com/" + user.ScreenName + "/followers";
107             this.LinkLabelFollowers.Text = user.FollowersCount.ToString();
108             this.LinkLabelFollowers.Tag = followersUrl;
109             this.ToolTip1.SetToolTip(this.LinkLabelFollowers, followersUrl);
110
111             var favoritesUrl = "https://twitter.com/" + user.ScreenName + "/favorites";
112             this.LinkLabelFav.Text = user.FavouritesCount.ToString();
113             this.LinkLabelFav.Tag = favoritesUrl;
114             this.ToolTip1.SetToolTip(this.LinkLabelFav, favoritesUrl);
115
116             var profileUrl = "https://twitter.com/" + user.ScreenName;
117             this.LinkLabelTweet.Text = user.StatusesCount.ToString();
118             this.LinkLabelTweet.Tag = profileUrl;
119             this.ToolTip1.SetToolTip(this.LinkLabelTweet, profileUrl);
120
121             if (this.Twitter.UserId == user.Id)
122             {
123                 this.ButtonEdit.Enabled = true;
124                 this.ChangeIconToolStripMenuItem.Enabled = true;
125                 this.ButtonBlock.Enabled = false;
126                 this.ButtonReportSpam.Enabled = false;
127                 this.ButtonBlockDestroy.Enabled = false;
128             }
129             else
130             {
131                 this.ButtonEdit.Enabled = false;
132                 this.ChangeIconToolStripMenuItem.Enabled = false;
133                 this.ButtonBlock.Enabled = true;
134                 this.ButtonReportSpam.Enabled = true;
135                 this.ButtonBlockDestroy.Enabled = true;
136             }
137
138             await Task.WhenAll(new[]
139             {
140                 this.SetDescriptionAsync(user.Description),
141                 this.SetRecentStatusAsync(user.Status),
142                 this.SetLinkLabelWebAsync(user.Url),
143                 this.SetUserImageAsync(user.ProfileImageUrlHttps),
144                 this.LoadFriendshipAsync(user.ScreenName),
145             });
146         }
147
148         private async Task SetDescriptionAsync(string descriptionText)
149         {
150             if (descriptionText != null)
151             {
152                 var atlist = new List<string>();
153
154                 var html = WebUtility.HtmlEncode(descriptionText);
155                 html = await this.Twitter.CreateHtmlAnchorAsync(html, atlist, null);
156                 html = this.Owner.createDetailHtml(html);
157
158                 this.DescriptionBrowser.DocumentText = html;
159             }
160             else
161             {
162                 this.DescriptionBrowser.DocumentText = "";
163             }
164         }
165
166         private async Task SetUserImageAsync(string imageUri)
167         {
168             var oldImage = this.UserPicture.Image;
169             if (oldImage != null)
170             {
171                 this.UserPicture.Image = null;
172                 oldImage.Dispose();
173             }
174
175             // ProfileImageUrlHttps が null になる場合があるらしい
176             // 参照: https://sourceforge.jp/ticket/browse.php?group_id=6526&tid=33871
177             if (imageUri == null)
178                 return;
179
180             using (var http = MyCommon.CreateHttpClient())
181             {
182                 var imageStream = await http.GetStreamAsync(imageUri.Replace("_normal", "_bigger"));
183                 this.UserPicture.Image = await MemoryImage.CopyFromStreamAsync(imageStream);
184             }
185         }
186
187         private async Task SetLinkLabelWebAsync(string uri)
188         {
189             if (uri != null)
190             {
191                 var expandedUrl = await ShortUrl.Instance.ExpandUrlStrAsync(uri);
192
193                 this.LinkLabelWeb.Text = uri;
194                 this.LinkLabelWeb.Tag = expandedUrl;
195                 this.ToolTip1.SetToolTip(this.LinkLabelWeb, expandedUrl);
196             }
197             else
198             {
199                 this.LinkLabelWeb.Text = "";
200                 this.LinkLabelWeb.Tag = null;
201                 this.ToolTip1.SetToolTip(this.LinkLabelWeb, null);
202             }
203         }
204
205         private async Task SetRecentStatusAsync(TwitterStatus status)
206         {
207             var atlist = new List<string>();
208
209             if (status != null)
210             {
211                 var html = await this.Twitter.CreateHtmlAnchorAsync(status.Text, atlist, status.Entities, null);
212                 html = this.Owner.createDetailHtml(html +
213                     " Posted at " + MyCommon.DateTimeParse(status.CreatedAt) +
214                     " via " + status.Source);
215
216                 this.RecentPostBrowser.DocumentText = html;
217             }
218             else
219             {
220                 this.RecentPostBrowser.DocumentText = Properties.Resources.ShowUserInfo2;
221             }
222         }
223
224         private async Task LoadFriendshipAsync(string screenName)
225         {
226             this.LabelIsFollowing.Text = "";
227             this.LabelIsFollowed.Text = "";
228             this.ButtonFollow.Enabled = false;
229             this.ButtonUnFollow.Enabled = false;
230
231             if (this.Twitter.Username == screenName)
232                 return;
233
234             var friendship = await Task.Run(() =>
235             {
236                 var IsFollowing = false;
237                 var IsFollowedBy = false;
238
239                 var ret = this.Twitter.GetFriendshipInfo(screenName, ref IsFollowing, ref IsFollowedBy);
240                 if (!string.IsNullOrEmpty(ret))
241                     return null;
242
243                 return new { IsFollowing, IsFollowedBy };
244             });
245
246             if (friendship == null)
247             {
248                 LabelIsFollowed.Text = Properties.Resources.GetFriendshipInfo6;
249                 LabelIsFollowing.Text = Properties.Resources.GetFriendshipInfo6;
250                 return;
251             }
252
253             this.LabelIsFollowing.Text = friendship.IsFollowing
254                 ? Properties.Resources.GetFriendshipInfo1
255                 : Properties.Resources.GetFriendshipInfo2;
256
257             this.LabelIsFollowed.Text = friendship.IsFollowedBy
258                 ? Properties.Resources.GetFriendshipInfo3
259                 : Properties.Resources.GetFriendshipInfo4;
260
261             this.ButtonFollow.Enabled = !friendship.IsFollowing;
262             this.ButtonUnFollow.Enabled = friendship.IsFollowing;
263         }
264
265         private void ShowUserInfo_Load(object sender, EventArgs e)
266         {
267             this.TextBoxName.Location = this.LabelName.Location;
268             this.TextBoxName.Height = this.LabelName.Height;
269             this.TextBoxName.Width = this.LabelName.Width;
270             this.TextBoxName.BackColor = this.Owner.InputBackColor;
271             this.TextBoxName.MaxLength = 20;
272
273             this.TextBoxLocation.Location = this.LabelLocation.Location;
274             this.TextBoxLocation.Height = this.LabelLocation.Height;
275             this.TextBoxLocation.Width = this.LabelLocation.Width;
276             this.TextBoxLocation.BackColor = this.Owner.InputBackColor;
277             this.TextBoxLocation.MaxLength = 30;
278
279             this.TextBoxWeb.Location = this.LinkLabelWeb.Location;
280             this.TextBoxWeb.Height = this.LinkLabelWeb.Height;
281             this.TextBoxWeb.Width = this.LinkLabelWeb.Width;
282             this.TextBoxWeb.BackColor = this.Owner.InputBackColor;
283             this.TextBoxWeb.MaxLength = 100;
284
285             this.TextBoxDescription.Location = this.DescriptionBrowser.Location;
286             this.TextBoxDescription.Height = this.DescriptionBrowser.Height;
287             this.TextBoxDescription.Width = this.DescriptionBrowser.Width;
288             this.TextBoxDescription.BackColor = this.Owner.InputBackColor;
289             this.TextBoxDescription.MaxLength = 160;
290             this.TextBoxDescription.Multiline = true;
291             this.TextBoxDescription.ScrollBars = ScrollBars.Vertical;
292         }
293
294         private async void LinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
295         {
296             var linkLabel = (LinkLabel)sender;
297
298             var linkUrl = (string)linkLabel.Tag;
299             if (linkUrl == null)
300                 return;
301
302             await this.Owner.OpenUriAsync(linkUrl);
303         }
304
305         private void ButtonFollow_Click(object sender, EventArgs e)
306         {
307             string ret = this.Twitter.PostFollowCommand(this._displayUser.ScreenName);
308             if (!string.IsNullOrEmpty(ret))
309             {
310                 MessageBox.Show(Properties.Resources.FRMessage2 + ret);
311             }
312             else
313             {
314                 MessageBox.Show(Properties.Resources.FRMessage3);
315                 LabelIsFollowing.Text = Properties.Resources.GetFriendshipInfo1;
316                 ButtonFollow.Enabled = false;
317                 ButtonUnFollow.Enabled = true;
318             }
319         }
320
321         private void ButtonUnFollow_Click(object sender, EventArgs e)
322         {
323             if (MessageBox.Show(this._displayUser.ScreenName + Properties.Resources.ButtonUnFollow_ClickText1,
324                                Properties.Resources.ButtonUnFollow_ClickText2,
325                                MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
326             {
327                 string ret = this.Twitter.PostRemoveCommand(this._displayUser.ScreenName);
328                 if (!string.IsNullOrEmpty(ret))
329                 {
330                     MessageBox.Show(Properties.Resources.FRMessage2 + ret);
331                 }
332                 else
333                 {
334                     MessageBox.Show(Properties.Resources.FRMessage3);
335                     LabelIsFollowing.Text = Properties.Resources.GetFriendshipInfo2;
336                     ButtonFollow.Enabled = true;
337                     ButtonUnFollow.Enabled = false;
338                 }
339             }
340         }
341
342         private void ShowUserInfo_Activated(object sender, EventArgs e)
343         {
344             //画面が他画面の裏に隠れると、アイコン画像が再描画されない問題の対応
345             if (UserPicture.Image != null)
346                 UserPicture.Invalidate(false);
347         }
348
349         private void ShowUserInfo_Shown(object sender, EventArgs e)
350         {
351             ButtonClose.Focus();
352         }
353
354         private void WebBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
355         {
356             if (e.Url.AbsoluteUri != "about:blank")
357             {
358                 e.Cancel = true;
359
360                 if (e.Url.AbsoluteUri.StartsWith("http://twitter.com/search?q=%23") ||
361                     e.Url.AbsoluteUri.StartsWith("https://twitter.com/search?q=%23"))
362                 {
363                     //ハッシュタグの場合は、タブで開く
364                     string urlStr = Uri.UnescapeDataString(e.Url.AbsoluteUri);
365                     string hash = urlStr.Substring(urlStr.IndexOf("#"));
366                     this.Owner.HashSupl.AddItem(hash);
367                     this.Owner.HashMgr.AddHashToHistory(hash.Trim(), false);
368                     this.Owner.AddNewTabForSearch(hash);
369                     return;
370                 }
371                 else
372                 {
373                     Match m = Regex.Match(e.Url.AbsoluteUri, @"^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)$");
374                     if (AppendSettingDialog.Instance.OpenUserTimeline && m.Success && this.Owner.IsTwitterId(m.Result("${ScreenName}")))
375                     {
376                         this.Owner.AddNewTabForUserTimeline(m.Result("${ScreenName}"));
377                     }
378                     else
379                     {
380                         this.Owner.OpenUriAsync(e.Url.OriginalString);
381                     }
382                 }
383             }
384         }
385
386         private void SelectAllToolStripMenuItem_Click(object sender, EventArgs e)
387         {
388             var browser = (WebBrowser)this.ContextMenuRecentPostBrowser.SourceControl;
389             browser.Document.ExecCommand("SelectAll", false, null);
390         }
391
392         private void SelectionCopyToolStripMenuItem_Click(object sender, EventArgs e)
393         {
394             var browser = (WebBrowser)this.ContextMenuRecentPostBrowser.SourceControl;
395             var selectedText = this.Owner.WebBrowser_GetSelectionText(ref browser);
396             if (selectedText != null)
397             {
398                 try
399                 {
400                     Clipboard.SetDataObject(selectedText, false, 5, 100);
401                 }
402                 catch (Exception ex)
403                 {
404                     MessageBox.Show(ex.Message);
405                 }
406             }
407         }
408
409         private void ContextMenuRecentPostBrowser_Opening(object sender, CancelEventArgs e)
410         {
411             var browser = (WebBrowser)this.ContextMenuRecentPostBrowser.SourceControl;
412             var selectedText = this.Owner.WebBrowser_GetSelectionText(ref browser);
413
414             this.SelectionCopyToolStripMenuItem.Enabled = selectedText != null;
415         }
416
417         private void LinkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
418         {
419             this.Owner.OpenUriAsync("https://support.twitter.com/groups/31-twitter-basics/topics/111-features/articles/268350-x8a8d-x8a3c-x6e08-x307f-x30a2-x30ab-x30a6-x30f3-x30c8-x306b-x3064-x3044-x3066");
420         }
421
422         private void LinkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
423         {
424             this.Owner.OpenUriAsync("https://support.twitter.com/groups/31-twitter-basics/topics/107-my-profile-account-settings/articles/243055-x516c-x958b-x3001-x975e-x516c-x958b-x30a2-x30ab-x30a6-x30f3-x30c8-x306b-x3064-x3044-x3066");
425         }
426
427         private void ButtonSearchPosts_Click(object sender, EventArgs e)
428         {
429             this.Owner.AddNewTabForUserTimeline(this._displayUser.ScreenName);
430         }
431
432         private async void UserPicture_Click(object sender, EventArgs e)
433         {
434             var imageUrl = this._displayUser.ProfileImageUrlHttps;
435             imageUrl = imageUrl.Remove(imageUrl.LastIndexOf("_normal"), 7);
436
437             await this.Owner.OpenUriAsync(imageUrl);
438         }
439
440         private bool IsEditing = false;
441         private string ButtonEditText = "";
442
443         private async void ButtonEdit_Click(object sender, EventArgs e)
444         {
445             // 自分以外のプロフィールは変更できない
446             if (this.Twitter.UserId != this._displayUser.Id)
447                 return;
448
449             this.ButtonEdit.Enabled = false;
450
451             if (!IsEditing)
452             {
453                 ButtonEditText = ButtonEdit.Text;
454                 ButtonEdit.Text = Properties.Resources.UserInfoButtonEdit_ClickText1;
455
456                 TextBoxName.Text = LabelName.Text;
457                 TextBoxName.Enabled = true;
458                 TextBoxName.Visible = true;
459                 LabelName.Visible = false;
460
461                 TextBoxLocation.Text = LabelLocation.Text;
462                 TextBoxLocation.Enabled = true;
463                 TextBoxLocation.Visible = true;
464                 LabelLocation.Visible = false;
465
466                 TextBoxWeb.Text = this._displayUser.Url;
467                 TextBoxWeb.Enabled = true;
468                 TextBoxWeb.Visible = true;
469                 LinkLabelWeb.Visible = false;
470
471                 TextBoxDescription.Text = this._displayUser.Description;
472                 TextBoxDescription.Enabled = true;
473                 TextBoxDescription.Visible = true;
474                 DescriptionBrowser.Visible = false;
475
476                 TextBoxName.Focus();
477                 TextBoxName.Select(TextBoxName.Text.Length, 0);
478
479                 IsEditing = true;
480             }
481             else
482             {
483                 if (TextBoxName.Modified ||
484                     TextBoxLocation.Modified ||
485                     TextBoxWeb.Modified ||
486                     TextBoxDescription.Modified)
487                 {
488                     try
489                     {
490                         var user = await Task.Run(() =>
491                             this.Twitter.PostUpdateProfile(
492                                 this.TextBoxName.Text,
493                                 this.TextBoxWeb.Text,
494                                 this.TextBoxLocation.Text,
495                                 this.TextBoxDescription.Text));
496
497                         this.DisplayUser = user;
498                     }
499                     catch (WebApiException ex)
500                     {
501                         MessageBox.Show(ex.Message);
502                         return;
503                     }
504                 }
505
506                 TextBoxName.Enabled = false;
507                 TextBoxName.Visible = false;
508                 LabelName.Visible = true;
509
510                 TextBoxLocation.Enabled = false;
511                 TextBoxLocation.Visible = false;
512                 LabelLocation.Visible = true;
513
514                 TextBoxWeb.Enabled = false;
515                 TextBoxWeb.Visible = false;
516                 LinkLabelWeb.Visible = true;
517
518                 TextBoxDescription.Enabled = false;
519                 TextBoxDescription.Visible = false;
520                 DescriptionBrowser.Visible = true;
521
522                 ButtonEdit.Text = ButtonEditText;
523
524                 IsEditing = false;
525             }
526
527             this.ButtonEdit.Enabled = true;
528         }
529
530         private async Task DoChangeIcon(string filename)
531         {
532             var ret = await Task.Run(() =>
533                 this.Twitter.PostUpdateProfileImage(filename));
534
535             if (!string.IsNullOrEmpty(ret))
536             {
537                 // "Err:"が付いたエラーメッセージが返ってくる
538                 MessageBox.Show(ret + Environment.NewLine + Properties.Resources.ChangeIconToolStripMenuItem_ClickText4);
539             }
540             else
541             {
542                 MessageBox.Show(Properties.Resources.ChangeIconToolStripMenuItem_ClickText5);
543             }
544
545             try
546             {
547                 var user = await Task.Run(() =>
548                 {
549                     TwitterUser result = null;
550
551                     var err = this.Twitter.GetUserInfo(this._displayUser.ScreenName, ref result);
552                     if (!string.IsNullOrEmpty(err))
553                         throw new WebApiException(err);
554
555                     return result;
556                 });
557
558                 if (user != null)
559                     this.DisplayUser = user;
560             }
561             catch (WebApiException ex)
562             {
563                 MessageBox.Show(ex.Message);
564             }
565         }
566
567         private async void ChangeIconToolStripMenuItem_Click(object sender, EventArgs e)
568         {
569             OpenFileDialogIcon.Filter = Properties.Resources.ChangeIconToolStripMenuItem_ClickText1;
570             OpenFileDialogIcon.Title = Properties.Resources.ChangeIconToolStripMenuItem_ClickText2;
571             OpenFileDialogIcon.FileName = "";
572
573             DialogResult rslt = OpenFileDialogIcon.ShowDialog();
574
575             if (rslt != DialogResult.OK)
576             {
577                 return;
578             }
579
580             string fn = OpenFileDialogIcon.FileName;
581             if (this.IsValidIconFile(new FileInfo(fn)))
582             {
583                 await this.DoChangeIcon(fn);
584             }
585             else
586             {
587                 MessageBox.Show(Properties.Resources.ChangeIconToolStripMenuItem_ClickText6);
588             }
589         }
590
591         private void ButtonBlock_Click(object sender, EventArgs e)
592         {
593             if (MessageBox.Show(this._displayUser.ScreenName + Properties.Resources.ButtonBlock_ClickText1,
594                                 Properties.Resources.ButtonBlock_ClickText2,
595                                 MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
596             {
597                 string res = this.Twitter.PostCreateBlock(this._displayUser.ScreenName);
598                 if (!string.IsNullOrEmpty(res))
599                 {
600                     MessageBox.Show(res + Environment.NewLine + Properties.Resources.ButtonBlock_ClickText3);
601                 }
602                 else
603                 {
604                     MessageBox.Show(Properties.Resources.ButtonBlock_ClickText4);
605                 }
606             }
607         }
608
609         private void ButtonReportSpam_Click(object sender, EventArgs e)
610         {
611             if (MessageBox.Show(this._displayUser.ScreenName + Properties.Resources.ButtonReportSpam_ClickText1,
612                                 Properties.Resources.ButtonReportSpam_ClickText2,
613                                 MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
614             {
615                 string res = this.Twitter.PostReportSpam(this._displayUser.ScreenName);
616                 if (!string.IsNullOrEmpty(res))
617                 {
618                     MessageBox.Show(res + Environment.NewLine + Properties.Resources.ButtonReportSpam_ClickText3);
619                 }
620                 else
621                 {
622                     MessageBox.Show(Properties.Resources.ButtonReportSpam_ClickText4);
623                 }
624             }
625         }
626
627         private void ButtonBlockDestroy_Click(object sender, EventArgs e)
628         {
629             if (MessageBox.Show(this._displayUser.ScreenName + Properties.Resources.ButtonBlockDestroy_ClickText1,
630                                 Properties.Resources.ButtonBlockDestroy_ClickText2,
631                                 MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
632             {
633                 string res = this.Twitter.PostDestroyBlock(this._displayUser.ScreenName);
634                 if (!string.IsNullOrEmpty(res))
635                 {
636                     MessageBox.Show(res + Environment.NewLine + Properties.Resources.ButtonBlockDestroy_ClickText3);
637                 }
638                 else
639                 {
640                     MessageBox.Show(Properties.Resources.ButtonBlockDestroy_ClickText4);
641                 }
642             }
643         }
644
645         private bool IsValidExtension(string ext)
646         {
647             ext = ext.ToLower();
648
649             return ext.Equals(".jpg", StringComparison.Ordinal) ||
650                 ext.Equals(".jpeg", StringComparison.Ordinal) ||
651                 ext.Equals(".png", StringComparison.Ordinal) ||
652                 ext.Equals(".gif", StringComparison.Ordinal);
653         }
654
655         private bool IsValidIconFile(FileInfo info)
656         {
657             return this.IsValidExtension(info.Extension) &&
658                 info.Length < 700 * 1024 &&
659                 !MyCommon.IsAnimatedGif(info.FullName);
660         }
661
662         private void ShowUserInfo_DragOver(object sender, DragEventArgs e)
663         {
664             if (e.Data.GetDataPresent(DataFormats.FileDrop))
665             {
666                 var files = (string[])e.Data.GetData(DataFormats.FileDrop, false);
667                 if (files.Length != 1)
668                     return;
669
670                 var finfo = new FileInfo(files[0]);
671                 if (this.IsValidIconFile(finfo))
672                 {
673                     e.Effect = DragDropEffects.Copy;
674                 }
675             }
676         }
677
678         private async void ShowUserInfo_DragDrop(object sender, DragEventArgs e)
679         {
680             if (e.Data.GetDataPresent(DataFormats.FileDrop))
681             {
682                 string filename = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
683                 await this.DoChangeIcon(filename);
684             }
685         }
686
687         protected override void Dispose(bool disposing)
688         {
689             if (disposing)
690             {
691                 var oldImage = this.UserPicture.Image;
692                 if (oldImage != null)
693                 {
694                     this.UserPicture.Image = null;
695                     oldImage.Dispose();
696                 }
697
698                 if (this.components != null)
699                     this.components.Dispose();
700             }
701
702             base.Dispose(disposing);
703         }
704     }
705 }