OSDN Git Service

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