improve sending image directly to other user

This commit is contained in:
otsmr 2025-04-08 14:00:23 +02:00
parent 742ad51daf
commit 1d84834a35
9 changed files with 87 additions and 103 deletions

View file

@ -7,7 +7,6 @@ import 'package:twonly/src/providers/api_provider.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:twonly/src/providers/hive.dart';
import 'package:twonly/src/providers/send_next_media_to.dart';
import 'package:twonly/src/providers/settings_change_provider.dart';
import 'package:twonly/src/services/fcm_service.dart';
import 'package:twonly/src/services/notification_service.dart';
@ -45,7 +44,6 @@ void main() async {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => SendNextMediaTo()),
ChangeNotifierProvider(create: (_) => settingsController),
],
child: MyApp(),

View file

@ -1,10 +1,9 @@
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:pie_menu/pie_menu.dart';
import 'package:provider/provider.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/providers/send_next_media_to.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/chats/chat_item_details_view.dart';
import 'package:twonly/src/views/contact/contact_verify_view.dart';
import 'package:twonly/src/views/home_view.dart';
@ -53,9 +52,7 @@ class _UserContextMenuState extends State<UserContextMenu> {
PieAction(
tooltip: Text(context.lang.contextMenuSendImage),
onSelect: () {
context
.read<SendNextMediaTo>()
.updateSendNextMediaTo(widget.contact.userId.toInt());
globalSendNextMediaToUser = widget.contact;
globalUpdateOfHomeViewPageIndex(0);
},
child: const FaIcon(FontAwesomeIcons.camera),

View file

@ -1,12 +0,0 @@
import 'package:flutter/foundation.dart';
// This provider will update the UI on changes in the contact list
class SendNextMediaTo with ChangeNotifier, DiagnosticableTreeMixin {
int? _sendNextMediaToUserId;
int? get sendNextMediaToUserId => _sendNextMediaToUserId;
void updateSendNextMediaTo(int? userId) {
_sendNextMediaToUserId = userId;
notifyListeners();
}
}

View file

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/components/image_editor/action_button.dart';
import 'package:twonly/src/components/media_view_sizing.dart';
@ -8,7 +7,6 @@ import 'package:twonly/src/components/notification_badge.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/providers/api/media.dart';
import 'package:twonly/src/providers/send_next_media_to.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/camera_to_share/share_image_view.dart';
@ -39,6 +37,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
int maxShowTime = 999999;
String? sendNextMediaToUserName;
double tabDownPostion = 0;
bool sendingImage = false;
ImageItem currentImage = ImageItem();
ScreenshotController screenshotController = ScreenshotController();
@ -261,11 +260,9 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
Widget build(BuildContext context) {
pixelRatio = MediaQuery.of(context).devicePixelRatio;
int? sendNextMediaToUserId =
context.watch<SendNextMediaTo>().sendNextMediaToUserId;
if (sendNextMediaToUserId != null) {
updateAsync(sendNextMediaToUserId);
if (globalSendNextMediaToUser != null) {
sendNextMediaToUserName =
getContactDisplayName(globalSendNextMediaToUser!);
}
return Scaffold(
@ -410,9 +407,22 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
if (sendNextMediaToUserName != null) SizedBox(width: 10),
if (sendNextMediaToUserName == null) SizedBox(width: 20),
FilledButton.icon(
icon: FaIcon(FontAwesomeIcons.solidPaperPlane),
icon: sendingImage
? SizedBox(
height: 12,
width: 12,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Theme.of(context).colorScheme.inversePrimary,
),
)
: FaIcon(FontAwesomeIcons.solidPaperPlane),
onPressed: () async {
if (sendNextMediaToUserId != null) {
if (sendingImage) return;
setState(() {
sendingImage = true;
});
if (globalSendNextMediaToUser != null) {
Uint8List? imageBytes = await getMergedImage();
if (!context.mounted) return;
if (imageBytes == null) {
@ -420,15 +430,13 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
return;
}
sendImage(
[sendNextMediaToUserId],
[globalSendNextMediaToUser!.userId],
imageBytes,
_isRealTwonly,
maxShowTime,
);
Navigator.popUntil(context, (route) => route.isFirst);
globalUpdateOfHomeViewPageIndex(1);
// send hier...
return;
}
Future<Uint8List?> imageBytes = getMergedImage();

View file

@ -3,7 +3,6 @@ import 'dart:collection';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/components/best_friends_selector.dart';
import 'package:twonly/src/components/flame.dart';
@ -13,10 +12,11 @@ import 'package:twonly/src/components/verified_shield.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/providers/api/media.dart';
import 'package:twonly/src/providers/send_next_media_to.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/home_view.dart';
Contact? globalSendNextMediaToUser;
class ShareImageView extends StatefulWidget {
const ShareImageView(
{super.key,
@ -47,10 +47,8 @@ class _ShareImageView extends State<ShareImageView> {
void initState() {
super.initState();
int? sendNextMediaToUserId =
context.read<SendNextMediaTo>().sendNextMediaToUserId;
if (sendNextMediaToUserId != null) {
_selectedUserIds.add(sendNextMediaToUserId);
if (globalSendNextMediaToUser != null) {
_selectedUserIds.add(globalSendNextMediaToUser!.userId);
}
Stream<List<Contact>> allContacts =

View file

@ -3,7 +3,6 @@ import 'dart:collection';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/components/animate_icon.dart';
import 'package:twonly/src/components/better_text.dart';
@ -16,8 +15,8 @@ import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/json_models/message.dart';
import 'package:twonly/src/providers/api/api.dart';
import 'package:twonly/src/providers/api/media.dart';
import 'package:twonly/src/providers/send_next_media_to.dart';
import 'package:twonly/src/services/notification_service.dart';
import 'package:twonly/src/views/camera_to_share/share_image_view.dart';
import 'package:twonly/src/views/chats/media_viewer_view.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/contact/contact_view.dart';
@ -25,10 +24,10 @@ import 'package:twonly/src/views/home_view.dart';
class ChatListEntry extends StatelessWidget {
const ChatListEntry(
this.message, this.userId, this.lastMessageFromSameUser, this.reactions,
this.message, this.contact, this.lastMessageFromSameUser, this.reactions,
{super.key});
final Message message;
final int userId;
final Contact contact;
final bool lastMessageFromSameUser;
final List<Message> reactions;
@ -71,10 +70,13 @@ class ChatListEntry extends StatelessWidget {
} else {
child = Text(content.text, style: TextStyle(fontSize: 14));
}
children.add(Padding(
children.insert(
0,
Padding(
padding: EdgeInsets.only(left: 3),
child: child,
));
),
);
}
}
@ -136,7 +138,7 @@ class ChatListEntry extends StatelessWidget {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return MediaViewerView(userId);
return MediaViewerView(contact);
}),
);
} else {
@ -354,6 +356,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
body: SafeArea(
child: Column(
children: [
if (user != null)
Expanded(
child: ListView.builder(
itemCount: messages.length,
@ -375,11 +378,12 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
if (msg.messageOtherId != null &&
reactionsToOtherMessages
.containsKey(msg.messageOtherId!)) {
reactions = reactionsToOtherMessages[msg.messageOtherId!]!;
reactions =
reactionsToOtherMessages[msg.messageOtherId!]!;
}
return ChatListEntry(
msg,
widget.userid,
user!,
lastMessageFromSameUser,
reactions,
);
@ -436,9 +440,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
: IconButton(
icon: FaIcon(FontAwesomeIcons.camera),
onPressed: () {
context
.read<SendNextMediaTo>()
.updateSendNextMediaTo(widget.userid);
globalSendNextMediaToUser = user;
globalUpdateOfHomeViewPageIndex(0);
Navigator.popUntil(
context, (route) => route.isFirst);

View file

@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/components/flame.dart';
import 'package:twonly/src/components/initialsavatar.dart';
@ -13,8 +12,8 @@ import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/json_models/message.dart';
import 'package:twonly/src/providers/api/media.dart';
import 'package:twonly/src/providers/send_next_media_to.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/chats/chat_item_details_view.dart';
import 'package:twonly/src/views/chats/media_viewer_view.dart';
import 'package:twonly/src/views/home_view.dart';
@ -277,9 +276,7 @@ class _UserListItem extends State<UserListItem> {
leading: ContactAvatar(contact: widget.user),
onTap: () {
if (currentMessage == null) {
context
.read<SendNextMediaTo>()
.updateSendNextMediaTo(widget.user.userId.toInt());
globalSendNextMediaToUser = widget.user;
globalUpdateOfHomeViewPageIndex(0);
return;
}
@ -301,7 +298,7 @@ class _UserListItem extends State<UserListItem> {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return MediaViewerView(widget.user.userId);
return MediaViewerView(widget.user);
}),
);
default:

View file

@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:lottie/lottie.dart';
import 'package:no_screenshot/no_screenshot.dart';
import 'package:provider/provider.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/components/animate_icon.dart';
import 'package:twonly/src/components/media_view_sizing.dart';
@ -14,17 +13,17 @@ import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/json_models/message.dart';
import 'package:twonly/src/providers/api/api.dart';
import 'package:twonly/src/providers/api/media.dart';
import 'package:twonly/src/providers/send_next_media_to.dart';
import 'package:twonly/src/services/notification_service.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/chats/chat_item_details_view.dart';
import 'package:twonly/src/views/home_view.dart';
final _noScreenshot = NoScreenshot.instance;
class MediaViewerView extends StatefulWidget {
final int userId;
const MediaViewerView(this.userId, {super.key});
final Contact contact;
const MediaViewerView(this.contact, {super.key});
@override
State<MediaViewerView> createState() => _MediaViewerViewState();
@ -59,8 +58,8 @@ class _MediaViewerViewState extends State<MediaViewerView> {
}
Future asyncLoadNextMedia(bool firstRun) async {
Stream<List<Message>> messages =
twonlyDatabase.messagesDao.watchMediaMessageNotOpened(widget.userId);
Stream<List<Message>> messages = twonlyDatabase.messagesDao
.watchMediaMessageNotOpened(widget.contact.userId);
_subscription = messages.listen((messages) {
for (Message msg in messages) {
@ -329,7 +328,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
child: GestureDetector(
onTap: () {
sendTextMessage(
widget.userId,
widget.contact.userId,
TextMessageContent(
text: emoji,
responseToMessageId:
@ -400,7 +399,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
});
encryptAndSendMessage(
null,
widget.userId,
widget.contact.userId,
MessageJson(
kind: MessageKind.storedMediaFile,
messageId: allMediaFiles.first.messageId,
@ -477,7 +476,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return ChatItemDetailsView(widget.userId);
return ChatItemDetailsView(widget.contact.userId);
}),
);
},
@ -491,9 +490,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
IconButton.outlined(
icon: FaIcon(FontAwesomeIcons.camera),
onPressed: () async {
context
.read<SendNextMediaTo>()
.updateSendNextMediaTo(widget.userId.toInt());
globalSendNextMediaToUser = widget.contact;
globalUpdateOfHomeViewPageIndex(0);
Navigator.popUntil(context, (route) => route.isFirst);
},

View file

@ -1,9 +1,8 @@
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:pie_menu/pie_menu.dart';
import 'package:provider/provider.dart';
import 'package:twonly/src/providers/send_next_media_to.dart';
import 'package:twonly/src/services/notification_service.dart';
import 'package:twonly/src/views/camera_to_share/share_image_view.dart';
import 'camera_to_share/camera_preview_view.dart';
import 'chats/chat_list_view.dart';
import 'package:flutter/material.dart';
@ -29,7 +28,7 @@ class HomeViewState extends State<HomeView> {
homeViewPageController = PageController(initialPage: widget.initialPage);
globalUpdateOfHomeViewPageIndex = (index) {
if (index == 1) {
context.read<SendNextMediaTo>().updateSendNextMediaTo(null);
globalSendNextMediaToUser = null;
}
homeViewPageController.jumpToPage(index);
setState(() {
@ -92,7 +91,7 @@ class HomeViewState extends State<HomeView> {
controller: homeViewPageController,
onPageChanged: (index) {
if (index == 1) {
context.read<SendNextMediaTo>().updateSendNextMediaTo(null);
globalSendNextMediaToUser = null;
}
activePageIdx = index;
setState(() {});
@ -121,7 +120,7 @@ class HomeViewState extends State<HomeView> {
onTap: (int index) {
activePageIdx = index;
if (index == 1) {
context.read<SendNextMediaTo>().updateSendNextMediaTo(null);
globalSendNextMediaToUser = null;
}
setState(() {
homeViewPageController.animateToPage(