allow editing in/out attachments from messages
This commit is contained in:
parent
e9b009d1b9
commit
e398043a49
4 changed files with 71 additions and 20 deletions
|
|
@ -29,6 +29,8 @@ class AttachmentController(final String roomId)
|
|||
state = (filename, content);
|
||||
}
|
||||
|
||||
void set((String, MessageContent?)? attachment) => state = attachment;
|
||||
|
||||
static final provider = NotifierProvider.family
|
||||
.autoDispose<AttachmentController, (String, MessageContent?)?, String>(
|
||||
AttachmentController.new,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import "package:fluttertagger/fluttertagger.dart";
|
|||
import "package:nexus/controllers/attachment.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/helpers/extensions/is_media.dart";
|
||||
import "package:nexus/helpers/extensions/send_failed.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/image_pack.dart";
|
||||
|
|
@ -231,22 +232,24 @@ class RoomChatController(final ChatParams info)
|
|||
required RelationType relationType,
|
||||
int? relatedEventRowId,
|
||||
}) async {
|
||||
Content? baseContent;
|
||||
final events = ref.read(RoomsController.provider)[info.roomId]?.events;
|
||||
final relatedEvent = relatedEventRowId == null
|
||||
? null
|
||||
: ref.read(
|
||||
RoomsController.provider.select(
|
||||
(rooms) => rooms[info.roomId]?.events[relatedEventRowId],
|
||||
),
|
||||
);
|
||||
: events?[relatedEventRowId];
|
||||
|
||||
if (relationType == .edit && relatedEventRowId != null) {
|
||||
baseContent = relatedEvent?.content;
|
||||
} else {
|
||||
final provider = AttachmentController.provider(info.roomId);
|
||||
baseContent = ref.read(provider)?.$2;
|
||||
ref.invalidate(provider);
|
||||
}
|
||||
final attachmentProvider = AttachmentController.provider(info.roomId);
|
||||
final attachment = ref.read(attachmentProvider)?.$2;
|
||||
ref.invalidate(attachmentProvider);
|
||||
|
||||
// Edits of media use the attachment, which starts as the current media
|
||||
final latestContent = relatedEvent == null
|
||||
? null
|
||||
: (events?[relatedEvent.lastEditRowId] ?? relatedEvent).content;
|
||||
final baseContent =
|
||||
attachment ??
|
||||
(relationType == .edit && latestContent?.isMedia == false
|
||||
? latestContent
|
||||
: null);
|
||||
|
||||
// Replaces each formatted tag, like "@id#name#", with its ID
|
||||
final taggedMessage = tags.fold(
|
||||
|
|
|
|||
12
lib/helpers/extensions/is_media.dart
Normal file
12
lib/helpers/extensions/is_media.dart
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/message.dart";
|
||||
|
||||
extension IsMedia on Content {
|
||||
bool get isMedia => switch (this) {
|
||||
ImageMessageContent() ||
|
||||
VideoMessageContent() ||
|
||||
AudioMessageContent() ||
|
||||
FileMessageContent() => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
|
@ -3,6 +3,8 @@ import "dart:io";
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/widgets/emoji_picker.dart";
|
||||
import "package:nexus/helpers/extensions/get_filename.dart";
|
||||
import "package:nexus/helpers/extensions/is_media.dart";
|
||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||
import "package:nexus/widgets/adaptive_menu_button.dart";
|
||||
import "package:material_ui/material_ui.dart";
|
||||
|
|
@ -111,6 +113,8 @@ class const Composer(
|
|||
);
|
||||
|
||||
final textBefore = useState<String?>(null);
|
||||
// Wrapped, since no attachment is a draft too
|
||||
final attachmentBefore = useState<((String, MessageContent?)?,)?>(null);
|
||||
|
||||
/// The sticker to send, which replaces the text field until it is sent or
|
||||
/// removed, as stickers can't have a caption
|
||||
|
|
@ -132,16 +136,24 @@ class const Composer(
|
|||
final isEditing = relationType == .edit && relatedEvent != null;
|
||||
|
||||
useEffect(() {
|
||||
final attachmentProvider = AttachmentController.provider(roomId);
|
||||
|
||||
if (relationType == .edit && relatedEvent != null) {
|
||||
textBefore.value ??= controller.text;
|
||||
attachmentBefore.value ??= (ref.read(attachmentProvider),);
|
||||
sticker.value = null;
|
||||
poll.value = null;
|
||||
location.value = null;
|
||||
|
||||
final content = relatedEvent.content;
|
||||
final text =
|
||||
relatedEvent.localContent?.editSource ??
|
||||
switch (relatedEvent.content) {
|
||||
TextMessageContent(:final body) => body,
|
||||
switch (content) {
|
||||
TextMessageContent(:final body) ||
|
||||
ImageMessageContent(:final body) ||
|
||||
VideoMessageContent(:final body) ||
|
||||
AudioMessageContent(:final body) ||
|
||||
FileMessageContent(:final body) => body,
|
||||
_ => "",
|
||||
};
|
||||
|
||||
|
|
@ -149,12 +161,34 @@ class const Composer(
|
|||
text: text,
|
||||
selection: .collapsed(offset: text.length),
|
||||
);
|
||||
} else if (textBefore.value case final draft?) {
|
||||
controller.value = .new(
|
||||
text: draft,
|
||||
selection: .collapsed(offset: draft.length),
|
||||
|
||||
Future.microtask(
|
||||
() => ref
|
||||
.read(attachmentProvider.notifier)
|
||||
.set(
|
||||
content is MessageContent && content.isMedia
|
||||
? (
|
||||
content.filename ?? content.body ?? "Attachment",
|
||||
content,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
textBefore.value = null;
|
||||
} else {
|
||||
if (textBefore.value case final draft?) {
|
||||
controller.value = .new(
|
||||
text: draft,
|
||||
selection: .collapsed(offset: draft.length),
|
||||
);
|
||||
textBefore.value = null;
|
||||
}
|
||||
|
||||
if (attachmentBefore.value case (final draft,)) {
|
||||
Future.microtask(
|
||||
() => ref.read(attachmentProvider.notifier).set(draft),
|
||||
);
|
||||
attachmentBefore.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
Loading…
Reference in a new issue