merged to origin/devlop

This commit is contained in:
2024-04-07 15:58:51 +02:00
185 changed files with 500 additions and 866 deletions

View File

@ -35,7 +35,7 @@ class _ChatInfoState extends State<ChatInfo> {
@override
Widget build(BuildContext context) {
bool isGroup = widget.room.type != GetRoomResponseObjectConversationType.oneToOne;
var isGroup = widget.room.type != GetRoomResponseObjectConversationType.oneToOne;
return Scaffold(
appBar: AppBar(
title: Text(widget.room.displayName),

View File

@ -13,20 +13,16 @@ class ParticipantsListView extends StatefulWidget {
class _ParticipantsListViewState extends State<ParticipantsListView> {
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Teilnehmende'),
),
body: ListView(
children: widget.participantsResponse.data.map((participant) {
return ListTile(
children: widget.participantsResponse.data.map((participant) => ListTile(
leading: UserAvatar(id: participant.actorId),
title: Text(participant.displayName),
subtitle: participant.statusMessage != null ? Text(participant.statusMessage!) : null,
);
}).toList(),
)).toList(),
),
);
}
}

View File

@ -119,14 +119,14 @@ class _ChatListState extends State<ChatList> {
if(data.primaryLoading()) return const LoadingSpinner();
latestData = data;
List<ChatTile> chats = [];
var chats = <ChatTile>[];
for (var chatRoom in data.getRoomsResponse.sortBy(
lastActivity: true,
favoritesToTop: Provider.of<SettingsProvider>(context).val().talkSettings.sortFavoritesToTop,
unreadToTop: Provider.of<SettingsProvider>(context).val().talkSettings.sortUnreadToTop,
)
) {
bool hasDraft = settings.val().talkSettings.drafts.containsKey(chatRoom.token);
var hasDraft = settings.val().talkSettings.drafts.containsKey(chatRoom.token);
chats.add(ChatTile(data: chatRoom, query: _query, hasDraft: hasDraft));
}
@ -146,4 +146,4 @@ class _ChatListState extends State<ChatList> {
),
);
}
}
}

View File

