OSDN Git Service

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