From ae93259d7787ce5f28fa53322278827722cbfd0f Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Thu, 23 May 2024 08:51:21 +0900 Subject: [PATCH 1/2] =?UTF-8?q?ISocialAccount.AccountState=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenTween/SocialProtocol/ISocialAccount.cs | 2 + .../SocialProtocol/ISocialAccountState.cs | 50 +++++++++++++++++++ OpenTween/SocialProtocol/InvalidAccount.cs | 34 ++++++++++++- .../SocialProtocol/Twitter/TwitterAccount.cs | 3 ++ .../Twitter/TwitterAccountState.cs | 9 +++- OpenTween/Tween.cs | 42 +++++++--------- OpenTween/TweetDetailsView.cs | 7 +-- 7 files changed, 116 insertions(+), 31 deletions(-) create mode 100644 OpenTween/SocialProtocol/ISocialAccountState.cs diff --git a/OpenTween/SocialProtocol/ISocialAccount.cs b/OpenTween/SocialProtocol/ISocialAccount.cs index 68dd53917..d4a4a08ba 100644 --- a/OpenTween/SocialProtocol/ISocialAccount.cs +++ b/OpenTween/SocialProtocol/ISocialAccount.cs @@ -41,6 +41,8 @@ public interface ISocialAccount : IDisposable public ISocialProtocolClient Client { get; } + public ISocialAccountState AccountState { get; } + public bool IsDisposed { get; } public void Initialize(UserAccount accountSettings, SettingCommon settingCommon); diff --git a/OpenTween/SocialProtocol/ISocialAccountState.cs b/OpenTween/SocialProtocol/ISocialAccountState.cs new file mode 100644 index 000000000..5d7590160 --- /dev/null +++ b/OpenTween/SocialProtocol/ISocialAccountState.cs @@ -0,0 +1,50 @@ +// OpenTween - Client of Twitter +// Copyright (c) 2024 kim_upsilon (@kim_upsilon) +// All rights reserved. +// +// This file is part of OpenTween. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. If not, see , or write to +// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +// Boston, MA 02110-1301, USA. + +#nullable enable + +using System.Collections.Generic; +using OpenTween.Api; +using OpenTween.Models; + +namespace OpenTween.SocialProtocol +{ + public interface ISocialAccountState + { + public PersonId UserId { get; } + + public string UserName { get; } + + public int? FollowersCount { get; } + + public int? FriendsCount { get; } + + public int? StatusesCount { get; } + + public ISet FollowerIds { get; } + + public ISet BlockedUserIds { get; } + + public RateLimitCollection RateLimits { get; } + + public bool HasUnrecoverableError { get; set; } + } +} diff --git a/OpenTween/SocialProtocol/InvalidAccount.cs b/OpenTween/SocialProtocol/InvalidAccount.cs index 20c1f7046..55424cd85 100644 --- a/OpenTween/SocialProtocol/InvalidAccount.cs +++ b/OpenTween/SocialProtocol/InvalidAccount.cs @@ -22,7 +22,9 @@ #nullable enable using System; +using System.Collections.Generic; using System.Threading.Tasks; +using OpenTween.Api; using OpenTween.Connection; using OpenTween.Models; @@ -36,15 +38,17 @@ public string AccountType public Guid UniqueKey { get; } public PersonId UserId - => new TwitterUserId("0"); + => this.AccountState.UserId; public string UserName - => "(Unknown account)"; + => this.AccountState.UserName; public IApiConnection Connection { get; } = new InvalidAccountConnection(); public ISocialProtocolClient Client { get; } = new InvalidAccountClient(); + public ISocialAccountState AccountState { get; } = new InvalidAccountState(); + public bool IsDisposed { get; private set; } public InvalidAccount(Guid uniqueKey) @@ -114,5 +118,31 @@ public Task RefreshConfiguration() private WebApiException CreateException() => new("Invalid account"); } + + private class InvalidAccountState : ISocialAccountState + { + public PersonId UserId + => new TwitterUserId("0"); + + public string UserName + => "(Unknown account)"; + + public int? FollowersCount + => null; + + public int? FriendsCount + => null; + + public int? StatusesCount + => null; + + public ISet FollowerIds { get; } = new HashSet(); + + public ISet BlockedUserIds { get; } = new HashSet(); + + public RateLimitCollection RateLimits { get; } = new(); + + public bool HasUnrecoverableError { get; set; } = true; + } } } diff --git a/OpenTween/SocialProtocol/Twitter/TwitterAccount.cs b/OpenTween/SocialProtocol/Twitter/TwitterAccount.cs index bd0c535bf..8692f88b3 100644 --- a/OpenTween/SocialProtocol/Twitter/TwitterAccount.cs +++ b/OpenTween/SocialProtocol/Twitter/TwitterAccount.cs @@ -44,6 +44,9 @@ public string AccountType public TwitterAccountState AccountState { get; private set; } = new(); + ISocialAccountState ISocialAccount.AccountState + => this.AccountState; + public OpenTween.Twitter Legacy => this.twLegacy; diff --git a/OpenTween/SocialProtocol/Twitter/TwitterAccountState.cs b/OpenTween/SocialProtocol/Twitter/TwitterAccountState.cs index 33f6b56a8..edda96541 100644 --- a/OpenTween/SocialProtocol/Twitter/TwitterAccountState.cs +++ b/OpenTween/SocialProtocol/Twitter/TwitterAccountState.cs @@ -22,15 +22,19 @@ #nullable enable using System.Collections.Generic; +using OpenTween.Api; using OpenTween.Api.DataModel; using OpenTween.Models; namespace OpenTween.SocialProtocol.Twitter { - public class TwitterAccountState + public class TwitterAccountState : ISocialAccountState { public TwitterUserId UserId { get; private set; } + PersonId ISocialAccountState.UserId + => this.UserId; + public string UserName { get; private set; } public int? FollowersCount { get; private set; } @@ -53,6 +57,9 @@ public class TwitterAccountState public TwitterRateLimitCollection RateLimits { get; } = new(); + RateLimitCollection ISocialAccountState.RateLimits + => this.RateLimits; + public bool HasUnrecoverableError { get; set; } = true; public TwitterAccountState() diff --git a/OpenTween/Tween.cs b/OpenTween/Tween.cs index a42eb15d5..d7ccf78de 100644 --- a/OpenTween/Tween.cs +++ b/OpenTween/Tween.cs @@ -1263,13 +1263,13 @@ private void NotifyIcon1_BalloonTipClicked(object sender, EventArgs e) private bool CheckAccountValid() { - if (this.tw.AccountState.HasUnrecoverableError) + if (this.CurrentTabAccount.AccountState.HasUnrecoverableError) { this.errorCount += 1; if (this.errorCount > 5) { this.errorCount = 0; - this.tw.AccountState.HasUnrecoverableError = false; + this.CurrentTabAccount.AccountState.HasUnrecoverableError = false; return true; } return false; @@ -1805,21 +1805,18 @@ from account in this.accounts.Items await Task.WhenAll(loadTasks); var primaryAccount = this.accounts.Primary; + this.statuses.RefreshOwl(primaryAccount.UniqueKey, primaryAccount.AccountState.FollowerIds, isPrimary: true); + if (primaryAccount is TwitterAccount twAccount) { - this.statuses.RefreshOwl(twAccount.UniqueKey, twAccount.AccountState.FollowerIds, isPrimary: true); - foreach (var (_, service) in this.ImageSelector.Model.MediaServices) { - service.UpdateTwitterConfiguration(this.tw.Configuration); + service.UpdateTwitterConfiguration(twAccount.AccountState.Configuration); } } foreach (var account in this.accounts.SecondaryAccounts) - { - if (account is TwitterAccount twAccountSecondary) - this.statuses.RefreshOwl(twAccountSecondary.UniqueKey, twAccountSecondary.AccountState.FollowerIds, isPrimary: false); - } + this.statuses.RefreshOwl(account.UniqueKey, account.AccountState.FollowerIds, isPrimary: false); this.listCache?.PurgeCache(); this.CurrentListView.Refresh(); @@ -2608,7 +2605,7 @@ private async void SettingStripMenuItem_Click(object sender, EventArgs e) } } - this.tw.AccountState.HasUnrecoverableError = false; + this.PrimaryAccount.AccountState.HasUnrecoverableError = false; this.TopMost = this.settings.Common.AlwaysTop; this.SaveConfigsAll(false); @@ -6746,13 +6743,14 @@ private void SetMainWindowTitle() ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText4, ur, al); break; case MyCommon.DispTitleEnum.OwnStatus: - if (followers == 0 && this.tw.FollowersCount != null) followers = this.tw.FollowersCount.Value; + var accountState = this.CurrentTabAccount.AccountState; + if (followers == 0 && accountState.FollowersCount != null) followers = accountState.FollowersCount.Value; ttl.AppendFormat( Properties.Resources.OwnStatusTitle, - this.tw.StatusesCount?.ToString() ?? "-", - this.tw.FriendsCount?.ToString() ?? "-", - this.tw.FollowersCount?.ToString() ?? "-", - this.tw.FollowersCount != null ? this.tw.FollowersCount.Value - followers : "-" + accountState.StatusesCount?.ToString() ?? "-", + accountState.FriendsCount?.ToString() ?? "-", + accountState.FollowersCount?.ToString() ?? "-", + accountState.FollowersCount != null ? accountState.FollowersCount.Value - followers : "-" ); break; } @@ -6821,14 +6819,12 @@ private string GetStatusLabelText() private void SubscribePrimaryAccountRatelimit() { this.unsubscribeRateLimitUpdate?.Dispose(); - if (this.accounts.Primary is TwitterAccount twAccount) - { - var rateLimits = twAccount.AccountState.RateLimits; - this.unsubscribeRateLimitUpdate = rateLimits.SubscribeAccessLimitUpdated(this.TwitterApiStatus_AccessLimitUpdated); - // アカウントの切替を反映するため初回だけ空の更新通知を送る - this.TwitterApiStatus_AccessLimitUpdated(rateLimits, new(null)); - } + var rateLimits = this.CurrentTabAccount.AccountState.RateLimits; + this.unsubscribeRateLimitUpdate = rateLimits.SubscribeAccessLimitUpdated(this.TwitterApiStatus_AccessLimitUpdated); + + // アカウントの切替を反映するため初回だけ空の更新通知を送る + this.TwitterApiStatus_AccessLimitUpdated(rateLimits, new(null)); } private async void TwitterApiStatus_AccessLimitUpdated(RateLimitCollection sender, RateLimitCollection.AccessLimitUpdatedEventArgs e) @@ -8077,7 +8073,7 @@ private async void ApiUsageInfoMenuItem_Click(object sender, EventArgs e) } using var apiDlg = new ApiInfoDialog(); - apiDlg.RateLimits = this.CurrentTabAccount is TwitterAccount twAccount ? twAccount.AccountState.RateLimits : null; + apiDlg.RateLimits = this.CurrentTabAccount.AccountState.RateLimits; apiDlg.ShowDialog(this); } diff --git a/OpenTween/TweetDetailsView.cs b/OpenTween/TweetDetailsView.cs index c4f709f46..c667742f8 100644 --- a/OpenTween/TweetDetailsView.cs +++ b/OpenTween/TweetDetailsView.cs @@ -372,11 +372,8 @@ private async Task CreateQuoteTweetHtml(PostId statusId, bool isReply) return FormatQuoteTweetHtml(statusId, WebUtility.HtmlEncode($"Err:{ex.Message}(GetStatus)"), isReply); } - if (this.Owner.CurrentTabAccount is TwitterAccount twAccount) - { - if (twAccount.AccountState.BlockedUserIds.Contains(post.UserId)) - return FormatQuoteTweetHtml(statusId, "This Tweet is unavailable.", isReply); - } + if (this.Owner.CurrentTabAccount.AccountState.BlockedUserIds.Contains(post.UserId)) + return FormatQuoteTweetHtml(statusId, "This Tweet is unavailable.", isReply); if (!TabInformations.GetInstance().AddQuoteTweet(post)) return FormatQuoteTweetHtml(statusId, "This Tweet is unavailable.", isReply); From 4483f02f92e88020afd0228ff4f8506a1c3a452e Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Thu, 23 May 2024 09:04:27 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E4=B8=AD=E3=81=AE?= =?UTF-8?q?=E3=82=BF=E3=83=96=E3=82=92=E5=88=87=E3=82=8A=E6=9B=BF=E3=81=88?= =?UTF-8?q?=E3=82=8B=E3=81=A8=E3=83=AC=E3=83=BC=E3=83=88=E3=83=AA=E3=83=9F?= =?UTF-8?q?=E3=83=83=E3=83=88=E3=81=AE=E6=83=85=E5=A0=B1=E3=81=8C=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA=E3=81=95=E3=82=8C=E3=81=AA=E3=81=8F=E3=81=AA=E3=82=8B?= =?UTF-8?q?=E4=B8=8D=E5=85=B7=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: f2ae9689 ("MyCommon.TwitterRateLimitsを廃止しアカウントごとにレートリミットを把握できるようにする") --- OpenTween/Tween.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/OpenTween/Tween.cs b/OpenTween/Tween.cs index d7ccf78de..79f6e1a76 100644 --- a/OpenTween/Tween.cs +++ b/OpenTween/Tween.cs @@ -3056,7 +3056,7 @@ private void ListTab_SelectedIndexChanged(object sender, EventArgs e) { this.SetMainWindowTitle(); this.SetStatusLabelUrl(); - this.SetApiStatusLabel(null); + this.SetApiStatusLabel(this.CurrentTabAccount.AccountState.RateLimits); if (this.ListTab.Focused || ((Control)this.CurrentTabPage.Tag).Focused) this.Tag = this.ListTab.Tag; this.TabMenuControl(this.CurrentTabName); @@ -6850,15 +6850,8 @@ private async void TwitterApiStatus_AccessLimitUpdated(RateLimitCollection sende } } - private void SetApiStatusLabel(RateLimitCollection? rateLimits, string? endpointName = null) + private void SetApiStatusLabel(RateLimitCollection rateLimits, string? endpointName = null) { - if (rateLimits == null) - { - this.toolStripApiGauge.ApiLimit = null; - this.toolStripApiGauge.ApiEndpoint = endpointName; - return; - } - var tabType = this.CurrentTab.TabType; if (endpointName == null)