@ -40,19 +40,18 @@ class _ChatViewState extends State<ChatView> {
}
@override
Widget build(BuildContext context) {
return Consumer<ChatProps>(
Widget build(BuildContext context) => Consumer<ChatProps>(
builder: (context, data, child) {
List<Widget> messages = List<Widget>.empty(growable: true);
var messages = List<Widget>.empty(growable: true);
if(!data.primaryLoading()) {
DateTime lastDate = DateTime.now();
var lastDate = DateTime.now();
data.getChatResponse.sortByTimestamp().forEach((element) {
DateTime elementDate = DateTime.fromMillisecondsSinceEpoch(element.timestamp * 1000);
var elementDate = DateTime.fromMillisecondsSinceEpoch(element.timestamp * 1000);
if(element.systemMessage.contains('reaction')) return;
int commonRead = int.parse(data.getChatResponse.headers?['x-chat-last-common-read'] ?? '0');
var commonRead = int.parse(data.getChatResponse.headers?['x-chat-last-common-read'] ?? '0');
if(!elementDate.isSameDay(lastDate)) {
lastDate = elementDate;
@ -140,5 +139,4 @@ class _ChatViewState extends State<ChatView> {
);
},
);
}
}

View File

@ -51,15 +51,13 @@ class ChatBubble extends StatefulWidget {
class _ChatBubbleState extends State<ChatBubble> {
BubbleStyle getSystemStyle() {
return BubbleStyle(
BubbleStyle getSystemStyle() => BubbleStyle(
color: AppTheme.isDarkMode(context) ? const Color(0xff182229) : Colors.white,
borderWidth: 1,
elevation: 2,
margin: const BubbleEdges.only(bottom: 20, top: 10),
alignment: Alignment.center,
);
}
BubbleStyle getRemoteStyle(bool seamless) {
var color = AppTheme.isDarkMode(context) ? const Color(0xff202c33) : Colors.white;
@ -105,17 +103,17 @@ class _ChatBubbleState extends State<ChatBubble> {
@override
Widget build(BuildContext context) {
message = ChatMessage(originalMessage: widget.bubbleData.message, originalData: widget.bubbleData.messageParameters);
bool showActorDisplayName = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne;
bool showBubbleTime = widget.bubbleData.messageType != GetRoomResponseObjectMessageType.system;
var showActorDisplayName = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne;
var showBubbleTime = widget.bubbleData.messageType != GetRoomResponseObjectMessageType.system;
Text actorText = Text(
var actorText = Text(
widget.bubbleData.actorDisplayName,
textAlign: TextAlign.start,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Theme.of(context).primaryColor, fontWeight: FontWeight.bold),
);
Text timeText = Text(
var timeText = Text(
Jiffy.parseFromMillisecondsSinceEpoch(widget.bubbleData.timestamp * 1000).format(pattern: 'HH:mm'),
textAlign: TextAlign.end,
style: TextStyle(color: widget.timeIconColor, fontSize: widget.timeIconSize),
@ -186,8 +184,8 @@ class _ChatBubbleState extends State<ChatBubble> {
),
onLongPress: () {
showDialog(context: context, builder: (context) {
List<String> commonReactions = ['👍', '👎', '😆', '❤️', '👀'];
bool canReact = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment;
var commonReactions = <String>['👍', '👎', '😆', '❤️', '👀'];
var canReact = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment;
return SimpleDialog(
children: [
Visibility(
@ -217,8 +215,7 @@ class _ChatBubbleState extends State<ChatBubble> {
),
IconButton(
onPressed: () {
showDialog(context: context, builder: (context) {
return AlertDialog(
showDialog(context: context, builder: (context) => AlertDialog(
contentPadding: const EdgeInsets.all(15),
titlePadding: const EdgeInsets.only(left: 6, top: 15),
title: Row(
@ -278,8 +275,7 @@ class _ChatBubbleState extends State<ChatBubble> {
],
),
),
);
});
));
},
style: IconButton.styleFrom(
padding: EdgeInsets.zero,
@ -350,8 +346,7 @@ class _ChatBubbleState extends State<ChatBubble> {
if(message.file == null) return;
if(downloadProgress > 0) {
showDialog(context: context, builder: (context) {
return AlertDialog(
showDialog(context: context, builder: (context) => AlertDialog(
title: const Text('Download abbrechen?'),
content: const Text('Möchtest du den Download abbrechen?'),
actions: [
@ -369,8 +364,7 @@ class _ChatBubbleState extends State<ChatBubble> {
});
}, child: const Text('Ja, Abbrechen'))
],
);
});
));
return;
}
@ -388,11 +382,9 @@ class _ChatBubbleState extends State<ChatBubble> {
});
if(result.type != ResultType.done) {
showDialog(context: context, builder: (context) {
return AlertDialog(
showDialog(context: context, builder: (context) => AlertDialog(
content: Text(result.message),
);
});
));
}
});
},
@ -408,7 +400,7 @@ class _ChatBubbleState extends State<ChatBubble> {
alignment: widget.isSender ? WrapAlignment.end : WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start,
children: widget.bubbleData.reactions?.entries.map<Widget>((e) {
bool hasSelfReacted = widget.bubbleData.reactionsSelf?.contains(e.key) ?? false;
var hasSelfReacted = widget.bubbleData.reactionsSelf?.contains(e.key) ?? false;
return Container(
margin: const EdgeInsets.only(right: 2.5, left: 2.5),
child: ActionChip(

View File

@ -37,8 +37,7 @@ class ChatMessage {
}
return CachedNetworkImage(
errorWidget: (context, url, error) {
return Padding(padding: const EdgeInsets.only(top: 10), child: Row(
errorWidget: (context, url, error) => Padding(padding: const EdgeInsets.only(top: 10), child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
@ -47,12 +46,9 @@ class ChatMessage {
Flexible(child: Text(file!.name, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle(fontWeight: FontWeight.bold))),
const SizedBox(width: 10),
],
));
},
)),
alignment: Alignment.center,
placeholder: (context, url) {
return const Padding(padding: EdgeInsets.all(10), child: CircularProgressIndicator());
},
placeholder: (context, url) => const Padding(padding: EdgeInsets.all(10), child: CircularProgressIndicator()),
fadeInDuration: Duration.zero,
fadeOutDuration: Duration.zero,
errorListener: (value) {},
@ -60,9 +56,9 @@ class ChatMessage {
);
}
void onOpen(LinkableElement link) async {
Future<void> onOpen(LinkableElement link) async {
if(await canLaunchUrlString(link.url)) {
await launchUrlString(link.url);
}
}
}
}

View File

@ -66,7 +66,6 @@ class _ChatTextfieldState extends State<ChatTextfield> {
);
}
void setDraft(String text) {
if(text.isNotEmpty) {
settings.val(write: true).talkSettings.drafts[widget.sendToToken] = text;
@ -96,8 +95,7 @@ class _ChatTextfieldState extends State<ChatTextfield> {
children: <Widget>[
GestureDetector(
onTap: (){
showDialog(context: context, builder: (context) {
return SimpleDialog(
showDialog(context: context, builder: (context) => SimpleDialog(
children: [
ListTile(
leading: const Icon(Icons.file_open),
@ -121,8 +119,7 @@ class _ChatTextfieldState extends State<ChatTextfield> {
),
),
],
);
});
));
},
child: Material(
elevation: 5,

View File

@ -40,7 +40,7 @@ class _ChatTileState extends State<ChatTile> {
username = value.getString('username')!
});
bool isGroup = widget.data.type != GetRoomResponseObjectConversationType.oneToOne;
var isGroup = widget.data.type != GetRoomResponseObjectConversationType.oneToOne;
circleAvatar = UserAvatar(id: isGroup ? widget.data.token : widget.data.name, isGroup: isGroup);
}
@ -56,10 +56,7 @@ class _ChatTileState extends State<ChatTile> {
@override
Widget build(BuildContext context) {
return Consumer<ChatProps>(builder: (context, chatData, child) {
return ListTile(
Widget build(BuildContext context) => Consumer<ChatProps>(builder: (context, chatData, child) => ListTile(
style: ListTileStyle.list,
tileColor: chatData.currentToken() == widget.data.token && TalkNavigator.isSecondaryVisible(context)
? Theme.of(context).primaryColor.withAlpha(100)
@ -120,7 +117,7 @@ class _ChatTileState extends State<ChatTile> {
),
onTap: () async {
setCurrentAsRead();
ChatView view = ChatView(room: widget.data, selfId: username, avatar: circleAvatar);
var view = ChatView(room: widget.data, selfId: username, avatar: circleAvatar);
TalkNavigator.pushSplitView(context, view, overrideToSingleSubScreen: true);
Provider.of<ChatProps>(context, listen: false).setQueryToken(widget.data.token);
},
@ -185,7 +182,5 @@ class _ChatTileState extends State<ChatTile> {
],
));
},
);
});
}
));
}

View File

@ -6,8 +6,7 @@ class SplitViewPlaceholder extends StatelessWidget {
const SplitViewPlaceholder({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
@ -25,5 +24,4 @@ class SplitViewPlaceholder extends StatelessWidget {
),
)
);
}
}

View File

@ -11,8 +11,7 @@ class JoinChat extends SearchDelegate<String> {
CancelableOperation<AutocompleteResponse>? future;
@override
List<Widget>? buildActions(BuildContext context) {
return [
List<Widget>? buildActions(BuildContext context) => [
if(future != null && query.isNotEmpty) FutureBuilder(
future: future!.value,
builder: (context, snapshot) {
@ -35,12 +34,9 @@ class JoinChat extends SearchDelegate<String> {
),
if(query.isNotEmpty) IconButton(onPressed: () => query = '', icon: const Icon(Icons.delete)),
];
}
@override
Widget? buildLeading(BuildContext context) {
return null;
}
Widget? buildLeading(BuildContext context) => null;
@override
Widget buildResults(BuildContext context) {
@ -61,8 +57,8 @@ class JoinChat extends SearchDelegate<String> {
return ListView.builder(
itemCount: snapshot.data!.data.length,
itemBuilder: (context, index) {
AutocompleteResponseObject object = snapshot.data!.data[index];
CircleAvatar circleAvatar = CircleAvatar(
var object = snapshot.data!.data[index];
var circleAvatar = CircleAvatar(
foregroundImage: Image.network('https://${EndpointData().nextcloud().full()}/avatar/${object.id}/128').image,
backgroundColor: Theme.of(context).primaryColor,
foregroundColor: Colors.white,
@ -89,8 +85,6 @@ class JoinChat extends SearchDelegate<String> {
}
@override
Widget buildSuggestions(BuildContext context) {
return buildResults(context);
}
Widget buildSuggestions(BuildContext context) => buildResults(context);
}
}

View File

@ -30,8 +30,7 @@ class _MessageReactionsState extends State<MessageReactions> {
}
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Reaktionen'),
),
@ -42,8 +41,7 @@ class _MessageReactionsState extends State<MessageReactions> {
if(snapshot.data == null) return const PlaceholderView(icon: Icons.search_off_outlined, text: 'Keine Reaktionen gefunden!');
return ListView(
children: [
...snapshot.data!.data.entries.map<Widget>((entry) {
return ExpansionTile(
...snapshot.data!.data.entries.map<Widget>((entry) => ExpansionTile(
textColor: Theme.of(context).colorScheme.onSurface,
collapsedTextColor: Theme.of(context).colorScheme.onSurface,
iconColor: Theme.of(context).colorScheme.onSurface,
@ -53,7 +51,7 @@ class _MessageReactionsState extends State<MessageReactions> {
leading: CenteredLeading(Text(entry.key)),
title: Text('${entry.value.length} mal reagiert'),
children: entry.value.map((e) {
bool isSelf = AccountData().getUsername() == e.actorId;
var isSelf = AccountData().getUsername() == e.actorId;
return ListTile(
leading: UserAvatar(id: e.actorId, isGroup: false),
title: Text(e.actorDisplayName),
@ -71,12 +69,10 @@ class _MessageReactionsState extends State<MessageReactions> {
),
);
}).toList(),
);
})
))
],
);
},
),
);
}
}

View File

@ -9,16 +9,12 @@ class SearchChat extends SearchDelegate {
SearchChat(this.chats);
@override
List<Widget>? buildActions(BuildContext context) {
return [
List<Widget>? buildActions(BuildContext context) => [
if(query.isNotEmpty) IconButton(onPressed: () => query = '', icon: const Icon(Icons.delete)),
];
}
@override
Widget? buildLeading(BuildContext context) {
return null;
}
Widget? buildLeading(BuildContext context) => null;
@override
Widget buildResults(BuildContext context) {
@ -35,7 +31,5 @@ class SearchChat extends SearchDelegate {
}
@override
Widget buildSuggestions(BuildContext context) {
return buildResults(context);
}
}
Widget buildSuggestions(BuildContext context) => buildResults(context);
}

View File

@ -9,10 +9,10 @@ class TalkNavigator {
static void pushSplitView(BuildContext context, Widget view, {bool overrideToSingleSubScreen = false}) {
if(isSecondaryVisible(context)) {
SplitViewState splitView = SplitView.of(context);
var splitView = SplitView.of(context);
overrideToSingleSubScreen ? splitView.setSecondary(view) : splitView.push(view);
} else {
pushScreen(context, screen: view, withNavBar: false);
}
}
}
}