This commit is contained in:
otsmr 2025-04-21 18:20:12 +02:00
parent 1e89809f27
commit 8f29461f72
7 changed files with 114 additions and 60 deletions

View file

@ -42,7 +42,7 @@ class PermissionHandlerViewState extends State<PermissionHandlerView> {
// } // }
if (statuses[Permission.camera]!.isPermanentlyDenied) { if (statuses[Permission.camera]!.isPermanentlyDenied) {
openAppSettings(); await openAppSettings();
// setState(() {}); // setState(() {});
} else { } else {
// if (statuses[Permission.camera]!.isDenied) { // if (statuses[Permission.camera]!.isDenied) {
@ -74,7 +74,7 @@ class PermissionHandlerViewState extends State<PermissionHandlerView> {
icon: const Icon(Icons.perm_camera_mic), icon: const Icon(Icons.perm_camera_mic),
onPressed: () async { onPressed: () async {
try { try {
permissionServices(); await permissionServices();
if (await checkPermissions()) { if (await checkPermissions()) {
widget.onSuccess(); widget.onSuccess();
} }

View file

@ -81,7 +81,7 @@
"settingsTitle": "Einstellungen", "settingsTitle": "Einstellungen",
"settingsChats": "Chats", "settingsChats": "Chats",
"settingsPreSelectedReactions": "Vorgewählte Reaktions-Emojis", "settingsPreSelectedReactions": "Vorgewählte Reaktions-Emojis",
"settingsPreSelectedReactionsError": "Es können maximal 6 Reaktionen ausgewählt werden.", "settingsPreSelectedReactionsError": "Es können maximal 12 Reaktionen ausgewählt werden.",
"settingsProfile": "Profil", "settingsProfile": "Profil",
"settingsProfileCustomizeAvatar": "Avatar anpassen", "settingsProfileCustomizeAvatar": "Avatar anpassen",
"settingsProfileEditDisplayName": "Anzeigename", "settingsProfileEditDisplayName": "Anzeigename",

View file

@ -136,7 +136,7 @@
"@settingsChats": {}, "@settingsChats": {},
"settingsPreSelectedReactions": "Preselected reaction emojis", "settingsPreSelectedReactions": "Preselected reaction emojis",
"@settingsPreSelectedReactions": {}, "@settingsPreSelectedReactions": {},
"settingsPreSelectedReactionsError": "A maximum of 6 reactions can be selected.", "settingsPreSelectedReactionsError": "A maximum of 12 reactions can be selected.",
"@settingsPreSelectedReactionsError": {}, "@settingsPreSelectedReactionsError": {},
"settingsProfile": "Profile", "settingsProfile": "Profile",
"@settingsProfile": {}, "@settingsProfile": {},

View file

@ -561,6 +561,10 @@ class _ReactionButtonsState extends State<ReactionButtons> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final firstRowEmojis = selectedEmojis.take(6).toList();
final secondRowEmojis =
selectedEmojis.length > 6 ? selectedEmojis.skip(6).toList() : [];
return AnimatedPositioned( return AnimatedPositioned(
duration: Duration(milliseconds: 200), // Animation duration duration: Duration(milliseconds: 200), // Animation duration
bottom: widget.show ? 100 : 90, bottom: widget.show ? 100 : 90,
@ -570,62 +574,112 @@ class _ReactionButtonsState extends State<ReactionButtons> {
child: AnimatedOpacity( child: AnimatedOpacity(
opacity: widget.show ? 1.0 : 0.0, // Fade in/out opacity: widget.show ? 1.0 : 0.0, // Fade in/out
duration: Duration(milliseconds: 150), duration: Duration(milliseconds: 150),
child: Row( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
crossAxisAlignment: CrossAxisAlignment.end, if (secondRowEmojis.isNotEmpty)
children: List.generate( Row(
6, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
(index) { crossAxisAlignment: CrossAxisAlignment.end,
final emoji = selectedEmojis[index]; children: secondRowEmojis
return AnimatedSize( .map((emoji) => EmojiReactionWidget(
duration: Duration(milliseconds: 200), // Animation duration userId: widget.userId,
curve: Curves.linearToEaseOut, responseToMessageId: widget.responseToMessageId,
child: GestureDetector( hide: widget.hide,
onTap: () { show: widget.show,
sendTextMessage(
widget.userId,
TextMessageContent(
text: emoji,
responseToMessageId: widget.responseToMessageId,
),
PushKind.reaction,
);
setState(() {
selectedShortReaction = index;
});
Future.delayed(Duration(milliseconds: 300), () {
setState(() {
widget.hide();
selectedShortReaction = -1;
});
});
},
child: (selectedShortReaction == index)
? EmojiAnimationFlying(
emoji: emoji, emoji: emoji,
duration: Duration(milliseconds: 300), ))
startPosition: 0.0, .toList(),
size: (widget.show) ? 40 : 10) ),
: AnimatedOpacity( if (secondRowEmojis.isNotEmpty) SizedBox(height: 15),
opacity: (selectedShortReaction == -1) Row(
? 1 mainAxisAlignment: MainAxisAlignment.spaceEvenly,
: 0, // Fade in/out crossAxisAlignment: CrossAxisAlignment.end,
duration: Duration(milliseconds: 150), children: firstRowEmojis
child: SizedBox( .map((emoji) => EmojiReactionWidget(
width: widget.show ? 40 : 10, userId: widget.userId,
child: Center( responseToMessageId: widget.responseToMessageId,
child: EmojiAnimation( hide: widget.hide,
emoji: emoji, show: widget.show,
), emoji: emoji,
), ))
), .toList(),
), ),
), ],
);
},
),
), ),
), ),
); );
} }
} }
class EmojiReactionWidget extends StatefulWidget {
final int userId;
final int responseToMessageId;
final Function hide;
final bool show;
final String emoji;
const EmojiReactionWidget({
super.key,
required this.userId,
required this.responseToMessageId,
required this.hide,
required this.show,
required this.emoji,
});
@override
_EmojiReactionWidgetState createState() => _EmojiReactionWidgetState();
}
class _EmojiReactionWidgetState extends State<EmojiReactionWidget> {
int selectedShortReaction = -1;
@override
Widget build(BuildContext context) {
return AnimatedSize(
duration: Duration(milliseconds: 200),
curve: Curves.linearToEaseOut,
child: GestureDetector(
onTap: () {
sendTextMessage(
widget.userId,
TextMessageContent(
text: widget.emoji,
responseToMessageId: widget.responseToMessageId,
),
PushKind.reaction,
);
setState(() {
selectedShortReaction = 0; // Assuming index is 0 for this example
});
Future.delayed(Duration(milliseconds: 300), () {
setState(() {
widget.hide();
selectedShortReaction = -1;
});
});
},
child: (selectedShortReaction ==
0) // Assuming index is 0 for this example
? EmojiAnimationFlying(
emoji: widget.emoji,
duration: Duration(milliseconds: 300),
startPosition: 0.0,
size: (widget.show) ? 40 : 10,
)
: AnimatedOpacity(
opacity: (selectedShortReaction == -1) ? 1 : 0, // Fade in/out
duration: Duration(milliseconds: 150),
child: SizedBox(
width: widget.show ? 40 : 10,
child: Center(
child: EmojiAnimation(
emoji: widget.emoji,
),
),
),
),
),
);
}
}

View file

@ -34,7 +34,7 @@ class _ChatReactionSelectionView extends State<ChatReactionSelectionView> {
if (selectedEmojis.contains(emoji)) { if (selectedEmojis.contains(emoji)) {
selectedEmojis.remove(emoji); selectedEmojis.remove(emoji);
} else { } else {
if (selectedEmojis.length < 6) { if (selectedEmojis.length < 12) {
selectedEmojis.add(emoji); selectedEmojis.add(emoji);
var user = await getUser(); var user = await getUser();
if (user != null) { if (user != null) {

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/settings/chat_reactions_view.dart'; import 'package:twonly/src/views/settings/chat/chat_reactions_view.dart';
class ChatSettingsView extends StatefulWidget { class ChatSettingsView extends StatefulWidget {
const ChatSettingsView({super.key}); const ChatSettingsView({super.key});

View file

@ -7,7 +7,7 @@ import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/settings/account_view.dart'; import 'package:twonly/src/views/settings/account_view.dart';
import 'package:twonly/src/views/settings/appearance_view.dart'; import 'package:twonly/src/views/settings/appearance_view.dart';
import 'package:twonly/src/views/settings/chat_settings_view.dart'; import 'package:twonly/src/views/settings/chat/chat_settings_view.dart';
import 'package:twonly/src/views/settings/notification_view.dart'; import 'package:twonly/src/views/settings/notification_view.dart';
import 'package:twonly/src/views/settings/profile/profile_view.dart'; import 'package:twonly/src/views/settings/profile/profile_view.dart';
import 'package:twonly/src/views/settings/help_view.dart'; import 'package:twonly/src/views/settings/help_view.dart';