From f31b2da08737032eb8490295d31693e196a8a5e5 Mon Sep 17 00:00:00 2001 From: provokateurin Date: Fri, 1 Nov 2024 10:19:28 +0100 Subject: [PATCH] feat(talk_app): Use existing user status data Signed-off-by: provokateurin --- .../packages/talk_app/lib/src/blocs/talk.dart | 4 ++- .../talk_app/lib/src/dialogs/create_room.dart | 14 ++++++-- .../lib/src/widgets/message_input.dart | 14 ++++++-- .../talk_app/lib/src/widgets/room_avatar.dart | 13 +++++-- .../test/create_room_dialog_test.dart | 35 ++++++++++++++----- .../talk_app/test/message_input_test.dart | 18 +--------- .../talk_app/test/room_avatar_test.dart | 10 ++---- 7 files changed, 68 insertions(+), 40 deletions(-) diff --git a/packages/neon_framework/packages/talk_app/lib/src/blocs/talk.dart b/packages/neon_framework/packages/talk_app/lib/src/blocs/talk.dart index 5449d8e921f..02dfb74e0c3 100644 --- a/packages/neon_framework/packages/talk_app/lib/src/blocs/talk.dart +++ b/packages/neon_framework/packages/talk_app/lib/src/blocs/talk.dart @@ -78,7 +78,9 @@ class _TalkBloc extends InteractiveBloc implements TalkBloc { await RequestManager.instance.wrap( account: account, subject: rooms, - getRequest: account.client.spreed.room.$getRooms_Request, + getRequest: () => account.client.spreed.room.$getRooms_Request( + includeStatus: spreed.RoomGetRoomsIncludeStatus.$1, + ), converter: ResponseConverter(account.client.spreed.room.$getRooms_Serializer()), unwrap: (response) => response.body.ocs.data.rebuild( (b) => b.sort((a, b) => b.lastActivity.compareTo(a.lastActivity)), diff --git a/packages/neon_framework/packages/talk_app/lib/src/dialogs/create_room.dart b/packages/neon_framework/packages/talk_app/lib/src/dialogs/create_room.dart index 0f4d90fecfd..3e584a0cad5 100644 --- a/packages/neon_framework/packages/talk_app/lib/src/dialogs/create_room.dart +++ b/packages/neon_framework/packages/talk_app/lib/src/dialogs/create_room.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:neon_framework/blocs.dart'; import 'package:neon_framework/models.dart'; import 'package:neon_framework/theme.dart'; import 'package:neon_framework/utils.dart'; import 'package:neon_framework/widgets.dart'; import 'package:nextcloud/core.dart' as core; import 'package:nextcloud/spreed.dart' as spreed; +import 'package:nextcloud/user_status.dart' as user_status; import 'package:talk_app/l10n/localizations.dart'; /// The data that will be returned when the [TalkCreateRoomDialog] is closed. @@ -165,11 +165,21 @@ class _TalkCreateRoomDialogState extends State { core.AutocompleteResult result, void Function(core.AutocompleteResult)? onSelected, ) { + final status = result.status.autocompleteResultStatus0; final icon = switch (result.source) { 'users' => NeonUserAvatar( username: result.id, account: NeonProvider.of(context), - userStatusBloc: NeonProvider.of(context), + userStatus: status != null + ? user_status.Public( + (b) => b + ..userId = result.id + ..message = status.message + ..icon = status.icon + ..clearAt = status.clearAt + ..status = user_status.$Type.valueOf(status.status), + ) + : null, ), 'groups' => CircleAvatar( child: Icon( diff --git a/packages/neon_framework/packages/talk_app/lib/src/widgets/message_input.dart b/packages/neon_framework/packages/talk_app/lib/src/widgets/message_input.dart index 58817eaad6f..0f16950dd09 100644 --- a/packages/neon_framework/packages/talk_app/lib/src/widgets/message_input.dart +++ b/packages/neon_framework/packages/talk_app/lib/src/widgets/message_input.dart @@ -3,12 +3,12 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; -import 'package:neon_framework/blocs.dart'; import 'package:neon_framework/models.dart'; import 'package:neon_framework/theme.dart'; import 'package:neon_framework/utils.dart'; import 'package:neon_framework/widgets.dart'; import 'package:nextcloud/spreed.dart' as spreed; +import 'package:nextcloud/user_status.dart' as user_status; import 'package:talk_app/l10n/localizations.dart'; import 'package:talk_app/src/blocs/room.dart'; import 'package:talk_app/src/widgets/message.dart'; @@ -187,6 +187,7 @@ class _TalkMessageInputState extends State { token: bloc.room.value.requireData.token, search: matchingPart.substring(1), limit: 5, + includeStatus: spreed.ChatMentionsIncludeStatus.$1, ); return response.body.ocs.data @@ -257,8 +258,17 @@ class _TalkMessageInputState extends State { final icon = switch (suggestion.mention.source) { 'users' => NeonUserAvatar( account: NeonProvider.of(context), - userStatusBloc: NeonProvider.of(context), username: suggestion.mention.id, + userStatus: suggestion.mention.status != null + ? user_status.Public( + (b) => b + ..userId = suggestion.mention.id + ..message = suggestion.mention.statusMessage + ..icon = suggestion.mention.statusIcon + ..clearAt = suggestion.mention.statusClearAt + ..status = user_status.$Type.valueOf(suggestion.mention.status!), + ) + : null, ), 'groups' || 'calls' => CircleAvatar( child: Icon( diff --git a/packages/neon_framework/packages/talk_app/lib/src/widgets/room_avatar.dart b/packages/neon_framework/packages/talk_app/lib/src/widgets/room_avatar.dart index 1d3411fdd7f..4a59af9b74b 100644 --- a/packages/neon_framework/packages/talk_app/lib/src/widgets/room_avatar.dart +++ b/packages/neon_framework/packages/talk_app/lib/src/widgets/room_avatar.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:neon_framework/blocs.dart'; import 'package:neon_framework/models.dart'; import 'package:neon_framework/theme.dart'; import 'package:neon_framework/utils.dart'; import 'package:neon_framework/widgets.dart'; import 'package:nextcloud/spreed.dart' as spreed; +import 'package:nextcloud/user_status.dart' as user_status; /// Displays the avatar of the [room]. /// @@ -50,7 +50,16 @@ class TalkRoomAvatar extends StatelessWidget { spreed.RoomType.oneToOne => NeonUserAvatar( username: room.name, account: NeonProvider.of(context), - userStatusBloc: NeonProvider.of(context), + userStatus: room.status != null + ? user_status.Public( + (b) => b + ..userId = room.name + ..message = room.statusMessage + ..icon = room.statusIcon + ..clearAt = room.statusClearAt + ..status = user_status.$Type.valueOf(room.status!), + ) + : null, ), spreed.RoomType.group => _buildIconAvatar(AdaptiveIcons.group), // coverage:ignore-start diff --git a/packages/neon_framework/packages/talk_app/test/create_room_dialog_test.dart b/packages/neon_framework/packages/talk_app/test/create_room_dialog_test.dart index d156e353d4a..884ea08327d 100644 --- a/packages/neon_framework/packages/talk_app/test/create_room_dialog_test.dart +++ b/packages/neon_framework/packages/talk_app/test/create_room_dialog_test.dart @@ -36,7 +36,11 @@ Account mockAutocompleteAccount() { 'label': 'Test', 'icon': '', 'source': source, - 'status': '', + 'status': source == 'users' + ? { + 'status': 'online', + } + : '', 'subline': '', 'shareWithDisplayNameUnique': '', }, @@ -69,21 +73,24 @@ void main() { }); final localizations = TalkLocalizationsEn(); - for (final (name, type, typeName, iconMatcher, iconCount, source) in [ + for (final (name, type, typeName, matchers, source) in [ ( 'One-to-one', spreed.RoomType.oneToOne, localizations.roomType(spreed.RoomType.oneToOne.name), - find.byType(NeonUserAvatar), - findsOne, + { + find.byType(NeonUserAvatar): findsOne, + find.byType(NeonUserStatusIcon): findsOne, + }, 'users', ), ( 'Group', spreed.RoomType.group, localizations.roomType(spreed.RoomType.group.name), - find.byIcon(AdaptiveIcons.group), - findsExactly(2), + { + find.byIcon(AdaptiveIcons.group): findsExactly(2), + }, 'groups', ), ]) { @@ -129,7 +136,9 @@ void main() { await tester.enterText(find.byType(TextFormField), 't'); await tester.pumpAndSettle(); - expect(iconMatcher, iconCount); + for (final entry in matchers.entries) { + expect(entry.key, entry.value); + } await tester.tap(find.text('Test')); await tester.pumpAndSettle(); @@ -147,7 +156,17 @@ void main() { ..label = 'Test' ..icon = '' ..source = source - ..status = (autocompleteResultStatus0: null, string: '') + ..status = source == 'users' + ? ( + autocompleteResultStatus0: core.AutocompleteResult_Status0( + (b) => b.status = 'online', + ), + string: null, + ) + : ( + autocompleteResultStatus0: null, + string: '', + ) ..subline = '' ..shareWithDisplayNameUnique = '', ), diff --git a/packages/neon_framework/packages/talk_app/test/message_input_test.dart b/packages/neon_framework/packages/talk_app/test/message_input_test.dart index 34a34be64aa..25f3d292cfb 100644 --- a/packages/neon_framework/packages/talk_app/test/message_input_test.dart +++ b/packages/neon_framework/packages/talk_app/test/message_input_test.dart @@ -15,7 +15,6 @@ import 'package:neon_framework/theme.dart'; import 'package:neon_framework/utils.dart'; import 'package:neon_framework/widgets.dart'; import 'package:nextcloud/spreed.dart' as spreed; -import 'package:nextcloud/user_status.dart' as user_status; import 'package:provider/provider.dart'; import 'package:rxdart/rxdart.dart'; import 'package:talk_app/l10n/localizations.dart'; @@ -47,6 +46,7 @@ Account mockTalkAccount() { 'id': 'id2', 'label': 'label2', 'source': 'users', + 'status': 'online', }, ], }, @@ -162,27 +162,11 @@ void main() { }); testWidgets('Mention suggestions', (tester) async { - final userStatusBloc = MockUserStatusBloc(); - when(() => userStatusBloc.statuses).thenAnswer( - (_) => BehaviorSubject.seeded( - BuiltMap({ - 'id2': Result.success( - user_status.Public( - (b) => b - ..userId = 'id1' - ..status = user_status.$Type.online, - ), - ), - }), - ), - ); - await tester.pumpWidgetWithAccessibility( TestApp( localizationsDelegates: TalkLocalizations.localizationsDelegates, supportedLocales: TalkLocalizations.supportedLocales, providers: [ - NeonProvider.value(value: userStatusBloc), NeonProvider.value(value: bloc), Provider.value(value: account), ], diff --git a/packages/neon_framework/packages/talk_app/test/room_avatar_test.dart b/packages/neon_framework/packages/talk_app/test/room_avatar_test.dart index 5b1c19c96d7..228a3f8f8eb 100644 --- a/packages/neon_framework/packages/talk_app/test/room_avatar_test.dart +++ b/packages/neon_framework/packages/talk_app/test/room_avatar_test.dart @@ -1,15 +1,11 @@ -import 'package:built_collection/built_collection.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; -import 'package:neon_framework/blocs.dart'; import 'package:neon_framework/models.dart'; import 'package:neon_framework/testing.dart'; import 'package:neon_framework/theme.dart'; -import 'package:neon_framework/utils.dart'; import 'package:neon_framework/widgets.dart'; import 'package:nextcloud/spreed.dart' as spreed; import 'package:provider/provider.dart'; -import 'package:rxdart/subjects.dart'; import 'package:talk_app/src/widgets/room_avatar.dart'; import 'testing.dart'; @@ -43,18 +39,15 @@ void main() { testWidgets('One to one', (tester) async { final account = MockAccount(); - final userStatusBloc = MockUserStatusBloc(); - when(() => userStatusBloc.statuses).thenAnswer((_) => BehaviorSubject.seeded(BuiltMap())); - final room = MockRoom(); when(() => room.isCustomAvatar).thenReturn(false); when(() => room.type).thenReturn(spreed.RoomType.oneToOne.value); when(() => room.name).thenReturn(''); + when(() => room.status).thenReturn('online'); await tester.pumpWidgetWithAccessibility( TestApp( providers: [ - NeonProvider.value(value: userStatusBloc), Provider.value(value: account), ], child: TalkRoomAvatar( @@ -63,6 +56,7 @@ void main() { ), ); expect(find.byType(NeonUserAvatar), findsOne); + expect(find.byType(NeonUserStatusIcon), findsOne); }); testWidgets('Other', (tester) async {