Files
buzz/mobile/lib/features/channels/compose_bar/draft_lifecycle.dart
klopez4212 98d3d77b42 Fix mobile composer input regressions (#5594)
## Summary

- reuse the channel member snapshot so first-use `@` suggestions appear
immediately
- reduce selection-only composer rebuilds so iOS selection handles stay
responsive
- make Return insert a newline, send only from the composer button, and
animate multiline growth with reduced-motion support

## Validation

- `just mobile-check`
- `just mobile-test` — 1,271 tests passed
- signed iPhone Release and Pixel 10 debug builds installed and launched
- `just ci` passed mobile, Rust, desktop, and web checks until the
unrelated `buzz-terminal` lifecycle test timed out waiting for `$0`;
reproduced unchanged in isolation

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
2026-08-13 17:58:29 +01:00

65 lines
2.3 KiB
Dart

part of '../compose_bar.dart';
void _useComposeDraftLifecycle({
required WidgetRef ref,
required _MarkdownEditingController controller,
required String draftKey,
required String channelId,
required String? threadHeadId,
required String draftIdentity,
required ObjectRef<int> draftRevision,
required ValueNotifier<List<_PendingAttachment>> attachments,
required ObjectRef<int> uploadGeneration,
required ObjectRef<UploadCancellationToken?> activeUploadCancellation,
required ValueNotifier<int> uploadingCount,
required ValueNotifier<bool> isSending,
required ValueNotifier<_AttachmentSurface> attachmentSurface,
required ValueNotifier<String?> uploadError,
required _IOSAttachmentPopoverController iosAttachmentPopover,
}) {
final lastDraftIdentity = useRef<String?>(null);
useEffect(() {
final identityChanged =
lastDraftIdentity.value != null &&
lastDraftIdentity.value != draftIdentity;
lastDraftIdentity.value = draftIdentity;
final saved = ref.read(composeDraftsProvider.notifier).textFor(draftKey);
if (identityChanged) {
draftRevision.value += 1;
uploadGeneration.value += 1;
activeUploadCancellation.value?.cancel();
activeUploadCancellation.value = null;
uploadingCount.value = 0;
isSending.value = false;
attachmentSurface.value = _AttachmentSurface.closed;
uploadError.value = null;
unawaited(iosAttachmentPopover.dispose());
final staleAttachments = attachments.value;
attachments.value = const [];
unawaited(_deleteOwnedAttachments(staleAttachments));
controller.text = saved ?? '';
} else if (saved != null && controller.text.isEmpty) {
controller.text = saved;
}
var lastPersistedText = controller.text;
void persistDraft() {
final text = controller.text;
if (text == lastPersistedText) return;
lastPersistedText = text;
draftRevision.value += 1;
ref
.read(composeDraftsProvider.notifier)
.save(
key: draftKey,
channelId: channelId,
threadHeadId: threadHeadId,
text: text,
);
}
controller.addListener(persistDraft);
return () => controller.removeListener(persistDraft);
}, [controller, draftKey, draftIdentity]);
}