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);
|
state = (filename, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set((String, MessageContent?)? attachment) => state = attachment;
|
||||||
|
|
||||||
static final provider = NotifierProvider.family
|
static final provider = NotifierProvider.family
|
||||||
.autoDispose<AttachmentController, (String, MessageContent?)?, String>(
|
.autoDispose<AttachmentController, (String, MessageContent?)?, String>(
|
||||||
AttachmentController.new,
|
AttachmentController.new,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import "package:fluttertagger/fluttertagger.dart";
|
||||||
import "package:nexus/controllers/attachment.dart";
|
import "package:nexus/controllers/attachment.dart";
|
||||||
import "package:nexus/controllers/client.dart";
|
import "package:nexus/controllers/client.dart";
|
||||||
import "package:nexus/controllers/rooms.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/helpers/extensions/send_failed.dart";
|
||||||
import "package:nexus/models/content/content.dart";
|
import "package:nexus/models/content/content.dart";
|
||||||
import "package:nexus/models/content/image_pack.dart";
|
import "package:nexus/models/content/image_pack.dart";
|
||||||
|
|
@ -231,22 +232,24 @@ class RoomChatController(final ChatParams info)
|
||||||
required RelationType relationType,
|
required RelationType relationType,
|
||||||
int? relatedEventRowId,
|
int? relatedEventRowId,
|
||||||
}) async {
|
}) async {
|
||||||
Content? baseContent;
|
final events = ref.read(RoomsController.provider)[info.roomId]?.events;
|
||||||
final relatedEvent = relatedEventRowId == null
|
final relatedEvent = relatedEventRowId == null
|
||||||
? null
|
? null
|
||||||
: ref.read(
|
: events?[relatedEventRowId];
|
||||||
RoomsController.provider.select(
|
|
||||||
(rooms) => rooms[info.roomId]?.events[relatedEventRowId],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (relationType == .edit && relatedEventRowId != null) {
|
final attachmentProvider = AttachmentController.provider(info.roomId);
|
||||||
baseContent = relatedEvent?.content;
|
final attachment = ref.read(attachmentProvider)?.$2;
|
||||||
} else {
|
ref.invalidate(attachmentProvider);
|
||||||
final provider = AttachmentController.provider(info.roomId);
|
|
||||||
baseContent = ref.read(provider)?.$2;
|
// Edits of media use the attachment, which starts as the current media
|
||||||
ref.invalidate(provider);
|
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
|
// Replaces each formatted tag, like "@id#name#", with its ID
|
||||||
final taggedMessage = tags.fold(
|
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:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:nexus/controllers/rooms.dart";
|
import "package:nexus/controllers/rooms.dart";
|
||||||
import "package:nexus/widgets/emoji_picker.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/helpers/extensions/show_adaptive_sheet.dart";
|
||||||
import "package:nexus/widgets/adaptive_menu_button.dart";
|
import "package:nexus/widgets/adaptive_menu_button.dart";
|
||||||
import "package:material_ui/material_ui.dart";
|
import "package:material_ui/material_ui.dart";
|
||||||
|
|
@ -111,6 +113,8 @@ class const Composer(
|
||||||
);
|
);
|
||||||
|
|
||||||
final textBefore = useState<String?>(null);
|
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
|
/// The sticker to send, which replaces the text field until it is sent or
|
||||||
/// removed, as stickers can't have a caption
|
/// removed, as stickers can't have a caption
|
||||||
|
|
@ -132,16 +136,24 @@ class const Composer(
|
||||||
final isEditing = relationType == .edit && relatedEvent != null;
|
final isEditing = relationType == .edit && relatedEvent != null;
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
|
final attachmentProvider = AttachmentController.provider(roomId);
|
||||||
|
|
||||||
if (relationType == .edit && relatedEvent != null) {
|
if (relationType == .edit && relatedEvent != null) {
|
||||||
textBefore.value ??= controller.text;
|
textBefore.value ??= controller.text;
|
||||||
|
attachmentBefore.value ??= (ref.read(attachmentProvider),);
|
||||||
sticker.value = null;
|
sticker.value = null;
|
||||||
poll.value = null;
|
poll.value = null;
|
||||||
location.value = null;
|
location.value = null;
|
||||||
|
|
||||||
|
final content = relatedEvent.content;
|
||||||
final text =
|
final text =
|
||||||
relatedEvent.localContent?.editSource ??
|
relatedEvent.localContent?.editSource ??
|
||||||
switch (relatedEvent.content) {
|
switch (content) {
|
||||||
TextMessageContent(:final body) => body,
|
TextMessageContent(:final body) ||
|
||||||
|
ImageMessageContent(:final body) ||
|
||||||
|
VideoMessageContent(:final body) ||
|
||||||
|
AudioMessageContent(:final body) ||
|
||||||
|
FileMessageContent(:final body) => body,
|
||||||
_ => "",
|
_ => "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -149,7 +161,21 @@ class const Composer(
|
||||||
text: text,
|
text: text,
|
||||||
selection: .collapsed(offset: text.length),
|
selection: .collapsed(offset: text.length),
|
||||||
);
|
);
|
||||||
} else if (textBefore.value case final draft?) {
|
|
||||||
|
Future.microtask(
|
||||||
|
() => ref
|
||||||
|
.read(attachmentProvider.notifier)
|
||||||
|
.set(
|
||||||
|
content is MessageContent && content.isMedia
|
||||||
|
? (
|
||||||
|
content.filename ?? content.body ?? "Attachment",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (textBefore.value case final draft?) {
|
||||||
controller.value = .new(
|
controller.value = .new(
|
||||||
text: draft,
|
text: draft,
|
||||||
selection: .collapsed(offset: draft.length),
|
selection: .collapsed(offset: draft.length),
|
||||||
|
|
@ -157,6 +183,14 @@ class const Composer(
|
||||||
textBefore.value = null;
|
textBefore.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (attachmentBefore.value case (final draft,)) {
|
||||||
|
Future.microtask(
|
||||||
|
() => ref.read(attachmentProvider.notifier).set(draft),
|
||||||
|
);
|
||||||
|
attachmentBefore.value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}, [relationType, relatedEvent == null]);
|
}, [relationType, relatedEvent == null]);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue