Added Chat context menu for chat 'mark as read', 'mark as unread', 'add to favorites', 'remove from favorites', 'leave conversation'
added Chat favorite badge and mark chat as read when entering it
This commit is contained in:
parent
16c251e4b1
commit
4ef21a362b
19
lib/api/marianumcloud/talk/leaveRoom/leaveRoom.dart
Normal file
19
lib/api/marianumcloud/talk/leaveRoom/leaveRoom.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
|
||||||
|
import '../talkApi.dart';
|
||||||
|
class LeaveRoom extends TalkApi<void> {
|
||||||
|
String chatToken;
|
||||||
|
|
||||||
|
LeaveRoom(this.chatToken) : super("v4/room/$chatToken/participants/self", null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
assemble(String raw) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response> request(Uri uri, Object? body, Map<String, String>? headers) {
|
||||||
|
return http.delete(uri, headers: headers);
|
||||||
|
}
|
||||||
|
}
|
27
lib/api/marianumcloud/talk/setFavorite/setFavorite.dart
Normal file
27
lib/api/marianumcloud/talk/setFavorite/setFavorite.dart
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
|
||||||
|
import '../talkApi.dart';
|
||||||
|
|
||||||
|
class SetFavorite extends TalkApi<void> {
|
||||||
|
String chatToken;
|
||||||
|
bool favoriteState;
|
||||||
|
|
||||||
|
SetFavorite(this.chatToken, this.favoriteState) : super("v4/room/$chatToken/favorite", null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
assemble(String raw) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response> request(Uri uri, Object? body, Map<String, String>? headers) {
|
||||||
|
if(favoriteState) {
|
||||||
|
return http.post(uri, headers: headers);
|
||||||
|
} else {
|
||||||
|
return http.delete(uri, headers: headers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
lib/api/marianumcloud/talk/setReadMarker/setReadMarker.dart
Normal file
32
lib/api/marianumcloud/talk/setReadMarker/setReadMarker.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:marianum_mobile/api/marianumcloud/talk/setReadMarker/setReadMarkerParams.dart';
|
||||||
|
|
||||||
|
import '../talkApi.dart';
|
||||||
|
|
||||||
|
class SetReadMarker extends TalkApi<void> {
|
||||||
|
String chatToken;
|
||||||
|
bool readState;
|
||||||
|
SetReadMarkerParams? setReadMarkerParams;
|
||||||
|
|
||||||
|
SetReadMarker(this.chatToken, this.readState, {this.setReadMarkerParams}) : super("v1/chat/$chatToken/read", null, getParameters: setReadMarkerParams?.toJson()) {
|
||||||
|
if(readState) assert(setReadMarkerParams?.lastReadMessage != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
assemble(String raw) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response> request(Uri uri, Object? body, Map<String, String>? headers) {
|
||||||
|
if(readState) {
|
||||||
|
|
||||||
|
return http.post(uri, headers: headers);
|
||||||
|
} else {
|
||||||
|
return http.delete(uri, headers: headers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
import 'package:marianum_mobile/api/apiParams.dart';
|
||||||
|
|
||||||
|
part 'setReadMarkerParams.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class SetReadMarkerParams extends ApiParams {
|
||||||
|
int? lastReadMessage;
|
||||||
|
|
||||||
|
SetReadMarkerParams({
|
||||||
|
this.lastReadMessage
|
||||||
|
});
|
||||||
|
|
||||||
|
factory SetReadMarkerParams.fromJson(Map<String, dynamic> json) => _$SetReadMarkerParamsFromJson(json);
|
||||||
|
Map<String, dynamic> toJson() => _$SetReadMarkerParamsToJson(this);
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'setReadMarkerParams.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
SetReadMarkerParams _$SetReadMarkerParamsFromJson(Map<String, dynamic> json) =>
|
||||||
|
SetReadMarkerParams(
|
||||||
|
lastReadMessage: json['lastReadMessage'] as int?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SetReadMarkerParamsToJson(
|
||||||
|
SetReadMarkerParams instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'lastReadMessage': instance.lastReadMessage,
|
||||||
|
};
|
@ -2,13 +2,18 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:jiffy/jiffy.dart';
|
import 'package:jiffy/jiffy.dart';
|
||||||
|
import 'package:marianum_mobile/api/marianumcloud/talk/leaveRoom/leaveRoom.dart';
|
||||||
|
import 'package:marianum_mobile/api/marianumcloud/talk/setReadMarker/setReadMarker.dart';
|
||||||
|
import 'package:marianum_mobile/api/marianumcloud/talk/setReadMarker/setReadMarkerParams.dart';
|
||||||
import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart';
|
import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
import '../../../api/marianumcloud/talk/chat/richObjectStringProcessor.dart';
|
import '../../../api/marianumcloud/talk/chat/richObjectStringProcessor.dart';
|
||||||
import '../../../api/marianumcloud/talk/room/getRoomResponse.dart';
|
import '../../../api/marianumcloud/talk/room/getRoomResponse.dart';
|
||||||
|
import '../../../api/marianumcloud/talk/setFavorite/setFavorite.dart';
|
||||||
import '../../../model/chatList/chatListProps.dart';
|
import '../../../model/chatList/chatListProps.dart';
|
||||||
|
import '../../../widget/confirmDialog.dart';
|
||||||
import '../../../widget/unimplementedDialog.dart';
|
import '../../../widget/unimplementedDialog.dart';
|
||||||
import 'chatView.dart';
|
import 'chatView.dart';
|
||||||
|
|
||||||
@ -31,10 +36,14 @@ class _ChatListState extends State<ChatList> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
Provider.of<ChatListProps>(context, listen: false).run();
|
_query();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _query({bool renew = false}) {
|
||||||
|
Provider.of<ChatListProps>(context, listen: false).run(renew: renew);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
@ -61,6 +70,16 @@ class _ChatListState extends State<ChatList> {
|
|||||||
|
|
||||||
for (var chatRoom in data.getRoomsResponse.sortByLastActivity()) {
|
for (var chatRoom in data.getRoomsResponse.sortByLastActivity()) {
|
||||||
|
|
||||||
|
setCurrentAsRead() {
|
||||||
|
SetReadMarker(
|
||||||
|
chatRoom.token,
|
||||||
|
true,
|
||||||
|
setReadMarkerParams: SetReadMarkerParams(
|
||||||
|
lastReadMessage: chatRoom.lastMessage.id
|
||||||
|
)
|
||||||
|
).run().then((value) => _query(renew: true));
|
||||||
|
}
|
||||||
|
|
||||||
CircleAvatar circleAvatar = CircleAvatar(
|
CircleAvatar circleAvatar = CircleAvatar(
|
||||||
foregroundImage: chatRoom.type == GetRoomResponseObjectConversationType.oneToOne ? Image.network("https://cloud.marianum-fulda.de/avatar/${chatRoom.name}/128").image : null,
|
foregroundImage: chatRoom.type == GetRoomResponseObjectConversationType.oneToOne ? Image.network("https://cloud.marianum-fulda.de/avatar/${chatRoom.name}/128").image : null,
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
@ -69,9 +88,32 @@ class _ChatListState extends State<ChatList> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
chats.add(ListTile(
|
chats.add(ListTile(
|
||||||
|
leading: Stack(
|
||||||
|
children: [
|
||||||
|
circleAvatar,
|
||||||
|
Visibility(
|
||||||
|
visible: chatRoom.isFavorite,
|
||||||
|
child: Positioned(
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(1),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).primaryColor.withAlpha(200),
|
||||||
|
borderRadius: BorderRadius.circular(90.0),
|
||||||
|
),
|
||||||
|
child: const Icon(Icons.star, color: Colors.amberAccent, size: 15),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
title: Text(chatRoom.displayName),
|
title: Text(chatRoom.displayName),
|
||||||
subtitle: Text("${Jiffy.parseFromMillisecondsSinceEpoch(chatRoom.lastMessage.timestamp * 1000).fromNow()}: ${RichObjectStringProcessor.parseToString(chatRoom.lastMessage.message.replaceAll("\n", " "), chatRoom.lastMessage.messageParameters)}", overflow: TextOverflow.ellipsis),
|
subtitle: Text("${Jiffy.parseFromMillisecondsSinceEpoch(chatRoom.lastMessage.timestamp * 1000).fromNow()}: ${RichObjectStringProcessor.parseToString(chatRoom.lastMessage.message.replaceAll("\n", " "), chatRoom.lastMessage.messageParameters)}", overflow: TextOverflow.ellipsis),
|
||||||
trailing: Visibility(
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Visibility(
|
||||||
visible: chatRoom.unreadMessages > 0,
|
visible: chatRoom.unreadMessages > 0,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(1),
|
padding: const EdgeInsets.all(1),
|
||||||
@ -93,21 +135,82 @@ class _ChatListState extends State<ChatList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
leading: circleAvatar,
|
],
|
||||||
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
setCurrentAsRead();
|
||||||
PersistentNavBarNavigator.pushNewScreen(
|
PersistentNavBarNavigator.pushNewScreen(
|
||||||
context,
|
context,
|
||||||
screen: ChatView(room: chatRoom, selfId: username, avatar: circleAvatar),
|
screen: ChatView(room: chatRoom, selfId: username, avatar: circleAvatar),
|
||||||
withNavBar: false
|
withNavBar: false
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
onLongPress: () {
|
||||||
|
showDialog(context: context, builder: (context) => SimpleDialog(
|
||||||
|
children: [
|
||||||
|
Visibility(
|
||||||
|
visible: chatRoom.unreadMessages > 0,
|
||||||
|
replacement: ListTile(
|
||||||
|
leading: const Icon(Icons.mark_chat_unread_outlined),
|
||||||
|
title: const Text("Als ungelesen markieren"),
|
||||||
|
onTap: () {
|
||||||
|
SetReadMarker(chatRoom.token, false).run().then((value) => _query(renew: true));
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
child: ListTile(
|
||||||
|
leading: const Icon(Icons.mark_chat_read_outlined),
|
||||||
|
title: const Text("Als gelesen markieren"),
|
||||||
|
onTap: () {
|
||||||
|
setCurrentAsRead();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: chatRoom.isFavorite,
|
||||||
|
replacement: ListTile(
|
||||||
|
leading: const Icon(Icons.star_outline),
|
||||||
|
title: const Text("Zu favoriten hinzufügen"),
|
||||||
|
onTap: () {
|
||||||
|
SetFavorite(chatRoom.token, true).run().then((value) => _query(renew: true));
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
child: ListTile(
|
||||||
|
leading: const Icon(Icons.stars_outlined),
|
||||||
|
title: const Text("Von favoriten entfernen"),
|
||||||
|
onTap: () {
|
||||||
|
SetFavorite(chatRoom.token, false).run().then((value) => _query(renew: true));
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.delete_outline),
|
||||||
|
title: const Text("Konversation verlassen"),
|
||||||
|
onTap: () {
|
||||||
|
ConfirmDialog(
|
||||||
|
title: "Chat verlassen",
|
||||||
|
content: "Du benötigst ggf. eine Einladung um erneut beizutreten.",
|
||||||
|
confirmButton: "Löschen",
|
||||||
|
onConfirm: () {
|
||||||
|
LeaveRoom(chatRoom.token).run().then((value) => _query(renew: true));
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
).asDialog(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
color: Theme.of(context).primaryColor,
|
color: Theme.of(context).primaryColor,
|
||||||
onRefresh: () {
|
onRefresh: () {
|
||||||
Provider.of<ChatListProps>(context, listen: false).run(renew: true);
|
_query(renew: true);
|
||||||
return Future.delayed(const Duration(seconds: 3));
|
return Future.delayed(const Duration(seconds: 3));
|
||||||
},
|
},
|
||||||
child: ListView(children: chats),
|
child: ListView(children: chats),
|
||||||
|
@ -25,8 +25,8 @@ class ConfirmDialog extends StatelessWidget {
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}, child: Text(cancelButton)),
|
}, child: Text(cancelButton)),
|
||||||
TextButton(onPressed: () {
|
TextButton(onPressed: () {
|
||||||
onConfirm();
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
onConfirm();
|
||||||
}, child: Text(confirmButton)),
|
}, child: Text(confirmButton)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -37,7 +37,7 @@ class ConfirmDialog extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (context) => ConfirmDialog(
|
builder: (context) => ConfirmDialog(
|
||||||
title: "Link öffnen",
|
title: "Link öffnen",
|
||||||
content: "Möchtest du den folgenden Link öffnen?\n${url}",
|
content: "Möchtest du den folgenden Link öffnen?\n$url",
|
||||||
confirmButton: "Öffnen",
|
confirmButton: "Öffnen",
|
||||||
onConfirm: () => launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication),
|
onConfirm: () => launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication),
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user