keep message drafts on room switches
this is for you courge
This commit is contained in:
parent
7f7bdbf525
commit
e899bb3929
4 changed files with 357 additions and 194 deletions
|
|
@ -7,7 +7,9 @@ import "package:nexus/models/content/message.dart";
|
|||
import "package:nexus/models/composer_params.dart";
|
||||
import "package:path/path.dart";
|
||||
|
||||
class AttachmentController(final ComposerParams composer)
|
||||
typedef AttachmentParams = ({ComposerParams composer, int? editingRowId});
|
||||
|
||||
class AttachmentController(final AttachmentParams params)
|
||||
extends Notifier<(String, MessageContent?)?> {
|
||||
@override
|
||||
Null build() => null;
|
||||
|
|
@ -19,7 +21,7 @@ class AttachmentController(final ComposerParams composer)
|
|||
final isEncrypted = ref.read(
|
||||
RoomsController.provider.select(
|
||||
(value) =>
|
||||
value[composer.roomId]
|
||||
value[params.composer.roomId]
|
||||
?.state[EventType.encryption.type]
|
||||
?.isNotEmpty ==
|
||||
true,
|
||||
|
|
@ -35,10 +37,10 @@ class AttachmentController(final ComposerParams composer)
|
|||
|
||||
void set((String, MessageContent?)? attachment) => state = attachment;
|
||||
|
||||
static final provider = NotifierProvider.family
|
||||
.autoDispose<
|
||||
static final provider =
|
||||
NotifierProvider.family<
|
||||
AttachmentController,
|
||||
(String, MessageContent?)?,
|
||||
ComposerParams
|
||||
AttachmentParams
|
||||
>(AttachmentController.new);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,10 +95,14 @@ class BotCommandDraftController(final ComposerParams composer)
|
|||
}
|
||||
}
|
||||
|
||||
void set(BotCommandDraft? draft) => state = draft;
|
||||
|
||||
void clear() => state = null;
|
||||
|
||||
static final provider = NotifierProvider.autoDispose
|
||||
.family<BotCommandDraftController, BotCommandDraft?, ComposerParams>(
|
||||
BotCommandDraftController.new,
|
||||
);
|
||||
static final provider =
|
||||
NotifierProvider.family<
|
||||
BotCommandDraftController,
|
||||
BotCommandDraft?,
|
||||
ComposerParams
|
||||
>(BotCommandDraftController.new);
|
||||
}
|
||||
|
|
|
|||
93
lib/controllers/composer_draft.dart
Normal file
93
lib/controllers/composer_draft.dart
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/attachment.dart";
|
||||
import "package:nexus/controllers/bot_command_draft.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/helpers/extensions/get_filename.dart";
|
||||
import "package:nexus/helpers/extensions/is_media.dart";
|
||||
import "package:nexus/helpers/extensions/with_latest_edit.dart";
|
||||
import "package:nexus/models/composer_draft.dart";
|
||||
import "package:nexus/models/composer_params.dart";
|
||||
import "package:nexus/models/content/message.dart";
|
||||
import "package:nexus/models/relation_type.dart";
|
||||
|
||||
class ComposerDraftController(final ComposerParams composer)
|
||||
extends Notifier<ComposerDraft> {
|
||||
@override
|
||||
ComposerDraft build() => const .new();
|
||||
|
||||
BotCommandDraftController get _botCommand =>
|
||||
ref.read(BotCommandDraftController.provider(composer).notifier);
|
||||
|
||||
void update(ComposerDraft Function(ComposerDraft draft) update) =>
|
||||
state = update(state);
|
||||
|
||||
void relate(int rowId, RelationType type) {
|
||||
if (type == .reply) {
|
||||
_restoreBeforeEdit();
|
||||
state = state.copyWith(relatedEvent: rowId, relationType: .reply);
|
||||
return;
|
||||
}
|
||||
|
||||
// Keeps the changes made so far
|
||||
if (state.isEditing && state.relatedEvent == rowId) return;
|
||||
|
||||
final event = ref
|
||||
.read(RoomsController.provider)[composer.roomId]
|
||||
?.withLatestEdit(rowId);
|
||||
final content = event?.content;
|
||||
final text =
|
||||
event?.localContent?.editSource ??
|
||||
switch (content) {
|
||||
TextMessageContent(:final body) ||
|
||||
ImageMessageContent(:final body) ||
|
||||
VideoMessageContent(:final body) ||
|
||||
AudioMessageContent(:final body) ||
|
||||
FileMessageContent(:final body) => body,
|
||||
_ => "",
|
||||
};
|
||||
|
||||
state = ComposerDraft(
|
||||
text: text,
|
||||
relatedEvent: rowId,
|
||||
relationType: .edit,
|
||||
beforeEdit:
|
||||
state.beforeEdit ??
|
||||
(
|
||||
draft: state,
|
||||
botCommand: ref.read(BotCommandDraftController.provider(composer)),
|
||||
),
|
||||
);
|
||||
ref
|
||||
.read(
|
||||
AttachmentController.provider((
|
||||
composer: composer,
|
||||
editingRowId: rowId,
|
||||
)).notifier,
|
||||
)
|
||||
.set(
|
||||
content is MessageContent && content.isMedia
|
||||
? (content.filename ?? content.body ?? "Attachment", content)
|
||||
: null,
|
||||
);
|
||||
_botCommand.clear();
|
||||
}
|
||||
|
||||
void dismiss() {
|
||||
if (state.isEditing) return _restoreBeforeEdit();
|
||||
state = state.copyWith(relatedEvent: null);
|
||||
}
|
||||
|
||||
void _restoreBeforeEdit() {
|
||||
if (state.beforeEdit case (:final draft, :final botCommand)) {
|
||||
state = draft;
|
||||
_botCommand.set(botCommand);
|
||||
}
|
||||
}
|
||||
|
||||
static final provider =
|
||||
NotifierProvider.family<
|
||||
ComposerDraftController,
|
||||
ComposerDraft,
|
||||
ComposerParams
|
||||
>(ComposerDraftController.new);
|
||||
}
|
||||
|
|
@ -404,7 +404,10 @@ class RoomChatController(final ChatParams info)
|
|||
roomId: info.roomId,
|
||||
threadRoot: info.threadRoot,
|
||||
);
|
||||
final attachmentProvider = AttachmentController.provider(composer);
|
||||
final attachmentProvider = AttachmentController.provider((
|
||||
composer: composer,
|
||||
editingRowId: relationType == .edit ? relatedEventRowId : null,
|
||||
));
|
||||
final attachment = ref.read(attachmentProvider)?.$2;
|
||||
ref.invalidate(attachmentProvider);
|
||||
|
||||
|
|
@ -418,11 +421,13 @@ class RoomChatController(final ChatParams info)
|
|||
? 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(
|
||||
text,
|
||||
(message, tag) => message.replaceAllMapped(
|
||||
RegExp(r"@+(" + RegExp.escape(tag.id) + r")(#[^#]*#)?"),
|
||||
RegExp(
|
||||
"${RegExp.escape(tag.triggerCharacter)}(${RegExp.escape(tag.id)})(#[^#]*#)?",
|
||||
),
|
||||
(match) => match.group(1)!,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue