mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 21:48:40 +00:00
fix #252
This commit is contained in:
parent
3fbf29b4e2
commit
c89a14fc2d
4 changed files with 317 additions and 302 deletions
|
|
@ -274,8 +274,11 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserListItem extends StatefulWidget {
|
class UserListItem extends StatefulWidget {
|
||||||
const UserListItem(
|
const UserListItem({
|
||||||
{required this.user, required this.firstUserListItemKey, super.key});
|
required this.user,
|
||||||
|
required this.firstUserListItemKey,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
final Contact user;
|
final Contact user;
|
||||||
final GlobalKey? firstUserListItemKey;
|
final GlobalKey? firstUserListItemKey;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -256,187 +256,192 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return GestureDetector(
|
||||||
appBar: AppBar(
|
onTap: () => FocusScope.of(context).unfocus(),
|
||||||
title: GestureDetector(
|
child: Scaffold(
|
||||||
onTap: () {
|
appBar: AppBar(
|
||||||
Navigator.push(context, MaterialPageRoute(builder: (context) {
|
title: GestureDetector(
|
||||||
return ContactView(widget.contact.userId);
|
onTap: () {
|
||||||
}));
|
Navigator.push(context, MaterialPageRoute(builder: (context) {
|
||||||
},
|
return ContactView(widget.contact.userId);
|
||||||
child: Row(
|
}));
|
||||||
children: [
|
},
|
||||||
ContactAvatar(
|
child: Row(
|
||||||
contact: user,
|
children: [
|
||||||
fontSize: 19,
|
ContactAvatar(
|
||||||
),
|
contact: user,
|
||||||
const SizedBox(width: 10),
|
fontSize: 19,
|
||||||
Expanded(
|
),
|
||||||
child: ColoredBox(
|
const SizedBox(width: 10),
|
||||||
color: Colors.transparent,
|
Expanded(
|
||||||
child: Row(
|
child: ColoredBox(
|
||||||
children: [
|
color: Colors.transparent,
|
||||||
Text(getContactDisplayName(user)),
|
child: Row(
|
||||||
const SizedBox(width: 10),
|
children: [
|
||||||
VerifiedShield(key: verifyShieldKey, user),
|
Text(getContactDisplayName(user)),
|
||||||
],
|
const SizedBox(width: 10),
|
||||||
|
VerifiedShield(key: verifyShieldKey, user),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
body: PieCanvas(
|
||||||
body: PieCanvas(
|
theme: getPieCanvasTheme(context),
|
||||||
theme: getPieCanvasTheme(context),
|
child: SafeArea(
|
||||||
child: SafeArea(
|
child: Column(
|
||||||
child: Column(
|
children: [
|
||||||
children: [
|
Expanded(
|
||||||
Expanded(
|
child: ListView.builder(
|
||||||
child: ListView.builder(
|
itemCount: messages.length + 1,
|
||||||
itemCount: messages.length + 1,
|
reverse: true,
|
||||||
reverse: true,
|
itemExtentBuilder: (index, dimensions) {
|
||||||
itemExtentBuilder: (index, dimensions) {
|
if (index == 0) return 10; // empty padding
|
||||||
if (index == 0) return 10; // empty padding
|
index -= 1;
|
||||||
index -= 1;
|
double size = 44;
|
||||||
double size = 44;
|
if (messages[index].kind == MessageKind.textMessage) {
|
||||||
if (messages[index].kind == MessageKind.textMessage) {
|
final content = TextMessageContent.fromJson(
|
||||||
final content = TextMessageContent.fromJson(
|
jsonDecode(messages[index].contentJson!) as Map);
|
||||||
jsonDecode(messages[index].contentJson!) as Map);
|
if (EmojiAnimation.supported(content.text)) {
|
||||||
if (EmojiAnimation.supported(content.text)) {
|
size = 99;
|
||||||
size = 99;
|
} else {
|
||||||
} else {
|
size = 11 +
|
||||||
size = 11 +
|
calculateNumberOfLines(
|
||||||
calculateNumberOfLines(
|
content.text,
|
||||||
content.text,
|
MediaQuery.of(context).size.width * 0.8,
|
||||||
MediaQuery.of(context).size.width * 0.8,
|
17) *
|
||||||
17) *
|
27;
|
||||||
27;
|
}
|
||||||
}
|
}
|
||||||
}
|
if (messages[index].mediaStored) {
|
||||||
if (messages[index].mediaStored) {
|
size = 271;
|
||||||
size = 271;
|
}
|
||||||
}
|
final reactions =
|
||||||
final reactions =
|
textReactionsToMessageId[messages[index].messageId];
|
||||||
textReactionsToMessageId[messages[index].messageId];
|
if (reactions != null && reactions.isNotEmpty) {
|
||||||
if (reactions != null && reactions.isNotEmpty) {
|
for (final reaction in reactions) {
|
||||||
for (final reaction in reactions) {
|
if (reaction.kind == MessageKind.textMessage) {
|
||||||
if (reaction.kind == MessageKind.textMessage) {
|
final content = TextMessageContent.fromJson(
|
||||||
final content = TextMessageContent.fromJson(
|
jsonDecode(reaction.contentJson!) as Map);
|
||||||
jsonDecode(reaction.contentJson!) as Map);
|
size += calculateNumberOfLines(
|
||||||
size += calculateNumberOfLines(content.text,
|
content.text,
|
||||||
MediaQuery.of(context).size.width * 0.5, 14) *
|
MediaQuery.of(context).size.width * 0.5,
|
||||||
27;
|
14) *
|
||||||
|
27;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!isLastMessageFromSameUser(messages, index)) {
|
if (!isLastMessageFromSameUser(messages, index)) {
|
||||||
size += 20;
|
size += 20;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
},
|
},
|
||||||
itemBuilder: (context, i) {
|
itemBuilder: (context, i) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
return Container(); // just a padding
|
return Container(); // just a padding
|
||||||
}
|
}
|
||||||
i -= 1;
|
i -= 1;
|
||||||
return ChatListEntry(
|
return ChatListEntry(
|
||||||
key: Key(messages[i].messageId.toString()),
|
key: Key(messages[i].messageId.toString()),
|
||||||
messages[i],
|
messages[i],
|
||||||
user,
|
user,
|
||||||
galleryItems,
|
galleryItems,
|
||||||
isLastMessageFromSameUser(messages, i),
|
isLastMessageFromSameUser(messages, i),
|
||||||
textReactionsToMessageId[messages[i].messageId] ?? [],
|
textReactionsToMessageId[messages[i].messageId] ?? [],
|
||||||
emojiReactionsToMessageId[messages[i].messageId] ?? [],
|
emojiReactionsToMessageId[messages[i].messageId] ?? [],
|
||||||
onResponseTriggered: (message) {
|
onResponseTriggered: (message) {
|
||||||
setState(() {
|
setState(() {
|
||||||
responseToMessage = message;
|
responseToMessage = message;
|
||||||
});
|
});
|
||||||
textFieldFocus.requestFocus();
|
textFieldFocus.requestFocus();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
if (responseToMessage != null && !user.deleted)
|
||||||
if (responseToMessage != null && !user.deleted)
|
Container(
|
||||||
Container(
|
padding: const EdgeInsets.only(
|
||||||
|
left: 20,
|
||||||
|
right: 20,
|
||||||
|
top: 10,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: getResponsePreview(responseToMessage!)),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
responseToMessage = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const FaIcon(
|
||||||
|
FontAwesomeIcons.xmark,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 30,
|
||||||
left: 20,
|
left: 20,
|
||||||
right: 20,
|
right: 20,
|
||||||
top: 10,
|
top: 10,
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: (user.deleted)
|
||||||
Expanded(child: getResponsePreview(responseToMessage!)),
|
? []
|
||||||
IconButton(
|
: [
|
||||||
onPressed: () {
|
Expanded(
|
||||||
setState(() {
|
child: TextField(
|
||||||
responseToMessage = null;
|
controller: newMessageController,
|
||||||
});
|
focusNode: textFieldFocus,
|
||||||
},
|
keyboardType: TextInputType.multiline,
|
||||||
icon: const FaIcon(
|
maxLines: 4,
|
||||||
FontAwesomeIcons.xmark,
|
minLines: 1,
|
||||||
size: 16,
|
onChanged: (value) {
|
||||||
),
|
currentInputText = value;
|
||||||
)
|
setState(() {});
|
||||||
],
|
},
|
||||||
|
onSubmitted: (_) {
|
||||||
|
_sendMessage();
|
||||||
|
},
|
||||||
|
decoration: inputTextMessageDeco(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (currentInputText != '')
|
||||||
|
IconButton(
|
||||||
|
padding: const EdgeInsets.all(15),
|
||||||
|
icon: const FaIcon(
|
||||||
|
FontAwesomeIcons.solidPaperPlane),
|
||||||
|
onPressed: _sendMessage,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
IconButton(
|
||||||
|
icon: const FaIcon(FontAwesomeIcons.camera),
|
||||||
|
padding: const EdgeInsets.all(15),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return CameraSendToView(widget.contact);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
],
|
||||||
padding: const EdgeInsets.only(
|
),
|
||||||
bottom: 30,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
top: 10,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: (user.deleted)
|
|
||||||
? []
|
|
||||||
: [
|
|
||||||
Expanded(
|
|
||||||
child: TextField(
|
|
||||||
controller: newMessageController,
|
|
||||||
focusNode: textFieldFocus,
|
|
||||||
keyboardType: TextInputType.multiline,
|
|
||||||
maxLines: 4,
|
|
||||||
minLines: 1,
|
|
||||||
onChanged: (value) {
|
|
||||||
currentInputText = value;
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
onSubmitted: (_) {
|
|
||||||
_sendMessage();
|
|
||||||
},
|
|
||||||
decoration: inputTextMessageDeco(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (currentInputText != '')
|
|
||||||
IconButton(
|
|
||||||
padding: const EdgeInsets.all(15),
|
|
||||||
icon: const FaIcon(
|
|
||||||
FontAwesomeIcons.solidPaperPlane),
|
|
||||||
onPressed: _sendMessage,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
IconButton(
|
|
||||||
icon: const FaIcon(FontAwesomeIcons.camera),
|
|
||||||
padding: const EdgeInsets.all(15),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return CameraSendToView(widget.contact);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -151,112 +151,115 @@ $debugLogToken
|
||||||
context.lang.contactUsReasonFeedback,
|
context.lang.contactUsReasonFeedback,
|
||||||
context.lang.contactUsReasonOther,
|
context.lang.contactUsReasonOther,
|
||||||
];
|
];
|
||||||
return Scaffold(
|
return GestureDetector(
|
||||||
appBar: AppBar(
|
onTap: () => FocusScope.of(context).unfocus(),
|
||||||
title: Text(context.lang.settingsHelpContactUs),
|
child: Scaffold(
|
||||||
),
|
appBar: AppBar(
|
||||||
body: Padding(
|
title: Text(context.lang.settingsHelpContactUs),
|
||||||
padding: const EdgeInsets.all(16),
|
),
|
||||||
child: ListView(
|
body: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.all(16),
|
||||||
Text(context.lang.contactUsMessageTitle),
|
child: ListView(
|
||||||
const SizedBox(height: 5),
|
children: [
|
||||||
TextField(
|
Text(context.lang.contactUsMessageTitle),
|
||||||
controller: _controller,
|
const SizedBox(height: 5),
|
||||||
decoration: InputDecoration(
|
TextField(
|
||||||
hintText: context.lang.contactUsYourMessage,
|
controller: _controller,
|
||||||
border: const OutlineInputBorder(),
|
decoration: InputDecoration(
|
||||||
|
hintText: context.lang.contactUsYourMessage,
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
minLines: 5,
|
||||||
|
maxLines: 10,
|
||||||
),
|
),
|
||||||
minLines: 5,
|
const SizedBox(height: 5),
|
||||||
maxLines: 10,
|
Text(
|
||||||
),
|
context.lang.contactUsMessage,
|
||||||
const SizedBox(height: 5),
|
textAlign: TextAlign.left,
|
||||||
Text(
|
style: const TextStyle(
|
||||||
context.lang.contactUsMessage,
|
fontSize: 10,
|
||||||
textAlign: TextAlign.left,
|
),
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 10,
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 20),
|
||||||
const SizedBox(height: 20),
|
Text(context.lang.contactUsReason),
|
||||||
Text(context.lang.contactUsReason),
|
const SizedBox(height: 5),
|
||||||
const SizedBox(height: 5),
|
DropdownButton<String>(
|
||||||
DropdownButton<String>(
|
hint: Text(context.lang.contactUsSelectOption),
|
||||||
hint: Text(context.lang.contactUsSelectOption),
|
underline: const SizedBox.shrink(),
|
||||||
underline: const SizedBox.shrink(),
|
value: _selectedReason,
|
||||||
value: _selectedReason,
|
onChanged: (String? newValue) {
|
||||||
onChanged: (String? newValue) {
|
setState(() {
|
||||||
setState(() {
|
_selectedReason = newValue;
|
||||||
_selectedReason = newValue;
|
});
|
||||||
});
|
},
|
||||||
},
|
items: reasons.map<DropdownMenuItem<String>>((String reason) {
|
||||||
items: reasons.map<DropdownMenuItem<String>>((String reason) {
|
return DropdownMenuItem<String>(
|
||||||
return DropdownMenuItem<String>(
|
value: reason,
|
||||||
value: reason,
|
child: Text(reason),
|
||||||
child: Text(reason),
|
);
|
||||||
);
|
}).toList(),
|
||||||
}).toList(),
|
),
|
||||||
),
|
const SizedBox(height: 20),
|
||||||
const SizedBox(height: 20),
|
Text(context.lang.contactUsEmojis),
|
||||||
Text(context.lang.contactUsEmojis),
|
const SizedBox(height: 5),
|
||||||
const SizedBox(height: 5),
|
FeedbackEmojiRow(
|
||||||
FeedbackEmojiRow(
|
selectedFeedback: _selectedFeedback,
|
||||||
selectedFeedback: _selectedFeedback,
|
onFeedbackChanged: (int? newValue) {
|
||||||
onFeedbackChanged: (int? newValue) {
|
setState(() {
|
||||||
setState(() {
|
_selectedFeedback = newValue;
|
||||||
_selectedFeedback = newValue;
|
});
|
||||||
});
|
},
|
||||||
},
|
),
|
||||||
),
|
const SizedBox(height: 20),
|
||||||
const SizedBox(height: 20),
|
IncludeDebugLog(
|
||||||
IncludeDebugLog(
|
isChecked: includeDebugLog,
|
||||||
isChecked: includeDebugLog,
|
onChanged: (value) {
|
||||||
onChanged: (value) {
|
setState(() {
|
||||||
setState(() {
|
includeDebugLog = value;
|
||||||
includeDebugLog = value;
|
});
|
||||||
});
|
},
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 40),
|
),
|
||||||
child: Row(
|
bottomNavigationBar: Padding(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 40),
|
||||||
children: [
|
child: Row(
|
||||||
GestureDetector(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
onTap: () {
|
children: [
|
||||||
launchUrl(Uri.parse('https://twonly.eu/en/faq/'));
|
GestureDetector(
|
||||||
},
|
onTap: () {
|
||||||
child: Text(
|
launchUrl(Uri.parse('https://twonly.eu/en/faq/'));
|
||||||
context.lang.contactUsFaq,
|
},
|
||||||
style: const TextStyle(
|
child: Text(
|
||||||
color: Colors.blue,
|
context.lang.contactUsFaq,
|
||||||
),
|
style: const TextStyle(
|
||||||
),
|
color: Colors.blue,
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
),
|
||||||
onPressed: isLoading
|
|
||||||
? null
|
|
||||||
: () async {
|
|
||||||
final fullMessage = await _getFeedbackText();
|
|
||||||
if (!context.mounted) return;
|
|
||||||
|
|
||||||
final feedbackSend = await Navigator.push(context,
|
|
||||||
MaterialPageRoute(builder: (context) {
|
|
||||||
return SubmitMessage(
|
|
||||||
fullMessage: fullMessage,
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (feedbackSend == true && context.mounted) {
|
|
||||||
Navigator.pop(context);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(context.lang.next),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
ElevatedButton(
|
||||||
],
|
onPressed: isLoading
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
final fullMessage = await _getFeedbackText();
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
final feedbackSend = await Navigator.push(context,
|
||||||
|
MaterialPageRoute(builder: (context) {
|
||||||
|
return SubmitMessage(
|
||||||
|
fullMessage: fullMessage,
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (feedbackSend == true && context.mounted) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(context.lang.next),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -64,41 +64,45 @@ class _ContactUsState extends State<SubmitMessage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return GestureDetector(
|
||||||
appBar: AppBar(
|
onTap: () => FocusScope.of(context).unfocus(),
|
||||||
title: Text(context.lang.settingsHelpContactUs),
|
child: Scaffold(
|
||||||
),
|
appBar: AppBar(
|
||||||
body: Padding(
|
title: Text(context.lang.settingsHelpContactUs),
|
||||||
padding: const EdgeInsets.all(16),
|
),
|
||||||
child: ListView(
|
body: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.all(16),
|
||||||
Text(
|
child: ListView(
|
||||||
context.lang.contactUsLastWarning,
|
children: [
|
||||||
textAlign: TextAlign.center,
|
Text(
|
||||||
),
|
context.lang.contactUsLastWarning,
|
||||||
const SizedBox(height: 10),
|
textAlign: TextAlign.center,
|
||||||
TextField(
|
|
||||||
controller: _controller,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: context.lang.contactUsYourMessage,
|
|
||||||
border: const OutlineInputBorder(),
|
|
||||||
),
|
),
|
||||||
minLines: 5,
|
const SizedBox(height: 10),
|
||||||
maxLines: 20,
|
TextField(
|
||||||
),
|
controller: _controller,
|
||||||
Padding(
|
decoration: InputDecoration(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 40),
|
hintText: context.lang.contactUsYourMessage,
|
||||||
child: Row(
|
border: const OutlineInputBorder(),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
),
|
||||||
children: [
|
minLines: 5,
|
||||||
ElevatedButton(
|
maxLines: 20,
|
||||||
onPressed: isLoading ? null : _submitFeedback,
|
|
||||||
child: Text(context.lang.submit),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
],
|
padding:
|
||||||
|
const EdgeInsets.symmetric(vertical: 40, horizontal: 40),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: isLoading ? null : _submitFeedback,
|
||||||
|
child: Text(context.lang.submit),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue