Paste to add attachment

This commit is contained in:
2024-11-22 00:28:29 +08:00
parent b52811d66e
commit 1af90cd9e7
14 changed files with 132 additions and 12 deletions

View File

@ -86,7 +86,10 @@ class PostWriteMedia {
if (file != null) {
return file!;
} else if (raw != null) {
return XFile.fromData(raw!, name: name);
return XFile.fromData(
raw!,
name: name,
);
}
return null;
}
@ -256,6 +259,9 @@ class PostWriteController extends ChangeNotifier {
media.name,
'interactive',
null,
mimetype: media.raw != null && media.type == PostWriteMediaType.image
? 'image/png'
: null,
);
final item = await attach.chunkedUploadParts(

View File

@ -130,8 +130,9 @@ class SnAttachmentProvider {
int size,
String filename,
String pool,
Map<String, dynamic>? metadata,
) async {
Map<String, dynamic>? metadata, {
String? mimetype,
}) async {
final fileAlt = filename.contains('.')
? filename.substring(0, filename.lastIndexOf('.'))
: filename;
@ -139,8 +140,10 @@ class SnAttachmentProvider {
filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
String? mimetypeOverride;
if (mimetypeOverrides.keys.contains(fileExt)) {
if (mimetype == null && mimetypeOverrides.keys.contains(fileExt)) {
mimetypeOverride = mimetypeOverrides[fileExt];
} else {
mimetypeOverride = mimetype;
}
final resp = await _sn.client.post('/cgi/uc/attachments/multipart', data: {

View File

@ -9,6 +9,7 @@ import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:pasteboard/pasteboard.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/controllers/post_write_controller.dart';
import 'package:surface/providers/sn_network.dart';
@ -82,6 +83,18 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
);
}
void _pasteMedia() async {
final imageBytes = await Pasteboard.image;
if (imageBytes == null) return;
_writeController.addAttachments([
PostWriteMedia.fromBytes(
imageBytes,
'attachmentPastedImage'.tr(),
PostWriteMediaType.image,
),
]);
}
@override
void dispose() {
_writeController.dispose();
@ -369,15 +382,39 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
scrollDirection: Axis.vertical,
child: Row(
children: [
IconButton(
onPressed: _writeController.isBusy
? null
: _selectMedia,
PopupMenuButton(
icon: Icon(
Symbols.add_photo_alternate,
color:
Theme.of(context).colorScheme.primary,
),
itemBuilder: (context) => [
PopupMenuItem(
child: Row(
children: [
const Icon(Symbols.photo_library),
const Gap(16),
Text('addAttachmentFromAlbum').tr(),
],
),
onTap: () {
_selectMedia();
},
),
PopupMenuItem(
child: Row(
children: [
const Icon(Symbols.content_paste),
const Gap(16),
Text('addAttachmentFromClipboard')
.tr(),
],
),
onTap: () {
_pasteMedia();
},
),
],
),
],
),

View File

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:image_picker/image_picker.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:pasteboard/pasteboard.dart';
import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/controllers/chat_message_controller.dart';
@ -72,6 +73,9 @@ class ChatMessageInputState extends State<ChatMessageInput> {
media.name,
'interactive',
null,
mimetype: media.raw != null && media.type == PostWriteMediaType.image
? 'image/png'
: null,
);
final item = await attach.chunkedUploadParts(
@ -133,6 +137,19 @@ class ChatMessageInputState extends State<ChatMessageInput> {
setState(() {});
}
void _pasteMedia() async {
final imageBytes = await Pasteboard.image;
if (imageBytes == null) return;
_attachments.add(
PostWriteMedia.fromBytes(
imageBytes,
'attachmentPastedImage'.tr(),
PostWriteMediaType.image,
),
);
setState(() {});
}
@override
void dispose() {
_contentController.dispose();
@ -266,12 +283,37 @@ class ChatMessageInputState extends State<ChatMessageInput> {
),
),
const Gap(8),
IconButton(
onPressed: _isBusy ? null : _selectMedia,
PopupMenuButton(
icon: Icon(
Symbols.add_photo_alternate,
color: Theme.of(context).colorScheme.primary,
),
itemBuilder: (context) => [
PopupMenuItem(
child: Row(
children: [
const Icon(Symbols.photo_library),
const Gap(16),
Text('addAttachmentFromAlbum').tr(),
],
),
onTap: () {
_selectMedia();
},
),
PopupMenuItem(
child: Row(
children: [
const Icon(Symbols.content_paste),
const Gap(16),
Text('addAttachmentFromClipboard').tr(),
],
),
onTap: () {
_pasteMedia();
},
),
],
),
IconButton(
onPressed: _isBusy ? null : _sendMessage,