mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 02:12:13 +00:00
smaller improvements
This commit is contained in:
parent
dcca2cbec0
commit
ce60f4e2f1
6 changed files with 221 additions and 242 deletions
|
|
@ -341,7 +341,7 @@ Future<(Uint8List, Uint8List?)?> sendCipherText(
|
||||||
final openReceipts = await twonlyDB.receiptsDao.getReceiptCountForContact(
|
final openReceipts = await twonlyDB.receiptsDao.getReceiptCountForContact(
|
||||||
contactId,
|
contactId,
|
||||||
);
|
);
|
||||||
if (openReceipts > 2) {
|
if (openReceipts > 6) {
|
||||||
// this prevents that these types of messages are send in case the receiver is offline
|
// this prevents that these types of messages are send in case the receiver is offline
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
@ -7,40 +5,24 @@ import 'package:twonly/locator.dart';
|
||||||
import 'package:twonly/src/constants/routes.keys.dart';
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
class FeedbackIconButtonComp extends StatefulWidget {
|
class FeedbackIconButtonComp extends StatelessWidget {
|
||||||
const FeedbackIconButtonComp({super.key});
|
const FeedbackIconButtonComp({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<FeedbackIconButtonComp> createState() => _FeedbackIconButtonCompState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _FeedbackIconButtonCompState extends State<FeedbackIconButtonComp> {
|
|
||||||
bool showFeedbackShortcut = false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
unawaited(initAsync());
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> initAsync() async {
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() {
|
|
||||||
showFeedbackShortcut = userService.currentUser.showFeedbackShortcut;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (!showFeedbackShortcut) {
|
return StreamBuilder(
|
||||||
return const SizedBox.shrink();
|
stream: userService.onUserUpdated,
|
||||||
}
|
builder: (context, asyncSnapshot) {
|
||||||
|
if (!userService.currentUser.showFeedbackShortcut) {
|
||||||
return IconButton(
|
return const SizedBox.shrink();
|
||||||
onPressed: () => context.push(Routes.settingsHelpContactUs),
|
}
|
||||||
color: Colors.grey,
|
return IconButton(
|
||||||
tooltip: context.lang.feedbackTooltip,
|
onPressed: () => context.push(Routes.settingsHelpContactUs),
|
||||||
icon: const FaIcon(FontAwesomeIcons.commentDots, size: 19),
|
color: Colors.grey,
|
||||||
|
tooltip: context.lang.feedbackTooltip,
|
||||||
|
icon: const FaIcon(FontAwesomeIcons.commentDots, size: 19),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
||||||
|
|
||||||
if (userService.currentUser.typingIndicators) {
|
if (userService.currentUser.typingIndicators) {
|
||||||
unawaited(sendTypingIndication(widget.groupId, false));
|
unawaited(sendTypingIndication(widget.groupId, false));
|
||||||
_nextTypingIndicator = Timer.periodic(const Duration(seconds: 4), (
|
_nextTypingIndicator = Timer.periodic(const Duration(seconds: 2), (
|
||||||
_,
|
_,
|
||||||
) async {
|
) async {
|
||||||
await sendTypingIndication(widget.groupId, false);
|
await sendTypingIndication(widget.groupId, false);
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ bool hasChatOpen(GroupMember member) {
|
||||||
member.lastChatOpened!,
|
member.lastChatOpened!,
|
||||||
)
|
)
|
||||||
.inSeconds <=
|
.inSeconds <=
|
||||||
6;
|
3;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypingIndicator extends StatefulWidget {
|
class TypingIndicator extends StatefulWidget {
|
||||||
|
|
|
||||||
|
|
@ -546,218 +546,215 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: SafeArea(
|
body: Stack(
|
||||||
child: Stack(
|
fit: StackFit.expand,
|
||||||
fit: StackFit.expand,
|
children: [
|
||||||
children: [
|
if (_showDownloadingLoader) _loader(),
|
||||||
if (_showDownloadingLoader) _loader(),
|
if ((currentMedia != null || videoController != null) &&
|
||||||
if ((currentMedia != null || videoController != null) &&
|
(canBeSeenUntil == null || progress >= 0))
|
||||||
(canBeSeenUntil == null || progress >= 0))
|
GestureDetector(
|
||||||
GestureDetector(
|
onTap: () {
|
||||||
onTap: () {
|
if (showSendTextMessageInput) {
|
||||||
if (showSendTextMessageInput) {
|
|
||||||
setState(() {
|
|
||||||
showShortReactions = false;
|
|
||||||
showSendTextMessageInput = false;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nextMediaOrExit();
|
|
||||||
},
|
|
||||||
child: MediaViewSizingHelper(
|
|
||||||
bottomNavigation: bottomNavigation(),
|
|
||||||
requiredHeight: 55,
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
if (videoController != null)
|
|
||||||
Positioned.fill(
|
|
||||||
child: PhotoView.customChild(
|
|
||||||
initialScale: PhotoViewComputedScale.contained,
|
|
||||||
minScale: PhotoViewComputedScale.contained,
|
|
||||||
child: VideoPlayer(videoController!),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else if (currentMedia != null &&
|
|
||||||
currentMedia!.mediaFile.type == MediaType.image ||
|
|
||||||
currentMedia!.mediaFile.type == MediaType.gif)
|
|
||||||
Positioned.fill(
|
|
||||||
child: PhotoView(
|
|
||||||
imageProvider: FileImage(
|
|
||||||
currentMedia!.tempPath,
|
|
||||||
),
|
|
||||||
initialScale: PhotoViewComputedScale.contained,
|
|
||||||
minScale: PhotoViewComputedScale.contained,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (displayTwonlyPresent)
|
|
||||||
Positioned.fill(
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () => loadCurrentMediaFile(showTwonly: true),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Lottie.asset(
|
|
||||||
'assets/animations/present.lottie.lottie',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(bottom: 200),
|
|
||||||
child: Text(context.lang.mediaViewerTwonlyTapToOpen),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
left: 10,
|
|
||||||
top: 10,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.close, size: 30),
|
|
||||||
color: Colors.white,
|
|
||||||
onPressed: () => Navigator.pop(context),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (currentMedia != null &&
|
|
||||||
currentMedia?.mediaFile.downloadState != DownloadState.ready)
|
|
||||||
Positioned.fill(child: _loader()),
|
|
||||||
if (canBeSeenUntil != null || progress >= 0)
|
|
||||||
Positioned(
|
|
||||||
right: 20,
|
|
||||||
top: 27,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
value: progress,
|
|
||||||
strokeWidth: 2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
top: 10,
|
|
||||||
left: showSendTextMessageInput ? 0 : null,
|
|
||||||
right: showSendTextMessageInput ? 0 : 15,
|
|
||||||
child: Text(
|
|
||||||
_currentMediaSender,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: showSendTextMessageInput ? 24 : 14,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: showSendTextMessageInput
|
|
||||||
? null
|
|
||||||
: const Color.fromARGB(255, 126, 126, 126),
|
|
||||||
shadows: const [
|
|
||||||
Shadow(
|
|
||||||
color: Color.fromARGB(122, 0, 0, 0),
|
|
||||||
blurRadius: 5,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (showSendTextMessageInput)
|
|
||||||
Positioned(
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
child: Container(
|
|
||||||
color: context.color.surface,
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
bottom: 10,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
top: 10,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
icon: const FaIcon(FontAwesomeIcons.xmark),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
showShortReactions = false;
|
|
||||||
showSendTextMessageInput = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: TextField(
|
|
||||||
autofocus: true,
|
|
||||||
controller: textMessageController,
|
|
||||||
onChanged: (value) async {
|
|
||||||
await twonlyDB.groupsDao.updateGroup(
|
|
||||||
widget.group.groupId,
|
|
||||||
GroupsCompanion(
|
|
||||||
draftMessage: Value(textMessageController.text),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onEditingComplete: () {
|
|
||||||
setState(() {
|
|
||||||
showSendTextMessageInput = false;
|
|
||||||
showShortReactions = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
decoration: inputTextMessageDeco(
|
|
||||||
context,
|
|
||||||
context.lang.chatListDetailInput,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const FaIcon(FontAwesomeIcons.solidPaperPlane),
|
|
||||||
onPressed: () async {
|
|
||||||
if (textMessageController.text.isNotEmpty) {
|
|
||||||
await insertAndSendTextMessage(
|
|
||||||
widget.group.groupId,
|
|
||||||
textMessageController.text,
|
|
||||||
currentMessage!.messageId,
|
|
||||||
);
|
|
||||||
textMessageController.clear();
|
|
||||||
}
|
|
||||||
setState(() {
|
|
||||||
showSendTextMessageInput = false;
|
|
||||||
showShortReactions = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (currentMessage != null)
|
|
||||||
AdditionalMessageContent(currentMessage!),
|
|
||||||
if (currentMedia != null)
|
|
||||||
ReactionButtons(
|
|
||||||
show: showShortReactions,
|
|
||||||
textInputFocused: showSendTextMessageInput,
|
|
||||||
mediaViewerDistanceFromBottom: mediaViewerDistanceFromBottom,
|
|
||||||
groupId: widget.group.groupId,
|
|
||||||
messageId: currentMessage!.messageId,
|
|
||||||
emojiKey: emojiKey,
|
|
||||||
hide: () {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
showShortReactions = false;
|
showShortReactions = false;
|
||||||
showSendTextMessageInput = false;
|
showSendTextMessageInput = false;
|
||||||
});
|
});
|
||||||
},
|
return;
|
||||||
|
}
|
||||||
|
nextMediaOrExit();
|
||||||
|
},
|
||||||
|
child: MediaViewSizingHelper(
|
||||||
|
bottomNavigation: bottomNavigation(),
|
||||||
|
requiredHeight: 55,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
if (videoController != null)
|
||||||
|
Positioned.fill(
|
||||||
|
child: PhotoView.customChild(
|
||||||
|
initialScale: PhotoViewComputedScale.contained,
|
||||||
|
minScale: PhotoViewComputedScale.contained,
|
||||||
|
child: VideoPlayer(videoController!),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else if (currentMedia != null &&
|
||||||
|
currentMedia!.mediaFile.type == MediaType.image ||
|
||||||
|
currentMedia!.mediaFile.type == MediaType.gif)
|
||||||
|
Positioned.fill(
|
||||||
|
child: PhotoView(
|
||||||
|
imageProvider: FileImage(
|
||||||
|
currentMedia!.tempPath,
|
||||||
|
),
|
||||||
|
initialScale: PhotoViewComputedScale.contained,
|
||||||
|
minScale: PhotoViewComputedScale.contained,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Positioned.fill(
|
|
||||||
child: EmojiFloatWidget(key: emojiKey),
|
|
||||||
),
|
),
|
||||||
],
|
if (displayTwonlyPresent)
|
||||||
),
|
Positioned.fill(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => loadCurrentMediaFile(showTwonly: true),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Lottie.asset(
|
||||||
|
'assets/animations/present.lottie.lottie',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(bottom: 200),
|
||||||
|
child: Text(context.lang.mediaViewerTwonlyTapToOpen),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
left: 10,
|
||||||
|
top: 10,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.close, size: 30),
|
||||||
|
color: Colors.white,
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (currentMedia != null &&
|
||||||
|
currentMedia?.mediaFile.downloadState != DownloadState.ready)
|
||||||
|
Positioned.fill(child: _loader()),
|
||||||
|
if (canBeSeenUntil != null || progress >= 0)
|
||||||
|
Positioned(
|
||||||
|
right: 20,
|
||||||
|
top: 27,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
value: progress,
|
||||||
|
strokeWidth: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
top: 10,
|
||||||
|
left: showSendTextMessageInput ? 0 : null,
|
||||||
|
right: showSendTextMessageInput ? 0 : 15,
|
||||||
|
child: Text(
|
||||||
|
_currentMediaSender,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: showSendTextMessageInput ? 24 : 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: showSendTextMessageInput
|
||||||
|
? null
|
||||||
|
: const Color.fromARGB(255, 126, 126, 126),
|
||||||
|
shadows: const [
|
||||||
|
Shadow(
|
||||||
|
color: Color.fromARGB(122, 0, 0, 0),
|
||||||
|
blurRadius: 5,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (showSendTextMessageInput)
|
||||||
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Container(
|
||||||
|
color: context.color.surface,
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10,
|
||||||
|
left: 20,
|
||||||
|
right: 20,
|
||||||
|
top: 10,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const FaIcon(FontAwesomeIcons.xmark),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
showShortReactions = false;
|
||||||
|
showSendTextMessageInput = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
autofocus: true,
|
||||||
|
controller: textMessageController,
|
||||||
|
onChanged: (value) async {
|
||||||
|
await twonlyDB.groupsDao.updateGroup(
|
||||||
|
widget.group.groupId,
|
||||||
|
GroupsCompanion(
|
||||||
|
draftMessage: Value(textMessageController.text),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onEditingComplete: () {
|
||||||
|
setState(() {
|
||||||
|
showSendTextMessageInput = false;
|
||||||
|
showShortReactions = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
decoration: inputTextMessageDeco(
|
||||||
|
context,
|
||||||
|
context.lang.chatListDetailInput,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const FaIcon(FontAwesomeIcons.solidPaperPlane),
|
||||||
|
onPressed: () async {
|
||||||
|
if (textMessageController.text.isNotEmpty) {
|
||||||
|
await insertAndSendTextMessage(
|
||||||
|
widget.group.groupId,
|
||||||
|
textMessageController.text,
|
||||||
|
currentMessage!.messageId,
|
||||||
|
);
|
||||||
|
textMessageController.clear();
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
showSendTextMessageInput = false;
|
||||||
|
showShortReactions = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (currentMessage != null) AdditionalMessageContent(currentMessage!),
|
||||||
|
if (currentMedia != null)
|
||||||
|
ReactionButtons(
|
||||||
|
show: showShortReactions,
|
||||||
|
textInputFocused: showSendTextMessageInput,
|
||||||
|
mediaViewerDistanceFromBottom: mediaViewerDistanceFromBottom,
|
||||||
|
groupId: widget.group.groupId,
|
||||||
|
messageId: currentMessage!.messageId,
|
||||||
|
emojiKey: emojiKey,
|
||||||
|
hide: () {
|
||||||
|
setState(() {
|
||||||
|
showShortReactions = false;
|
||||||
|
showSendTextMessageInput = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Positioned.fill(
|
||||||
|
child: EmojiFloatWidget(key: emojiKey),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
||||||
.get_own_promotions_after_version(received_version.promotion)
|
.get_own_promotions_after_version(received_version.promotion)
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|x| x.is_empty()) // filter ignored versions
|
.filter(|x| !x.is_empty()) // filter ignored versions
|
||||||
.collect();
|
.collect();
|
||||||
messages.extend_from_slice(&promoting_messages);
|
messages.extend_from_slice(&promoting_messages);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue