diff --git a/OpenTween/Api/TwitterApi.cs b/OpenTween/Api/TwitterApi.cs
index df5ac4c7d..3cca489fe 100644
--- a/OpenTween/Api/TwitterApi.cs
+++ b/OpenTween/Api/TwitterApi.cs
@@ -43,7 +43,7 @@ public sealed class TwitterApi : IDisposable
internal IApiConnection? ApiConnection;
- private TwitterAppToken appToken = TwitterAppToken.GetDefault();
+ public TwitterAppToken AppToken { get; private set; } = TwitterAppToken.GetDefault();
public TwitterApi()
{
@@ -51,22 +51,22 @@ public TwitterApi()
public TwitterApi(ApiKey consumerKey, ApiKey consumerSecret)
{
- this.appToken = new()
+ this.AppToken = new()
{
AuthType = APIAuthType.OAuth1,
- OAuth1ConsumerKey = consumerKey,
- OAuth1ConsumerSecret = consumerSecret,
+ OAuth1CustomConsumerKey = consumerKey,
+ OAuth1CustomConsumerSecret = consumerSecret,
};
}
public void Initialize(string accessToken, string accessSecret, long userId, string screenName)
- => this.Initialize(this.appToken, accessToken, accessSecret, userId, screenName);
+ => this.Initialize(this.AppToken, accessToken, accessSecret, userId, screenName);
public void Initialize(TwitterAppToken appToken, string accessToken, string accessSecret, long userId, string screenName)
{
- this.appToken = appToken;
+ this.AppToken = appToken;
- var newInstance = new TwitterApiConnection(this.appToken, accessToken, accessSecret);
+ var newInstance = new TwitterApiConnection(this.AppToken, accessToken, accessSecret);
var oldInstance = Interlocked.Exchange(ref this.ApiConnection, newInstance);
oldInstance?.Dispose();
diff --git a/OpenTween/AppendSettingDialog.cs b/OpenTween/AppendSettingDialog.cs
index fa4cc1ea4..0803eb487 100644
--- a/OpenTween/AppendSettingDialog.cs
+++ b/OpenTween/AppendSettingDialog.cs
@@ -299,8 +299,8 @@ public void ApplyNetworkSettings()
return new UserAccount
{
TwitterAuthType = appToken.AuthType,
- TwitterOAuth1ConsumerKey = appToken.OAuth1ConsumerKey.Value,
- TwitterOAuth1ConsumerSecret = appToken.OAuth1ConsumerSecret.Value,
+ TwitterOAuth1ConsumerKey = appToken.OAuth1CustomConsumerKey?.Value ?? "",
+ TwitterOAuth1ConsumerSecret = appToken.OAuth1CustomConsumerSecret?.Value ?? "",
Username = accessTokenResponse["screen_name"],
UserId = long.Parse(accessTokenResponse["user_id"]),
Token = accessTokenResponse["oauth_token"],
diff --git a/OpenTween/ApplicationPreconditions.cs b/OpenTween/ApplicationPreconditions.cs
index a0bf56297..a9a021c21 100644
--- a/OpenTween/ApplicationPreconditions.cs
+++ b/OpenTween/ApplicationPreconditions.cs
@@ -33,6 +33,10 @@ namespace OpenTween
///
public sealed class ApplicationPreconditions
{
+ // Windows の最小要件
+ private static readonly string OSMinimumVersionName = "Windows 10";
+ private static readonly Version OSMinimumVersion = new(10, 0, 0, 0);
+
// .NET Framework ランタイムの最小要件
// 参照: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed
private const string RuntimeMinimumVersionName = ".NET Framework 4.8";
@@ -48,11 +52,11 @@ public static bool CheckAll()
{
var conditions = new ApplicationPreconditions();
- if (!conditions.CheckApiKey())
+ if (!conditions.CheckOSVersion())
{
- var message = Properties.Resources.WarnIfApiKeyError_Message;
- ShowMessageBox(message, MessageBoxIcon.Error);
- return false;
+ // 警告のみ表示し、起動は中断しない
+ var message = string.Format(Properties.Resources.CheckOSVersion_Error, OSMinimumVersionName);
+ ShowMessageBox(message, MessageBoxIcon.Warning);
}
if (!conditions.CheckRuntimeVersion())
@@ -62,6 +66,13 @@ public static bool CheckAll()
return false;
}
+ if (!conditions.CheckApiKey())
+ {
+ var message = Properties.Resources.WarnIfApiKeyError_Message;
+ ShowMessageBox(message, MessageBoxIcon.Error);
+ return false;
+ }
+
if (!conditions.CheckRunAsNormalUser())
{
var message = string.Format(Properties.Resources.WarnIfRunAsAdministrator_Message, ApplicationSettings.ApplicationName);
@@ -80,6 +91,22 @@ private static void ShowMessageBox(string message, MessageBoxIcon icon)
public bool CheckApiKey()
=> this.CanDecryptApiKey(ApplicationSettings.TwitterConsumerKey);
+ ///
+ /// 起動中の OS のバージョンが最小要件を満たしているか確認する
+ ///
+ public bool CheckOSVersion()
+ {
+ var os = Environment.OSVersion;
+
+ if (os.Platform != PlatformID.Win32NT)
+ return false;
+
+ if (os.Version < ApplicationPreconditions.OSMinimumVersion)
+ return false;
+
+ return true;
+ }
+
///
/// 動作中の .NET Framework のバージョンが適切か確認する
///
diff --git a/OpenTween/AuthTypeSelectDialog.Designer.cs b/OpenTween/AuthTypeSelectDialog.Designer.cs
index adeb42976..b97c22189 100644
--- a/OpenTween/AuthTypeSelectDialog.Designer.cs
+++ b/OpenTween/AuthTypeSelectDialog.Designer.cs
@@ -31,6 +31,7 @@ private void InitializeComponent()
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AuthTypeSelectDialog));
this.label1 = new System.Windows.Forms.Label();
this.AuthByOAuth2RadioButton = new System.Windows.Forms.RadioButton();
+ this.AuthByOAuth1BuiltinKeyRadioButton = new System.Windows.Forms.RadioButton();
this.AuthByOAuth1RadioButton = new System.Windows.Forms.RadioButton();
this.label2 = new System.Windows.Forms.Label();
this.OAuth1ConsumerKeyTextBox = new System.Windows.Forms.TextBox();
@@ -53,6 +54,13 @@ private void InitializeComponent()
this.AuthByOAuth2RadioButton.TabStop = true;
this.AuthByOAuth2RadioButton.UseVisualStyleBackColor = true;
//
+ // AuthByOAuth1BuiltinKeyRadioButton
+ //
+ resources.ApplyResources(this.AuthByOAuth1BuiltinKeyRadioButton, "AuthByOAuth1BuiltinKeyRadioButton");
+ this.AuthByOAuth1BuiltinKeyRadioButton.Name = "AuthByOAuth1BuiltinKeyRadioButton";
+ this.AuthByOAuth1BuiltinKeyRadioButton.TabStop = true;
+ this.AuthByOAuth1BuiltinKeyRadioButton.UseVisualStyleBackColor = true;
+ //
// AuthByOAuth1RadioButton
//
resources.ApplyResources(this.AuthByOAuth1RadioButton, "AuthByOAuth1RadioButton");
@@ -106,6 +114,7 @@ private void InitializeComponent()
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.label1);
this.Controls.Add(this.AuthByOAuth2RadioButton);
+ this.Controls.Add(this.AuthByOAuth1BuiltinKeyRadioButton);
this.Controls.Add(this.AuthByOAuth1RadioButton);
this.Controls.Add(this.label2);
this.Controls.Add(this.OAuth1ConsumerKeyTextBox);
@@ -128,6 +137,7 @@ private void InitializeComponent()
private System.Windows.Forms.Label label1;
private System.Windows.Forms.RadioButton AuthByOAuth2RadioButton;
+ private System.Windows.Forms.RadioButton AuthByOAuth1BuiltinKeyRadioButton;
private System.Windows.Forms.RadioButton AuthByOAuth1RadioButton;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox OAuth1ConsumerKeyTextBox;
diff --git a/OpenTween/AuthTypeSelectDialog.cs b/OpenTween/AuthTypeSelectDialog.cs
index a23767eb8..0961b9803 100644
--- a/OpenTween/AuthTypeSelectDialog.cs
+++ b/OpenTween/AuthTypeSelectDialog.cs
@@ -44,13 +44,19 @@ public AuthTypeSelectDialog()
private void OKButton_Click(object sender, EventArgs e)
{
TwitterAppToken result;
- if (this.AuthByOAuth1RadioButton.Checked)
+ if (this.AuthByOAuth1BuiltinKeyRadioButton.Checked)
{
+ result = TwitterAppToken.GetDefault();
+ }
+ else if (this.AuthByOAuth1RadioButton.Checked)
+ {
+ var consumerKey = this.OAuth1ConsumerKeyTextBox.Text;
+ var consumerSecret = this.OAuth1ConsumerSecretTextBox.Text;
result = new()
{
AuthType = APIAuthType.OAuth1,
- OAuth1ConsumerKey = ApiKey.Create(this.OAuth1ConsumerKeyTextBox.Text),
- OAuth1ConsumerSecret = ApiKey.Create(this.OAuth1ConsumerSecretTextBox.Text),
+ OAuth1CustomConsumerKey = MyCommon.IsNullOrEmpty(consumerKey) ? null : ApiKey.Create(consumerKey),
+ OAuth1CustomConsumerSecret = MyCommon.IsNullOrEmpty(consumerSecret) ? null : ApiKey.Create(consumerSecret),
};
}
else if (this.UseTwitterComCookieRadioButton.Checked)
diff --git a/OpenTween/AuthTypeSelectDialog.en.resx b/OpenTween/AuthTypeSelectDialog.en.resx
index 94140fa83..a8fd37374 100644
--- a/OpenTween/AuthTypeSelectDialog.en.resx
+++ b/OpenTween/AuthTypeSelectDialog.en.resx
@@ -5,6 +5,8 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 284, 16
+ Use OAuth 1.0a (with OpenTween built-in API key)
103, 16
Use OAuth 1.0a
215, 16
diff --git a/OpenTween/AuthTypeSelectDialog.resx b/OpenTween/AuthTypeSelectDialog.resx
index 1788bfbd0..35839df3d 100644
--- a/OpenTween/AuthTypeSelectDialog.resx
+++ b/OpenTween/AuthTypeSelectDialog.resx
@@ -8,14 +8,18 @@
96, 96
- 455, 291
+ 455, 304
True
AuthTypeSelectDialog
- OpenTween.OTBaseForm, OpenTween, Version=3.2.0.1, Culture=neutral, PublicKeyToken=null
+ OpenTween.OTBaseForm, OpenTween, Version=3.4.0.1, Culture=neutral, PublicKeyToken=null
+ AuthByOAuth1BuiltinKeyRadioButton
+ $this
+ System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 2
AuthByOAuth1RadioButton
$this
System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 2
+ 3
AuthByOAuth2RadioButton
$this
System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
@@ -27,35 +31,41 @@
label2
$this
System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 3
+ 4
label3
$this
System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 5
+ 6
OAuth1ConsumerKeyTextBox
$this
System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 4
+ 5
OAuth1ConsumerSecretTextBox
$this
System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 6
+ 7
OKButton
$this
System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 9
+ 10
TwitterComCookieTextBox
$this
System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 8
+ 9
UseTwitterComCookieRadioButton
$this
System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 7
+ 8
+ True
+ NoControl
+ 15, 60
+ 287, 16
+ 2
+ OAuth 1.0a を使用する(OpenTweenのAPIキーを使用)
True
- 15, 61
+ 15, 82
135, 16
- 2
+ 3
OAuth 1.0a を使用する
True
False
@@ -70,35 +80,35 @@
0
Twitter API にアクセスする方法を選択して下さい:
True
- 29, 83
+ 29, 104
20, 3, 3, 3
132, 12
- 3
+ 4
Consumer Key (API Key)
True
- 29, 126
+ 29, 147
3, 3, 3, 3
160, 12
- 5
+ 6
Consumer Secret (API Secret)
- 31, 101
+ 31, 122
400, 19
- 4
- 31, 144
+ 5
+ 31, 165
400, 19
- 6
+ 7
Bottom, Right
- 368, 256
+ 368, 269
75, 23
- 9
+ 10
OK
- 31, 193
+ 31, 213
True
400, 50
- 8
+ 9
True
- 15, 170
+ 15, 191
236, 16
- 7
+ 8
twitter.com の Cookie を使用する(実験的)
diff --git a/OpenTween/Connection/TwitterApiConnection.cs b/OpenTween/Connection/TwitterApiConnection.cs
index 21d664c7e..34317795a 100644
--- a/OpenTween/Connection/TwitterApiConnection.cs
+++ b/OpenTween/Connection/TwitterApiConnection.cs
@@ -67,8 +67,8 @@ public TwitterApiConnection(ApiKey consumerKey, ApiKey consumerSecret, string ac
new()
{
AuthType = APIAuthType.OAuth1,
- OAuth1ConsumerKey = consumerKey,
- OAuth1ConsumerSecret = consumerSecret,
+ OAuth1CustomConsumerKey = consumerKey,
+ OAuth1CustomConsumerSecret = consumerSecret,
},
accessToken,
accessSecret
diff --git a/OpenTween/Connection/TwitterAppToken.cs b/OpenTween/Connection/TwitterAppToken.cs
index b762ab739..6808485a1 100644
--- a/OpenTween/Connection/TwitterAppToken.cs
+++ b/OpenTween/Connection/TwitterAppToken.cs
@@ -32,21 +32,25 @@ namespace OpenTween.Connection
{
public class TwitterAppToken
{
- public APIAuthType AuthType { get; set; }
+ public APIAuthType AuthType { get; init; }
- public ApiKey OAuth1ConsumerKey { get; set; } = ApiKey.Create("");
+ public ApiKey? OAuth1CustomConsumerKey { get; init; }
- public ApiKey OAuth1ConsumerSecret { get; set; } = ApiKey.Create("");
+ public ApiKey? OAuth1CustomConsumerSecret { get; init; }
- public string TwitterComCookie { get; set; } = "";
+ public string TwitterComCookie { get; init; } = "";
+
+ public ApiKey OAuth1ConsumerKey
+ => this.OAuth1CustomConsumerKey ?? ApplicationSettings.TwitterConsumerKey;
+
+ public ApiKey OAuth1ConsumerSecret
+ => this.OAuth1CustomConsumerSecret ?? ApplicationSettings.TwitterConsumerSecret;
public static TwitterAppToken GetDefault()
{
return new()
{
AuthType = APIAuthType.OAuth1,
- OAuth1ConsumerKey = ApplicationSettings.TwitterConsumerKey,
- OAuth1ConsumerSecret = ApplicationSettings.TwitterConsumerSecret,
};
}
}
diff --git a/OpenTween/ImageCache.cs b/OpenTween/ImageCache.cs
index 335c49c12..f16725384 100644
--- a/OpenTween/ImageCache.cs
+++ b/OpenTween/ImageCache.cs
@@ -58,6 +58,23 @@ public ImageCache()
{
// まだ参照されている場合もあるのでDisposeはファイナライザ任せ
this.CacheRemoveCount++;
+
+ var task = e.Item.Value;
+ if (task.Status != TaskStatus.RanToCompletion || task.IsFaulted)
+ {
+ // Task の例外がハンドルされないまま破棄されると AggregateException が発生するため try-catch で処理する Task を挟む
+ static async Task HandleException(Task t)
+ {
+ try
+ {
+ _ = await t.ConfigureAwait(false);
+ }
+ catch
+ {
+ }
+ }
+ _ = HandleException(task);
+ }
};
this.cancelTokenSource = new CancellationTokenSource();
diff --git a/OpenTween/Models/TabInformations.cs b/OpenTween/Models/TabInformations.cs
index 1eac80f61..9ef2b85b4 100644
--- a/OpenTween/Models/TabInformations.cs
+++ b/OpenTween/Models/TabInformations.cs
@@ -176,16 +176,6 @@ public void RemoveTab(string tabName)
}
}
- public void ReplaceTab(TabModel tab)
- {
- if (!this.ContainsTab(tab.TabName))
- throw new ArgumentOutOfRangeException(nameof(tab));
-
- var index = this.tabs.IndexOf(tab);
- this.tabs.RemoveAt(index);
- this.tabs.Insert(index, tab);
- }
-
public void MoveTab(int newIndex, TabModel tab)
{
if (!this.ContainsTab(tab))
diff --git a/OpenTween/MyCommon.cs b/OpenTween/MyCommon.cs
index e06124e30..caf7b5a3e 100644
--- a/OpenTween/MyCommon.cs
+++ b/OpenTween/MyCommon.cs
@@ -1032,6 +1032,12 @@ await Task.Run(() =>
var message = string.Format(Properties.Resources.BrowserStartFailed, ex.Message);
MessageBox.Show(owner, message, ApplicationSettings.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
+ catch (MissingMethodException ex)
+ {
+ // WinRT API で存在しないメソッドを呼び出した(非対応の OS 上で実行した)場合に発生する
+ var message = string.Format(Properties.Resources.BrowserStartFailed, ex.Message);
+ MessageBox.Show(owner, message, ApplicationSettings.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
}
public static ProcessStartInfo CreateBrowserProcessStartInfo(string browserPathWithArgs, string url)
diff --git a/OpenTween/Properties/AssemblyInfo.cs b/OpenTween/Properties/AssemblyInfo.cs
index fb040dd6c..66fc212c8 100644
--- a/OpenTween/Properties/AssemblyInfo.cs
+++ b/OpenTween/Properties/AssemblyInfo.cs
@@ -22,7 +22,7 @@
// 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です
[assembly: Guid("2d0ae0ba-adac-49a2-9b10-26fd69e695bf")]
-[assembly: AssemblyVersion("3.4.0.0")]
+[assembly: AssemblyVersion("3.5.0.0")]
[assembly: InternalsVisibleTo("OpenTween.Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] // for Moq
diff --git a/OpenTween/Properties/Resources.Designer.cs b/OpenTween/Properties/Resources.Designer.cs
index c8e4ae7f9..4c2de913e 100644
--- a/OpenTween/Properties/Resources.Designer.cs
+++ b/OpenTween/Properties/Resources.Designer.cs
@@ -580,6 +580,13 @@ internal static string ChangeIconToolStripMenuItem_Confirm {
///
/// 更新履歴
///
+ ///==== Ver 3.5.0(2023/06/16)
+ /// * CHG: アカウント追加時にOpenTweenのAPIキーによる認可を選択肢に追加
+ /// * CHG: 非対応のOSを使用している場合に起動時に警告を表示する
+ /// * FIX: 削除したタブの取消時に同名のタブが存在した場合のエラーが適切に処理されない不具合を修正
+ /// * FIX: 発言一覧のアイコン画像の取得に失敗した場合のエラーが適切に処理されない不具合を修正
+ /// * FIX: Cookieを使用する場合にUserTimelineで99件を超えて取得するとエラーが返る問題の回避策を追加
+ ///
///==== Ver 3.4.0(2023/01/29)
/// * NEW: 複数枚の画像を添付する際に画像の削除や順序の変更ができるようになりました
/// * FIX: APIアクセス方式の選択画面でのタブオーダーの誤りを修正
@@ -587,15 +594,7 @@ internal static string ChangeIconToolStripMenuItem_Confirm {
///==== Ver 3.3.0(2023/01/22)
/// * NEW: アカウント追加時にAPIキーを指定可能になりました
/// * CHG: API v2 の使用を設定状態に関わらず無効化しました
- /// * FIX: 同一の画像を複数枚添付する時にプレビュー画像の表示がエラーになる不具合を修正
- ///
- ///==== Ver 3.2.0(2023/01/20)
- /// * NEW: 複数枚の画像を添付する際にリスト上で画像を確認できるようになりました
- /// * CHG: アカウント追加時の認可関連のエラーメッセージがより詳細になるように変更
- ///
- ///==== Ver 3.1.0(2023/01/14)
- /// * NEW: 引用ツイートを Ctrl+Shift+L で実行するショートカットを追加 (thx @WizardOfPSG!)
- /// * CHG: 発言一覧のフォントサイズがアイコンより [残りの文字列は切り詰められました]"; に類似しているローカライズされた文字列を検索します。
+ /// * FIX: 同 [残りの文字列は切り詰められました]"; に類似しているローカライズされた文字列を検索します。
///
internal static string ChangeLog {
get {
@@ -684,6 +683,15 @@ internal static string CheckNewVersionText9 {
}
}
+ ///
+ /// このソフトウェアは {0} 以降が必要です に類似しているローカライズされた文字列を検索します。
+ ///
+ internal static string CheckOSVersion_Error {
+ get {
+ return ResourceManager.GetString("CheckOSVersion_Error", resourceCulture);
+ }
+ }
+
///
/// このソフトウェアは {0} 以降が必要です。 に類似しているローカライズされた文字列を検索します。
///
@@ -3021,6 +3029,15 @@ internal static string Unauthorized {
}
}
+ ///
+ /// 削除したタブの取消に失敗しました。「{0}」と同じ名前のタブが存在します に類似しているローカライズされた文字列を検索します。
+ ///
+ internal static string UndoRemovedTab_DuplicateError {
+ get {
+ return ResourceManager.GetString("UndoRemovedTab_DuplicateError", resourceCulture);
+ }
+ }
+
///
/// **** エラー ログ: {0} **** に類似しているローカライズされた文字列を検索します。
///
diff --git a/OpenTween/Properties/Resources.en.resx b/OpenTween/Properties/Resources.en.resx
index a0779cc7b..824d29560 100644
--- a/OpenTween/Properties/Resources.en.resx
+++ b/OpenTween/Properties/Resources.en.resx
@@ -66,6 +66,7 @@
New version is not found. Latest version is {0}. Download it?
Your %AppName% is latest; you don't need to update. Version: {0} Latest version: {1}
Version check failed
+ This software requires {0} or later version.
This software requires {0} or later version.
Delete all tweets in this tab {0} ? (posts aren't deleted from the server.)
Confirm Clearing Tab
@@ -313,6 +314,7 @@ Do you retry to update status?
Version {0}
Failed to add tab.
You are not authorized.
+ Failed to undo the removed tab. A tab with the same name as "{0}" exists.
**** Error Log: {0} ****
Error
Administrator authority:
diff --git a/OpenTween/Properties/Resources.resx b/OpenTween/Properties/Resources.resx
index 28f41dea6..7b43171b8 100644
--- a/OpenTween/Properties/Resources.resx
+++ b/OpenTween/Properties/Resources.resx
@@ -72,6 +72,7 @@
新しいバージョンは見つかりません。 {0} が公開されています。強制的に更新しますか?
最新版をお使いです。更新の必要はありませんでした。使用中Ver:{0} 最新Ver:{1}
バージョンチェック失敗
+ このソフトウェアは {0} 以降が必要です
このソフトウェアは {0} 以降が必要です。
このタブの発言をクリアしてもよろしいですか?{0}(サーバーから発言は削除しません。)
タブクリア確認
@@ -347,6 +348,7 @@
バージョン {0}
タブ作成エラー
You are not authorized.
+ 削除したタブの取消に失敗しました。「{0}」と同じ名前のタブが存在します
**** エラー ログ: {0} ****
エラー発生
Administrator権限:
diff --git a/OpenTween/Resources/ChangeLog.txt b/OpenTween/Resources/ChangeLog.txt
index 24d167929..53a1e6496 100644
--- a/OpenTween/Resources/ChangeLog.txt
+++ b/OpenTween/Resources/ChangeLog.txt
@@ -1,5 +1,12 @@
更新履歴
+==== Ver 3.5.0(2023/06/16)
+ * CHG: アカウント追加時にOpenTweenのAPIキーによる認可を選択肢に追加
+ * CHG: 非対応のOSを使用している場合に起動時に警告を表示する
+ * FIX: 削除したタブの取消時に同名のタブが存在した場合のエラーが適切に処理されない不具合を修正
+ * FIX: 発言一覧のアイコン画像の取得に失敗した場合のエラーが適切に処理されない不具合を修正
+ * FIX: Cookieを使用する場合にUserTimelineで99件を超えて取得するとエラーが返る問題の回避策を追加
+
==== Ver 3.4.0(2023/01/29)
* NEW: 複数枚の画像を添付する際に画像の削除や順序の変更ができるようになりました
* FIX: APIアクセス方式の選択画面でのタブオーダーの誤りを修正
diff --git a/OpenTween/Setting/SettingCommon.cs b/OpenTween/Setting/SettingCommon.cs
index 4eca6796f..3e9f65684 100644
--- a/OpenTween/Setting/SettingCommon.cs
+++ b/OpenTween/Setting/SettingCommon.cs
@@ -392,8 +392,8 @@ public TwitterAppToken GetTwitterAppToken()
return new()
{
AuthType = this.TwitterAuthType,
- OAuth1ConsumerKey = ApiKey.Create(this.TwitterOAuth1ConsumerKey),
- OAuth1ConsumerSecret = ApiKey.Create(this.TwitterOAuth1ConsumerSecret),
+ OAuth1CustomConsumerKey = MyCommon.IsNullOrEmpty(this.TwitterOAuth1ConsumerKey) ? null : ApiKey.Create(this.TwitterOAuth1ConsumerKey),
+ OAuth1CustomConsumerSecret = MyCommon.IsNullOrEmpty(this.TwitterOAuth1ConsumerSecret) ? null : ApiKey.Create(this.TwitterOAuth1ConsumerSecret),
TwitterComCookie = this.TwitterComCookie,
};
}
diff --git a/OpenTween/Tween.cs b/OpenTween/Tween.cs
index e5706119f..9ce577427 100644
--- a/OpenTween/Tween.cs
+++ b/OpenTween/Tween.cs
@@ -8699,56 +8699,20 @@ private void UndoRemoveTabMenuItem_Click(object sender, EventArgs e)
else
{
var tb = this.statuses.RemovedTab.Pop();
- if (tb.TabType == MyCommon.TabUsageType.Related)
+ if (this.statuses.ContainsTab(tb.TabName))
{
- var relatedTab = this.statuses.GetTabByType(MyCommon.TabUsageType.Related);
- if (relatedTab != null)
- {
- // 関連発言なら既存のタブを置き換える
- tb.TabName = relatedTab.TabName;
- this.ClearTab(tb.TabName, false);
-
- this.statuses.ReplaceTab(tb);
-
- var tabIndex = this.statuses.Tabs.IndexOf(tb);
- this.ListTab.SelectedIndex = tabIndex;
- }
- else
- {
- const string TabName = "Related Tweets";
- var renamed = TabName;
- for (var i = 2; i <= 100; i++)
- {
- if (!this.statuses.ContainsTab(renamed))
- break;
- renamed = TabName + i;
- }
- tb.TabName = renamed;
-
- this.statuses.AddTab(tb);
- this.AddNewTab(tb, startup: false);
-
- var tabIndex = this.statuses.Tabs.Count - 1;
- this.ListTab.SelectedIndex = tabIndex;
- }
+ var message = string.Format(Properties.Resources.UndoRemovedTab_DuplicateError, tb.TabName);
+ MessageBox.Show(this, message, ApplicationSettings.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ this.statuses.RemovedTab.Push(tb);
+ return;
}
- else
- {
- var renamed = tb.TabName;
- for (var i = 1; i < int.MaxValue; i++)
- {
- if (!this.statuses.ContainsTab(renamed))
- break;
- renamed = tb.TabName + "(" + i + ")";
- }
- tb.TabName = renamed;
- this.statuses.AddTab(tb);
- this.AddNewTab(tb, startup: false);
+ this.statuses.AddTab(tb);
+ this.AddNewTab(tb, startup: false);
+
+ var tabIndex = this.statuses.Tabs.Count - 1;
+ this.ListTab.SelectedIndex = tabIndex;
- var tabIndex = this.statuses.Tabs.Count - 1;
- this.ListTab.SelectedIndex = tabIndex;
- }
this.SaveConfigsTabs();
}
}
diff --git a/OpenTween/Twitter.cs b/OpenTween/Twitter.cs
index 490e3bd7f..7aa503dbb 100644
--- a/OpenTween/Twitter.cs
+++ b/OpenTween/Twitter.cs
@@ -583,6 +583,10 @@ public async Task GetUserTimelineApi(bool read, string userName, UserTimelineTab
var count = GetApiResultCount(MyCommon.WORKERTYPE.UserTimeline, more, false);
+ // Cookie を使用する場合のみ 99 件を超えて取得するとエラーが返る
+ if (this.Api.AppToken.AuthType == APIAuthType.TwitterComCookie)
+ count = Math.Min(count, 99);
+
TwitterStatus[] statuses;
if (MyCommon.IsNullOrEmpty(userName))
{
diff --git a/appveyor.yml b/appveyor.yml
index bb1410bea..bf4b8edbb 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 3.3.0.{build}
+version: 3.4.0.{build}
os: Visual Studio 2022