diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml index 6ad2e2b..6a4da8f 100644 --- a/.idea/libraries/Dart_Packages.xml +++ b/.idea/libraries/Dart_Packages.xml @@ -5,14 +5,14 @@ - - @@ -47,14 +47,14 @@ - - @@ -103,7 +103,7 @@ - @@ -124,21 +124,21 @@ - - - @@ -152,7 +152,7 @@ - @@ -208,7 +208,7 @@ - @@ -229,7 +229,7 @@ - @@ -257,7 +257,7 @@ - @@ -268,17 +268,10 @@ - - - - - - - @@ -306,7 +299,7 @@ - @@ -334,7 +327,7 @@ - @@ -425,7 +418,7 @@ - @@ -446,7 +439,7 @@ - @@ -474,7 +467,7 @@ - @@ -495,14 +488,14 @@ - - @@ -544,21 +537,21 @@ - - - @@ -628,7 +621,7 @@ - @@ -642,7 +635,7 @@ - @@ -663,7 +656,7 @@ - @@ -705,7 +698,7 @@ - @@ -761,7 +754,7 @@ - @@ -775,7 +768,7 @@ - @@ -887,49 +880,49 @@ - - - - - - - @@ -964,14 +957,14 @@ - - @@ -992,7 +985,7 @@ - @@ -1027,63 +1020,63 @@ - - - - - - - - - @@ -1111,7 +1104,7 @@ - @@ -1132,7 +1125,7 @@ - @@ -1146,7 +1139,7 @@ - @@ -1174,14 +1167,14 @@ - - @@ -1266,30 +1259,30 @@ - - - - + + + + - - + + - + - - - + + + - + @@ -1297,24 +1290,23 @@ - + - + - + - - + - + @@ -1325,23 +1317,23 @@ - + - + - + - - + + - - - + + + @@ -1351,12 +1343,12 @@ - + - + - + @@ -1369,9 +1361,9 @@ - + - + @@ -1387,48 +1379,48 @@ - - - - - - - + + + + + + + - - + + - + - - - - - - - - - + + + + + + + + + - + - + - + - - + + diff --git a/.idea/libraries/Flutter_Plugins.xml b/.idea/libraries/Flutter_Plugins.xml index 960b61a..a5c2842 100644 --- a/.idea/libraries/Flutter_Plugins.xml +++ b/.idea/libraries/Flutter_Plugins.xml @@ -13,29 +13,29 @@ - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - diff --git a/lib/api/marianumcloud/talk/getReactions/getReactions.dart b/lib/api/marianumcloud/talk/getReactions/getReactions.dart new file mode 100644 index 0000000..815f910 --- /dev/null +++ b/lib/api/marianumcloud/talk/getReactions/getReactions.dart @@ -0,0 +1,27 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:http/http.dart' as http; +import 'package:http/http.dart'; + +import '../../../apiParams.dart'; +import '../talkApi.dart'; +import 'getReactionsResponse.dart'; + +class GetReactions extends TalkApi { + String chatToken; + int messageId; + GetReactions({required this.chatToken, required this.messageId}) : super("v1/reaction/$chatToken/$messageId", null); + + @override + assemble(String raw) { + log(raw); + return GetReactionsResponse.fromJson(jsonDecode(raw)['ocs']); + } + + @override + Future? request(Uri uri, ApiParams? body, Map? headers) { + return http.get(uri, headers: headers); + } + +} \ No newline at end of file diff --git a/lib/api/marianumcloud/talk/getReactions/getReactionsResponse.dart b/lib/api/marianumcloud/talk/getReactions/getReactionsResponse.dart new file mode 100644 index 0000000..f316a13 --- /dev/null +++ b/lib/api/marianumcloud/talk/getReactions/getReactionsResponse.dart @@ -0,0 +1,31 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'getReactionsResponse.g.dart'; + +@JsonSerializable(explicitToJson: true) +class GetReactionsResponse { + Map> data; + + GetReactionsResponse(this.data); + + factory GetReactionsResponse.fromJson(Map json) => _$GetReactionsResponseFromJson(json); + Map toJson() => _$GetReactionsResponseToJson(this); +} + +@JsonSerializable() +class GetReactionsResponseObject { + GetReactionsResponseObjectActorType actorType; + String actorId; + String actorDisplayName; + int timestamp; + + GetReactionsResponseObject(this.actorType, this.actorId, this.actorDisplayName, this.timestamp); + + factory GetReactionsResponseObject.fromJson(Map json) => _$GetReactionsResponseObjectFromJson(json); + Map toJson() => _$GetReactionsResponseObjectToJson(this); +} + +enum GetReactionsResponseObjectActorType { + @JsonValue("guests") guests, + @JsonValue("users") users, +} \ No newline at end of file diff --git a/lib/api/marianumcloud/talk/getReactions/getReactionsResponse.g.dart b/lib/api/marianumcloud/talk/getReactions/getReactionsResponse.g.dart new file mode 100644 index 0000000..0a122e2 --- /dev/null +++ b/lib/api/marianumcloud/talk/getReactions/getReactionsResponse.g.dart @@ -0,0 +1,52 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'getReactionsResponse.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +GetReactionsResponse _$GetReactionsResponseFromJson( + Map json) => + GetReactionsResponse( + (json['data'] as Map).map( + (k, e) => MapEntry( + k, + (e as List) + .map((e) => GetReactionsResponseObject.fromJson( + e as Map)) + .toList()), + ), + ); + +Map _$GetReactionsResponseToJson( + GetReactionsResponse instance) => + { + 'data': instance.data + .map((k, e) => MapEntry(k, e.map((e) => e.toJson()).toList())), + }; + +GetReactionsResponseObject _$GetReactionsResponseObjectFromJson( + Map json) => + GetReactionsResponseObject( + $enumDecode( + _$GetReactionsResponseObjectActorTypeEnumMap, json['actorType']), + json['actorId'] as String, + json['actorDisplayName'] as String, + json['timestamp'] as int, + ); + +Map _$GetReactionsResponseObjectToJson( + GetReactionsResponseObject instance) => + { + 'actorType': + _$GetReactionsResponseObjectActorTypeEnumMap[instance.actorType]!, + 'actorId': instance.actorId, + 'actorDisplayName': instance.actorDisplayName, + 'timestamp': instance.timestamp, + }; + +const _$GetReactionsResponseObjectActorTypeEnumMap = { + GetReactionsResponseObjectActorType.guests: 'guests', + GetReactionsResponseObjectActorType.users: 'users', +}; diff --git a/lib/api/marianumcloud/talk/room/getRoomResponse.g.dart b/lib/api/marianumcloud/talk/room/getRoomResponse.g.dart index cc44798..7e2243b 100644 --- a/lib/api/marianumcloud/talk/room/getRoomResponse.g.dart +++ b/lib/api/marianumcloud/talk/room/getRoomResponse.g.dart @@ -53,7 +53,7 @@ GetRoomResponseObject _$GetRoomResponseObjectFromJson( json['status'] as String?, json['statusIcon'] as String?, json['statusMessage'] as String?, - ); + )..sort = json['sort'] as String?; Map _$GetRoomResponseObjectToJson( GetRoomResponseObject instance) => @@ -90,6 +90,7 @@ Map _$GetRoomResponseObjectToJson( 'status': instance.status, 'statusIcon': instance.statusIcon, 'statusMessage': instance.statusMessage, + 'sort': instance.sort, }; const _$GetRoomResponseObjectConversationTypeEnumMap = { diff --git a/lib/view/pages/talk/chatBubble.dart b/lib/view/pages/talk/chatBubble.dart index 9d4ef04..ba7a61e 100644 --- a/lib/view/pages/talk/chatBubble.dart +++ b/lib/view/pages/talk/chatBubble.dart @@ -18,6 +18,7 @@ import '../../../theming/appTheme.dart'; import '../../../widget/debug/debugTile.dart'; import '../files/fileElement.dart'; import 'chatMessage.dart'; +import 'messageReactions.dart'; class ChatBubble extends StatefulWidget { final BuildContext context; @@ -199,6 +200,20 @@ class _ChatBubbleState extends State { ), ], ), + const Divider(), + Visibility( + visible: true, + child: ListTile( + leading: const Icon(Icons.add_reaction_outlined), + title: const Text("Reaktionen"), + onTap: () { + Navigator.of(context).push(MaterialPageRoute(builder: (context) => MessageReactions( + token: widget.chatData.token, + messageId: widget.bubbleData.id, + ))); + }, + ), + ), Visibility( visible: !message.containsFile && widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment, child: ListTile( diff --git a/lib/view/pages/talk/messageReactions.dart b/lib/view/pages/talk/messageReactions.dart new file mode 100644 index 0000000..c1bbd7b --- /dev/null +++ b/lib/view/pages/talk/messageReactions.dart @@ -0,0 +1,73 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; + +import '../../../api/marianumcloud/talk/getReactions/getReactions.dart'; +import '../../../api/marianumcloud/talk/getReactions/getReactionsResponse.dart'; +import '../../../model/accountData.dart'; +import '../../../widget/centeredLeading.dart'; +import '../../../widget/loadingSpinner.dart'; +import '../../../widget/unimplementedDialog.dart'; + +class MessageReactions extends StatefulWidget { + final String token; + final int messageId; + const MessageReactions({super.key, required this.token, required this.messageId}); + + @override + State createState() => _MessageReactionsState(); +} + +class _MessageReactionsState extends State { + late Future data; + + @override + void initState() { + super.initState(); + data = GetReactions(chatToken: widget.token, messageId: widget.messageId).run(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("Reaktionen"), + ), + body: FutureBuilder( + future: data, + builder: (context, snapshot) { + if(snapshot.data == null) return const LoadingSpinner(); + log(snapshot.data!.toJson().toString()); + return ListView( + children: [ + ...snapshot.data!.data.entries.map((entry) { + return ExpansionTile( + textColor: Theme.of(context).colorScheme.onSurface, + collapsedTextColor: Theme.of(context).colorScheme.onSurface, + iconColor: Theme.of(context).colorScheme.onSurface, + collapsedIconColor: Theme.of(context).colorScheme.onSurface, + + subtitle: const Text("Tippe für mehr"), + leading: Text(entry.key), + title: Text("${entry.value.length} mal reagiert"), + children: entry.value.map((e) { + bool isSelf = AccountData().getUsername() == e.actorId; + return ListTile( + leading: const CenteredLeading(Icon(Icons.person)), + title: Text(e.actorDisplayName), + subtitle: isSelf ? const Text("Du") : e.actorType == GetReactionsResponseObjectActorType.guests ? const Text("Gast") : null, + trailing: isSelf ? null : IconButton( + onPressed: () => UnimplementedDialog.show(context), + icon: const Icon(Icons.textsms_outlined), + ), + ); + }).toList(), + ); + }).toList() + ], + ); + }, + ), + ); + } +}