Skip to content

Commit c3ee35e

Browse files
committed
Merge branch 'develop' into release
2 parents b954c0f + e8df69d commit c3ee35e

File tree

252 files changed

+11882
-4393
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

252 files changed

+11882
-4393
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ env:
1111
jobs:
1212
build:
1313
uses: ./.github/workflows/build.yml
14+
with:
15+
msbuild_args: /p:ContinuousIntegrationBuild=true
1416

1517
test:
1618
runs-on: windows-2022

CHANGELOG.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
更新履歴
22

3+
==== Ver 3.14.0(2024/06/11)
4+
* NEW: メインアカウント以外のホームタイムライン表示に対応
5+
- タブ単位で切り替わるマルチアカウント機能です
6+
- 投稿欄やふぁぼ・RT等の機能も表示中のタブに連動して使用するアカウントが変わります
7+
- 現時点ではメインアカウント以外のタブ設定は次回起動時に保持されません
8+
* NEW: Misskeyアカウントのホームタイムライン表示・投稿に対応しました
9+
- 現時点では Misskey アカウントをメインに設定することはできません
10+
- MFMの表示には対応していません
11+
* NEW: Twemoji 15.1.0 に対応しました
12+
- Unicode 15.1 で追加された絵文字が表示されるようになります
13+
* NEW: WebP画像の表示に対応しました
14+
- プロフィール画像やサムネイル画像にWebPが使われている場合も表示が可能になります
15+
- 「WebP画像拡張機能」がインストールされている環境でのみ動作します
16+
* CHG: 設定画面でのアカウント一覧の表示形式を変更
17+
* CHG: 新規アカウント追加時のダイアログの構成を変更
18+
* CHG: 新規タブの初回に読み込まれた発言を既読状態にする(起動時の初回の読み込みと同じ動作となる)
19+
* CHG: ドメインに x.com が使われている引用ツイートの展開・投稿に対応
20+
* CHG: 不具合調査のために追加していた発言一覧の定期更新タスクの待機時間チェックを削除
21+
* FIX: 発言の削除中にタブを切り替えるとエラーが発生する不具合を修正 (thx @Tan90909090!)
22+
* FIX: 発言一覧のプロフィール画像の読み込みでエラーが発生すると無限ループが生じる不具合を修正
23+
* FIX: 発言詳細欄からプロフィール画像の再読み込みを行う機能が動作していない不具合を修正
24+
* FIX: DMの添付画像の読み込み時に発生したエラーが適切に処理されない不具合を修正 (thx @wahho!)
25+
326
==== Ver 3.13.0(2024/01/27)
427
* NEW: Cookie使用時のReplyタブの更新に対応(/statuses/mentions_timeline.json 廃止に伴う対応)
528
* NEW: Cookie使用時のFavoritesタブの更新に対応

Directory.Build.props

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<Project>
2+
<PropertyGroup>
3+
<DefineConstants Condition="'$(ContinuousIntegrationBuild)' == 'true'">$(DefineConstants);CI_BUILD</DefineConstants>
4+
</PropertyGroup>
5+
</Project>

OpenTween.Tests/Api/GraphQL/CreateTweetRequestTest.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using System.Threading.Tasks;
2323
using Moq;
2424
using OpenTween.Connection;
25+
using OpenTween.Models;
2526
using Xunit;
2627

2728
namespace OpenTween.Api.GraphQL
@@ -78,7 +79,7 @@ public async Task Send_ReplyTest()
7879
{
7980
TweetText = "tetete",
8081
InReplyToTweetId = new("12345"),
81-
ExcludeReplyUserIds = new[] { "11111", "22222" },
82+
ExcludeReplyUserIds = new TwitterUserId[] { new("11111"), new("22222") },
8283
};
8384
await request.Send(mock.Object);
8485
mock.VerifyAll();

OpenTween.Tests/Api/GraphQL/HomeLatestTimelineRequestTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ public async Task Send_Test()
5757

5858
var response = await request.Send(mock.Object);
5959
Assert.Single(response.Tweets);
60-
Assert.Equal("DAABCgABGENe-W5AJxEKAAIWeWboXhcQAAgAAwAAAAEAAA", response.CursorTop);
61-
Assert.Equal("DAABCgABGENe-W4__5oKAAIWK_5v3BcQAAgAAwAAAAIAAA", response.CursorBottom);
60+
Assert.Equal("DAABCgABGENe-W5AJxEKAAIWeWboXhcQAAgAAwAAAAEAAA", response.CursorTop?.Value.Value);
61+
Assert.Equal("DAABCgABGENe-W4__5oKAAIWK_5v3BcQAAgAAwAAAAIAAA", response.CursorBottom?.Value.Value);
6262

6363
mock.VerifyAll();
6464
}
@@ -87,7 +87,7 @@ public async Task Send_RequestCursor_Test()
8787
var request = new HomeLatestTimelineRequest
8888
{
8989
Count = 20,
90-
Cursor = "aaa",
90+
Cursor = new("aaa"),
9191
};
9292

9393
await request.Send(mock.Object);

OpenTween.Tests/Api/GraphQL/LikesRequestTest.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ public async Task Send_Test()
5151

5252
var request = new LikesRequest
5353
{
54-
UserId = "12345",
54+
UserId = new("12345"),
5555
Count = 20,
5656
};
5757

5858
var response = await request.Send(mock.Object);
5959
Assert.Single(response.Tweets);
60-
Assert.Equal("DAAHCgABGEs2Ve9AAAELAAIAAAATMTc4OTA3OTU2MDM5NDcxNTMyMggAAwAAAAEAAA", response.CursorTop);
61-
Assert.Equal("DAAHCgABGEs2Ve8___8LAAIAAAATMTc4OTA3OTU2MDM5NDcxNTMyMggAAwAAAAIAAA", response.CursorBottom);
60+
Assert.Equal("DAAHCgABGEs2Ve9AAAELAAIAAAATMTc4OTA3OTU2MDM5NDcxNTMyMggAAwAAAAEAAA", response.CursorTop?.Value.Value);
61+
Assert.Equal("DAAHCgABGEs2Ve8___8LAAIAAAATMTc4OTA3OTU2MDM5NDcxNTMyMggAAwAAAAIAAA", response.CursorBottom?.Value.Value);
6262

6363
mock.VerifyAll();
6464
}
@@ -83,9 +83,9 @@ public async Task Send_RequestCursor_Test()
8383

8484
var request = new LikesRequest
8585
{
86-
UserId = "12345",
86+
UserId = new("12345"),
8787
Count = 20,
88-
Cursor = "aaa",
88+
Cursor = new("aaa"),
8989
};
9090

9191
await request.Send(mock.Object);

OpenTween.Tests/Api/GraphQL/ListLatestTweetsTimelineRequestTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ public async Task Send_Test()
5656

5757
var response = await request.Send(mock.Object);
5858
Assert.Single(response.Tweets);
59-
Assert.Equal("DAABCgABF0HfRMjAJxEKAAIWes8rE1oQAAgAAwAAAAEAAA", response.CursorTop);
60-
Assert.Equal("DAABCgABF0HfRMi__7QKAAIVAxUYmFWQAwgAAwAAAAIAAA", response.CursorBottom);
59+
Assert.Equal("DAABCgABF0HfRMjAJxEKAAIWes8rE1oQAAgAAwAAAAEAAA", response.CursorTop?.Value.Value);
60+
Assert.Equal("DAABCgABF0HfRMi__7QKAAIVAxUYmFWQAwgAAwAAAAIAAA", response.CursorBottom?.Value.Value);
6161

6262
mock.VerifyAll();
6363
}
@@ -86,7 +86,7 @@ public async Task Send_RequestCursor_Test()
8686
var request = new ListLatestTweetsTimelineRequest(listId: "1675863884757110790")
8787
{
8888
Count = 20,
89-
Cursor = "aaa",
89+
Cursor = new("aaa"),
9090
};
9191

9292
await request.Send(mock.Object);

OpenTween.Tests/Api/GraphQL/SearchTimelineRequestTest.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ public async Task Send_Test()
5656

5757
var response = await request.Send(mock.Object);
5858
Assert.Single(response.Tweets);
59-
Assert.Equal("DAADDAABCgABFnlh4hraMAYKAAIOTm0DEhTAAQAIAAIAAAABCAADAAAAAAgABAAAAAAKAAUX8j3ezIAnEAoABhfyPd7Mf9jwAAA", response.CursorTop);
60-
Assert.Equal("DAADDAABCgABFnlh4hraMAYKAAIOTm0DEhTAAQAIAAIAAAACCAADAAAAAAgABAAAAAAKAAUX8j3ezIAnEAoABhfyPd7Mf9jwAAA", response.CursorBottom);
59+
Assert.Equal("DAADDAABCgABFnlh4hraMAYKAAIOTm0DEhTAAQAIAAIAAAABCAADAAAAAAgABAAAAAAKAAUX8j3ezIAnEAoABhfyPd7Mf9jwAAA", response.CursorTop?.Value.Value);
60+
Assert.Equal("DAADDAABCgABFnlh4hraMAYKAAIOTm0DEhTAAQAIAAIAAAACCAADAAAAAAgABAAAAAAKAAUX8j3ezIAnEAoABhfyPd7Mf9jwAAA", response.CursorBottom?.Value.Value);
6161

6262
mock.VerifyAll();
6363
}
@@ -78,8 +78,8 @@ public async Task Send_ReplaceCursorTest()
7878

7979
var response = await request.Send(mock.Object);
8080
Assert.Empty(response.Tweets);
81-
Assert.Equal("DAADDAABCgABFnlh4hraMAYKAAIOTm0DEhTAAQAIAAIAAAABCAADAAAAAQgABAAAAAAKAAUX8j3ezIBOIAoABhfyPd7Mf9jwAAA", response.CursorTop);
82-
Assert.Equal("DAADDAABCgABFnlh4hraMAYKAAIOTm0DEhTAAQAIAAIAAAACCAADAAAAAQgABAAAAAAKAAUX8j3ezIBOIAoABhfyPd7Mf9jwAAA", response.CursorBottom);
81+
Assert.Equal("DAADDAABCgABFnlh4hraMAYKAAIOTm0DEhTAAQAIAAIAAAABCAADAAAAAQgABAAAAAAKAAUX8j3ezIBOIAoABhfyPd7Mf9jwAAA", response.CursorTop?.Value.Value);
82+
Assert.Equal("DAADDAABCgABFnlh4hraMAYKAAIOTm0DEhTAAQAIAAIAAAACCAADAAAAAQgABAAAAAAKAAUX8j3ezIBOIAoABhfyPd7Mf9jwAAA", response.CursorBottom?.Value.Value);
8383

8484
mock.VerifyAll();
8585
}
@@ -108,7 +108,7 @@ public async Task Send_RequestCursor_Test()
108108
var request = new SearchTimelineRequest(rawQuery: "#OpenTween")
109109
{
110110
Count = 20,
111-
Cursor = "aaa",
111+
Cursor = new("aaa"),
112112
};
113113

114114
await request.Send(mock.Object);

OpenTween.Tests/Api/GraphQL/TimelineResponseTest.cs renamed to OpenTween.Tests/Api/GraphQL/TimelineGraphqlResponseTest.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,19 @@
2020
// Boston, MA 02110-1301, USA.
2121

2222
using System.Threading.Tasks;
23+
using OpenTween.Models;
2324
using Xunit;
2425

2526
namespace OpenTween.Api.GraphQL
2627
{
27-
public class TimelineResponseTest
28+
public class TimelineGraphqlResponseTest
2829
{
2930
[Fact]
3031
public async Task ToTwitterStatuses_Test()
3132
{
3233
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/SearchTimeline_SimpleTweet.json");
3334
var tweets = TimelineTweet.ExtractTimelineTweets(await apiResponse.ReadAsJsonXml());
34-
var timelineResponse = new TimelineResponse(tweets, "", "");
35+
var timelineResponse = new TimelineGraphqlResponse(tweets, new(CursorType.Top, new("")), new(CursorType.Bottom, new("")));
3536

3637
var statuses = timelineResponse.ToTwitterStatuses();
3738
Assert.Single(statuses);

OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ public void ToStatus_WithTwitterPostFactory_SimpleTweet_Test()
7272
var rootElm = this.LoadResponseDocument("TimelineTweet_SimpleTweet.json");
7373
var timelineTweet = new TimelineTweet(rootElm);
7474
var status = timelineTweet.ToTwitterStatus();
75-
var postFactory = new TwitterPostFactory(this.CreateTabInfo());
76-
var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet<long>());
75+
var postFactory = new TwitterPostFactory(this.CreateTabInfo(), new());
76+
var post = postFactory.CreateFromStatus(status, selfUserId: new("1"), new HashSet<PersonId>(), firstLoad: false);
7777

7878
Assert.Equal("1613784711020826626", post.StatusId.Id);
79-
Assert.Equal(40480664L, post.UserId);
79+
Assert.Equal(new TwitterUserId("40480664"), post.UserId);
8080
Assert.False(post.IsPromoted);
8181
}
8282

@@ -86,11 +86,11 @@ public void ToStatus_WithTwitterPostFactory_TweetWithMedia_Test()
8686
var rootElm = this.LoadResponseDocument("TimelineTweet_TweetWithMedia.json");
8787
var timelineTweet = new TimelineTweet(rootElm);
8888
var status = timelineTweet.ToTwitterStatus();
89-
var postFactory = new TwitterPostFactory(this.CreateTabInfo());
90-
var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet<long>());
89+
var postFactory = new TwitterPostFactory(this.CreateTabInfo(), new());
90+
var post = postFactory.CreateFromStatus(status, selfUserId: new("1"), new HashSet<PersonId>(), firstLoad: false);
9191

9292
Assert.Equal("1614587968567783424", post.StatusId.Id);
93-
Assert.Equal(40480664L, post.UserId);
93+
Assert.Equal(new TwitterUserId("40480664"), post.UserId);
9494
Assert.Equal(2, post.Media.Count);
9595
Assert.Equal("https://pbs.twimg.com/media/FmgrJiEaAAEU42G.png", post.Media[0].Url);
9696
Assert.Equal("OpenTweenで @opentween のツイート一覧を表示しているスクショ", post.Media[0].AltText);
@@ -104,13 +104,13 @@ public void ToStatus_WithTwitterPostFactory_RetweetedTweet_Test()
104104
var rootElm = this.LoadResponseDocument("TimelineTweet_RetweetedTweet.json");
105105
var timelineTweet = new TimelineTweet(rootElm);
106106
var status = timelineTweet.ToTwitterStatus();
107-
var postFactory = new TwitterPostFactory(this.CreateTabInfo());
108-
var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet<long>());
107+
var postFactory = new TwitterPostFactory(this.CreateTabInfo(), new());
108+
var post = postFactory.CreateFromStatus(status, selfUserId: new("1"), new HashSet<PersonId>(), firstLoad: false);
109109

110110
Assert.Equal("1617128268548964354", post.StatusId.Id);
111-
Assert.Equal(40480664L, post.RetweetedByUserId);
111+
Assert.Equal(new TwitterUserId("40480664"), post.RetweetedByUserId);
112112
Assert.Equal("1617126084138659840", post.RetweetedId!.Id);
113-
Assert.Equal(514241801L, post.UserId);
113+
Assert.Equal(new TwitterUserId("514241801"), post.UserId);
114114
}
115115

116116
[Fact]
@@ -119,11 +119,11 @@ public void ToStatus_WithTwitterPostFactory_TweetWithVisibility_Test()
119119
var rootElm = this.LoadResponseDocument("TimelineTweet_TweetWithVisibility.json");
120120
var timelineTweet = new TimelineTweet(rootElm);
121121
var status = timelineTweet.ToTwitterStatus();
122-
var postFactory = new TwitterPostFactory(this.CreateTabInfo());
123-
var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet<long>());
122+
var postFactory = new TwitterPostFactory(this.CreateTabInfo(), new());
123+
var post = postFactory.CreateFromStatus(status, selfUserId: new("1"), new HashSet<PersonId>(), firstLoad: false);
124124

125125
Assert.Equal("1602775353088524288", post.StatusId.Id);
126-
Assert.Equal(357750891L, post.UserId);
126+
Assert.Equal(new TwitterUserId("357750891"), post.UserId);
127127
}
128128

129129
[Fact]
@@ -132,11 +132,11 @@ public void ToStatus_WithTwitterPostFactory_SelfThread_Test()
132132
var rootElm = this.LoadResponseDocument("TimelineTweet_SelfThread.json");
133133
var timelineTweet = new TimelineTweet(rootElm);
134134
var status = timelineTweet.ToTwitterStatus();
135-
var postFactory = new TwitterPostFactory(this.CreateTabInfo());
136-
var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet<long>());
135+
var postFactory = new TwitterPostFactory(this.CreateTabInfo(), new());
136+
var post = postFactory.CreateFromStatus(status, selfUserId: new("1"), new HashSet<PersonId>(), firstLoad: false);
137137

138138
Assert.Equal("1511751702684499968", post.StatusId.Id);
139-
Assert.Equal(40480664L, post.UserId);
139+
Assert.Equal(new TwitterUserId("40480664"), post.UserId);
140140
}
141141

142142
[Fact]
@@ -145,8 +145,8 @@ public void ToStatus_WithTwitterPostFactory_QuotedTweet_Test()
145145
var rootElm = this.LoadResponseDocument("TimelineTweet_QuotedTweet.json");
146146
var timelineTweet = new TimelineTweet(rootElm);
147147
var status = timelineTweet.ToTwitterStatus();
148-
var postFactory = new TwitterPostFactory(this.CreateTabInfo());
149-
var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet<long>());
148+
var postFactory = new TwitterPostFactory(this.CreateTabInfo(), new());
149+
var post = postFactory.CreateFromStatus(status, selfUserId: new("1"), new HashSet<PersonId>(), firstLoad: false);
150150

151151
Assert.Equal("1588614645866147840", post.StatusId.Id);
152152
var quotedPostId = Assert.Single(post.QuoteStatusIds);
@@ -159,8 +159,8 @@ public void ToStatus_WithTwitterPostFactory_QuotedTweet_Tombstone_Test()
159159
var rootElm = this.LoadResponseDocument("TimelineTweet_QuotedTweet_Tombstone.json");
160160
var timelineTweet = new TimelineTweet(rootElm);
161161
var status = timelineTweet.ToTwitterStatus();
162-
var postFactory = new TwitterPostFactory(this.CreateTabInfo());
163-
var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet<long>());
162+
var postFactory = new TwitterPostFactory(this.CreateTabInfo(), new());
163+
var post = postFactory.CreateFromStatus(status, selfUserId: new("1"), new HashSet<PersonId>(), firstLoad: false);
164164

165165
Assert.Equal("1614653321310253057", post.StatusId.Id);
166166
var quotedPostId = Assert.Single(post.QuoteStatusIds);
@@ -173,11 +173,11 @@ public void ToStatus_WithTwitterPostFactory_PromotedTweet_Test()
173173
var rootElm = this.LoadResponseDocument("TimelineTweet_PromotedTweet.json");
174174
var timelineTweet = new TimelineTweet(rootElm);
175175
var status = timelineTweet.ToTwitterStatus();
176-
var postFactory = new TwitterPostFactory(this.CreateTabInfo());
177-
var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet<long>());
176+
var postFactory = new TwitterPostFactory(this.CreateTabInfo(), new());
177+
var post = postFactory.CreateFromStatus(status, selfUserId: new("1"), new HashSet<PersonId>(), firstLoad: false);
178178

179179
Assert.Equal("1674737917363888129", post.StatusId.Id);
180-
Assert.Equal(2941313791L, post.UserId);
180+
Assert.Equal(new TwitterUserId("2941313791"), post.UserId);
181181
Assert.True(post.IsPromoted);
182182
Assert.Matches(new Regex(@"^\[Promoted\]\n"), post.TextFromApi);
183183
}
@@ -195,6 +195,16 @@ public void ToStatus_TweetTombstone_Test()
195195
Assert.Equal("This Post is from a suspended account. Learn more", ex.Message);
196196
}
197197

198+
[Fact]
199+
public void ToStatus_MissingLegacy_Test()
200+
{
201+
// legacy プロパティが欠けておりツイートの表示に必要な情報が不足している場合
202+
var rootElm = this.LoadResponseDocument("TimelineTweet_MissingLegacy.json");
203+
var timelineTweet = new TimelineTweet(rootElm);
204+
205+
Assert.False(timelineTweet.IsAvailable);
206+
}
207+
198208
[Fact]
199209
public void ToStatus_EmptyTweet_Test()
200210
{

0 commit comments

Comments
 (0)