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.
10 // This file is part of OpenTween.
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)
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
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.
28 using System.Collections.Generic;
29 using System.ComponentModel;
34 using System.Threading;
35 using System.Threading.Tasks;
36 using System.Windows.Forms;
37 using System.Text.RegularExpressions;
42 using OpenTween.Api.DataModel;
43 using OpenTween.Connection;
44 using System.Diagnostics.CodeAnalysis;
48 public partial class UserInfoDialog : OTBaseForm
50 private TwitterUser _displayUser;
51 private CancellationTokenSource cancellationTokenSource = null;
53 private readonly TweenMain mainForm;
54 private readonly TwitterApi twitterApi;
56 public UserInfoDialog(TweenMain mainForm, TwitterApi twitterApi)
58 this.mainForm = mainForm;
59 this.twitterApi = twitterApi;
61 InitializeComponent();
63 // LabelScreenName のフォントを OTBaseForm.GlobalFont に変更
64 this.LabelScreenName.Font = this.ReplaceToGlobalFont(this.LabelScreenName.Font);
67 [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]
68 private void CancelLoading()
70 CancellationTokenSource newTokenSource = null, oldTokenSource = null;
73 newTokenSource = new CancellationTokenSource();
74 oldTokenSource = Interlocked.Exchange(ref this.cancellationTokenSource, newTokenSource);
78 if (oldTokenSource != null)
80 oldTokenSource.Cancel();
81 oldTokenSource.Dispose();
86 public async Task ShowUserAsync(TwitterUser user)
91 if (user == null || user == this._displayUser)
96 var cancellationToken = this.cancellationTokenSource.Token;
98 this._displayUser = user;
100 this.LabelId.Text = user.IdStr;
101 this.LabelScreenName.Text = user.ScreenName;
102 this.LabelName.Text = user.Name;
103 this.LabelLocation.Text = user.Location ?? "";
104 this.LabelCreatedAt.Text = MyCommon.DateTimeParse(user.CreatedAt).ToString();
107 this.LabelIsProtected.Text = Properties.Resources.Yes;
109 this.LabelIsProtected.Text = Properties.Resources.No;
112 this.LabelIsVerified.Text = Properties.Resources.Yes;
114 this.LabelIsVerified.Text = Properties.Resources.No;
116 var followingUrl = "https://twitter.com/" + user.ScreenName + "/following";
117 this.LinkLabelFollowing.Text = user.FriendsCount.ToString();
118 this.LinkLabelFollowing.Tag = followingUrl;
119 this.ToolTip1.SetToolTip(this.LinkLabelFollowing, followingUrl);
121 var followersUrl = "https://twitter.com/" + user.ScreenName + "/followers";
122 this.LinkLabelFollowers.Text = user.FollowersCount.ToString();
123 this.LinkLabelFollowers.Tag = followersUrl;
124 this.ToolTip1.SetToolTip(this.LinkLabelFollowers, followersUrl);
126 var favoritesUrl = "https://twitter.com/" + user.ScreenName + "/favorites";
127 this.LinkLabelFav.Text = user.FavouritesCount.ToString();
128 this.LinkLabelFav.Tag = favoritesUrl;
129 this.ToolTip1.SetToolTip(this.LinkLabelFav, favoritesUrl);
131 var profileUrl = "https://twitter.com/" + user.ScreenName;
132 this.LinkLabelTweet.Text = user.StatusesCount.ToString();
133 this.LinkLabelTweet.Tag = profileUrl;
134 this.ToolTip1.SetToolTip(this.LinkLabelTweet, profileUrl);
136 if (this.twitterApi.CurrentUserId == user.Id)
138 this.ButtonEdit.Enabled = true;
139 this.ChangeIconToolStripMenuItem.Enabled = true;
140 this.ButtonBlock.Enabled = false;
141 this.ButtonReportSpam.Enabled = false;
142 this.ButtonBlockDestroy.Enabled = false;
146 this.ButtonEdit.Enabled = false;
147 this.ChangeIconToolStripMenuItem.Enabled = false;
148 this.ButtonBlock.Enabled = true;
149 this.ButtonReportSpam.Enabled = true;
150 this.ButtonBlockDestroy.Enabled = true;
153 await Task.WhenAll(new[]
155 this.SetDescriptionAsync(user.Description, user.Entities.Description, cancellationToken),
156 this.SetRecentStatusAsync(user.Status, cancellationToken),
157 this.SetLinkLabelWebAsync(user.Url, user.Entities.Url, cancellationToken),
158 this.SetUserImageAsync(user.ProfileImageUrlHttps, cancellationToken),
159 this.LoadFriendshipAsync(user.ScreenName, cancellationToken),
163 private async Task SetDescriptionAsync(string descriptionText, TwitterEntities entities, CancellationToken cancellationToken)
165 if (descriptionText != null)
167 foreach (var entity in entities.Urls)
168 entity.ExpandedUrl = await ShortUrl.Instance.ExpandUrlAsync(entity.ExpandedUrl);
170 // user.entities には urls 以外のエンティティが含まれていないため、テキストをもとに生成する
171 entities.Hashtags = TweetExtractor.ExtractHashtagEntities(descriptionText).ToArray();
172 entities.UserMentions = TweetExtractor.ExtractMentionEntities(descriptionText).ToArray();
174 var html = TweetFormatter.AutoLinkHtml(descriptionText, entities);
175 html = this.mainForm.createDetailHtml(html);
177 if (cancellationToken.IsCancellationRequested)
180 this.DescriptionBrowser.DocumentText = html;
184 this.DescriptionBrowser.DocumentText = "";
188 private async Task SetUserImageAsync(string imageUri, CancellationToken cancellationToken)
190 var oldImage = this.UserPicture.Image;
191 this.UserPicture.Image = null;
194 // ProfileImageUrlHttps が null になる場合があるらしい
195 // 参照: https://sourceforge.jp/ticket/browse.php?group_id=6526&tid=33871
196 if (imageUri == null)
199 await this.UserPicture.SetImageFromTask(async () =>
201 var uri = imageUri.Replace("_normal", "_bigger");
203 using (var imageStream = await Networking.Http.GetStreamAsync(uri).ConfigureAwait(false))
205 var image = await MemoryImage.CopyFromStreamAsync(imageStream)
206 .ConfigureAwait(false);
208 if (cancellationToken.IsCancellationRequested)
211 throw new OperationCanceledException(cancellationToken);
219 private async Task SetLinkLabelWebAsync(string uri, TwitterEntities entities, CancellationToken cancellationToken)
223 var origUrl = entities?.Urls[0].ExpandedUrl ?? uri;
224 var expandedUrl = await ShortUrl.Instance.ExpandUrlAsync(origUrl);
226 if (cancellationToken.IsCancellationRequested)
229 this.LinkLabelWeb.Text = expandedUrl;
230 this.LinkLabelWeb.Tag = expandedUrl;
231 this.ToolTip1.SetToolTip(this.LinkLabelWeb, expandedUrl);
235 this.LinkLabelWeb.Text = "";
236 this.LinkLabelWeb.Tag = null;
237 this.ToolTip1.SetToolTip(this.LinkLabelWeb, null);
241 private async Task SetRecentStatusAsync(TwitterStatus status, CancellationToken cancellationToken)
245 var entities = status.MergedEntities;
247 foreach (var entity in entities.Urls)
248 entity.ExpandedUrl = await ShortUrl.Instance.ExpandUrlAsync(entity.ExpandedUrl);
250 var html = TweetFormatter.AutoLinkHtml(status.FullText, entities);
251 html = this.mainForm.createDetailHtml(html +
252 " Posted at " + MyCommon.DateTimeParse(status.CreatedAt) +
253 " via " + status.Source);
255 if (cancellationToken.IsCancellationRequested)
258 this.RecentPostBrowser.DocumentText = html;
262 this.RecentPostBrowser.DocumentText = Properties.Resources.ShowUserInfo2;
266 private async Task LoadFriendshipAsync(string screenName, CancellationToken cancellationToken)
268 this.LabelIsFollowing.Text = "";
269 this.LabelIsFollowed.Text = "";
270 this.ButtonFollow.Enabled = false;
271 this.ButtonUnFollow.Enabled = false;
273 if (this.twitterApi.CurrentScreenName == screenName)
276 TwitterFriendship friendship;
279 friendship = await this.twitterApi.FriendshipsShow(this.twitterApi.CurrentScreenName, screenName);
281 catch (WebApiException)
283 LabelIsFollowed.Text = Properties.Resources.GetFriendshipInfo6;
284 LabelIsFollowing.Text = Properties.Resources.GetFriendshipInfo6;
288 if (cancellationToken.IsCancellationRequested)
291 var isFollowing = friendship.Relationship.Source.Following;
292 var isFollowedBy = friendship.Relationship.Source.FollowedBy;
294 this.LabelIsFollowing.Text = isFollowing
295 ? Properties.Resources.GetFriendshipInfo1
296 : Properties.Resources.GetFriendshipInfo2;
298 this.LabelIsFollowed.Text = isFollowedBy
299 ? Properties.Resources.GetFriendshipInfo3
300 : Properties.Resources.GetFriendshipInfo4;
302 this.ButtonFollow.Enabled = !isFollowing;
303 this.ButtonUnFollow.Enabled = isFollowing;
306 private void ShowUserInfo_Load(object sender, EventArgs e)
308 this.TextBoxName.Location = this.LabelName.Location;
309 this.TextBoxName.Height = this.LabelName.Height;
310 this.TextBoxName.Width = this.LabelName.Width;
311 this.TextBoxName.BackColor = this.mainForm.InputBackColor;
312 this.TextBoxName.MaxLength = 20;
314 this.TextBoxLocation.Location = this.LabelLocation.Location;
315 this.TextBoxLocation.Height = this.LabelLocation.Height;
316 this.TextBoxLocation.Width = this.LabelLocation.Width;
317 this.TextBoxLocation.BackColor = this.mainForm.InputBackColor;
318 this.TextBoxLocation.MaxLength = 30;
320 this.TextBoxWeb.Location = this.LinkLabelWeb.Location;
321 this.TextBoxWeb.Height = this.LinkLabelWeb.Height;
322 this.TextBoxWeb.Width = this.LinkLabelWeb.Width;
323 this.TextBoxWeb.BackColor = this.mainForm.InputBackColor;
324 this.TextBoxWeb.MaxLength = 100;
326 this.TextBoxDescription.Location = this.DescriptionBrowser.Location;
327 this.TextBoxDescription.Height = this.DescriptionBrowser.Height;
328 this.TextBoxDescription.Width = this.DescriptionBrowser.Width;
329 this.TextBoxDescription.BackColor = this.mainForm.InputBackColor;
330 this.TextBoxDescription.MaxLength = 160;
331 this.TextBoxDescription.Multiline = true;
332 this.TextBoxDescription.ScrollBars = ScrollBars.Vertical;
335 private async void LinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
337 var linkLabel = (LinkLabel)sender;
339 var linkUrl = (string)linkLabel.Tag;
343 await this.mainForm.OpenUriInBrowserAsync(linkUrl);
346 private async void ButtonFollow_Click(object sender, EventArgs e)
348 using (ControlTransaction.Disabled(this.ButtonFollow))
352 await this.twitterApi.FriendshipsCreate(this._displayUser.ScreenName)
355 catch (WebApiException ex)
357 MessageBox.Show(Properties.Resources.FRMessage2 + ex.Message);
362 MessageBox.Show(Properties.Resources.FRMessage3);
363 LabelIsFollowing.Text = Properties.Resources.GetFriendshipInfo1;
364 ButtonFollow.Enabled = false;
365 ButtonUnFollow.Enabled = true;
368 private async void ButtonUnFollow_Click(object sender, EventArgs e)
370 if (MessageBox.Show(this._displayUser.ScreenName + Properties.Resources.ButtonUnFollow_ClickText1,
371 Properties.Resources.ButtonUnFollow_ClickText2,
372 MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
374 using (ControlTransaction.Disabled(this.ButtonUnFollow))
378 await this.twitterApi.FriendshipsDestroy(this._displayUser.ScreenName)
381 catch (WebApiException ex)
383 MessageBox.Show(Properties.Resources.FRMessage2 + ex.Message);
388 MessageBox.Show(Properties.Resources.FRMessage3);
389 LabelIsFollowing.Text = Properties.Resources.GetFriendshipInfo2;
390 ButtonFollow.Enabled = true;
391 ButtonUnFollow.Enabled = false;
395 private void ShowUserInfo_Activated(object sender, EventArgs e)
397 //画面が他画面の裏に隠れると、アイコン画像が再描画されない問題の対応
398 if (UserPicture.Image != null)
399 UserPicture.Invalidate(false);
402 private void ShowUserInfo_Shown(object sender, EventArgs e)
407 private async void WebBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
409 if (e.Url.AbsoluteUri != "about:blank")
413 // Ctrlを押しながらリンクを開いた場合は、設定と逆の動作をするフラグを true としておく
414 await this.mainForm.OpenUriAsync(e.Url, MyCommon.IsKeyDown(Keys.Control));
418 private void SelectAllToolStripMenuItem_Click(object sender, EventArgs e)
420 var browser = (WebBrowser)this.ContextMenuRecentPostBrowser.SourceControl;
421 browser.Document.ExecCommand("SelectAll", false, null);
424 private void SelectionCopyToolStripMenuItem_Click(object sender, EventArgs e)
426 var browser = (WebBrowser)this.ContextMenuRecentPostBrowser.SourceControl;
427 var selectedText = browser.GetSelectedText();
428 if (selectedText != null)
432 Clipboard.SetDataObject(selectedText, false, 5, 100);
436 MessageBox.Show(ex.Message);
441 private void ContextMenuRecentPostBrowser_Opening(object sender, CancelEventArgs e)
443 var browser = (WebBrowser)this.ContextMenuRecentPostBrowser.SourceControl;
444 var selectedText = browser.GetSelectedText();
446 this.SelectionCopyToolStripMenuItem.Enabled = selectedText != null;
449 private async void LinkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
451 await this.mainForm.OpenUriInBrowserAsync("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");
454 private async void LinkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
456 await this.mainForm.OpenUriInBrowserAsync("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");
459 private void ButtonSearchPosts_Click(object sender, EventArgs e)
461 this.mainForm.AddNewTabForUserTimeline(this._displayUser.ScreenName);
464 private async void UserPicture_Click(object sender, EventArgs e)
466 var imageUrl = this._displayUser.ProfileImageUrlHttps;
467 imageUrl = imageUrl.Remove(imageUrl.LastIndexOf("_normal", StringComparison.Ordinal), 7);
469 await this.mainForm.OpenUriInBrowserAsync(imageUrl);
472 private bool IsEditing = false;
473 private string ButtonEditText = "";
475 private async void ButtonEdit_Click(object sender, EventArgs e)
477 // 自分以外のプロフィールは変更できない
478 if (this.twitterApi.CurrentUserId != this._displayUser.Id)
481 using (ControlTransaction.Disabled(this.ButtonEdit))
485 ButtonEditText = ButtonEdit.Text;
486 ButtonEdit.Text = Properties.Resources.UserInfoButtonEdit_ClickText1;
488 TextBoxName.Text = LabelName.Text;
489 TextBoxName.Enabled = true;
490 TextBoxName.Visible = true;
491 LabelName.Visible = false;
493 TextBoxLocation.Text = LabelLocation.Text;
494 TextBoxLocation.Enabled = true;
495 TextBoxLocation.Visible = true;
496 LabelLocation.Visible = false;
498 TextBoxWeb.Text = this._displayUser.Url;
499 TextBoxWeb.Enabled = true;
500 TextBoxWeb.Visible = true;
501 LinkLabelWeb.Visible = false;
503 TextBoxDescription.Text = this._displayUser.Description;
504 TextBoxDescription.Enabled = true;
505 TextBoxDescription.Visible = true;
506 DescriptionBrowser.Visible = false;
509 TextBoxName.Select(TextBoxName.Text.Length, 0);
515 Task showUserTask = null;
517 if (TextBoxName.Modified ||
518 TextBoxLocation.Modified ||
519 TextBoxWeb.Modified ||
520 TextBoxDescription.Modified)
524 var response = await this.twitterApi.AccountUpdateProfile(
525 this.TextBoxName.Text,
526 this.TextBoxWeb.Text,
527 this.TextBoxLocation.Text,
528 this.TextBoxDescription.Text);
530 var user = await response.LoadJsonAsync();
531 showUserTask = this.ShowUserAsync(user);
533 catch (WebApiException ex)
535 MessageBox.Show($"Err:{ex.Message}(AccountUpdateProfile)");
540 TextBoxName.Enabled = false;
541 TextBoxName.Visible = false;
542 LabelName.Visible = true;
544 TextBoxLocation.Enabled = false;
545 TextBoxLocation.Visible = false;
546 LabelLocation.Visible = true;
548 TextBoxWeb.Enabled = false;
549 TextBoxWeb.Visible = false;
550 LinkLabelWeb.Visible = true;
552 TextBoxDescription.Enabled = false;
553 TextBoxDescription.Visible = false;
554 DescriptionBrowser.Visible = true;
556 ButtonEdit.Text = ButtonEditText;
560 if (showUserTask != null)
566 private async Task DoChangeIcon(string filename)
570 var mediaItem = new FileMediaItem(filename);
572 await this.twitterApi.AccountUpdateProfileImage(mediaItem)
575 catch (WebApiException ex)
577 MessageBox.Show("Err:" + ex.Message + Environment.NewLine + Properties.Resources.ChangeIconToolStripMenuItem_ClickText4);
581 MessageBox.Show(Properties.Resources.ChangeIconToolStripMenuItem_ClickText5);
585 var user = await this.twitterApi.UsersShow(this._displayUser.ScreenName);
588 await this.ShowUserAsync(user);
590 catch (WebApiException ex)
592 MessageBox.Show($"Err:{ex.Message}(UsersShow)");
596 private async void ChangeIconToolStripMenuItem_Click(object sender, EventArgs e)
598 OpenFileDialogIcon.Filter = Properties.Resources.ChangeIconToolStripMenuItem_ClickText1;
599 OpenFileDialogIcon.Title = Properties.Resources.ChangeIconToolStripMenuItem_ClickText2;
600 OpenFileDialogIcon.FileName = "";
602 DialogResult rslt = OpenFileDialogIcon.ShowDialog();
604 if (rslt != DialogResult.OK)
609 string fn = OpenFileDialogIcon.FileName;
610 if (this.IsValidIconFile(new FileInfo(fn)))
612 await this.DoChangeIcon(fn);
616 MessageBox.Show(Properties.Resources.ChangeIconToolStripMenuItem_ClickText6);
620 private async void ButtonBlock_Click(object sender, EventArgs e)
622 if (MessageBox.Show(this._displayUser.ScreenName + Properties.Resources.ButtonBlock_ClickText1,
623 Properties.Resources.ButtonBlock_ClickText2,
624 MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
626 using (ControlTransaction.Disabled(this.ButtonBlock))
630 await this.twitterApi.BlocksCreate(this._displayUser.ScreenName)
633 catch (WebApiException ex)
635 MessageBox.Show("Err:" + ex.Message + Environment.NewLine + Properties.Resources.ButtonBlock_ClickText3);
639 MessageBox.Show(Properties.Resources.ButtonBlock_ClickText4);
644 private async void ButtonReportSpam_Click(object sender, EventArgs e)
646 if (MessageBox.Show(this._displayUser.ScreenName + Properties.Resources.ButtonReportSpam_ClickText1,
647 Properties.Resources.ButtonReportSpam_ClickText2,
648 MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
650 using (ControlTransaction.Disabled(this.ButtonReportSpam))
654 await this.twitterApi.UsersReportSpam(this._displayUser.ScreenName)
657 catch (WebApiException ex)
659 MessageBox.Show("Err:" + ex.Message + Environment.NewLine + Properties.Resources.ButtonReportSpam_ClickText3);
663 MessageBox.Show(Properties.Resources.ButtonReportSpam_ClickText4);
668 private async void ButtonBlockDestroy_Click(object sender, EventArgs e)
670 if (MessageBox.Show(this._displayUser.ScreenName + Properties.Resources.ButtonBlockDestroy_ClickText1,
671 Properties.Resources.ButtonBlockDestroy_ClickText2,
672 MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
674 using (ControlTransaction.Disabled(this.ButtonBlockDestroy))
678 await this.twitterApi.BlocksDestroy(this._displayUser.ScreenName)
681 catch (WebApiException ex)
683 MessageBox.Show("Err:" + ex.Message + Environment.NewLine + Properties.Resources.ButtonBlockDestroy_ClickText3);
687 MessageBox.Show(Properties.Resources.ButtonBlockDestroy_ClickText4);
692 private bool IsValidExtension(string ext)
694 ext = ext.ToLowerInvariant();
696 return ext.Equals(".jpg", StringComparison.Ordinal) ||
697 ext.Equals(".jpeg", StringComparison.Ordinal) ||
698 ext.Equals(".png", StringComparison.Ordinal) ||
699 ext.Equals(".gif", StringComparison.Ordinal);
702 private bool IsValidIconFile(FileInfo info)
704 return this.IsValidExtension(info.Extension) &&
705 info.Length < 700 * 1024 &&
706 !MyCommon.IsAnimatedGif(info.FullName);
709 private void ShowUserInfo_DragEnter(object sender, DragEventArgs e)
711 if (e.Data.GetDataPresent(DataFormats.FileDrop) &&
712 !e.Data.GetDataPresent(DataFormats.Html, false)) // WebBrowserコントロールからの絵文字画像D&Dは弾く
714 var files = (string[])e.Data.GetData(DataFormats.FileDrop, false);
715 if (files.Length != 1)
718 var finfo = new FileInfo(files[0]);
719 if (this.IsValidIconFile(finfo))
721 e.Effect = DragDropEffects.Copy;
726 private async void ShowUserInfo_DragDrop(object sender, DragEventArgs e)
728 if (e.Data.GetDataPresent(DataFormats.FileDrop) &&
729 !e.Data.GetDataPresent(DataFormats.Html, false)) // WebBrowserコントロールからの絵文字画像D&Dは弾く
731 var ret = MessageBox.Show(this, Properties.Resources.ChangeIconToolStripMenuItem_Confirm,
732 Application.ProductName, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
733 if (ret != DialogResult.OK)
736 string filename = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
737 await this.DoChangeIcon(filename);
741 protected override void Dispose(bool disposing)
745 var cts = this.cancellationTokenSource;
749 var oldImage = this.UserPicture.Image;
750 this.UserPicture.Image = null;
753 this.components?.Dispose();
756 base.Dispose(disposing);