Skip to content

Commit

Permalink
feat: display amount of reblog and favourites on status cards
Browse files Browse the repository at this point in the history
  • Loading branch information
aitorres committed Jan 6, 2025
1 parent be11d57 commit 22a8e25
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 16 deletions.
10 changes: 10 additions & 0 deletions lib/data/status.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ class Status {
// If this status is a reblog, the reblogged status content will be available here
final Status? reblog;

// Amount of times ths status has been favorited
final int favouritesCount;

// Amount of times this status has been reblogged
final int reblogsCount;

Status({
required this.id,
required this.createdAt,
Expand All @@ -41,6 +47,8 @@ class Status {
required this.favorited,
required this.reblogged,
required this.bookmarked,
required this.favouritesCount,
required this.reblogsCount,
this.reblog,
});

Expand All @@ -55,6 +63,8 @@ class Status {
favorited: data["favourited"]!,
reblogged: data["reblogged"]!,
bookmarked: data["bookmarked"]!,
favouritesCount: data["favourites_count"]!,
reblogsCount: data["reblogs_count"]!,
reblog: data["reblog"] == null ? null : Status.fromJson(data["reblog"]),
);
}
Expand Down
24 changes: 24 additions & 0 deletions lib/services/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,30 @@ class ApiService {
);
}

/// Given a Mastodon instance's base URL, requests the Mastodon API to
/// return custom emojis available on that server.
/// The returned data is a map of shortcode to URL for each custom emoji.
/// Note that this request is not tied to the current user or its instance,
/// as it's a public endpoint. Returns a list of custom emojis, if any.
Future<Map<String, String>> getCustomEmojis(
String mastodonInstanceUrl) async {
final apiUrl = "$mastodonInstanceUrl/api/v1/custom_emojis";
http.Response resp = await _apiGet(apiUrl);

if (resp.statusCode == 200) {
List<Map<String, dynamic>> jsonData = jsonDecode(resp.body);

return {
for (var item in jsonData)
item['shortcode'] as String: item['url'] as String
};
}

throw ApiException(
"Unexpected status code ${resp.statusCode} on `getCustomEmojis`",
);
}

/// Given a [Status]'s ID, requests the Mastodon API to un-boost
/// the status. Note that this is idempotent: a non-boosted
/// status will remain non-boosted. Returns the (new) [Status] instance
Expand Down
32 changes: 22 additions & 10 deletions lib/widgets/status_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,29 @@ class _StatusCardState extends State<StatusCard> {
OverflowBar(
alignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
onPressed: onBoostPress,
tooltip: "Boost",
icon: const Icon(FeatherIcons.repeat),
color: status.reblogged ? Colors.green : null,
Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: onBoostPress,
tooltip: "Boost",
icon: const Icon(FeatherIcons.repeat),
color: status.reblogged ? Colors.green : null,
),
Text("${status.reblogsCount}"),
],
),
IconButton(
onPressed: onFavoritePress,
tooltip: "Favorite",
icon: const Icon(FeatherIcons.star),
color: status.favorited ? Colors.yellow : null,
Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: onFavoritePress,
tooltip: "Favorite",
icon: const Icon(FeatherIcons.star),
color: status.favorited ? Colors.orange : null,
),
Text("${status.favouritesCount}"),
],
),
IconButton(
onPressed: onBookmarkPress,
Expand Down
12 changes: 12 additions & 0 deletions test/data_test/status_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ void main() {
"favourited": true,
"bookmarked": false,
"reblogged": true,
"favourites_count": 1,
"reblogs_count": 0,
"account": {
"id": "this is an id",
"username": "username123",
Expand All @@ -30,6 +32,8 @@ void main() {
"favourited": true,
"bookmarked": false,
"reblogged": true,
"favourites_count": 1,
"reblogs_count": 0,
"account": {
"id": "this is an id",
"username": "username123",
Expand All @@ -47,6 +51,8 @@ void main() {
"favourited": false,
"bookmarked": true,
"reblogged": false,
"favourites_count": 1,
"reblogs_count": 0,
"account": {
"id": "this is another id",
"username": "username456",
Expand All @@ -71,6 +77,8 @@ void main() {
expect(status.favorited, isTrue);
expect(status.bookmarked, isFalse);
expect(status.reblogged, isTrue);
expect(status.favouritesCount, equals(1));
expect(status.reblogsCount, equals(0));
expect(status.account.id, equals("this is an id"));
expect(status.account.username, equals("username123"));
expect(status.account.displayName, equals("user display name"));
Expand All @@ -92,6 +100,8 @@ void main() {
expect(status.favorited, isTrue);
expect(status.bookmarked, isFalse);
expect(status.reblogged, isTrue);
expect(status.favouritesCount, equals(1));
expect(status.reblogsCount, equals(0));
expect(status.account.id, equals("this is an id"));
expect(status.account.username, equals("username123"));
expect(status.account.displayName, equals("user display name"));
Expand All @@ -107,6 +117,8 @@ void main() {
expect(reblog.favorited, isFalse);
expect(reblog.bookmarked, isTrue);
expect(reblog.reblogged, isFalse);
expect(status.favouritesCount, equals(1));
expect(status.reblogsCount, equals(0));
expect(reblog.account.id, equals("this is another id"));
expect(reblog.account.username, equals("username456"));
expect(reblog.account.displayName, equals("user456 display name"));
Expand Down
12 changes: 6 additions & 6 deletions test/services_test/api_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void main() {
httpClient: mockClient))
.thenAnswer(
(_) async => http.Response(
'{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":true,"bookmarked":false,"reblogged":true,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}',
'{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":true,"bookmarked":false,"reblogged":true,"favourites_count":1,"reblogs_count":3,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}',
200,
),
);
Expand Down Expand Up @@ -181,7 +181,7 @@ void main() {
httpClient: mockClient))
.thenAnswer(
(_) async => http.Response(
'{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":false,"bookmarked":false,"reblogged":true,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}',
'{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":false,"bookmarked":false,"reblogged":true,"favourites_count":1,"reblogs_count":3,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}',
200,
),
);
Expand Down Expand Up @@ -248,7 +248,7 @@ void main() {
httpClient: mockClient))
.thenAnswer(
(_) async => http.Response(
'{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":true,"bookmarked":true,"reblogged":true,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}',
'{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":true,"bookmarked":true,"reblogged":true,"favourites_count":1,"reblogs_count":3,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}',
200,
),
);
Expand Down Expand Up @@ -315,7 +315,7 @@ void main() {
httpClient: mockClient))
.thenAnswer(
(_) async => http.Response(
'{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":false,"bookmarked":false,"reblogged":true,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}',
'{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":false,"bookmarked":false,"reblogged":true,"favourites_count":1,"reblogs_count":3,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}',
200,
),
);
Expand Down Expand Up @@ -379,7 +379,7 @@ void main() {
httpClient: mockClient))
.thenAnswer(
(_) async => http.Response(
'{"reblog":{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":true,"bookmarked":true,"reblogged":true,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}}',
'{"reblog":{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":true,"bookmarked":true,"reblogged":true,"favourites_count":1,"reblogs_count":3,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}}',
200,
),
);
Expand Down Expand Up @@ -446,7 +446,7 @@ void main() {
httpClient: mockClient))
.thenAnswer(
(_) async => http.Response(
'{"reblog":{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":true,"bookmarked":true,"reblogged":true,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}}',
'{"reblog":{"id":"$testStatusId","created_at": "2025-01-01T00:00:00Z","content":"<p>I am a toot!</p>","favourited":true,"bookmarked":true,"reblogged":true,"favourites_count":1,"reblogs_count":3,"account":{"id":"this is an id","username":"username123","acct":"username123","display_name":"user display name","locked":false,"bot":true,"avatar":"avatar-url","header":"header-url"}}}',
200,
),
);
Expand Down
2 changes: 2 additions & 0 deletions test/widgets_test/status_card_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ void main() {
favorited: true,
reblogged: false,
bookmarked: true,
favouritesCount: 10,
reblogsCount: 5,
);

await tester.pumpWidget(
Expand Down

0 comments on commit 22a8e25

Please sign in to comment.