This commit is contained in:
otsmr 2025-03-09 11:37:22 +01:00
parent f7306fe7db
commit cfd6bd92cb
8 changed files with 192 additions and 153 deletions

View file

@ -44,7 +44,7 @@ class _UserContextMenuState extends State<UserContextMenu> {
onSelect: () { onSelect: () {
Navigator.push(context, MaterialPageRoute( Navigator.push(context, MaterialPageRoute(
builder: (context) { builder: (context) {
return ChatItemDetailsView(user: widget.contact); return ChatItemDetailsView(widget.contact.userId);
}, },
)); ));
}, },

View file

@ -26,20 +26,35 @@ class TwonlyDatabase extends _$TwonlyDatabase {
// ------------ // ------------
Stream<List<Message>> watchMessageNotOpened(int userId) { Stream<List<Message>> watchMessageNotOpened(int contactId) {
return (select(messages) return (select(messages)
..where((t) => t.openedAt.isNull() & t.contactId.equals(userId))) ..where((t) => t.openedAt.isNull() & t.contactId.equals(contactId)))
.watch(); .watch();
} }
Stream<Message?> watchLastMessage(int userId) { Stream<Message?> watchLastMessage(int contactId) {
return (select(messages) return (select(messages)
..where((t) => t.contactId.equals(userId)) ..where((t) => t.contactId.equals(contactId))
..orderBy([(t) => OrderingTerm.desc(t.sendAt)]) ..orderBy([(t) => OrderingTerm.desc(t.sendAt)])
..limit(1)) ..limit(1))
.watchSingleOrNull(); .watchSingleOrNull();
} }
Stream<List<Message>> watchAllMessagesFrom(int contactId) {
return (select(messages)..where((t) => t.contactId.equals(contactId)))
.watch();
}
Future openedAllTextMessages(int contactId) {
final updates = MessagesCompanion(openedAt: Value(DateTime.now()));
return (update(messages)
..where((t) =>
t.contactId.equals(contactId) &
t.openedAt.isNull() &
t.kind.equals(MessageKind.textMessage.name)))
.write(updates);
}
// ------------ // ------------
Future<int> insertContact(ContactsCompanion contact) { Future<int> insertContact(ContactsCompanion contact) {
@ -72,6 +87,11 @@ class TwonlyDatabase extends _$TwonlyDatabase {
return (select(contacts)..where((t) => t.accepted.equals(false))).watch(); return (select(contacts)..where((t) => t.accepted.equals(false))).watch();
} }
Stream<Contact> watchContact(int userid) {
return (select(contacts)..where((t) => t.userId.equals(userid)))
.watchSingle();
}
Stream<List<Contact>> watchContactsForChatList() { Stream<List<Contact>> watchContactsForChatList() {
return (select(contacts) return (select(contacts)
..where((t) => t.accepted.equals(true) & t.blocked.equals(false)) ..where((t) => t.accepted.equals(true) & t.blocked.equals(false))

View file

@ -10,10 +10,9 @@ enum MessageKind {
ack ack
} }
Color getMessageColorFromType(MessageJson msg, Color primary) { Color getMessageColorFromType(MessageContent content, Color primary) {
Color color; Color color;
final content = msg.content;
if (content is TextMessageContent) { if (content is TextMessageContent) {
color = Colors.lightBlue; color = Colors.lightBlue;
} else { } else {

View file

@ -301,12 +301,12 @@ Future tryDownloadMedia(int messageId, int fromUserId, List<int> mediaToken,
apiProvider.triggerDownload(mediaToken, offset); apiProvider.triggerDownload(mediaToken, offset);
} }
Future userOpenedOtherMessage(int fromUserId, int messageOtherId) async { Future notifyContactAboutOpeningMessage(int fromUserId, int messageOtherId) async {
await DbMessages.userOpenedOtherMessage(fromUserId, messageOtherId); //await DbMessages.userOpenedOtherMessage(fromUserId, messageOtherId);
encryptAndSendMessage( encryptAndSendMessage(
Int64(fromUserId), fromUserId,
Message( MessageJson(
kind: MessageKind.opened, kind: MessageKind.opened,
messageId: messageOtherId, messageId: messageOtherId,
content: MessageContent(), content: MessageContent(),

View file

@ -1,12 +1,12 @@
import 'package:fixnum/fixnum.dart';
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:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/src/components/image_editor/action_button.dart'; import 'package:twonly/src/components/image_editor/action_button.dart';
import 'package:twonly/src/components/media_view_sizing.dart'; import 'package:twonly/src/components/media_view_sizing.dart';
import 'package:twonly/src/components/notification_badge.dart'; import 'package:twonly/src/components/notification_badge.dart';
import 'package:twonly/src/database/contacts_db.dart';
import 'package:twonly/src/database/database.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/providers/api/api.dart';
import 'package:twonly/src/providers/contacts_change_provider.dart';
import 'package:twonly/src/providers/send_next_media_to.dart'; import 'package:twonly/src/providers/send_next_media_to.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/camera_to_share/share_image_view.dart'; import 'package:twonly/src/views/camera_to_share/share_image_view.dart';
@ -35,6 +35,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
bool _imageSaving = false; bool _imageSaving = false;
bool _isRealTwonly = false; bool _isRealTwonly = false;
int _maxShowTime = 18; int _maxShowTime = 18;
String? sendNextMediaToUserName;
ImageItem currentImage = ImageItem(); ImageItem currentImage = ImageItem();
ScreenshotController screenshotController = ScreenshotController(); ScreenshotController screenshotController = ScreenshotController();
@ -51,6 +52,15 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
super.dispose(); super.dispose();
} }
Future updateAsync(int userId) async {
if (sendNextMediaToUserName != null) return;
Contact? contact =
await context.db.getContactByUserId(userId).getSingleOrNull();
if (contact != null) {
sendNextMediaToUserName = getContactDisplayName(contact);
}
}
List<Widget> get actionsAtTheRight { List<Widget> get actionsAtTheRight {
if (layers.isNotEmpty && if (layers.isNotEmpty &&
layers.last.isEditing && layers.last.isEditing &&
@ -229,13 +239,9 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
int? sendNextMediaToUserId = int? sendNextMediaToUserId =
context.watch<SendNextMediaTo>().sendNextMediaToUserId; context.watch<SendNextMediaTo>().sendNextMediaToUserId;
String? sendNextMediaToUserName;
if (sendNextMediaToUserId != null) { if (sendNextMediaToUserId != null) {
sendNextMediaToUserName = context updateAsync(sendNextMediaToUserId);
.watch<ContactChangeProvider>()
.allContacts
.firstWhere((x) => x.userId == sendNextMediaToUserId)
.displayName;
} }
return Scaffold( return Scaffold(
@ -406,7 +412,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
label: Text( label: Text(
(sendNextMediaToUserName == null) (sendNextMediaToUserName == null)
? context.lang.shareImagedEditorShareWith ? context.lang.shareImagedEditorShareWith
: sendNextMediaToUserName, : sendNextMediaToUserName!,
style: TextStyle(fontSize: 17), style: TextStyle(fontSize: 17),
), ),
), ),

View file

@ -1,4 +1,6 @@
import 'dart:async';
import 'dart:collection'; import 'dart:collection';
import 'dart:convert';
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:provider/provider.dart'; import 'package:provider/provider.dart';
@ -6,13 +8,11 @@ import 'package:twonly/src/components/animate_icon.dart';
import 'package:twonly/src/components/initialsavatar.dart'; import 'package:twonly/src/components/initialsavatar.dart';
import 'package:twonly/src/components/message_send_state_icon.dart'; import 'package:twonly/src/components/message_send_state_icon.dart';
import 'package:twonly/src/components/verified_shield.dart'; import 'package:twonly/src/components/verified_shield.dart';
import '../../../../.blocked/archives/contacts_model.dart'; import 'package:twonly/src/database/contacts_db.dart';
import 'package:twonly/src/database/database.dart';
import 'package:twonly/src/database/messages_db.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import '../../../../.blocked/archives/messages_model.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/providers/api/api.dart';
import 'package:twonly/src/providers/contacts_change_provider.dart';
import 'package:twonly/src/providers/download_change_provider.dart';
import 'package:twonly/src/providers/messages_change_provider.dart';
import 'package:twonly/src/providers/send_next_media_to.dart'; import 'package:twonly/src/providers/send_next_media_to.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification_service.dart';
import 'package:twonly/src/views/chats/media_viewer_view.dart'; import 'package:twonly/src/views/chats/media_viewer_view.dart';
@ -21,27 +21,25 @@ import 'package:twonly/src/views/contact/contact_view.dart';
import 'package:twonly/src/views/home_view.dart'; import 'package:twonly/src/views/home_view.dart';
class ChatListEntry extends StatelessWidget { class ChatListEntry extends StatelessWidget {
const ChatListEntry(this.message, this.user, this.lastMessageFromSameUser, const ChatListEntry(this.message, this.userId, this.lastMessageFromSameUser,
{super.key}); {super.key});
final DbMessage message; final Message message;
final Contact user; final int userId;
final bool lastMessageFromSameUser; final bool lastMessageFromSameUser;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool right = message.messageOtherId == null; bool right = message.messageOtherId == null;
MessageSendState state = message.getSendState(); MessageSendState state = messageSendStateFromMessage(message);
bool isDownloading = false; bool isDownloading = false;
List<int> token = []; List<int> token = [];
final content = message.messageContent; final messageJson = MessageJson.fromJson(jsonDecode(message.contentJson!));
if (message.messageReceived && content is MediaMessageContent) { final content = messageJson.content;
if (message.messageOtherId != null && content is MediaMessageContent) {
token = content.downloadToken; token = content.downloadToken;
isDownloading = context isDownloading = message.downloadState == DownloadState.downloading;
.watch<DownloadChangeProvider>()
.currentlyDownloading
.contains(token.toString());
} }
Widget child = Container(); Widget child = Container();
@ -81,20 +79,21 @@ class ChatListEntry extends StatelessWidget {
); );
} }
} else if (content is MediaMessageContent && !content.isVideo) { } else if (content is MediaMessageContent && !content.isVideo) {
Color color = message.messageContent Color color = getMessageColorFromType(
.getColor(Theme.of(context).colorScheme.primary); content, Theme.of(context).colorScheme.primary);
child = GestureDetector( child = GestureDetector(
onTap: () { onTap: () {
if (state == MessageSendState.received && !isDownloading) { if (state == MessageSendState.received && !isDownloading) {
if (message.isDownloaded) { if (message.downloadState == DownloadState.downloaded) {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) { MaterialPageRoute(builder: (context) {
return MediaViewerView(user, message); return MediaViewerView(userId);
}), }),
); );
} else { } else {
tryDownloadMedia(message.messageId, message.otherUserId, token, tryDownloadMedia(message.messageId, message.contactId, token,
force: true); force: true);
} }
} }
@ -112,7 +111,7 @@ class ChatListEntry extends StatelessWidget {
child: Align( child: Align(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: MessageSendStateIcon( child: MessageSendStateIcon(
message, [message],
mainAxisAlignment: mainAxisAlignment:
right ? MainAxisAlignment.center : MainAxisAlignment.center, right ? MainAxisAlignment.center : MainAxisAlignment.center,
), ),
@ -134,9 +133,9 @@ class ChatListEntry extends StatelessWidget {
/// Displays detailed information about a SampleItem. /// Displays detailed information about a SampleItem.
class ChatItemDetailsView extends StatefulWidget { class ChatItemDetailsView extends StatefulWidget {
const ChatItemDetailsView({super.key, required this.user}); const ChatItemDetailsView(this.userid, {super.key});
final Contact user; final int userid;
@override @override
State<ChatItemDetailsView> createState() => _ChatItemDetailsViewState(); State<ChatItemDetailsView> createState() => _ChatItemDetailsViewState();
@ -145,86 +144,99 @@ class ChatItemDetailsView extends StatefulWidget {
class _ChatItemDetailsViewState extends State<ChatItemDetailsView> { class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
TextEditingController newMessageController = TextEditingController(); TextEditingController newMessageController = TextEditingController();
HashSet<int> alreadyReportedOpened = HashSet<int>(); HashSet<int> alreadyReportedOpened = HashSet<int>();
late Contact user; Contact? user;
String currentInputText = ""; String currentInputText = "";
late StreamSubscription<Contact> userSub;
late StreamSubscription<List<Message>> messageSub;
List<Message> messages = [];
@override @override
void initState() { void initState() {
super.initState(); super.initState();
user = widget.user; initStreams();
context
.read<MessagesChangeProvider>()
.loadMessagesForUser(user.userId.toInt());
initAsync();
} }
Future initAsync() async { @override
context void dispose() {
.read<MessagesChangeProvider>() super.dispose();
.loadMessagesForUser(user.userId.toInt(), force: true); userSub.cancel();
setState(() {}); messageSub.cancel();
}
Future initStreams() async {
Stream<Contact> contact = context.db.watchContact(widget.userid);
userSub = contact.listen((contact) {
setState(() {
user = contact;
});
});
Stream<List<Message>> msgStream =
context.db.watchAllMessagesFrom(widget.userid);
messageSub = msgStream.listen((msgs) {
if (!context.mounted) return;
var updated = false;
for (Message msg in msgs) {
if (msg.kind == MessageKind.textMessage &&
msg.messageOtherId != null &&
msg.openedAt == null) {
updated = true;
flutterLocalNotificationsPlugin.cancel(msg.messageId);
notifyContactAboutOpeningMessage(widget.userid, msg.messageOtherId!);
}
}
if (updated) {
context.db.openedAllTextMessages(widget.userid);
} else {
// The stream should be get an update, so only update the UI when all are opened
setState(() {
messages = msgs;
});
}
});
} }
Future _sendMessage() async { Future _sendMessage() async {
if (newMessageController.text == "") return; if (newMessageController.text == "" || user == null) return;
setState(() {}); await sendTextMessage(user!.userId, newMessageController.text);
await sendTextMessage(user.userId, newMessageController.text);
newMessageController.clear(); newMessageController.clear();
currentInputText = ""; currentInputText = "";
setState(() {});
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
user = context
.watch<ContactChangeProvider>()
.allContacts
.firstWhere((c) => c.userId == widget.user.userId);
List<DbMessage> messages = context
.watch<MessagesChangeProvider>()
.allMessagesFromUser[user.userId.toInt()] ??
[];
messages.where((x) => x.messageOpenedAt == null).forEach((message) {
if (message.messageOtherId != null &&
message.messageContent is TextMessageContent) {
if (!alreadyReportedOpened.contains(message.messageOtherId!)) {
userOpenedOtherMessage(message.otherUserId, message.messageOtherId!);
flutterLocalNotificationsPlugin.cancel(message.messageId);
alreadyReportedOpened.add(message.messageOtherId!);
}
}
});
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: GestureDetector( title: GestureDetector(
onTap: () { onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) { Navigator.push(context, MaterialPageRoute(builder: (context) {
return ContactView(user.userId.toInt()); return ContactView(widget.userid);
})); }));
}, },
child: Row( child: (user == null)
children: [ ? Container()
InitialsAvatar( : Row(
displayName: user.displayName, children: [
fontSize: 19, InitialsAvatar(
), getContactDisplayName(user!),
SizedBox(width: 10), fontSize: 19,
Expanded( ),
child: Container( SizedBox(width: 10),
color: Colors.transparent, Expanded(
child: Row( child: Container(
children: [ color: Colors.transparent,
Text(user.displayName), child: Row(
SizedBox(width: 10), children: [
VerifiedShield(user), Text(getContactDisplayName(user!)),
], SizedBox(width: 10),
), VerifiedShield(user!),
],
),
),
),
],
), ),
),
],
),
), ),
), ),
body: Column( body: Column(
@ -242,17 +254,17 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
(messages[i - 1].messageOtherId != null && (messages[i - 1].messageOtherId != null &&
messages[i].messageOtherId != null); messages[i].messageOtherId != null);
} }
if (messages[i].messageOpenedAt != null) { // if (messages[i].openedAt != null) {
if (calculateTimeDifference( // if (calculateTimeDifference(
DateTime.now(), messages[i].messageOpenedAt!) // DateTime.now(), messages[i].openedAt!)
.inHours >= // .inHours >=
24) { // 24) {
return Container(); // return Container();
} // }
} // }
return ChatListEntry( return ChatListEntry(
messages[i], messages[i],
user, widget.userid,
lastMessageFromSameUser, lastMessageFromSameUser,
); );
}, },
@ -310,8 +322,9 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
: IconButton( : IconButton(
icon: FaIcon(FontAwesomeIcons.camera), icon: FaIcon(FontAwesomeIcons.camera),
onPressed: () { onPressed: () {
context.read<SendNextMediaTo>().updateSendNextMediaTo( context
widget.user.userId.toInt()); .read<SendNextMediaTo>()
.updateSendNextMediaTo(widget.userid);
globalUpdateOfHomeViewPageIndex(0); globalUpdateOfHomeViewPageIndex(0);
Navigator.popUntil(context, (route) => route.isFirst); Navigator.popUntil(context, (route) => route.isFirst);
}, },

View file

@ -283,7 +283,7 @@ class _UserListItem extends State<UserListItem> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) { MaterialPageRoute(builder: (context) {
return MediaViewerView(widget.user, msg); return MediaViewerView(widget.user.userId);
}), }),
); );
return; return;
@ -291,7 +291,7 @@ class _UserListItem extends State<UserListItem> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) { MaterialPageRoute(builder: (context) {
return ChatItemDetailsView(user: widget.user); return ChatItemDetailsView(widget.user.userId);
}), }),
); );
}, },

View file

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
@ -7,11 +8,10 @@ import 'package:no_screenshot/no_screenshot.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/src/components/animate_icon.dart'; import 'package:twonly/src/components/animate_icon.dart';
import 'package:twonly/src/components/media_view_sizing.dart'; import 'package:twonly/src/components/media_view_sizing.dart';
import '../../../../.blocked/archives/contacts_model.dart'; import 'package:twonly/src/database/database.dart';
import 'package:twonly/src/database/messages_db.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import '../../../../.blocked/archives/messages_model.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/providers/api/api.dart';
import 'package:twonly/src/providers/messages_change_provider.dart';
import 'package:twonly/src/providers/send_next_media_to.dart'; import 'package:twonly/src/providers/send_next_media_to.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification_service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
@ -21,9 +21,8 @@ import 'package:twonly/src/views/home_view.dart';
final _noScreenshot = NoScreenshot.instance; final _noScreenshot = NoScreenshot.instance;
class MediaViewerView extends StatefulWidget { class MediaViewerView extends StatefulWidget {
final Contact otherUser; final int userId;
final DbMessage message; const MediaViewerView(this.userId, {super.key});
const MediaViewerView(this.otherUser, this.message, {super.key});
@override @override
State<MediaViewerView> createState() => _MediaViewerViewState(); State<MediaViewerView> createState() => _MediaViewerViewState();
@ -44,35 +43,29 @@ class _MediaViewerViewState extends State<MediaViewerView> {
bool isRealTwonly = false; bool isRealTwonly = false;
bool isDownloading = false; bool isDownloading = false;
List<DbMessage> allMediaFiles = []; List<Message> allMediaFiles = [];
late StreamSubscription<List<Message>> _subscription;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
allMediaFiles = [widget.message];
asyncLoadNextMedia(); asyncLoadNextMedia();
loadCurrentMediaFile(); loadCurrentMediaFile();
} }
Future asyncLoadNextMedia() async { Future asyncLoadNextMedia() async {
await context Stream<List<Message>> messages =
.read<MessagesChangeProvider>() context.db.watchMessageNotOpened(widget.userId);
.loadMessagesForUser(widget.otherUser.userId.toInt());
if (!context.mounted) return; _subscription = messages.listen((messages) {
final allMessages = context for (Message msg in messages) {
.read<MessagesChangeProvider>() if (!allMediaFiles.any((m) => m.messageId == msg.messageId)) {
.allMessagesFromUser[widget.otherUser.userId.toInt()]; allMediaFiles.add(msg);
if (allMessages == null) { }
return; }
} setState(() {});
final nextMediaFiles = allMessages.where((x) => });
x.isMedia() &&
x.messageOtherId != null &&
x.messageOpenedAt == null &&
x.messageId != widget.message.messageId);
allMediaFiles.addAll(nextMediaFiles.map((x) => x));
setState(() {});
} }
Future nextMediaOrExit() async { Future nextMediaOrExit() async {
@ -92,7 +85,10 @@ class _MediaViewerViewState extends State<MediaViewerView> {
await _noScreenshot.screenshotOff(); await _noScreenshot.screenshotOff();
if (!context.mounted || allMediaFiles.isEmpty) return; if (!context.mounted || allMediaFiles.isEmpty) return;
final DbMessage current = allMediaFiles.first; final Message current = allMediaFiles.first;
final MessageJson messageJson =
MessageJson.fromJson(jsonDecode(current.contentJson!));
final MessageContent? content = messageJson.content;
setState(() { setState(() {
// reset current image values // reset current image values
@ -101,16 +97,19 @@ class _MediaViewerViewState extends State<MediaViewerView> {
maxShowTime = 999999; maxShowTime = 999999;
progress = 0; progress = 0;
isDownloading = false; isDownloading = false;
isRealTwonly = current.isRealTwonly(); isRealTwonly = false;
}); });
// This will show the extra screen for the twonly
if (current.isRealTwonly() && !showTwonly) {
return;
}
final content = current.messageContent;
if (content is MediaMessageContent) { if (content is MediaMessageContent) {
if (content.isRealTwonly) {
setState(() {
isRealTwonly = true;
});
if (!showTwonly) {
return;
}
}
if (isRealTwonly) { if (isRealTwonly) {
bool isAuth = await authenticateUser(context.lang.mediaViewerAuthReason, bool isAuth = await authenticateUser(context.lang.mediaViewerAuthReason,
force: false); force: false);
@ -120,22 +119,22 @@ class _MediaViewerViewState extends State<MediaViewerView> {
} }
} }
flutterLocalNotificationsPlugin.cancel(current.messageId); flutterLocalNotificationsPlugin.cancel(current.messageId);
if (!current.isDownloaded) { if (current.downloadState == DownloadState.pending) {
setState(() { setState(() {
isDownloading = true; isDownloading = true;
}); });
await tryDownloadMedia( await tryDownloadMedia(
current.messageId, current.otherUserId, content.downloadToken, current.messageId, current.contactId, content.downloadToken,
force: true); force: true);
} }
do { do {
if (isDownloading) { if (isDownloading) {
await Future.delayed(Duration(milliseconds: 100)); await Future.delayed(Duration(milliseconds: 10));
} }
imageBytes = await getDownloadedMedia( imageBytes = await getDownloadedMedia(
content.downloadToken, content.downloadToken,
current.messageOtherId!, current.messageOtherId!,
current.otherUserId, current.contactId,
); );
} while (isDownloading && imageBytes == null); } while (isDownloading && imageBytes == null);
@ -181,6 +180,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
nextMediaTimer?.cancel(); nextMediaTimer?.cancel();
progressTimer?.cancel(); progressTimer?.cancel();
_noScreenshot.screenshotOn(); _noScreenshot.screenshotOn();
_subscription.cancel();
} }
@override @override
@ -303,7 +303,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
curve: Curves.linearToEaseOut, curve: Curves.linearToEaseOut,
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
sendTextMessage(widget.otherUser.userId, emoji); sendTextMessage(widget.userId, emoji);
setState(() { setState(() {
selectedShortReaction = index; selectedShortReaction = index;
}); });
@ -351,8 +351,9 @@ class _MediaViewerViewState extends State<MediaViewerView> {
IconButton.outlined( IconButton.outlined(
icon: FaIcon(FontAwesomeIcons.camera), icon: FaIcon(FontAwesomeIcons.camera),
onPressed: () async { onPressed: () async {
context.read<SendNextMediaTo>().updateSendNextMediaTo( context
widget.otherUser.userId.toInt()); .read<SendNextMediaTo>()
.updateSendNextMediaTo(widget.userId.toInt());
globalUpdateOfHomeViewPageIndex(0); globalUpdateOfHomeViewPageIndex(0);
Navigator.popUntil(context, (route) => route.isFirst); Navigator.popUntil(context, (route) => route.isFirst);
}, },
@ -410,7 +411,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) { MaterialPageRoute(builder: (context) {
return ChatItemDetailsView(user: widget.otherUser); return ChatItemDetailsView(widget.userId);
}), }),
); );
}, },