flutter_message_composer 0.2.2 copy "flutter_message_composer: ^0.2.2" to clipboard
flutter_message_composer: ^0.2.2 copied to clipboard

An adaptive Flutter message composer with multiline text, attachments, audio previews, and hold-to-record gestures with slide-to-cancel and locking.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_message_composer/flutter_message_composer.dart';

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
      ),
      home: const ComposerExamplePage(),
    );
  }
}

class ComposerExamplePage extends StatefulWidget {
  const ComposerExamplePage({super.key});

  @override
  State<ComposerExamplePage> createState() => _ComposerExamplePageState();
}

class _ComposerExamplePageState extends State<ComposerExamplePage> {
  final controller = TextEditingController();
  final focusNode = FocusNode();
  String latestSubmission = 'Nothing sent yet';

  static const quickReplies = ['Thanks!', 'Sounds good', 'I will check'];

  @override
  void dispose() {
    controller.dispose();
    focusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Message composer')),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: Text(
            latestSubmission,
            textAlign: TextAlign.center,
            style: Theme.of(context).textTheme.titleMedium,
          ),
        ),
      ),
      bottomNavigationBar: MessageComposer(
        controller: controller,
        focusNode: focusNode,
        hintText: 'Message',
        sendTooltip: 'Send',
        attachTooltip: 'Attachments',
        recordTooltip: 'Record audio',
        cancelRecordingTooltip: 'Discard audio',
        stopRecordingTooltip: 'Stop recording',
        playRecordingTooltip: 'Play audio',
        pauseRecordingTooltip: 'Pause audio',
        sendRecordingTooltip: 'Send audio',
        lockRecordingLabel: 'Lock recording',
        recordingLockedLabel: 'Recording locked',
        recordingTimerStyle: const TextStyle(fontWeight: FontWeight.w600),
        suggestions: SizedBox(
          height: 42,
          child: ListView.separated(
            scrollDirection: Axis.horizontal,
            padding: const EdgeInsets.symmetric(horizontal: 4),
            itemCount: quickReplies.length,
            separatorBuilder: (_, _) => const SizedBox(width: 8),
            itemBuilder: (context, index) {
              final reply = quickReplies[index];
              return ActionChip(
                label: Text(reply),
                onPressed: () {
                  controller.value = TextEditingValue(
                    text: reply,
                    selection: TextSelection.collapsed(offset: reply.length),
                  );
                  focusNode.requestFocus();
                },
              );
            },
          ),
        ),
        menuActions: [
          ChatInputMenuAction(
            id: 'photo',
            label: 'Photo',
            icon: const Icon(Icons.image_outlined),
            onPressed: () => showNotice('Connect an image picker here.'),
          ),
          ChatInputMenuAction(
            id: 'document',
            label: 'Document',
            icon: const Icon(Icons.description_outlined),
            onPressed: () => showNotice('Connect a file picker here.'),
          ),
        ],
        onRecordingPermissionDenied: () {
          showNotice('Microphone permission is required.');
        },
        onRecordingError: (_) {
          showNotice('The audio recording could not be completed.');
        },
        onAudioPreviewError: (_) {
          showNotice('The audio preview could not be played.');
        },
        onSend: handleSubmission,
      ),
    );
  }

  void handleSubmission(ChatInputSubmission submission) {
    setState(() {
      if (submission.hasAudio) {
        latestSubmission =
            'Audio: ${submission.audio!.name} '
            '(${submission.audio!.duration.inSeconds}s)';
      } else {
        latestSubmission = submission.text;
      }
    });

    if (!submission.hasAudio) controller.clear();
  }

  void showNotice(String message) {
    ScaffoldMessenger.of(
      context,
    ).showSnackBar(SnackBar(content: Text(message)));
  }
}
1
likes
0
points
393
downloads

Publisher

unverified uploader

Weekly Downloads

An adaptive Flutter message composer with multiline text, attachments, audio previews, and hold-to-record gestures with slide-to-cancel and locking.

Homepage

Topics

#chat #messaging #composer #audio-recording #user-interface

License

unknown (license)

Dependencies

audioplayers, flutter, hugeicons, path_provider, record

More

Packages that depend on flutter_message_composer