OSDN Git Service

0f922e1142c9680e960f80b49a668071b33307af
[opentween/open-tween.git] / OpenTween / ListManage.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 OpenTween.Connection;
37 using OpenTween.Models;
38
39 namespace OpenTween
40 {
41     public partial class ListManage : OTBaseForm
42     {
43         private readonly Twitter tw;
44
45         public ListManage(Twitter tw)
46         {
47             InitializeComponent();
48
49             this.tw = tw;
50         }
51
52         private void ListManage_KeyDown(object sender, KeyEventArgs e)
53         {
54             if (e.KeyCode == Keys.Enter && this.EditCheckBox.Checked)
55                 this.OKEditButton.PerformClick();
56         }
57
58         private async void ListManage_Load(object sender, EventArgs e)
59         {
60             using (ControlTransaction.Disabled(this))
61             {
62                 try
63                 {
64                     var lists = (IReadOnlyList<ListElement>)TabInformations.GetInstance().SubscribableLists;
65                     if (lists.Count == 0)
66                         lists = await this.FetchListsAsync();
67
68                     this.UpdateListsListBox(lists);
69                 }
70                 catch (OperationCanceledException)
71                 {
72                     this.DialogResult = DialogResult.Cancel;
73                     return;
74                 }
75                 catch (WebApiException)
76                 {
77                     this.DialogResult = DialogResult.Abort;
78                     return;
79                 }
80             }
81         }
82
83         private void ListsList_SelectedIndexChanged(object sender, EventArgs e)
84         {
85             if (this.ListsList.SelectedItem == null) return;
86
87             ListElement list = (ListElement) this.ListsList.SelectedItem;
88             this.UsernameTextBox.Text = list.Username;
89             this.NameTextBox.Text = list.Name;
90             this.PublicRadioButton.Checked = list.IsPublic;
91             this.PrivateRadioButton.Checked = !list.IsPublic;
92             this.MemberCountTextBox.Text = list.MemberCount.ToString();
93             this.SubscriberCountTextBox.Text = list.SubscriberCount.ToString();
94             this.DescriptionText.Text = list.Description;
95
96             this.UserList.Items.Clear();
97             foreach (UserInfo user in list.Members)
98                 this.UserList.Items.Add(user);
99
100             this.GetMoreUsersButton.Text = this.UserList.Items.Count > 0 ? Properties.Resources.ListManageGetMoreUsers2 : Properties.Resources.ListManageGetMoreUsers1;
101         }
102
103         private void EditCheckBox_CheckedChanged(object sender, EventArgs e)
104         {
105             this.AddListButton.Enabled = !this.EditCheckBox.Checked;
106             this.EditCheckBox.Enabled = !this.EditCheckBox.Checked;
107             this.DeleteListButton.Enabled = !this.EditCheckBox.Checked;
108
109             this.NameTextBox.ReadOnly = !this.EditCheckBox.Checked;
110             this.PublicRadioButton.Enabled = this.EditCheckBox.Checked;
111             this.PrivateRadioButton.Enabled = this.EditCheckBox.Checked;
112             this.DescriptionText.ReadOnly = !this.EditCheckBox.Checked;
113             this.ListsList.Enabled = !this.EditCheckBox.Checked;
114
115             this.OKEditButton.Enabled = this.EditCheckBox.Checked;
116             this.CancelEditButton.Enabled = this.EditCheckBox.Checked;
117             this.EditCheckBox.AutoCheck = !this.EditCheckBox.Checked;
118
119             this.MemberGroup.Enabled = !this.EditCheckBox.Checked;
120             this.UserGroup.Enabled = !this.EditCheckBox.Checked;
121             this.CloseButton.Enabled = !this.EditCheckBox.Checked;
122
123             this.UsernameTextBox.TabStop = !this.EditCheckBox.Checked;
124             this.MemberCountTextBox.TabStop = !this.EditCheckBox.Checked;
125             this.SubscriberCountTextBox.TabStop = !this.EditCheckBox.Checked;
126             if (this.EditCheckBox.Checked == true) this.NameTextBox.Focus();
127         }
128
129         private async void OKEditButton_Click(object sender, EventArgs e)
130         {
131             if (this.ListsList.SelectedItem == null) return;
132
133             using (ControlTransaction.Disabled(this))
134             {
135                 ListElement listItem = (ListElement)this.ListsList.SelectedItem;
136
137                 if (string.IsNullOrEmpty(this.NameTextBox.Text))
138                 {
139                     MessageBox.Show(Properties.Resources.ListManageOKButton1);
140                     return;
141                 }
142
143                 listItem.Name = this.NameTextBox.Text;
144                 listItem.IsPublic = this.PublicRadioButton.Checked;
145                 listItem.Description = this.DescriptionText.Text;
146
147                 try
148                 {
149                     await listItem.Refresh();
150                 }
151                 catch (WebApiException ex)
152                 {
153                     MessageBox.Show(string.Format(Properties.Resources.ListManageOKButton2, ex.Message));
154                     return;
155                 }
156
157                 this.ListsList.Items.Clear();
158                 this.ListManage_Load(null, EventArgs.Empty);
159
160                 this.EditCheckBox.AutoCheck = true;
161                 this.EditCheckBox.Checked = false;
162             }
163         }
164
165         private void CancelEditButton_Click(object sender, EventArgs e)
166         {
167             this.EditCheckBox.AutoCheck = true;
168             this.EditCheckBox.Checked = false;
169
170             for (int i = this.ListsList.Items.Count - 1; i >= 0; i--)
171                 if (this.ListsList.Items[i] is NewListElement)
172                     this.ListsList.Items.RemoveAt(i);
173
174             this.ListsList_SelectedIndexChanged(this.ListsList, EventArgs.Empty);
175         }
176
177         private async void RefreshUsersButton_Click(object sender, EventArgs e)
178         {
179             using (ControlTransaction.Disabled(this))
180             {
181                 if (this.ListsList.SelectedItem == null) return;
182                 this.UserList.Items.Clear();
183
184                 var list = (ListElement)this.ListsList.SelectedItem;
185                 try
186                 {
187                     await list.RefreshMembers();
188                 }
189                 catch (WebApiException ex)
190                 {
191                     MessageBox.Show(string.Format(Properties.Resources.ListManageGetListMembersCallback1, ex.Message));
192                     return;
193                 }
194
195                 this.ListsList_SelectedIndexChanged(this.ListsList, EventArgs.Empty);
196                 this.GetMoreUsersButton.Text = Properties.Resources.ListManageGetMoreUsers1;
197             }
198         }
199
200         private async void GetMoreUsersButton_Click(object sender, EventArgs e)
201         {
202             using (ControlTransaction.Disabled(this))
203             {
204                 if (this.ListsList.SelectedItem == null) return;
205                 this.UserList.Items.Clear();
206
207                 var list = (ListElement)this.ListsList.SelectedItem;
208                 try
209                 {
210                     await list.GetMoreMembers();
211                 }
212                 catch (WebApiException ex)
213                 {
214                     MessageBox.Show(string.Format(Properties.Resources.ListManageGetListMembersCallback1, ex.Message));
215                     return;
216                 }
217
218                 this.ListsList_SelectedIndexChanged(this.ListsList, EventArgs.Empty);
219                 this.GetMoreUsersButton.Text = Properties.Resources.ListManageGetMoreUsers1;
220             }
221         }
222
223         private async void DeleteUserButton_Click(object sender, EventArgs e)
224         {
225             if (this.ListsList.SelectedItem == null || this.UserList.SelectedItem == null)
226                 return;
227
228             using (ControlTransaction.Disabled(this))
229             {
230                 ListElement list = (ListElement)this.ListsList.SelectedItem;
231                 UserInfo user = (UserInfo)this.UserList.SelectedItem;
232                 if (MessageBox.Show(Properties.Resources.ListManageDeleteUser1, ApplicationSettings.ApplicationName, MessageBoxButtons.OKCancel) == DialogResult.OK)
233                 {
234                     try
235                     {
236                         await this.tw.Api.ListsMembersDestroy(list.Id, user.ScreenName)
237                             .IgnoreResponse();
238                     }
239                     catch (WebApiException ex)
240                     {
241                         MessageBox.Show(string.Format(Properties.Resources.ListManageDeleteUser2, ex.Message));
242                         return;
243                     }
244
245                     int idx = ListsList.SelectedIndex;
246                     list.Members.Remove(user);
247                     this.ListsList_SelectedIndexChanged(this.ListsList, EventArgs.Empty);
248                     if (idx < ListsList.Items.Count) ListsList.SelectedIndex = idx;
249                 }
250             }
251         }
252
253         private async void DeleteListButton_Click(object sender, EventArgs e)
254         {
255             if (this.ListsList.SelectedItem == null) return;
256
257             using (ControlTransaction.Disabled(this))
258             {
259                 ListElement list = (ListElement)this.ListsList.SelectedItem;
260
261                 if (MessageBox.Show(Properties.Resources.ListManageDeleteLists1, ApplicationSettings.ApplicationName, MessageBoxButtons.OKCancel) == DialogResult.OK)
262                 {
263                     try
264                     {
265                         await this.tw.DeleteList(list.Id);
266                     }
267                     catch (WebApiException ex)
268                     {
269                         MessageBox.Show(Properties.Resources.ListManageOKButton2, ex.Message);
270                         return;
271                     }
272
273                     try
274                     {
275                         await this.tw.GetListsApi();
276                     }
277                     catch (WebApiException ex)
278                     {
279                         MessageBox.Show(Properties.Resources.ListsDeleteFailed, ex.Message);
280                         return;
281                     }
282
283                     this.ListsList.Items.Clear();
284                     this.ListManage_Load(this, EventArgs.Empty);
285                 }
286             }
287         }
288
289         private void AddListButton_Click(object sender, EventArgs e)
290         {
291             NewListElement newList = new NewListElement(this.tw);
292             this.ListsList.Items.Add(newList);
293             this.ListsList.SelectedItem = newList;
294             this.EditCheckBox.Checked = true;
295             this.EditCheckBox_CheckedChanged(this.EditCheckBox, EventArgs.Empty);
296         }
297
298         private async void UserList_SelectedIndexChanged(object sender, EventArgs e)
299         {
300             if (UserList.SelectedItem == null)
301             {
302                 this.UserIcon.Image?.Dispose();
303                 this.UserIcon.Image = null;
304                 this.UserLocation.Text = "";
305                 this.UserWeb.Text = "";
306                 this.UserFollowNum.Text = "0";
307                 this.UserFollowerNum.Text = "0";
308                 this.UserPostsNum.Text = "0";
309                 this.UserProfile.Text = "";
310                 this.UserTweetDateTime.Text = "";
311                 this.UserTweet.Text = "";
312                 this.DeleteUserButton.Enabled = false;
313             }
314             else
315             {
316                 UserInfo user = (UserInfo)this.UserList.SelectedItem;
317                 this.UserLocation.Text = user.Location;
318                 this.UserWeb.Text = user.Url;
319                 this.UserFollowNum.Text = user.FriendsCount.ToString("#,###,##0");
320                 this.UserFollowerNum.Text = user.FollowersCount.ToString("#,###,##0");
321                 this.UserPostsNum.Text = user.StatusesCount.ToString("#,###,##0");
322                 this.UserProfile.Text = user.Description;
323                 if (!String.IsNullOrEmpty(user.RecentPost))
324                 {
325                     this.UserTweetDateTime.Text = user.PostCreatedAt.ToLocalTimeString("yy/MM/dd HH:mm");
326                     this.UserTweet.Text = user.RecentPost;
327                 }
328                 else
329                 {
330                     this.UserTweetDateTime.Text = "";
331                     this.UserTweet.Text = "";
332                 }
333                 this.DeleteUserButton.Enabled = true;
334
335                 await this.LoadUserIconAsync(user.ImageUrl, user.Id);
336             }
337         }
338
339         private async Task LoadUserIconAsync(Uri imageUri, long userId)
340         {
341             var oldImage = this.UserIcon.Image;
342             this.UserIcon.Image = null;
343             oldImage?.Dispose();
344
345             await this.UserIcon.SetImageFromTask(async () =>
346             {
347                 var uri = imageUri.AbsoluteUri.Replace("_normal", "_bigger");
348
349                 using (var imageStream = await Networking.Http.GetStreamAsync(uri))
350                 {
351                     var image = await MemoryImage.CopyFromStreamAsync(imageStream);
352
353                     // 画像の読み込み中に選択中のユーザーが変化していたらキャンセルとして扱う
354                     var selectedUser = (UserInfo)this.UserList.SelectedItem;
355                     if (selectedUser.Id != userId)
356                     {
357                         image.Dispose();
358                         throw new OperationCanceledException();
359                     }
360
361                     return image;
362                 }
363             });
364         }
365
366         private async void RefreshListsButton_Click(object sender, EventArgs e)
367         {
368             using (ControlTransaction.Disabled(this))
369             {
370                 try
371                 {
372                     var lists = await this.FetchListsAsync();
373                     this.UpdateListsListBox(lists);
374                 }
375                 catch (OperationCanceledException) { }
376                 catch (WebApiException ex)
377                 {
378                     MessageBox.Show(string.Format(Properties.Resources.ListsDeleteFailed, ex.Message));
379                 }
380             }
381         }
382
383         private async Task<IReadOnlyList<ListElement>> FetchListsAsync()
384         {
385             using (var dialog = new WaitingDialog(Properties.Resources.ListsGetting))
386             {
387                 var cancellationToken = dialog.EnableCancellation();
388
389                 var task = this.tw.GetListsApi();
390                 await dialog.WaitForAsync(this, task);
391
392                 cancellationToken.ThrowIfCancellationRequested();
393             }
394
395             return TabInformations.GetInstance().SubscribableLists;
396         }
397
398         private void UpdateListsListBox(IEnumerable<ListElement> lists)
399         {
400             using (ControlTransaction.Update(this.ListsList))
401             {
402                 this.ListsList.Items.Clear();
403                 foreach (var listItem in lists.Where(x => x.UserId == this.tw.UserId))
404                 {
405                     this.ListsList.Items.Add(listItem);
406                 }
407                 if (this.ListsList.Items.Count > 0)
408                     this.ListsList.SelectedIndex = 0;
409                 this.ListsList.Focus();
410             }
411         }
412
413         private async void UserWeb_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
414         {
415             if (this.Owner != null)
416                 await ((TweenMain)this.Owner).OpenUriInBrowserAsync(UserWeb.Text);
417         }
418
419         private class NewListElement : ListElement
420         {
421             public bool IsCreated { get; private set; } = false;
422
423             public NewListElement(Twitter tw)
424                 => this._tw = tw;
425
426             public override async Task Refresh()
427             {
428                 if (this.IsCreated)
429                 {
430                     await base.Refresh().ConfigureAwait(false);
431                 }
432                 else
433                 {
434                     await this._tw.CreateListApi(this.Name, !this.IsPublic, this.Description)
435                         .ConfigureAwait(false);
436
437                     this.IsCreated = true;
438                 }
439             }
440
441             public override string ToString()
442             {
443                 if (IsCreated)
444                     return base.ToString();
445                 else
446                     return "NewList";
447             }
448         }
449
450         private void ListManage_Validating(object sender, CancelEventArgs e)
451         {
452             if (this.EditCheckBox.Checked)
453             {
454                 e.Cancel = true;
455                 this.CancelButton.PerformClick();
456             }
457         }
458     }
459 }