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.Tasks;
35 using System.Windows.Forms;
36 using System.Text.RegularExpressions;
43 public partial class ShowUserInfo : OTBaseForm
45 private TwitterDataModel.User _displayUser;
46 public TwitterDataModel.User DisplayUser
48 get { return this._displayUser; }
51 if (this._displayUser != value)
53 this._displayUser = value;
54 this.OnDisplayUserChanged();
59 private new TweenMain Owner
61 get { return (TweenMain)base.Owner; }
64 private Twitter Twitter
66 get { return this.Owner.TwitterInstance; }
71 InitializeComponent();
73 // LabelScreenName のフォントを OTBaseForm.GlobalFont に変更
74 this.LabelScreenName.Font = this.ReplaceToGlobalFont(this.LabelScreenName.Font);
77 protected virtual async void OnDisplayUserChanged()
79 if (this._displayUser == null)
82 var user = this._displayUser;
84 this.LabelId.Text = user.IdStr;
85 this.LabelScreenName.Text = user.ScreenName;
86 this.LabelName.Text = WebUtility.HtmlDecode(user.Name);
87 this.LabelLocation.Text = user.Location ?? "";
88 this.LabelCreatedAt.Text = MyCommon.DateTimeParse(user.CreatedAt).ToString();
91 this.LabelIsProtected.Text = Properties.Resources.Yes;
93 this.LabelIsProtected.Text = Properties.Resources.No;
96 this.LabelIsVerified.Text = Properties.Resources.Yes;
98 this.LabelIsVerified.Text = Properties.Resources.No;
100 var followingUrl = "https://twitter.com/" + user.ScreenName + "/following";
101 this.LinkLabelFollowing.Text = user.FriendsCount.ToString();
102 this.LinkLabelFollowing.Tag = followingUrl;
103 this.ToolTip1.SetToolTip(this.LinkLabelFollowing, followingUrl);
105 var followersUrl = "https://twitter.com/" + user.ScreenName + "/followers";
106 this.LinkLabelFollowers.Text = user.FollowersCount.ToString();
107 this.LinkLabelFollowers.Tag = followersUrl;
108 this.ToolTip1.SetToolTip(this.LinkLabelFollowers, followersUrl);
110 var favoritesUrl = "https://twitter.com/" + user.ScreenName + "/favorites";
111 this.LinkLabelFav.Text = user.FavouritesCount.ToString();
112 this.LinkLabelFav.Tag = favoritesUrl;
113 this.ToolTip1.SetToolTip(this.LinkLabelFav, favoritesUrl);
115 var profileUrl = "https://twitter.com/" + user.ScreenName;
116 this.LinkLabelTweet.Text = user.StatusesCount.ToString();
117 this.LinkLabelTweet.Tag = profileUrl;
118 this.ToolTip1.SetToolTip(this.LinkLabelTweet, profileUrl);
120 if (this.Twitter.UserId == user.Id)
122 this.ButtonEdit.Enabled = true;
123 this.ChangeIconToolStripMenuItem.Enabled = true;
124 this.ButtonBlock.Enabled = false;
125 this.ButtonReportSpam.Enabled = false;
126 this.ButtonBlockDestroy.Enabled = false;
130 this.ButtonEdit.Enabled = false;
131 this.ChangeIconToolStripMenuItem.Enabled = false;
132 this.ButtonBlock.Enabled = true;
133 this.ButtonReportSpam.Enabled = true;
134 this.ButtonBlockDestroy.Enabled = true;
137 await Task.WhenAll(new[]
139 this.SetDescriptionAsync(user.Description),
140 this.SetRecentStatusAsync(user.Status),
141 this.SetLinkLabelWebAsync(user.Url),
142 this.SetUserImageAsync(user.ProfileImageUrlHttps),
143 this.LoadFriendshipAsync(user.ScreenName),
147 private async Task SetDescriptionAsync(string descriptionText)
149 if (descriptionText != null)
151 var atlist = new List<string>();
153 var html = WebUtility.HtmlEncode(descriptionText);
154 html = await this.Twitter.CreateHtmlAnchorAsync(html, atlist, null);
155 html = this.Owner.createDetailHtml(html);
157 this.DescriptionBrowser.DocumentText = html;
161 this.DescriptionBrowser.DocumentText = "";
165 private async Task SetUserImageAsync(string imageUri)
167 var oldImage = this.UserPicture.Image;
168 if (oldImage != null)
170 this.UserPicture.Image = null;
174 using (var http = MyCommon.CreateHttpClient())
176 var imageStream = await http.GetStreamAsync(imageUri.Replace("_normal", "_bigger"));
177 this.UserPicture.Image = await MemoryImage.CopyFromStreamAsync(imageStream);
181 private async Task SetLinkLabelWebAsync(string uri)
185 var expandedUrl = await ShortUrl.Instance.ExpandUrlStrAsync(uri);
187 this.LinkLabelWeb.Text = uri;
188 this.LinkLabelWeb.Tag = expandedUrl;
189 this.ToolTip1.SetToolTip(this.LinkLabelWeb, expandedUrl);
193 this.LinkLabelWeb.Text = "";
194 this.LinkLabelWeb.Tag = null;
195 this.ToolTip1.SetToolTip(this.LinkLabelWeb, null);
199 private async Task SetRecentStatusAsync(TwitterDataModel.Status status)
201 var atlist = new List<string>();
205 var html = await this.Twitter.CreateHtmlAnchorAsync(status.Text, atlist, status.Entities, null);
206 html = this.Owner.createDetailHtml(html +
207 " Posted at " + MyCommon.DateTimeParse(status.CreatedAt) +
208 " via " + status.Source);
210 this.RecentPostBrowser.DocumentText = html;
214 this.RecentPostBrowser.DocumentText = Properties.Resources.ShowUserInfo2;
218 private async Task LoadFriendshipAsync(string screenName)
220 this.LabelIsFollowing.Text = "";
221 this.LabelIsFollowed.Text = "";
222 this.ButtonFollow.Enabled = false;
223 this.ButtonUnFollow.Enabled = false;
225 if (this.Twitter.Username == screenName)
228 var friendship = await Task.Run(() =>
230 var IsFollowing = false;
231 var IsFollowedBy = false;
233 var ret = this.Twitter.GetFriendshipInfo(screenName, ref IsFollowing, ref IsFollowedBy);
234 if (!string.IsNullOrEmpty(ret))
237 return new { IsFollowing, IsFollowedBy };
240 if (friendship == null)
242 LabelIsFollowed.Text = Properties.Resources.GetFriendshipInfo6;
243 LabelIsFollowing.Text = Properties.Resources.GetFriendshipInfo6;
247 this.LabelIsFollowing.Text = friendship.IsFollowing
248 ? Properties.Resources.GetFriendshipInfo1
249 : Properties.Resources.GetFriendshipInfo2;
251 this.LabelIsFollowed.Text = friendship.IsFollowedBy
252 ? Properties.Resources.GetFriendshipInfo3
253 : Properties.Resources.GetFriendshipInfo4;
255 this.ButtonFollow.Enabled = !friendship.IsFollowing;
256 this.ButtonUnFollow.Enabled = friendship.IsFollowing;
259 private void ShowUserInfo_Load(object sender, EventArgs e)
261 this.TextBoxName.Location = this.LabelName.Location;
262 this.TextBoxName.Height = this.LabelName.Height;
263 this.TextBoxName.Width = this.LabelName.Width;
264 this.TextBoxName.BackColor = this.Owner.InputBackColor;
265 this.TextBoxName.MaxLength = 20;
267 this.TextBoxLocation.Location = this.LabelLocation.Location;
268 this.TextBoxLocation.Height = this.LabelLocation.Height;
269 this.TextBoxLocation.Width = this.LabelLocation.Width;
270 this.TextBoxLocation.BackColor = this.Owner.InputBackColor;
271 this.TextBoxLocation.MaxLength = 30;
273 this.TextBoxWeb.Location = this.LinkLabelWeb.Location;
274 this.TextBoxWeb.Height = this.LinkLabelWeb.Height;
275 this.TextBoxWeb.Width = this.LinkLabelWeb.Width;
276 this.TextBoxWeb.BackColor = this.Owner.InputBackColor;
277 this.TextBoxWeb.MaxLength = 100;
279 this.TextBoxDescription.Location = this.DescriptionBrowser.Location;
280 this.TextBoxDescription.Height = this.DescriptionBrowser.Height;
281 this.TextBoxDescription.Width = this.DescriptionBrowser.Width;
282 this.TextBoxDescription.BackColor = this.Owner.InputBackColor;
283 this.TextBoxDescription.MaxLength = 160;
284 this.TextBoxDescription.Multiline = true;
285 this.TextBoxDescription.ScrollBars = ScrollBars.Vertical;
288 private void ButtonClose_Click(object sender, EventArgs e)
293 private async void LinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
295 var linkLabel = (LinkLabel)sender;
297 var linkUrl = (string)linkLabel.Tag;
301 await this.Owner.OpenUriAsync(linkUrl);
304 private void ButtonFollow_Click(object sender, EventArgs e)
306 string ret = this.Twitter.PostFollowCommand(this._displayUser.ScreenName);
307 if (!string.IsNullOrEmpty(ret))
309 MessageBox.Show(Properties.Resources.FRMessage2 + ret);
313 MessageBox.Show(Properties.Resources.FRMessage3);
314 LabelIsFollowing.Text = Properties.Resources.GetFriendshipInfo1;
315 ButtonFollow.Enabled = false;
316 ButtonUnFollow.Enabled = true;
320 private void ButtonUnFollow_Click(object sender, EventArgs e)
322 if (MessageBox.Show(this._displayUser.ScreenName + Properties.Resources.ButtonUnFollow_ClickText1,
323 Properties.Resources.ButtonUnFollow_ClickText2,
324 MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
326 string ret = this.Twitter.PostRemoveCommand(this._displayUser.ScreenName);
327 if (!string.IsNullOrEmpty(ret))
329 MessageBox.Show(Properties.Resources.FRMessage2 + ret);
333 MessageBox.Show(Properties.Resources.FRMessage3);
334 LabelIsFollowing.Text = Properties.Resources.GetFriendshipInfo2;
335 ButtonFollow.Enabled = true;
336 ButtonUnFollow.Enabled = false;
341 private void ShowUserInfo_Activated(object sender, EventArgs e)
343 //画面が他画面の裏に隠れると、アイコン画像が再描画されない問題の対応
344 if (UserPicture.Image != null)
345 UserPicture.Invalidate(false);
348 private void ShowUserInfo_Shown(object sender, EventArgs e)
353 private void WebBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
355 if (e.Url.AbsoluteUri != "about:blank")
359 if (e.Url.AbsoluteUri.StartsWith("http://twitter.com/search?q=%23") ||
360 e.Url.AbsoluteUri.StartsWith("https://twitter.com/search?q=%23"))
363 string urlStr = Uri.UnescapeDataString(e.Url.AbsoluteUri);
364 string hash = urlStr.Substring(urlStr.IndexOf("#"));
365 this.Owner.HashSupl.AddItem(hash);
366 this.Owner.HashMgr.AddHashToHistory(hash.Trim(), false);
367 this.Owner.AddNewTabForSearch(hash);
372 Match m = Regex.Match(e.Url.AbsoluteUri, @"^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)$");
373 if (AppendSettingDialog.Instance.OpenUserTimeline && m.Success && this.Owner.IsTwitterId(m.Result("${ScreenName}")))
375 this.Owner.AddNewTabForUserTimeline(m.Result("${ScreenName}"));
379 this.Owner.OpenUriAsync(e.Url.OriginalString);
385 private void SelectAllToolStripMenuItem_Click(object sender, EventArgs e)
387 var browser = (WebBrowser)this.ContextMenuRecentPostBrowser.SourceControl;
388 browser.Document.ExecCommand("SelectAll", false, null);
391 private void SelectionCopyToolStripMenuItem_Click(object sender, EventArgs e)
393 var browser = (WebBrowser)this.ContextMenuRecentPostBrowser.SourceControl;
394 var selectedText = this.Owner.WebBrowser_GetSelectionText(ref browser);
395 if (selectedText != null)
399 Clipboard.SetDataObject(selectedText, false, 5, 100);
403 MessageBox.Show(ex.Message);
408 private void ContextMenuRecentPostBrowser_Opening(object sender, CancelEventArgs e)
410 var browser = (WebBrowser)this.ContextMenuRecentPostBrowser.SourceControl;
411 var selectedText = this.Owner.WebBrowser_GetSelectionText(ref browser);
413 this.SelectionCopyToolStripMenuItem.Enabled = selectedText != null;
416 private void LinkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
418 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");
421 private void LinkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
423 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");
426 private void ButtonSearchPosts_Click(object sender, EventArgs e)
428 this.Owner.AddNewTabForUserTimeline(this._displayUser.ScreenName);
431 private void UserPicture_Click(object sender, EventArgs e)
433 if (UserPicture.Image != null)
435 string name = this._displayUser.ProfileImageUrlHttps;
436 this.Owner.OpenUriAsync(name.Remove(name.LastIndexOf("_normal"), 7));
440 private bool IsEditing = false;
441 private string ButtonEditText = "";
443 private async void ButtonEdit_Click(object sender, EventArgs e)
445 // 自分以外のプロフィールは変更できない
446 if (this.Twitter.UserId != this._displayUser.Id)
449 this.ButtonEdit.Enabled = false;
453 ButtonEditText = ButtonEdit.Text;
454 ButtonEdit.Text = Properties.Resources.UserInfoButtonEdit_ClickText1;
456 TextBoxName.Text = LabelName.Text;
457 TextBoxName.Enabled = true;
458 TextBoxName.Visible = true;
459 LabelName.Visible = false;
461 TextBoxLocation.Text = LabelLocation.Text;
462 TextBoxLocation.Enabled = true;
463 TextBoxLocation.Visible = true;
464 LabelLocation.Visible = false;
466 TextBoxWeb.Text = this._displayUser.Url;
467 TextBoxWeb.Enabled = true;
468 TextBoxWeb.Visible = true;
469 LinkLabelWeb.Visible = false;
471 TextBoxDescription.Text = this._displayUser.Description;
472 TextBoxDescription.Enabled = true;
473 TextBoxDescription.Visible = true;
474 DescriptionBrowser.Visible = false;
477 TextBoxName.Select(TextBoxName.Text.Length, 0);
483 if (TextBoxName.Modified ||
484 TextBoxLocation.Modified ||
485 TextBoxWeb.Modified ||
486 TextBoxDescription.Modified)
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));
497 this.DisplayUser = user;
499 catch (WebApiException ex)
501 MessageBox.Show(ex.Message);
506 TextBoxName.Enabled = false;
507 TextBoxName.Visible = false;
508 LabelName.Visible = true;
510 TextBoxLocation.Enabled = false;
511 TextBoxLocation.Visible = false;
512 LabelLocation.Visible = true;
514 TextBoxWeb.Enabled = false;
515 TextBoxWeb.Visible = false;
516 LinkLabelWeb.Visible = true;
518 TextBoxDescription.Enabled = false;
519 TextBoxDescription.Visible = false;
520 DescriptionBrowser.Visible = true;
522 ButtonEdit.Text = ButtonEditText;
527 this.ButtonEdit.Enabled = true;
530 private async Task DoChangeIcon(string filename)
532 var ret = await Task.Run(() =>
533 this.Twitter.PostUpdateProfileImage(filename));
535 if (!string.IsNullOrEmpty(ret))
537 // "Err:"が付いたエラーメッセージが返ってくる
538 MessageBox.Show(ret + Environment.NewLine + Properties.Resources.ChangeIconToolStripMenuItem_ClickText4);
542 MessageBox.Show(Properties.Resources.ChangeIconToolStripMenuItem_ClickText5);
547 var user = await Task.Run(() =>
549 TwitterDataModel.User result = null;
551 var err = this.Twitter.GetUserInfo(this._displayUser.ScreenName, ref result);
552 if (!string.IsNullOrEmpty(err))
553 throw new WebApiException(err);
559 this.DisplayUser = user;
561 catch (WebApiException ex)
563 MessageBox.Show(ex.Message);
567 private async void ChangeIconToolStripMenuItem_Click(object sender, EventArgs e)
569 OpenFileDialogIcon.Filter = Properties.Resources.ChangeIconToolStripMenuItem_ClickText1;
570 OpenFileDialogIcon.Title = Properties.Resources.ChangeIconToolStripMenuItem_ClickText2;
571 OpenFileDialogIcon.FileName = "";
573 DialogResult rslt = OpenFileDialogIcon.ShowDialog();
575 if (rslt != DialogResult.OK)
580 string fn = OpenFileDialogIcon.FileName;
581 if (this.IsValidIconFile(new FileInfo(fn)))
583 await this.DoChangeIcon(fn);
587 MessageBox.Show(Properties.Resources.ChangeIconToolStripMenuItem_ClickText6);
591 private void ButtonBlock_Click(object sender, EventArgs e)
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)
597 string res = this.Twitter.PostCreateBlock(this._displayUser.ScreenName);
598 if (!string.IsNullOrEmpty(res))
600 MessageBox.Show(res + Environment.NewLine + Properties.Resources.ButtonBlock_ClickText3);
604 MessageBox.Show(Properties.Resources.ButtonBlock_ClickText4);
609 private void ButtonReportSpam_Click(object sender, EventArgs e)
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)
615 string res = this.Twitter.PostReportSpam(this._displayUser.ScreenName);
616 if (!string.IsNullOrEmpty(res))
618 MessageBox.Show(res + Environment.NewLine + Properties.Resources.ButtonReportSpam_ClickText3);
622 MessageBox.Show(Properties.Resources.ButtonReportSpam_ClickText4);
627 private void ButtonBlockDestroy_Click(object sender, EventArgs e)
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)
633 string res = this.Twitter.PostDestroyBlock(this._displayUser.ScreenName);
634 if (!string.IsNullOrEmpty(res))
636 MessageBox.Show(res + Environment.NewLine + Properties.Resources.ButtonBlockDestroy_ClickText3);
640 MessageBox.Show(Properties.Resources.ButtonBlockDestroy_ClickText4);
645 private bool IsValidExtension(string ext)
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);
655 private bool IsValidIconFile(FileInfo info)
657 return this.IsValidExtension(info.Extension) &&
658 info.Length < 700 * 1024 &&
659 !MyCommon.IsAnimatedGif(info.FullName);
662 private void ShowUserInfo_DragOver(object sender, DragEventArgs e)
664 if (e.Data.GetDataPresent(DataFormats.FileDrop))
666 var files = (string[])e.Data.GetData(DataFormats.FileDrop, false);
667 if (files.Length != 1)
670 var finfo = new FileInfo(files[0]);
671 if (this.IsValidIconFile(finfo))
673 e.Effect = DragDropEffects.Copy;
678 private async void ShowUserInfo_DragDrop(object sender, DragEventArgs e)
680 if (e.Data.GetDataPresent(DataFormats.FileDrop))
682 string filename = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
683 await this.DoChangeIcon(filename);
687 protected override void Dispose(bool disposing)
691 var oldImage = this.UserPicture.Image;
692 if (oldImage != null)
694 this.UserPicture.Image = null;
698 if (this.components != null)
699 this.components.Dispose();
702 base.Dispose(disposing);