Skip to content

Commit

Permalink
TW-731: remove copy/paste images in mobile for now because of load im…
Browse files Browse the repository at this point in the history
…age in memory
  • Loading branch information
sherlockvn authored and hoangdat committed Oct 11, 2023
1 parent 9cb84df commit 65727b6
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 126 deletions.
45 changes: 18 additions & 27 deletions lib/pages/chat/chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import 'package:fluffychat/widgets/mixins/popup_context_menu_action_mixin.dart';
import 'package:fluffychat/widgets/mixins/popup_menu_widget_mixin.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart' as flutter;
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
Expand Down Expand Up @@ -780,28 +779,24 @@ class ChatController extends State<Chat>
void copySingleEventAction() async {
if (selectedEvents.length == 1) {
final event = selectedEvents.first;
final matrixFile = event.getMatrixFile() ??
await event.downloadAndDecryptAttachment(
getThumbnail: true,
);
if (event.messageType == MessageTypes.Image) {
if (matrixFile.filePath != null) {
await Clipboard.instance.copyImageAsStream(
File(matrixFile.filePath!),
mimeType: event.mimeType,
);
if (!PlatformInfos.isAndroid) {
TwakeSnackBar.show(context, L10n.of(context)!.copyImageSuccess);
}
} else if (matrixFile.bytes != null) {
await Clipboard.instance.copyImageAsBytes(
matrixFile.bytes!,
mimeType: event.mimeType,
);
if (!PlatformInfos.isAndroid) {
TwakeSnackBar.show(context, L10n.of(context)!.copyImageSuccess);
if (event.messageType == MessageTypes.Image && PlatformInfos.isWeb) {
final matrixFile = event.getMatrixFile() ??
await event.downloadAndDecryptAttachment(
getThumbnail: true,
);
try {
if (matrixFile.filePath != null) {
await Clipboard.instance.copyImageAsStream(
File(matrixFile.filePath!),
mimeType: event.mimeType,
);
} else if (matrixFile.bytes != null) {
await Clipboard.instance.copyImageAsBytes(
matrixFile.bytes!,
mimeType: event.mimeType,
);
}
} else {
} catch (e) {
TwakeSnackBar.show(context, L10n.of(context)!.copyImageFailed);
Logs().e(
'copySingleEventAction(): failed to copy file ${matrixFile.name}',
Expand All @@ -814,11 +809,7 @@ class ChatController extends State<Chat>
}

void copyEventsAction() {
flutter.Clipboard.setData(
flutter.ClipboardData(
text: _getSelectedEventString(),
),
);
Clipboard.instance.copyText(_getSelectedEventString());

showEmojiPickerNotifier.value = false;
setState(() {
Expand Down
92 changes: 33 additions & 59 deletions lib/pages/chat/input_bar.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:fluffychat/pages/chat/send_file_dialog.dart';
import 'package:fluffychat/presentation/enum/chat/popup_menu_item_web_enum.dart';
import 'package:fluffychat/presentation/extensions/text_editting_controller_extension.dart';
import 'package:fluffychat/presentation/mixins/paste_image_mixin.dart';
Expand Down Expand Up @@ -426,65 +425,40 @@ class InputBar extends StatelessWidget with PasteImageMixin {
// it sets the types for the callback incorrectly
onChanged!(text);
},
textCapitalization: TextCapitalization.sentences,
contentInsertionConfiguration: ContentInsertionConfiguration(
onContentInserted: (keyboardInsertContent) async {
if (room == null || !keyboardInsertContent.hasData) {
return;
}
await showDialog(
context: context,
useRootNavigator: PlatformInfos.isWeb,
builder: (context) {
return SendFileDialog(
room: room!,
files: [
MatrixImageFile(
name: keyboardInsertContent.uri,
bytes: keyboardInsertContent.data,
)
],
contextMenuBuilder: !PlatformInfos.isWeb
? (
BuildContext contextMenucontext,
EditableTextState editableTextState,
) {
return AdaptiveTextSelectionToolbar.editable(
anchors: editableTextState.contextMenuAnchors,
clipboardStatus: ClipboardStatus.pasteable,
onPaste: !PlatformInfos.isWeb
? () async {
if (room == null) {
// FIXME: need to handle the case when in draft chat
return;
}
editableTextState
.pasteText(SelectionChangedCause.toolbar);
}
: null,
onCopy: () {
editableTextState
.copySelection(SelectionChangedCause.toolbar);
},
onCut: () {
editableTextState
.cutSelection(SelectionChangedCause.toolbar);
},
onSelectAll: () {
editableTextState
.selectAll(SelectionChangedCause.toolbar);
},
);
},
);
},
),
contextMenuBuilder: (
BuildContext contextMenucontext,
EditableTextState editableTextState,
) {
return AdaptiveTextSelectionToolbar.editable(
anchors: editableTextState.contextMenuAnchors,
clipboardStatus: ClipboardStatus.pasteable,
onPaste: !PlatformInfos.isWeb
? () async {
if (room == null) {
// FIXME: need to handle the case when in draft chat
return;
}
await Clipboard.instance.initReader();
if (await Clipboard.instance
.isReadableImageFormat()) {
await pasteImage(context, room!);
} else {
editableTextState
.pasteText(SelectionChangedCause.toolbar);
}
}
: null,
onCopy: () {
editableTextState
.copySelection(SelectionChangedCause.toolbar);
},
onCut: () {
editableTextState
.cutSelection(SelectionChangedCause.toolbar);
},
onSelectAll: () {
editableTextState.selectAll(SelectionChangedCause.toolbar);
},
);
},
}
: null,
textCapitalization: TextCapitalization.sentences,
),
suggestionsCallback: getSuggestions,
itemBuilder: (context, suggestion) => SuggestionTile(
Expand Down
17 changes: 2 additions & 15 deletions lib/pages/chat/send_file_dialog.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:fluffychat/presentation/extensions/send_file_web_extension.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:fluffychat/utils/twake_snackbar.dart';
import 'package:flutter/material.dart';

import 'package:flutter_gen/gen_l10n/l10n.dart';
Expand Down Expand Up @@ -52,9 +53,7 @@ class SendFileDialogState extends State<SendFileDialog> {
shrinkImageMaxDimension: origImage ? null : 1600,
)
.catchError((e) {
scaffoldMessenger.showSnackBar(
SnackBar(content: Text((e as Object).toLocalizedString(context))),
);
TwakeSnackBar.show(context, (e as Object).toLocalizedString(context));
return null;
});
}
Expand Down Expand Up @@ -93,18 +92,6 @@ class SendFileDialogState extends State<SendFileDialog> {
fit: BoxFit.contain,
),
),
Row(
children: <Widget>[
Checkbox(
value: origImage,
onChanged: (v) => setState(() => origImage = v ?? false),
),
InkWell(
onTap: () => setState(() => origImage = !origImage),
child: Text('${L10n.of(context)!.sendOriginal} ($sizeString)'),
),
],
)
],
);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import 'package:fluffychat/utils/clipboard.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' as flutter;

extension TextEdittingControllerExtension on TextEditingController {
Future<void> pasteText() async {
final start = selection.start;
final end = selection.end;
Clipboard.instance.initReader();
final pastedText = await Clipboard.instance.pasteText();
if (pastedText != null) {
if (start == -1 || end == -1) {
text = pastedText + text;
selection = TextSelection.collapsed(offset: text.length);
return;
}
if (start == end) {
Expand All @@ -19,18 +20,15 @@ extension TextEdittingControllerExtension on TextEditingController {
} else {
text = text.replaceRange(start, end, pastedText);
}
selection = TextSelection.collapsed(offset: end + pastedText.length);
}
}

Future<void> copyText() async {
final start = selection.start;
final end = selection.end;
if (start < end) {
await flutter.Clipboard.setData(
flutter.ClipboardData(
text: text.substring(start, end),
),
);
await Clipboard.instance.copyText(text.substring(start, end));
}
}

Expand Down
1 change: 0 additions & 1 deletion lib/presentation/mixins/paste_image_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';

mixin PasteImageMixin {
Future<void> pasteImage(BuildContext context, Room room) async {
await Clipboard.instance.initReader();
if (!(await Clipboard.instance.isReadableImageFormat())) {
TwakeSnackBar.show(context, L10n.of(context)!.fileFormatNotSupported);
Logs().e('PasteImageMixin::pasteImage(): not readable image format');
Expand Down
30 changes: 14 additions & 16 deletions lib/utils/clipboard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,34 @@ class Clipboard {
Formats.svg,
];

Future<void> copyText(String text) async {
final item = DataWriterItem();
item.add(Formats.plainText(text));
await ClipboardWriter.instance.write([item]);
}

Future<void> copyImageAsStream(File image, {String? mimeType}) async {
final item = DataWriterItem(suggestedName: image.path);
final imageStream = image.openRead();
final mime = mimeType ?? lookupMimeType(image.path);
await imageStream.forEach((data) {
item.add(getFormatFrom(mime)(Uint8List.fromList(data)));
});
try {
await ClipboardWriter.instance.write([item]);
} catch (e) {
Logs().e('Clipboard::copyImageAsStream(): $e');
}
await ClipboardWriter.instance.write([item]);
}

Future<void> copyImageAsBytes(Uint8List data, {String? mimeType}) async {
try {
final item = DataWriterItem();
item.add(getFormatFrom(mimeType)(data));
await ClipboardWriter.instance.write([item]);
} catch (e) {
Logs().e('Clipboard::copyImageAsBytes(): $e');
}
final item = DataWriterItem();
item.add(getFormatFrom(mimeType)(data));
await ClipboardWriter.instance.write([item]);
}

Future<void> initReader() async {
_reader = await ClipboardReader.readClipboard();
}

Future<ClipboardImageInfo?> pasteImageUsingStream() async {
_reader ??= await ClipboardReader.readClipboard();
_reader = await ClipboardReader.readClipboard();
ClipboardImageInfo? imageInfo;

final readableFormats = _reader!.getFormats(allImageFormatsSupported);
Expand Down Expand Up @@ -90,7 +88,7 @@ class Clipboard {
}

Future<Uint8List?>? pasteImageUsingBytes() async {
_reader ??= await ClipboardReader.readClipboard();
_reader = await ClipboardReader.readClipboard();
final readableFormats = _reader!.getFormats(allImageFormatsSupported);
if (readableFormats.isEmpty != false &&
readableFormats.first is! SimpleFileFormat) {
Expand Down Expand Up @@ -121,7 +119,7 @@ class Clipboard {
}

Future<bool> isReadableImageFormat() async {
_reader ??= await ClipboardReader.readClipboard();
_reader = await ClipboardReader.readClipboard();
return _reader!.canProvide(Formats.png) ||
_reader!.canProvide(Formats.jpeg) ||
_reader!.canProvide(Formats.heic) ||
Expand All @@ -130,7 +128,7 @@ class Clipboard {
}

Future<String?> pasteText() async {
_reader ??= await ClipboardReader.readClipboard();
_reader = await ClipboardReader.readClipboard();
String? copied;

final readersFormat = _reader!.getFormats(Formats.standardFormats);
Expand Down
4 changes: 2 additions & 2 deletions lib/utils/platform_infos.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ abstract class PlatformInfos {
static bool get platformCanRecord => (isMobile || isMacOS);

static bool get isMacKeyboardPlatform =>
isMacOS &&
isMacOS ||
(kIsWeb &&
html.window.navigator.platform != null &&
html.window.navigator.platform!.contains('mac'));
html.window.navigator.platform!.toLowerCase().contains('mac'));

static String get clientName =>
'${AppConfig.applicationName} ${isWeb ? 'web' : Platform.operatingSystem}${kReleaseMode ? '' : 'Debug'}';
Expand Down

0 comments on commit 65727b6

Please sign in to comment.