diff --git a/.cspell/nextcloud.txt b/.cspell/nextcloud.txt index 98b66006262..04267a6c5c0 100644 --- a/.cspell/nextcloud.txt +++ b/.cspell/nextcloud.txt @@ -1,6 +1,7 @@ apirequest apppassword bigfilechunking +boardname bools bulkupload clearsky @@ -44,6 +45,7 @@ shareapi sharebymail sharee shareesapi +stackname statuscode stime stunservers diff --git a/packages/neon/neon_talk/lib/src/widgets/message.dart b/packages/neon/neon_talk/lib/src/widgets/message.dart index c9913c36a4c..1759503cbdd 100644 --- a/packages/neon/neon_talk/lib/src/widgets/message.dart +++ b/packages/neon/neon_talk/lib/src/widgets/message.dart @@ -5,6 +5,10 @@ import 'package:neon_framework/theme.dart'; import 'package:neon_talk/l10n/localizations.dart'; import 'package:neon_talk/src/widgets/actor_avatar.dart'; import 'package:neon_talk/src/widgets/reactions.dart'; +import 'package:neon_talk/src/widgets/rich_object/deck_card.dart'; +import 'package:neon_talk/src/widgets/rich_object/fallback.dart'; +import 'package:neon_talk/src/widgets/rich_object/file.dart'; +import 'package:neon_talk/src/widgets/rich_object/mention.dart'; import 'package:nextcloud/spreed.dart' as spreed; import 'package:nextcloud/utils.dart'; import 'package:timezone/timezone.dart' as tz; @@ -35,9 +39,117 @@ TextSpan buildChatMessage({ message = message.replaceAll('\n', ' '); } + final unusedParameters = {}; + + var parts = [message]; + for (final entry in chatMessage.messageParameters.entries) { + final newParts = []; + + var found = false; + for (final part in parts) { + final p = part.split('{${entry.key}}'); + newParts.addAll(p.intersperse('{${entry.key}}')); + if (p.length > 1) { + found = true; + } + } + + if (!found) { + unusedParameters[entry.key] = entry.value; + } + + parts = newParts; + } + + final children = []; + + for (final entry in unusedParameters.entries) { + if (entry.key == 'actor' || entry.key == 'user') { + continue; + } + + children + ..add( + buildRichObjectParameter( + parameter: entry.value, + textStyle: style, + isPreview: isPreview, + ), + ) + ..add(const TextSpan(text: '\n')); + } + + for (final part in parts) { + var match = false; + for (final entry in chatMessage.messageParameters.entries) { + if ('{${entry.key}}' == part) { + children.add( + buildRichObjectParameter( + parameter: entry.value, + textStyle: style, + isPreview: isPreview, + ), + ); + match = true; + break; + } + } + + if (!match) { + children.add( + TextSpan( + text: part, + ), + ); + } + } + return TextSpan( - text: message, style: style, + children: children, + ); +} + +/// Renders a rich object [parameter] to be interactive. +InlineSpan buildRichObjectParameter({ + required spreed.RichObjectParameter parameter, + required TextStyle? textStyle, + required bool isPreview, +}) { + Widget child; + + const mentionTypes = ['user', 'call', 'guest', 'user-group', 'group']; + if (mentionTypes.contains(parameter.type)) { + child = TalkRichObjectMention( + parameter: parameter, + textStyle: textStyle, + ); + } else { + if (isPreview) { + child = Text(parameter.name); + } else { + switch (parameter.type) { + case 'file': + child = TalkRichObjectFile( + parameter: parameter, + textStyle: textStyle, + ); + case 'deck-card': + child = TalkRichObjectDeckCard( + parameter: parameter, + ); + default: + child = TalkRichObjectFallback( + parameter: parameter, + textStyle: textStyle, + ); + } + } + } + + return WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: child, ); } diff --git a/packages/neon/neon_talk/lib/src/widgets/rich_object/deck_card.dart b/packages/neon/neon_talk/lib/src/widgets/rich_object/deck_card.dart new file mode 100644 index 00000000000..a8c13cf12e7 --- /dev/null +++ b/packages/neon/neon_talk/lib/src/widgets/rich_object/deck_card.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_material_design_icons/flutter_material_design_icons.dart'; +import 'package:go_router/go_router.dart'; +import 'package:nextcloud/spreed.dart' as spreed; + +/// Widget to display a Deck card from a rich object. +class TalkRichObjectDeckCard extends StatelessWidget { + /// Creates a new Talk rich object Deck card. + const TalkRichObjectDeckCard({ + required this.parameter, + super.key, + }); + + /// The parameter to display. + final spreed.RichObjectParameter parameter; + + @override + Widget build(BuildContext context) { + return IntrinsicWidth( + child: Card( + clipBehavior: Clip.hardEdge, + child: InkWell( + onTap: () { + context.go(parameter.link!); + }, + child: ListTile( + // TODO: Use the actual Deck logo + leading: const Icon(MdiIcons.cardMultiple), + title: Text(parameter.name), + subtitle: Text('${parameter.boardname!}: ${parameter.stackname!}'), + ), + ), + ), + ); + } +} diff --git a/packages/neon/neon_talk/lib/src/widgets/rich_object/fallback.dart b/packages/neon/neon_talk/lib/src/widgets/rich_object/fallback.dart new file mode 100644 index 00000000000..8659abae8fa --- /dev/null +++ b/packages/neon/neon_talk/lib/src/widgets/rich_object/fallback.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:neon_framework/widgets.dart'; +import 'package:nextcloud/spreed.dart' as spreed; + +/// Widget used to render rich object parameters with unknown types. +class TalkRichObjectFallback extends StatelessWidget { + /// Creates a new Talk rich object fallback + const TalkRichObjectFallback({ + required this.parameter, + required this.textStyle, + super.key, + }); + + /// The parameter to display. + final spreed.RichObjectParameter parameter; + + /// The TextStyle to applied to all text elements in this rich object. + final TextStyle? textStyle; + + @override + Widget build(BuildContext context) { + final iconUrl = parameter.iconUrl; + + EdgeInsetsGeometry? labelPadding; + Widget? avatar; + if (iconUrl != null) { + labelPadding = const EdgeInsetsDirectional.only(end: 8); + avatar = Padding( + padding: const EdgeInsets.all(4), + child: CircleAvatar( + child: ClipOval( + child: NeonUriImage( + uri: Uri.parse(iconUrl), + ), + ), + ), + ); + } + + return ActionChip( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50)), + padding: EdgeInsets.zero, + labelPadding: labelPadding, + avatar: avatar, + label: Text( + parameter.name, + style: textStyle, + ), + onPressed: () { + final link = parameter.link; + if (link != null) { + context.go(link); + } + }, + ); + } +} diff --git a/packages/neon/neon_talk/lib/src/widgets/rich_object/file.dart b/packages/neon/neon_talk/lib/src/widgets/rich_object/file.dart new file mode 100644 index 00000000000..98fcd073300 --- /dev/null +++ b/packages/neon/neon_talk/lib/src/widgets/rich_object/file.dart @@ -0,0 +1,98 @@ +import 'package:file_icons/file_icons.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:neon_framework/blocs.dart'; +import 'package:neon_framework/theme.dart'; +import 'package:neon_framework/utils.dart'; +import 'package:neon_framework/widgets.dart'; +import 'package:nextcloud/core.dart'; +import 'package:nextcloud/spreed.dart' as spreed; + +/// Displays a file preview from a rich object. +class TalkRichObjectFile extends StatelessWidget { + /// Creates a new Talk rich object file. + const TalkRichObjectFile({ + required this.parameter, + required this.textStyle, + super.key, + }); + + /// The parameter to display. + final spreed.RichObjectParameter parameter; + + /// The TextStyle to applied to all text elements in this rich object. + final TextStyle? textStyle; + + @override + Widget build(BuildContext context) { + Widget child; + + if (parameter.previewAvailable == spreed.RichObjectParameter_PreviewAvailable.yes) { + final maxHeight = MediaQuery.sizeOf(context).height / 2; + + var width = parameter.width; + var height = parameter.height; + if (width != null && height != null) { + final devicePixelRatio = MediaQuery.of(context).devicePixelRatio; + + var size = Size(width.toDouble(), height.toDouble()); + + // Convert to logical pixels + size /= devicePixelRatio; + + // Constrain size to max height but keep aspect ration + if (size.height > maxHeight) { + size = size * (maxHeight / size.height); + } + + // Convert back to device pixels + size *= devicePixelRatio; + + width = size.width.toInt(); + height = size.height.toInt(); + } + + child = ConstrainedBox( + constraints: BoxConstraints( + maxHeight: maxHeight, + ), + child: Tooltip( + message: parameter.name, + child: NeonApiImage( + cacheKey: 'preview-${parameter.path!}-$width-$height', + etag: parameter.etag, + expires: null, + request: (client) => client.core.preview.$getPreviewByFileId_Request( + fileId: int.parse(parameter.id), + x: width, + y: height, + ), + ), + ), + ); + } else { + child = Row( + children: [ + FileIcon( + parameter.name, + color: Theme.of(context).colorScheme.primary, + size: largeIconSize, + ), + Text( + parameter.name, + style: textStyle, + ), + ], + ); + } + + return InkWell( + onTap: () { + final link = Uri.parse(parameter.link!); + final account = NeonProvider.of(context).activeAccount.value!; + context.go(account.completeUri(link).toString()); + }, + child: child, + ); + } +} diff --git a/packages/neon/neon_talk/lib/src/widgets/rich_object/mention.dart b/packages/neon/neon_talk/lib/src/widgets/rich_object/mention.dart new file mode 100644 index 00000000000..6d7e13cb4e0 --- /dev/null +++ b/packages/neon/neon_talk/lib/src/widgets/rich_object/mention.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:neon_framework/theme.dart'; +import 'package:neon_framework/widgets.dart'; +import 'package:nextcloud/spreed.dart' as spreed; + +/// Displays a mention chip from a rich object. +class TalkRichObjectMention extends StatelessWidget { + /// Create a new Talk rich object mention. + const TalkRichObjectMention({ + required this.parameter, + required this.textStyle, + super.key, + }); + + /// The parameter to display. + final spreed.RichObjectParameter parameter; + + /// The TextStyle to applied to all text elements in this rich object. + final TextStyle? textStyle; + + @override + Widget build(BuildContext context) { + final child = switch (parameter.type) { + 'user' => NeonUserAvatar( + username: parameter.id, + showStatus: false, + ), + 'call' => CircleAvatar( + child: ClipOval( + child: NeonUriImage( + uri: Uri.parse(parameter.iconUrl!), + ), + ), + ), + 'guest' => CircleAvatar( + child: Icon(AdaptiveIcons.person), + ), + 'user-group' || 'group' => CircleAvatar( + child: Icon(AdaptiveIcons.group), + ), + _ => throw UnimplementedError('Unknown mention type: $parameter'), // coverage:ignore-line + }; + + return Chip( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50)), + padding: EdgeInsets.zero, + labelPadding: const EdgeInsetsDirectional.only(end: 4, start: -4), + avatar: Padding( + padding: const EdgeInsets.all(6), + child: child, + ), + visualDensity: const VisualDensity( + horizontal: VisualDensity.minimumDensity, + vertical: VisualDensity.minimumDensity, + ), + label: Text( + parameter.name, + style: textStyle, + ), + ); + } +} diff --git a/packages/neon/neon_talk/pubspec.yaml b/packages/neon/neon_talk/pubspec.yaml index 0b03799645f..cfdebabde05 100644 --- a/packages/neon/neon_talk/pubspec.yaml +++ b/packages/neon/neon_talk/pubspec.yaml @@ -8,10 +8,15 @@ environment: dependencies: built_collection: ^5.0.0 + file_icons: + git: + url: https://github.com/nextcloud/neon + path: packages/file_icons flutter: sdk: flutter flutter_localizations: sdk: flutter + flutter_material_design_icons: ^1.0.0 go_router: ^13.0.0 intersperse: ^2.0.0 intl: ^0.18.1 diff --git a/packages/neon/neon_talk/pubspec_overrides.yaml b/packages/neon/neon_talk/pubspec_overrides.yaml index 76e02e96ad7..7d69f8a4139 100644 --- a/packages/neon/neon_talk/pubspec_overrides.yaml +++ b/packages/neon/neon_talk/pubspec_overrides.yaml @@ -1,7 +1,9 @@ -# melos_managed_dependency_overrides: dynamite_runtime,neon_framework,neon_lints,nextcloud,sort_box +# melos_managed_dependency_overrides: dynamite_runtime,file_icons,neon_framework,neon_lints,nextcloud,sort_box dependency_overrides: dynamite_runtime: path: ../../dynamite/dynamite_runtime + file_icons: + path: ../../file_icons neon_framework: path: ../../neon_framework neon_lints: diff --git a/packages/neon/neon_talk/test/goldens/rich_object_deck_card.png b/packages/neon/neon_talk/test/goldens/rich_object_deck_card.png new file mode 100644 index 00000000000..a9d84dba157 Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_deck_card.png differ diff --git a/packages/neon/neon_talk/test/goldens/rich_object_fallback_with_icon.png b/packages/neon/neon_talk/test/goldens/rich_object_fallback_with_icon.png new file mode 100644 index 00000000000..40a7bb837ca Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_fallback_with_icon.png differ diff --git a/packages/neon/neon_talk/test/goldens/rich_object_fallback_without_icon.png b/packages/neon/neon_talk/test/goldens/rich_object_fallback_without_icon.png new file mode 100644 index 00000000000..b6115461d26 Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_fallback_without_icon.png differ diff --git a/packages/neon/neon_talk/test/goldens/rich_object_file_with_preview.png b/packages/neon/neon_talk/test/goldens/rich_object_file_with_preview.png new file mode 100644 index 00000000000..f2b6958447b Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_file_with_preview.png differ diff --git a/packages/neon/neon_talk/test/goldens/rich_object_file_without_preview.png b/packages/neon/neon_talk/test/goldens/rich_object_file_without_preview.png new file mode 100644 index 00000000000..d93d9562f72 Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_file_without_preview.png differ diff --git a/packages/neon/neon_talk/test/goldens/rich_object_mention_call.png b/packages/neon/neon_talk/test/goldens/rich_object_mention_call.png new file mode 100644 index 00000000000..a6a25550377 Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_mention_call.png differ diff --git a/packages/neon/neon_talk/test/goldens/rich_object_mention_group.png b/packages/neon/neon_talk/test/goldens/rich_object_mention_group.png new file mode 100644 index 00000000000..542ba53063b Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_mention_group.png differ diff --git a/packages/neon/neon_talk/test/goldens/rich_object_mention_guest.png b/packages/neon/neon_talk/test/goldens/rich_object_mention_guest.png new file mode 100644 index 00000000000..542ba53063b Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_mention_guest.png differ diff --git a/packages/neon/neon_talk/test/goldens/rich_object_mention_user-group.png b/packages/neon/neon_talk/test/goldens/rich_object_mention_user-group.png new file mode 100644 index 00000000000..542ba53063b Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_mention_user-group.png differ diff --git a/packages/neon/neon_talk/test/goldens/rich_object_mention_user.png b/packages/neon/neon_talk/test/goldens/rich_object_mention_user.png new file mode 100644 index 00000000000..a6a25550377 Binary files /dev/null and b/packages/neon/neon_talk/test/goldens/rich_object_mention_user.png differ diff --git a/packages/neon/neon_talk/test/message_test.dart b/packages/neon/neon_talk/test/message_test.dart index 5454167ed7c..140e4fd41ff 100644 --- a/packages/neon/neon_talk/test/message_test.dart +++ b/packages/neon/neon_talk/test/message_test.dart @@ -11,6 +11,10 @@ import 'package:neon_talk/l10n/localizations_en.dart'; import 'package:neon_talk/src/widgets/actor_avatar.dart'; import 'package:neon_talk/src/widgets/message.dart'; import 'package:neon_talk/src/widgets/reactions.dart'; +import 'package:neon_talk/src/widgets/rich_object/deck_card.dart'; +import 'package:neon_talk/src/widgets/rich_object/fallback.dart'; +import 'package:neon_talk/src/widgets/rich_object/file.dart'; +import 'package:neon_talk/src/widgets/rich_object/mention.dart'; import 'package:nextcloud/nextcloud.dart'; import 'package:nextcloud/spreed.dart' as spreed; import 'package:rxdart/rxdart.dart'; @@ -27,6 +31,8 @@ void main() { setUpAll(() { final storage = MockNeonStorage(); when(() => storage.requestCache).thenReturn(null); + + registerFallbackValue(Uri()); }); group('getActorDisplayName', () { @@ -54,6 +60,7 @@ void main() { when(() => chatMessage.actorId).thenReturn('test'); when(() => chatMessage.message).thenReturn('message'); when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -73,6 +80,7 @@ void main() { when(() => chatMessage.actorDisplayName).thenReturn('Test'); when(() => chatMessage.message).thenReturn('message'); when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -91,6 +99,7 @@ void main() { when(() => chatMessage.actorId).thenReturn('test'); when(() => chatMessage.message).thenReturn('message'); when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -109,6 +118,7 @@ void main() { when(() => chatMessage.actorId).thenReturn('test'); when(() => chatMessage.message).thenReturn('message'); when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -127,6 +137,7 @@ void main() { when(() => chatMessage.actorId).thenReturn('test'); when(() => chatMessage.message).thenReturn('message'); when(() => chatMessage.messageType).thenReturn(spreed.MessageType.system); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -145,6 +156,7 @@ void main() { when(() => chatMessage.actorId).thenReturn('test'); when(() => chatMessage.message).thenReturn('message\n123'); when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -165,6 +177,7 @@ void main() { when(() => chatMessage.messageType).thenReturn(spreed.MessageType.system); when(() => chatMessage.systemMessage).thenReturn(''); when(() => chatMessage.message).thenReturn(''); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -192,6 +205,7 @@ void main() { when(() => chatMessage.actorDisplayName).thenReturn(''); when(() => chatMessage.message).thenReturn(''); when(() => chatMessage.reactions).thenReturn(BuiltMap()); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -229,6 +243,7 @@ void main() { final chatMessage = MockChatMessage(); when(() => chatMessage.systemMessage).thenReturn(''); when(() => chatMessage.message).thenReturn('test'); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -250,6 +265,7 @@ void main() { final chatMessage = MockChatMessage(); when(() => chatMessage.systemMessage).thenReturn(''); when(() => chatMessage.message).thenReturn('test'); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -284,6 +300,7 @@ void main() { when(() => chatMessage.actorDisplayName).thenReturn('test'); when(() => chatMessage.message).thenReturn('abc'); when(() => chatMessage.reactions).thenReturn(BuiltMap()); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -321,6 +338,7 @@ void main() { when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); when(() => chatMessage.message).thenReturn('abc'); when(() => chatMessage.reactions).thenReturn(BuiltMap({'😀': 1, '😊': 23})); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -365,6 +383,7 @@ void main() { when(() => chatMessage.messageType).thenReturn(spreed.MessageType.commentDeleted); when(() => chatMessage.message).thenReturn('abc'); when(() => chatMessage.reactions).thenReturn(BuiltMap()); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -399,6 +418,7 @@ void main() { when(() => chatMessage.actorDisplayName).thenReturn('test'); when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); when(() => chatMessage.message).thenReturn('abc'); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -441,6 +461,7 @@ void main() { when(() => parentChatMessage.actorDisplayName).thenReturn('test'); when(() => parentChatMessage.messageType).thenReturn(spreed.MessageType.comment); when(() => parentChatMessage.message).thenReturn('abc'); + when(() => parentChatMessage.messageParameters).thenReturn(BuiltMap()); final chatMessage = MockChatMessageWithParent(); when(() => chatMessage.timestamp).thenReturn(0); @@ -451,6 +472,7 @@ void main() { when(() => chatMessage.message).thenReturn('abc'); when(() => chatMessage.reactions).thenReturn(BuiltMap()); when(() => chatMessage.parent).thenReturn(parentChatMessage); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -492,6 +514,7 @@ void main() { when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); when(() => chatMessage.message).thenReturn('abc'); when(() => chatMessage.reactions).thenReturn(BuiltMap({'😀': 1, '😊': 23})); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -536,6 +559,7 @@ void main() { when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); when(() => chatMessage.message).thenReturn('abc'); when(() => chatMessage.reactions).thenReturn(BuiltMap({'😀': 1, '😊': 23})); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -580,6 +604,7 @@ void main() { when(() => chatMessage.messageType).thenReturn(spreed.MessageType.comment); when(() => chatMessage.message).thenReturn('abc'); when(() => chatMessage.reactions).thenReturn(BuiltMap({'😀': 1, '😊': 23})); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); await tester.pumpWidget( wrapWidget( @@ -604,4 +629,204 @@ void main() { }); }); }); + + group('buildRichObjectParameter', () { + for (final isPreview in [true, false]) { + group(isPreview ? 'As preview' : 'Complete', () { + group('Mention', () { + for (final type in ['user', 'call', 'guest', 'user-group', 'group']) { + testWidgets(type, (tester) async { + final account = MockAccount(); + when(() => account.client).thenReturn(NextcloudClient(Uri())); + when(() => account.completeUri(any())) + .thenAnswer((invocation) => invocation.positionalArguments[0]! as Uri); + + final accountsBloc = MockAccountsBloc(); + when(() => accountsBloc.activeAccount).thenAnswer((_) => BehaviorSubject.seeded(account)); + + await tester.pumpWidget( + TestApp( + child: NeonProvider.value( + value: accountsBloc, + child: RichText( + text: buildRichObjectParameter( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = type + ..id = '' + ..name = 'name' + ..iconUrl = '', + ), + textStyle: null, + isPreview: isPreview, + ), + ), + ), + ), + ); + + expect(find.byType(TalkRichObjectMention), findsOne); + expect(find.text('name'), findsOne); + }); + } + }); + + testWidgets('File', (tester) async { + await tester.pumpWidget( + TestApp( + child: RichText( + text: buildRichObjectParameter( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = 'file' + ..id = '' + ..name = 'name', + ), + textStyle: null, + isPreview: isPreview, + ), + ), + ), + ); + + expect(find.byType(TalkRichObjectFile), isPreview ? findsNothing : findsOne); + expect(find.text('name'), findsOne); + }); + + testWidgets('Deck card', (tester) async { + await tester.pumpWidget( + TestApp( + child: RichText( + text: buildRichObjectParameter( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = 'deck-card' + ..id = '' + ..name = 'name' + ..boardname = 'boardname' + ..stackname = 'stackname', + ), + textStyle: null, + isPreview: isPreview, + ), + ), + ), + ); + + expect(find.byType(TalkRichObjectDeckCard), isPreview ? findsNothing : findsOne); + expect(find.text('name'), findsOne); + }); + + testWidgets('Fallback', (tester) async { + await tester.pumpWidget( + TestApp( + child: RichText( + text: buildRichObjectParameter( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = 'unknown' + ..id = '' + ..name = 'name', + ), + textStyle: null, + isPreview: isPreview, + ), + ), + ), + ); + + expect(find.byType(TalkRichObjectFallback), isPreview ? findsNothing : findsOne); + expect(find.text('name'), findsOne); + }); + }); + } + }); + + group('buildChatMessage', () { + test('Preview without newlines', () { + final chatMessage = MockChatMessage(); + when(() => chatMessage.message).thenReturn('123\n456'); + when(() => chatMessage.messageParameters).thenReturn(BuiltMap()); + + var span = buildChatMessage(chatMessage: chatMessage).children!.single as TextSpan; + expect(span.text, '123\n456'); + + span = buildChatMessage(chatMessage: chatMessage, isPreview: true).children!.single as TextSpan; + expect(span.text, '123 456'); + }); + + group('Unused parameters', () { + group('Discard', () { + for (final type in ['actor', 'user']) { + test(type, () { + final chatMessage = MockChatMessage(); + when(() => chatMessage.message).thenReturn('test'); + when(() => chatMessage.messageParameters).thenReturn( + BuiltMap({ + type: spreed.RichObjectParameter( + (b) => b + ..type = '' + ..id = '' + ..name = '', + ), + }), + ); + + final spans = buildChatMessage(chatMessage: chatMessage).children!; + expect((spans.single as TextSpan).text, 'test'); + }); + } + }); + + test('Display', () { + final chatMessage = MockChatMessage(); + when(() => chatMessage.message).thenReturn('test'); + when(() => chatMessage.messageParameters).thenReturn( + BuiltMap({ + 'file': spreed.RichObjectParameter( + (b) => b + ..type = 'file' + ..id = '' + ..name = '', + ), + }), + ); + + final spans = buildChatMessage(chatMessage: chatMessage).children!; + expect(spans, hasLength(3)); + expect((spans[0] as WidgetSpan).child, isA()); + expect((spans[1] as TextSpan).text, '\n'); + expect((spans[2] as TextSpan).text, 'test'); + }); + }); + + test('Used parameters', () { + final chatMessage = MockChatMessage(); + when(() => chatMessage.message).thenReturn('123 {actor1} 456 {actor2} 789'); + when(() => chatMessage.messageParameters).thenReturn( + BuiltMap({ + 'actor1': spreed.RichObjectParameter( + (b) => b + ..type = 'user' + ..id = '' + ..name = '', + ), + 'actor2': spreed.RichObjectParameter( + (b) => b + ..type = 'user' + ..id = '' + ..name = '', + ), + }), + ); + + final spans = buildChatMessage(chatMessage: chatMessage).children!; + expect(spans, hasLength(5)); + expect((spans[0] as TextSpan).text, '123 '); + expect((spans[1] as WidgetSpan).child, isA()); + expect((spans[2] as TextSpan).text, ' 456 '); + expect((spans[3] as WidgetSpan).child, isA()); + expect((spans[4] as TextSpan).text, ' 789'); + }); + }); } diff --git a/packages/neon/neon_talk/test/rich_object_test.dart b/packages/neon/neon_talk/test/rich_object_test.dart new file mode 100644 index 00000000000..3ec441dec27 --- /dev/null +++ b/packages/neon/neon_talk/test/rich_object_test.dart @@ -0,0 +1,281 @@ +import 'package:file_icons/file_icons.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:neon_framework/blocs.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:neon_talk/src/widgets/rich_object/deck_card.dart'; +import 'package:neon_talk/src/widgets/rich_object/fallback.dart'; +import 'package:neon_talk/src/widgets/rich_object/file.dart'; +import 'package:neon_talk/src/widgets/rich_object/mention.dart'; +import 'package:nextcloud/nextcloud.dart'; +import 'package:nextcloud/spreed.dart' as spreed; +import 'package:rxdart/rxdart.dart'; + +void main() { + setUpAll(() { + final storage = MockNeonStorage(); + when(() => storage.requestCache).thenReturn(null); + + registerFallbackValue(Uri()); + }); + + testWidgets('Deck card', (tester) async { + await tester.pumpWidget( + TestApp( + child: TalkRichObjectDeckCard( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = '' + ..id = '' + ..name = 'name' + ..boardname = 'boardname' + ..stackname = 'stackname', + ), + ), + ), + ); + expect(find.text('name'), findsOne); + expect(find.text('boardname: stackname'), findsOne); + await expectLater( + find.byType(TalkRichObjectDeckCard), + matchesGoldenFile('goldens/rich_object_deck_card.png'), + ); + }); + + group('Mention', () { + testWidgets('user', (tester) async { + final account = MockAccount(); + when(() => account.client).thenReturn(NextcloudClient(Uri())); + + final accountsBloc = MockAccountsBloc(); + when(() => accountsBloc.activeAccount).thenAnswer((_) => BehaviorSubject.seeded(account)); + + await tester.pumpWidget( + TestApp( + child: NeonProvider.value( + value: accountsBloc, + child: TalkRichObjectMention( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = 'user' + ..id = '' + ..name = 'name', + ), + textStyle: null, + ), + ), + ), + ); + expect(find.byType(NeonUserAvatar), findsOne); + expect(find.text('name'), findsOne); + await expectLater( + find.byType(TalkRichObjectMention), + matchesGoldenFile('goldens/rich_object_mention_user.png'), + ); + }); + + testWidgets('call', (tester) async { + final account = MockAccount(); + when(() => account.client).thenReturn(NextcloudClient(Uri())); + when(() => account.completeUri(any())).thenAnswer((invocation) => invocation.positionalArguments[0]! as Uri); + + final accountsBloc = MockAccountsBloc(); + when(() => accountsBloc.activeAccount).thenAnswer((_) => BehaviorSubject.seeded(account)); + + await tester.pumpWidget( + TestApp( + child: NeonProvider.value( + value: accountsBloc, + child: TalkRichObjectMention( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = 'call' + ..id = '' + ..name = 'name' + ..iconUrl = '', + ), + textStyle: null, + ), + ), + ), + ); + expect(find.byType(NeonUriImage), findsOne); + expect(find.text('name'), findsOne); + await expectLater( + find.byType(TalkRichObjectMention), + matchesGoldenFile('goldens/rich_object_mention_call.png'), + ); + }); + + testWidgets('guest', (tester) async { + await tester.pumpWidget( + TestApp( + child: TalkRichObjectMention( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = 'guest' + ..id = '' + ..name = 'name', + ), + textStyle: null, + ), + ), + ); + expect(find.byIcon(AdaptiveIcons.person), findsOne); + expect(find.text('name'), findsOne); + await expectLater( + find.byType(TalkRichObjectMention), + matchesGoldenFile('goldens/rich_object_mention_guest.png'), + ); + }); + + for (final type in ['user-group', 'group']) { + testWidgets(type, (tester) async { + await tester.pumpWidget( + TestApp( + child: TalkRichObjectMention( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = type + ..id = '' + ..name = 'name', + ), + textStyle: null, + ), + ), + ); + expect(find.byIcon(AdaptiveIcons.group), findsOne); + expect(find.text('name'), findsOne); + await expectLater( + find.byType(TalkRichObjectMention), + matchesGoldenFile('goldens/rich_object_mention_$type.png'), + ); + }); + } + }); + + group('File', () { + testWidgets('With preview', (tester) async { + final account = MockAccount(); + when(() => account.client).thenReturn( + NextcloudClient( + Uri(), + loginName: '', + password: '', + ), + ); + + final accountsBloc = MockAccountsBloc(); + when(() => accountsBloc.activeAccount).thenAnswer((_) => BehaviorSubject.seeded(account)); + + await tester.pumpWidget( + TestApp( + child: NeonProvider.value( + value: accountsBloc, + child: TalkRichObjectFile( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = '' + ..id = '0' + ..name = 'name' + ..previewAvailable = spreed.RichObjectParameter_PreviewAvailable.yes + ..path = '', + ), + textStyle: null, + ), + ), + ), + ); + expect(find.byType(NeonApiImage), findsOne); + expect(find.byTooltip('name'), findsOne); + await expectLater( + find.byType(TalkRichObjectFile), + matchesGoldenFile('goldens/rich_object_file_with_preview.png'), + ); + }); + + testWidgets('Without preview', (tester) async { + await tester.pumpWidget( + TestApp( + child: TalkRichObjectFile( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = '' + ..id = '0' + ..name = 'name' + ..previewAvailable = spreed.RichObjectParameter_PreviewAvailable.no + ..path = '', + ), + textStyle: null, + ), + ), + ); + expect(find.byType(FileIcon), findsOne); + expect(find.text('name'), findsOne); + await expectLater( + find.byType(TalkRichObjectFile), + matchesGoldenFile('goldens/rich_object_file_without_preview.png'), + ); + }); + }); + + group('Fallback', () { + testWidgets('Without icon', (tester) async { + await tester.pumpWidget( + TestApp( + child: TalkRichObjectFallback( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = '' + ..id = '' + ..name = 'name', + ), + textStyle: null, + ), + ), + ); + expect(find.byType(NeonUriImage), findsNothing); + expect(find.text('name'), findsOne); + await expectLater( + find.byType(TalkRichObjectFallback), + matchesGoldenFile('goldens/rich_object_fallback_without_icon.png'), + ); + }); + + testWidgets('With icon', (tester) async { + final account = MockAccount(); + when(() => account.client).thenReturn(NextcloudClient(Uri())); + when(() => account.completeUri(any())).thenAnswer((invocation) => invocation.positionalArguments[0]! as Uri); + + final accountsBloc = MockAccountsBloc(); + when(() => accountsBloc.activeAccount).thenAnswer((_) => BehaviorSubject.seeded(account)); + + await tester.pumpWidget( + TestApp( + child: NeonProvider.value( + value: accountsBloc, + child: TalkRichObjectFallback( + parameter: spreed.RichObjectParameter( + (b) => b + ..type = '' + ..id = '' + ..name = 'name' + ..iconUrl = '', + ), + textStyle: null, + ), + ), + ), + ); + expect(find.byType(NeonUriImage), findsOne); + expect(find.text('name'), findsOne); + await expectLater( + find.byType(TalkRichObjectFallback), + matchesGoldenFile('goldens/rich_object_fallback_with_icon.png'), + ); + }); + }); +} diff --git a/packages/neon/neon_talk/test/room_page_test.dart b/packages/neon/neon_talk/test/room_page_test.dart index 30bb150652c..46deb46df8a 100644 --- a/packages/neon/neon_talk/test/room_page_test.dart +++ b/packages/neon/neon_talk/test/room_page_test.dart @@ -100,6 +100,7 @@ void main() { when(() => chatMessage1.message).thenReturn('abc'); when(() => chatMessage1.reactions).thenReturn(BuiltMap()); when(() => chatMessage1.parent).thenReturn(null); + when(() => chatMessage1.messageParameters).thenReturn(BuiltMap()); final chatMessage2 = MockChatMessageWithParent(); when(() => chatMessage2.timestamp).thenReturn(0); @@ -110,6 +111,7 @@ void main() { when(() => chatMessage2.message).thenReturn('abc'); when(() => chatMessage2.reactions).thenReturn(BuiltMap()); when(() => chatMessage2.parent).thenReturn(null); + when(() => chatMessage2.messageParameters).thenReturn(BuiltMap()); when(() => bloc.messages).thenAnswer( (_) => BehaviorSubject.seeded( diff --git a/packages/nextcloud/lib/src/api/spreed.openapi.dart b/packages/nextcloud/lib/src/api/spreed.openapi.dart index 79578cc24e2..426feb66587 100644 --- a/packages/nextcloud/lib/src/api/spreed.openapi.dart +++ b/packages/nextcloud/lib/src/api/spreed.openapi.dart @@ -13960,6 +13960,328 @@ class _$ChatMessage_DeletedSerializer implements PrimitiveSerializer get values => _$richObjectParameterCallTypeValues; + // coverage:ignore-end + + /// Returns the enum value associated to the [name]. + static RichObjectParameter_CallType valueOf(String name) => _$valueOfRichObjectParameter_CallType(name); + + /// Returns the serialized value of this enum value. + String get value => _$jsonSerializers.serializeWith(serializer, this)! as String; + + /// Serializer for RichObjectParameter_CallType. + @BuiltValueSerializer(custom: true) + static Serializer get serializer => const _$RichObjectParameter_CallTypeSerializer(); +} + +class _$RichObjectParameter_CallTypeSerializer implements PrimitiveSerializer { + const _$RichObjectParameter_CallTypeSerializer(); + + static const Map _toWire = { + RichObjectParameter_CallType.one2one: 'one2one', + RichObjectParameter_CallType.group: 'group', + RichObjectParameter_CallType.public: 'public', + }; + + static const Map _fromWire = { + 'one2one': RichObjectParameter_CallType.one2one, + 'group': RichObjectParameter_CallType.group, + 'public': RichObjectParameter_CallType.public, + }; + + @override + Iterable get types => const [RichObjectParameter_CallType]; + + @override + String get wireName => 'RichObjectParameter_CallType'; + + @override + Object serialize( + Serializers serializers, + RichObjectParameter_CallType object, { + FullType specifiedType = FullType.unspecified, + }) => + _toWire[object]!; + + @override + RichObjectParameter_CallType deserialize( + Serializers serializers, + Object serialized, { + FullType specifiedType = FullType.unspecified, + }) => + _fromWire[serialized]!; +} + +class RichObjectParameter_PreviewAvailable extends EnumClass { + const RichObjectParameter_PreviewAvailable._(super.name); + + /// `yes` + static const RichObjectParameter_PreviewAvailable yes = _$richObjectParameterPreviewAvailableYes; + + /// `no` + static const RichObjectParameter_PreviewAvailable no = _$richObjectParameterPreviewAvailableNo; + + /// Returns a set with all values this enum contains. + // coverage:ignore-start + static BuiltSet get values => _$richObjectParameterPreviewAvailableValues; + // coverage:ignore-end + + /// Returns the enum value associated to the [name]. + static RichObjectParameter_PreviewAvailable valueOf(String name) => + _$valueOfRichObjectParameter_PreviewAvailable(name); + + /// Returns the serialized value of this enum value. + String get value => _$jsonSerializers.serializeWith(serializer, this)! as String; + + /// Serializer for RichObjectParameter_PreviewAvailable. + @BuiltValueSerializer(custom: true) + static Serializer get serializer => + const _$RichObjectParameter_PreviewAvailableSerializer(); +} + +class _$RichObjectParameter_PreviewAvailableSerializer + implements PrimitiveSerializer { + const _$RichObjectParameter_PreviewAvailableSerializer(); + + static const Map _toWire = + { + RichObjectParameter_PreviewAvailable.yes: 'yes', + RichObjectParameter_PreviewAvailable.no: 'no', + }; + + static const Map _fromWire = + { + 'yes': RichObjectParameter_PreviewAvailable.yes, + 'no': RichObjectParameter_PreviewAvailable.no, + }; + + @override + Iterable get types => const [RichObjectParameter_PreviewAvailable]; + + @override + String get wireName => 'RichObjectParameter_PreviewAvailable'; + + @override + Object serialize( + Serializers serializers, + RichObjectParameter_PreviewAvailable object, { + FullType specifiedType = FullType.unspecified, + }) => + _toWire[object]!; + + @override + RichObjectParameter_PreviewAvailable deserialize( + Serializers serializers, + Object serialized, { + FullType specifiedType = FullType.unspecified, + }) => + _fromWire[serialized]!; +} + +class RichObjectParameter_Visibility extends EnumClass { + const RichObjectParameter_Visibility._(super.name); + + /// `0` + @BuiltValueEnumConst(wireName: '0') + static const RichObjectParameter_Visibility $0 = _$richObjectParameterVisibility$0; + + /// `1` + @BuiltValueEnumConst(wireName: '1') + static const RichObjectParameter_Visibility $1 = _$richObjectParameterVisibility$1; + + /// Returns a set with all values this enum contains. + // coverage:ignore-start + static BuiltSet get values => _$richObjectParameterVisibilityValues; + // coverage:ignore-end + + /// Returns the enum value associated to the [name]. + static RichObjectParameter_Visibility valueOf(String name) => _$valueOfRichObjectParameter_Visibility(name); + + /// Returns the serialized value of this enum value. + String get value => _$jsonSerializers.serializeWith(serializer, this)! as String; + + /// Serializer for RichObjectParameter_Visibility. + @BuiltValueSerializer(custom: true) + static Serializer get serializer => + const _$RichObjectParameter_VisibilitySerializer(); +} + +class _$RichObjectParameter_VisibilitySerializer implements PrimitiveSerializer { + const _$RichObjectParameter_VisibilitySerializer(); + + static const Map _toWire = { + RichObjectParameter_Visibility.$0: '0', + RichObjectParameter_Visibility.$1: '1', + }; + + static const Map _fromWire = { + '0': RichObjectParameter_Visibility.$0, + '1': RichObjectParameter_Visibility.$1, + }; + + @override + Iterable get types => const [RichObjectParameter_Visibility]; + + @override + String get wireName => 'RichObjectParameter_Visibility'; + + @override + Object serialize( + Serializers serializers, + RichObjectParameter_Visibility object, { + FullType specifiedType = FullType.unspecified, + }) => + _toWire[object]!; + + @override + RichObjectParameter_Visibility deserialize( + Serializers serializers, + Object serialized, { + FullType specifiedType = FullType.unspecified, + }) => + _fromWire[serialized]!; +} + +class RichObjectParameter_Assignable extends EnumClass { + const RichObjectParameter_Assignable._(super.name); + + /// `0` + @BuiltValueEnumConst(wireName: '0') + static const RichObjectParameter_Assignable $0 = _$richObjectParameterAssignable$0; + + /// `1` + @BuiltValueEnumConst(wireName: '1') + static const RichObjectParameter_Assignable $1 = _$richObjectParameterAssignable$1; + + /// Returns a set with all values this enum contains. + // coverage:ignore-start + static BuiltSet get values => _$richObjectParameterAssignableValues; + // coverage:ignore-end + + /// Returns the enum value associated to the [name]. + static RichObjectParameter_Assignable valueOf(String name) => _$valueOfRichObjectParameter_Assignable(name); + + /// Returns the serialized value of this enum value. + String get value => _$jsonSerializers.serializeWith(serializer, this)! as String; + + /// Serializer for RichObjectParameter_Assignable. + @BuiltValueSerializer(custom: true) + static Serializer get serializer => + const _$RichObjectParameter_AssignableSerializer(); +} + +class _$RichObjectParameter_AssignableSerializer implements PrimitiveSerializer { + const _$RichObjectParameter_AssignableSerializer(); + + static const Map _toWire = { + RichObjectParameter_Assignable.$0: '0', + RichObjectParameter_Assignable.$1: '1', + }; + + static const Map _fromWire = { + '0': RichObjectParameter_Assignable.$0, + '1': RichObjectParameter_Assignable.$1, + }; + + @override + Iterable get types => const [RichObjectParameter_Assignable]; + + @override + String get wireName => 'RichObjectParameter_Assignable'; + + @override + Object serialize( + Serializers serializers, + RichObjectParameter_Assignable object, { + FullType specifiedType = FullType.unspecified, + }) => + _toWire[object]!; + + @override + RichObjectParameter_Assignable deserialize( + Serializers serializers, + Object serialized, { + FullType specifiedType = FullType.unspecified, + }) => + _fromWire[serialized]!; +} + +@BuiltValue(instantiable: false) +abstract interface class $RichObjectParameterInterface { + String get type; + String get id; + String get name; + String? get server; + String? get link; + @BuiltValueField(wireName: 'call-type') + RichObjectParameter_CallType? get callType; + @BuiltValueField(wireName: 'icon-url') + String? get iconUrl; + @BuiltValueField(wireName: 'message-id') + String? get messageId; + String? get boardname; + String? get stackname; + int? get size; + String? get path; + String? get mimetype; + @BuiltValueField(wireName: 'preview-available') + RichObjectParameter_PreviewAvailable? get previewAvailable; + String? get mtime; + String? get latitude; + String? get longitude; + String? get description; + String? get thumb; + String? get website; + RichObjectParameter_Visibility? get visibility; + RichObjectParameter_Assignable? get assignable; + String? get conversation; + String? get etag; + int? get width; + int? get height; +} + +abstract class RichObjectParameter + implements $RichObjectParameterInterface, Built { + /// Creates a new RichObjectParameter object using the builder pattern. + factory RichObjectParameter([void Function(RichObjectParameterBuilder)? b]) = _$RichObjectParameter; + + // coverage:ignore-start + const RichObjectParameter._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory RichObjectParameter.fromJson(Map json) => + _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for RichObjectParameter. + static Serializer get serializer => _$richObjectParameterSerializer; +} + class MessageType extends EnumClass { const MessageType._(super.name); @@ -14078,7 +14400,7 @@ abstract interface class $ChatMessageInterface { bool get isReplyable; bool? get markdown; String get message; - BuiltMap> get messageParameters; + BuiltMap get messageParameters; MessageType get messageType; BuiltMap get reactions; String get referenceId; @@ -39794,16 +40116,15 @@ final Serializers _$serializers = (Serializers().toBuilder() ..addBuilderFactory(const FullType(ChatMessage), ChatMessageBuilder.new) ..add(ChatMessage.serializer) ..add(ChatMessage_Deleted.serializer) + ..addBuilderFactory(const FullType(RichObjectParameter), RichObjectParameterBuilder.new) + ..add(RichObjectParameter.serializer) + ..add(RichObjectParameter_CallType.serializer) + ..add(RichObjectParameter_PreviewAvailable.serializer) + ..add(RichObjectParameter_Visibility.serializer) + ..add(RichObjectParameter_Assignable.serializer) ..addBuilderFactory( - const FullType(BuiltMap, [FullType(String), FullType(JsonObject)]), - MapBuilder.new, - ) - ..addBuilderFactory( - const FullType(BuiltMap, [ - FullType(String), - FullType(BuiltMap, [FullType(String), FullType(JsonObject)]), - ]), - MapBuilder>.new, + const FullType(BuiltMap, [FullType(String), FullType(RichObjectParameter)]), + MapBuilder.new, ) ..add(MessageType.serializer) ..addBuilderFactory(const FullType(BuiltMap, [FullType(String), FullType(int)]), MapBuilder.new) @@ -40367,6 +40688,10 @@ final Serializers _$serializers = (Serializers().toBuilder() HostedSignalingServerRequestTrialResponseApplicationJson_OcsBuilder.new, ) ..add(HostedSignalingServerRequestTrialResponseApplicationJson_Ocs.serializer) + ..addBuilderFactory( + const FullType(BuiltMap, [FullType(String), FullType(JsonObject)]), + MapBuilder.new, + ) ..add(HostedSignalingServerDeleteAccountApiVersion.serializer) ..addBuilderFactory( const FullType(HostedSignalingServerDeleteAccountResponseApplicationJson), diff --git a/packages/nextcloud/lib/src/api/spreed.openapi.g.dart b/packages/nextcloud/lib/src/api/spreed.openapi.g.dart index af28baa2609..dbc57b1e9ae 100644 --- a/packages/nextcloud/lib/src/api/spreed.openapi.g.dart +++ b/packages/nextcloud/lib/src/api/spreed.openapi.g.dart @@ -121,6 +121,92 @@ final BuiltSet _$chatMessageDeletedValues = _$chatMessageDeleted$true, ]); +const RichObjectParameter_CallType _$richObjectParameterCallTypeOne2one = RichObjectParameter_CallType._('one2one'); +const RichObjectParameter_CallType _$richObjectParameterCallTypeGroup = RichObjectParameter_CallType._('group'); +const RichObjectParameter_CallType _$richObjectParameterCallTypePublic = RichObjectParameter_CallType._('public'); + +RichObjectParameter_CallType _$valueOfRichObjectParameter_CallType(String name) { + switch (name) { + case 'one2one': + return _$richObjectParameterCallTypeOne2one; + case 'group': + return _$richObjectParameterCallTypeGroup; + case 'public': + return _$richObjectParameterCallTypePublic; + default: + throw ArgumentError(name); + } +} + +final BuiltSet _$richObjectParameterCallTypeValues = + BuiltSet(const [ + _$richObjectParameterCallTypeOne2one, + _$richObjectParameterCallTypeGroup, + _$richObjectParameterCallTypePublic, +]); + +const RichObjectParameter_PreviewAvailable _$richObjectParameterPreviewAvailableYes = + RichObjectParameter_PreviewAvailable._('yes'); +const RichObjectParameter_PreviewAvailable _$richObjectParameterPreviewAvailableNo = + RichObjectParameter_PreviewAvailable._('no'); + +RichObjectParameter_PreviewAvailable _$valueOfRichObjectParameter_PreviewAvailable(String name) { + switch (name) { + case 'yes': + return _$richObjectParameterPreviewAvailableYes; + case 'no': + return _$richObjectParameterPreviewAvailableNo; + default: + throw ArgumentError(name); + } +} + +final BuiltSet _$richObjectParameterPreviewAvailableValues = + BuiltSet(const [ + _$richObjectParameterPreviewAvailableYes, + _$richObjectParameterPreviewAvailableNo, +]); + +const RichObjectParameter_Visibility _$richObjectParameterVisibility$0 = RichObjectParameter_Visibility._('\$0'); +const RichObjectParameter_Visibility _$richObjectParameterVisibility$1 = RichObjectParameter_Visibility._('\$1'); + +RichObjectParameter_Visibility _$valueOfRichObjectParameter_Visibility(String name) { + switch (name) { + case '\$0': + return _$richObjectParameterVisibility$0; + case '\$1': + return _$richObjectParameterVisibility$1; + default: + throw ArgumentError(name); + } +} + +final BuiltSet _$richObjectParameterVisibilityValues = + BuiltSet(const [ + _$richObjectParameterVisibility$0, + _$richObjectParameterVisibility$1, +]); + +const RichObjectParameter_Assignable _$richObjectParameterAssignable$0 = RichObjectParameter_Assignable._('\$0'); +const RichObjectParameter_Assignable _$richObjectParameterAssignable$1 = RichObjectParameter_Assignable._('\$1'); + +RichObjectParameter_Assignable _$valueOfRichObjectParameter_Assignable(String name) { + switch (name) { + case '\$0': + return _$richObjectParameterAssignable$0; + case '\$1': + return _$richObjectParameterAssignable$1; + default: + throw ArgumentError(name); + } +} + +final BuiltSet _$richObjectParameterAssignableValues = + BuiltSet(const [ + _$richObjectParameterAssignable$0, + _$richObjectParameterAssignable$1, +]); + const MessageType _$messageTypeComment = MessageType._('comment'); const MessageType _$messageTypeSystem = MessageType._('system'); const MessageType _$messageTypeObjectShared = MessageType._('objectShared'); @@ -7289,6 +7375,7 @@ final BuiltSet _$signalingGetWelcomeMessag ]); Serializer _$oCSMetaSerializer = _$OCSMetaSerializer(); +Serializer _$richObjectParameterSerializer = _$RichObjectParameterSerializer(); Serializer _$chatMessageSerializer = _$ChatMessageSerializer(); Serializer _$roomSerializer = _$RoomSerializer(); Serializer _$avatarUploadAvatarResponseApplicationJsonOcsSerializer = @@ -7975,6 +8062,266 @@ class _$OCSMetaSerializer implements StructuredSerializer { } } +class _$RichObjectParameterSerializer implements StructuredSerializer { + @override + final Iterable types = const [RichObjectParameter, _$RichObjectParameter]; + @override + final String wireName = 'RichObjectParameter'; + + @override + Iterable serialize(Serializers serializers, RichObjectParameter object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'type', + serializers.serialize(object.type, specifiedType: const FullType(String)), + 'id', + serializers.serialize(object.id, specifiedType: const FullType(String)), + 'name', + serializers.serialize(object.name, specifiedType: const FullType(String)), + ]; + Object? value; + value = object.server; + if (value != null) { + result + ..add('server') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.link; + if (value != null) { + result + ..add('link') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.callType; + if (value != null) { + result + ..add('call-type') + ..add(serializers.serialize(value, specifiedType: const FullType(RichObjectParameter_CallType))); + } + value = object.iconUrl; + if (value != null) { + result + ..add('icon-url') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.messageId; + if (value != null) { + result + ..add('message-id') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.boardname; + if (value != null) { + result + ..add('boardname') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.stackname; + if (value != null) { + result + ..add('stackname') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.size; + if (value != null) { + result + ..add('size') + ..add(serializers.serialize(value, specifiedType: const FullType(int))); + } + value = object.path; + if (value != null) { + result + ..add('path') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.mimetype; + if (value != null) { + result + ..add('mimetype') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.previewAvailable; + if (value != null) { + result + ..add('preview-available') + ..add(serializers.serialize(value, specifiedType: const FullType(RichObjectParameter_PreviewAvailable))); + } + value = object.mtime; + if (value != null) { + result + ..add('mtime') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.latitude; + if (value != null) { + result + ..add('latitude') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.longitude; + if (value != null) { + result + ..add('longitude') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.description; + if (value != null) { + result + ..add('description') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.thumb; + if (value != null) { + result + ..add('thumb') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.website; + if (value != null) { + result + ..add('website') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.visibility; + if (value != null) { + result + ..add('visibility') + ..add(serializers.serialize(value, specifiedType: const FullType(RichObjectParameter_Visibility))); + } + value = object.assignable; + if (value != null) { + result + ..add('assignable') + ..add(serializers.serialize(value, specifiedType: const FullType(RichObjectParameter_Assignable))); + } + value = object.conversation; + if (value != null) { + result + ..add('conversation') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.etag; + if (value != null) { + result + ..add('etag') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.width; + if (value != null) { + result + ..add('width') + ..add(serializers.serialize(value, specifiedType: const FullType(int))); + } + value = object.height; + if (value != null) { + result + ..add('height') + ..add(serializers.serialize(value, specifiedType: const FullType(int))); + } + return result; + } + + @override + RichObjectParameter deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = RichObjectParameterBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'type': + result.type = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'id': + result.id = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'name': + result.name = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'server': + result.server = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'link': + result.link = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'call-type': + result.callType = serializers.deserialize(value, specifiedType: const FullType(RichObjectParameter_CallType)) + as RichObjectParameter_CallType?; + break; + case 'icon-url': + result.iconUrl = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'message-id': + result.messageId = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'boardname': + result.boardname = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'stackname': + result.stackname = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'size': + result.size = serializers.deserialize(value, specifiedType: const FullType(int)) as int?; + break; + case 'path': + result.path = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'mimetype': + result.mimetype = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'preview-available': + result.previewAvailable = + serializers.deserialize(value, specifiedType: const FullType(RichObjectParameter_PreviewAvailable)) + as RichObjectParameter_PreviewAvailable?; + break; + case 'mtime': + result.mtime = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'latitude': + result.latitude = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'longitude': + result.longitude = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'description': + result.description = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'thumb': + result.thumb = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'website': + result.website = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'visibility': + result.visibility = serializers.deserialize(value, + specifiedType: const FullType(RichObjectParameter_Visibility)) as RichObjectParameter_Visibility?; + break; + case 'assignable': + result.assignable = serializers.deserialize(value, + specifiedType: const FullType(RichObjectParameter_Assignable)) as RichObjectParameter_Assignable?; + break; + case 'conversation': + result.conversation = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'etag': + result.etag = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'width': + result.width = serializers.deserialize(value, specifiedType: const FullType(int)) as int?; + break; + case 'height': + result.height = serializers.deserialize(value, specifiedType: const FullType(int)) as int?; + break; + } + } + + return result.build(); + } +} + class _$ChatMessageSerializer implements StructuredSerializer { @override final Iterable types = const [ChatMessage, _$ChatMessage]; @@ -8001,10 +8348,7 @@ class _$ChatMessageSerializer implements StructuredSerializer { serializers.serialize(object.message, specifiedType: const FullType(String)), 'messageParameters', serializers.serialize(object.messageParameters, - specifiedType: const FullType(BuiltMap, [ - FullType(String), - FullType(BuiltMap, [FullType(String), FullType(JsonObject)]) - ])), + specifiedType: const FullType(BuiltMap, [FullType(String), FullType(RichObjectParameter)])), 'messageType', serializers.serialize(object.messageType, specifiedType: const FullType(MessageType)), 'reactions', @@ -8076,10 +8420,7 @@ class _$ChatMessageSerializer implements StructuredSerializer { break; case 'messageParameters': result.messageParameters.replace(serializers.deserialize(value, - specifiedType: const FullType(BuiltMap, [ - FullType(String), - FullType(BuiltMap, [FullType(String), FullType(JsonObject)]) - ]))!); + specifiedType: const FullType(BuiltMap, [FullType(String), FullType(RichObjectParameter)]))!); break; case 'messageType': result.messageType = @@ -11160,10 +11501,7 @@ class _$ChatMessageWithParentSerializer implements StructuredSerializer, $OCSMetaInterf } } +abstract mixin class $RichObjectParameterInterfaceBuilder { + void replace($RichObjectParameterInterface other); + void update(void Function($RichObjectParameterInterfaceBuilder) updates); + String? get type; + set type(String? type); + + String? get id; + set id(String? id); + + String? get name; + set name(String? name); + + String? get server; + set server(String? server); + + String? get link; + set link(String? link); + + RichObjectParameter_CallType? get callType; + set callType(RichObjectParameter_CallType? callType); + + String? get iconUrl; + set iconUrl(String? iconUrl); + + String? get messageId; + set messageId(String? messageId); + + String? get boardname; + set boardname(String? boardname); + + String? get stackname; + set stackname(String? stackname); + + int? get size; + set size(int? size); + + String? get path; + set path(String? path); + + String? get mimetype; + set mimetype(String? mimetype); + + RichObjectParameter_PreviewAvailable? get previewAvailable; + set previewAvailable(RichObjectParameter_PreviewAvailable? previewAvailable); + + String? get mtime; + set mtime(String? mtime); + + String? get latitude; + set latitude(String? latitude); + + String? get longitude; + set longitude(String? longitude); + + String? get description; + set description(String? description); + + String? get thumb; + set thumb(String? thumb); + + String? get website; + set website(String? website); + + RichObjectParameter_Visibility? get visibility; + set visibility(RichObjectParameter_Visibility? visibility); + + RichObjectParameter_Assignable? get assignable; + set assignable(RichObjectParameter_Assignable? assignable); + + String? get conversation; + set conversation(String? conversation); + + String? get etag; + set etag(String? etag); + + int? get width; + set width(int? width); + + int? get height; + set height(int? height); +} + +class _$RichObjectParameter extends RichObjectParameter { + @override + final String type; + @override + final String id; + @override + final String name; + @override + final String? server; + @override + final String? link; + @override + final RichObjectParameter_CallType? callType; + @override + final String? iconUrl; + @override + final String? messageId; + @override + final String? boardname; + @override + final String? stackname; + @override + final int? size; + @override + final String? path; + @override + final String? mimetype; + @override + final RichObjectParameter_PreviewAvailable? previewAvailable; + @override + final String? mtime; + @override + final String? latitude; + @override + final String? longitude; + @override + final String? description; + @override + final String? thumb; + @override + final String? website; + @override + final RichObjectParameter_Visibility? visibility; + @override + final RichObjectParameter_Assignable? assignable; + @override + final String? conversation; + @override + final String? etag; + @override + final int? width; + @override + final int? height; + + factory _$RichObjectParameter([void Function(RichObjectParameterBuilder)? updates]) => + (RichObjectParameterBuilder()..update(updates))._build(); + + _$RichObjectParameter._( + {required this.type, + required this.id, + required this.name, + this.server, + this.link, + this.callType, + this.iconUrl, + this.messageId, + this.boardname, + this.stackname, + this.size, + this.path, + this.mimetype, + this.previewAvailable, + this.mtime, + this.latitude, + this.longitude, + this.description, + this.thumb, + this.website, + this.visibility, + this.assignable, + this.conversation, + this.etag, + this.width, + this.height}) + : super._() { + BuiltValueNullFieldError.checkNotNull(type, r'RichObjectParameter', 'type'); + BuiltValueNullFieldError.checkNotNull(id, r'RichObjectParameter', 'id'); + BuiltValueNullFieldError.checkNotNull(name, r'RichObjectParameter', 'name'); + } + + @override + RichObjectParameter rebuild(void Function(RichObjectParameterBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + RichObjectParameterBuilder toBuilder() => RichObjectParameterBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is RichObjectParameter && + type == other.type && + id == other.id && + name == other.name && + server == other.server && + link == other.link && + callType == other.callType && + iconUrl == other.iconUrl && + messageId == other.messageId && + boardname == other.boardname && + stackname == other.stackname && + size == other.size && + path == other.path && + mimetype == other.mimetype && + previewAvailable == other.previewAvailable && + mtime == other.mtime && + latitude == other.latitude && + longitude == other.longitude && + description == other.description && + thumb == other.thumb && + website == other.website && + visibility == other.visibility && + assignable == other.assignable && + conversation == other.conversation && + etag == other.etag && + width == other.width && + height == other.height; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, type.hashCode); + _$hash = $jc(_$hash, id.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, server.hashCode); + _$hash = $jc(_$hash, link.hashCode); + _$hash = $jc(_$hash, callType.hashCode); + _$hash = $jc(_$hash, iconUrl.hashCode); + _$hash = $jc(_$hash, messageId.hashCode); + _$hash = $jc(_$hash, boardname.hashCode); + _$hash = $jc(_$hash, stackname.hashCode); + _$hash = $jc(_$hash, size.hashCode); + _$hash = $jc(_$hash, path.hashCode); + _$hash = $jc(_$hash, mimetype.hashCode); + _$hash = $jc(_$hash, previewAvailable.hashCode); + _$hash = $jc(_$hash, mtime.hashCode); + _$hash = $jc(_$hash, latitude.hashCode); + _$hash = $jc(_$hash, longitude.hashCode); + _$hash = $jc(_$hash, description.hashCode); + _$hash = $jc(_$hash, thumb.hashCode); + _$hash = $jc(_$hash, website.hashCode); + _$hash = $jc(_$hash, visibility.hashCode); + _$hash = $jc(_$hash, assignable.hashCode); + _$hash = $jc(_$hash, conversation.hashCode); + _$hash = $jc(_$hash, etag.hashCode); + _$hash = $jc(_$hash, width.hashCode); + _$hash = $jc(_$hash, height.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'RichObjectParameter') + ..add('type', type) + ..add('id', id) + ..add('name', name) + ..add('server', server) + ..add('link', link) + ..add('callType', callType) + ..add('iconUrl', iconUrl) + ..add('messageId', messageId) + ..add('boardname', boardname) + ..add('stackname', stackname) + ..add('size', size) + ..add('path', path) + ..add('mimetype', mimetype) + ..add('previewAvailable', previewAvailable) + ..add('mtime', mtime) + ..add('latitude', latitude) + ..add('longitude', longitude) + ..add('description', description) + ..add('thumb', thumb) + ..add('website', website) + ..add('visibility', visibility) + ..add('assignable', assignable) + ..add('conversation', conversation) + ..add('etag', etag) + ..add('width', width) + ..add('height', height)) + .toString(); + } +} + +class RichObjectParameterBuilder + implements Builder, $RichObjectParameterInterfaceBuilder { + _$RichObjectParameter? _$v; + + String? _type; + String? get type => _$this._type; + set type(covariant String? type) => _$this._type = type; + + String? _id; + String? get id => _$this._id; + set id(covariant String? id) => _$this._id = id; + + String? _name; + String? get name => _$this._name; + set name(covariant String? name) => _$this._name = name; + + String? _server; + String? get server => _$this._server; + set server(covariant String? server) => _$this._server = server; + + String? _link; + String? get link => _$this._link; + set link(covariant String? link) => _$this._link = link; + + RichObjectParameter_CallType? _callType; + RichObjectParameter_CallType? get callType => _$this._callType; + set callType(covariant RichObjectParameter_CallType? callType) => _$this._callType = callType; + + String? _iconUrl; + String? get iconUrl => _$this._iconUrl; + set iconUrl(covariant String? iconUrl) => _$this._iconUrl = iconUrl; + + String? _messageId; + String? get messageId => _$this._messageId; + set messageId(covariant String? messageId) => _$this._messageId = messageId; + + String? _boardname; + String? get boardname => _$this._boardname; + set boardname(covariant String? boardname) => _$this._boardname = boardname; + + String? _stackname; + String? get stackname => _$this._stackname; + set stackname(covariant String? stackname) => _$this._stackname = stackname; + + int? _size; + int? get size => _$this._size; + set size(covariant int? size) => _$this._size = size; + + String? _path; + String? get path => _$this._path; + set path(covariant String? path) => _$this._path = path; + + String? _mimetype; + String? get mimetype => _$this._mimetype; + set mimetype(covariant String? mimetype) => _$this._mimetype = mimetype; + + RichObjectParameter_PreviewAvailable? _previewAvailable; + RichObjectParameter_PreviewAvailable? get previewAvailable => _$this._previewAvailable; + set previewAvailable(covariant RichObjectParameter_PreviewAvailable? previewAvailable) => + _$this._previewAvailable = previewAvailable; + + String? _mtime; + String? get mtime => _$this._mtime; + set mtime(covariant String? mtime) => _$this._mtime = mtime; + + String? _latitude; + String? get latitude => _$this._latitude; + set latitude(covariant String? latitude) => _$this._latitude = latitude; + + String? _longitude; + String? get longitude => _$this._longitude; + set longitude(covariant String? longitude) => _$this._longitude = longitude; + + String? _description; + String? get description => _$this._description; + set description(covariant String? description) => _$this._description = description; + + String? _thumb; + String? get thumb => _$this._thumb; + set thumb(covariant String? thumb) => _$this._thumb = thumb; + + String? _website; + String? get website => _$this._website; + set website(covariant String? website) => _$this._website = website; + + RichObjectParameter_Visibility? _visibility; + RichObjectParameter_Visibility? get visibility => _$this._visibility; + set visibility(covariant RichObjectParameter_Visibility? visibility) => _$this._visibility = visibility; + + RichObjectParameter_Assignable? _assignable; + RichObjectParameter_Assignable? get assignable => _$this._assignable; + set assignable(covariant RichObjectParameter_Assignable? assignable) => _$this._assignable = assignable; + + String? _conversation; + String? get conversation => _$this._conversation; + set conversation(covariant String? conversation) => _$this._conversation = conversation; + + String? _etag; + String? get etag => _$this._etag; + set etag(covariant String? etag) => _$this._etag = etag; + + int? _width; + int? get width => _$this._width; + set width(covariant int? width) => _$this._width = width; + + int? _height; + int? get height => _$this._height; + set height(covariant int? height) => _$this._height = height; + + RichObjectParameterBuilder(); + + RichObjectParameterBuilder get _$this { + final $v = _$v; + if ($v != null) { + _type = $v.type; + _id = $v.id; + _name = $v.name; + _server = $v.server; + _link = $v.link; + _callType = $v.callType; + _iconUrl = $v.iconUrl; + _messageId = $v.messageId; + _boardname = $v.boardname; + _stackname = $v.stackname; + _size = $v.size; + _path = $v.path; + _mimetype = $v.mimetype; + _previewAvailable = $v.previewAvailable; + _mtime = $v.mtime; + _latitude = $v.latitude; + _longitude = $v.longitude; + _description = $v.description; + _thumb = $v.thumb; + _website = $v.website; + _visibility = $v.visibility; + _assignable = $v.assignable; + _conversation = $v.conversation; + _etag = $v.etag; + _width = $v.width; + _height = $v.height; + _$v = null; + } + return this; + } + + @override + void replace(covariant RichObjectParameter other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$RichObjectParameter; + } + + @override + void update(void Function(RichObjectParameterBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + RichObjectParameter build() => _build(); + + _$RichObjectParameter _build() { + final _$result = _$v ?? + _$RichObjectParameter._( + type: BuiltValueNullFieldError.checkNotNull(type, r'RichObjectParameter', 'type'), + id: BuiltValueNullFieldError.checkNotNull(id, r'RichObjectParameter', 'id'), + name: BuiltValueNullFieldError.checkNotNull(name, r'RichObjectParameter', 'name'), + server: server, + link: link, + callType: callType, + iconUrl: iconUrl, + messageId: messageId, + boardname: boardname, + stackname: stackname, + size: size, + path: path, + mimetype: mimetype, + previewAvailable: previewAvailable, + mtime: mtime, + latitude: latitude, + longitude: longitude, + description: description, + thumb: thumb, + website: website, + visibility: visibility, + assignable: assignable, + conversation: conversation, + etag: etag, + width: width, + height: height); + replace(_$result); + return _$result; + } +} + abstract mixin class $ChatMessageInterfaceBuilder { void replace($ChatMessageInterface other); void update(void Function($ChatMessageInterfaceBuilder) updates); @@ -21765,8 +22570,8 @@ abstract mixin class $ChatMessageInterfaceBuilder { String? get message; set message(String? message); - MapBuilder> get messageParameters; - set messageParameters(MapBuilder>? messageParameters); + MapBuilder get messageParameters; + set messageParameters(MapBuilder? messageParameters); MessageType? get messageType; set messageType(MessageType? messageType); @@ -21807,7 +22612,7 @@ class _$ChatMessage extends ChatMessage { @override final String message; @override - final BuiltMap> messageParameters; + final BuiltMap messageParameters; @override final MessageType messageType; @override @@ -21971,10 +22776,10 @@ class ChatMessageBuilder implements Builder, $C String? get message => _$this._message; set message(covariant String? message) => _$this._message = message; - MapBuilder>? _messageParameters; - MapBuilder> get messageParameters => - _$this._messageParameters ??= MapBuilder>(); - set messageParameters(covariant MapBuilder>? messageParameters) => + MapBuilder? _messageParameters; + MapBuilder get messageParameters => + _$this._messageParameters ??= MapBuilder(); + set messageParameters(covariant MapBuilder? messageParameters) => _$this._messageParameters = messageParameters; MessageType? _messageType; @@ -29662,8 +30467,8 @@ abstract mixin class $ChatMessageWithParentInterfaceBuilder implements $ChatMess String? get message; set message(covariant String? message); - MapBuilder> get messageParameters; - set messageParameters(covariant MapBuilder>? messageParameters); + MapBuilder get messageParameters; + set messageParameters(covariant MapBuilder? messageParameters); MessageType? get messageType; set messageType(covariant MessageType? messageType); @@ -29706,7 +30511,7 @@ class _$ChatMessageWithParent extends ChatMessageWithParent { @override final String message; @override - final BuiltMap> messageParameters; + final BuiltMap messageParameters; @override final MessageType messageType; @override @@ -29880,10 +30685,10 @@ class ChatMessageWithParentBuilder String? get message => _$this._message; set message(covariant String? message) => _$this._message = message; - MapBuilder>? _messageParameters; - MapBuilder> get messageParameters => - _$this._messageParameters ??= MapBuilder>(); - set messageParameters(covariant MapBuilder>? messageParameters) => + MapBuilder? _messageParameters; + MapBuilder get messageParameters => + _$this._messageParameters ??= MapBuilder(); + set messageParameters(covariant MapBuilder? messageParameters) => _$this._messageParameters = messageParameters; MessageType? _messageType; diff --git a/packages/nextcloud/lib/src/api/spreed.openapi.json b/packages/nextcloud/lib/src/api/spreed.openapi.json index 1a36a3c5042..0f15cc72698 100644 --- a/packages/nextcloud/lib/src/api/spreed.openapi.json +++ b/packages/nextcloud/lib/src/api/spreed.openapi.json @@ -232,10 +232,7 @@ "messageParameters": { "type": "object", "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "object" - } + "$ref": "#/components/schemas/RichObjectParameter" } }, "messageType": { @@ -1244,6 +1241,111 @@ "federated_users", "phones" ] + }, + "RichObjectParameter": { + "type": "object", + "required": [ + "type", + "id", + "name" + ], + "properties": { + "type": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "server": { + "type": "string" + }, + "link": { + "type": "string" + }, + "call-type": { + "type": "string", + "enum": [ + "one2one", + "group", + "public" + ] + }, + "icon-url": { + "type": "string" + }, + "message-id": { + "type": "string" + }, + "boardname": { + "type": "string" + }, + "stackname": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "path": { + "type": "string" + }, + "mimetype": { + "type": "string" + }, + "preview-available": { + "type": "string", + "enum": [ + "yes", + "no" + ] + }, + "mtime": { + "type": "string" + }, + "latitude": { + "type": "string" + }, + "longitude": { + "type": "string" + }, + "description": { + "type": "string" + }, + "thumb": { + "type": "string" + }, + "website": { + "type": "string" + }, + "visibility": { + "type": "string", + "enum": [ + "0", + "1" + ] + }, + "assignable": { + "type": "string", + "enum": [ + "0", + "1" + ] + }, + "conversation": { + "type": "string" + }, + "etag": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + } + } } } }, diff --git a/packages/nextcloud/lib/src/patches/spreed/3-message-parameters.json b/packages/nextcloud/lib/src/patches/spreed/3-message-parameters.json new file mode 100644 index 00000000000..03a19e84dc6 --- /dev/null +++ b/packages/nextcloud/lib/src/patches/spreed/3-message-parameters.json @@ -0,0 +1,118 @@ +[ + { + "op": "add", + "path": "/components/schemas/RichObjectParameter", + "value": { + "type": "object", + "required": [ + "type", + "id", + "name" + ], + "properties": { + "type": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "server": { + "type": "string" + }, + "link": { + "type": "string" + }, + "call-type": { + "type": "string", + "enum": [ + "one2one", + "group", + "public" + ] + }, + "icon-url": { + "type": "string" + }, + "message-id": { + "type": "string" + }, + "boardname": { + "type": "string" + }, + "stackname": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "path": { + "type": "string" + }, + "mimetype": { + "type": "string" + }, + "preview-available": { + "type": "string", + "enum": [ + "yes", + "no" + ] + }, + "mtime": { + "type": "string" + }, + "latitude": { + "type": "string" + }, + "longitude": { + "type": "string" + }, + "description": { + "type": "string" + }, + "thumb": { + "type": "string" + }, + "website": { + "type": "string" + }, + "visibility": { + "type": "string", + "enum": [ + "0", + "1" + ] + }, + "assignable": { + "type": "string", + "enum": [ + "0", + "1" + ] + }, + "conversation": { + "type": "string" + }, + "etag": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + } + } + } + }, + { + "op": "replace", + "path": "/components/schemas/ChatMessage/properties/messageParameters/additionalProperties", + "value": { + "$ref": "#/components/schemas/RichObjectParameter" + } + } +]