zuraffa_messaging 0.1.0 copy "zuraffa_messaging: ^0.1.0" to clipboard
zuraffa_messaging: ^0.1.0 copied to clipboard

Interface-based messaging for the Zuraffa ecosystem: pluggable transports behind one channel-routed facade, with send history, read receipts, and the versioned platform-channel contract the federated [...]

example/lib/main.dart

// The zuraffa_messaging example: every plugin operation, wired end to
// end, on android, ios and macos.
//
// Two in-memory transports (sms, push) are registered on the
// [MessagingService] — the panels exercise: send (per-channel), the
// sent-history feed, markRead (per message), and the verbatim
// `no_transport` error when a channel has no registered transport.
// Errors surface verbatim in the banner.
library;

import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:zuraffa_messaging/zuraffa_messaging.dart';

void main() {
  final messaging = MessagingService()
    ..register(InMemoryTransport('sms'))
    ..register(InMemoryTransport('push'));
  GetIt.instance.registerSingleton<MessagingService>(messaging);
  runApp(ZuraffaMessagingExampleApp(initialService: messaging));
}

class ZuraffaMessagingExampleApp extends StatelessWidget {
  const ZuraffaMessagingExampleApp({super.key, this.initialService});

  final MessagingService? initialService;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'zuraffa_messaging example',
      theme: ThemeData(colorSchemeSeed: const Color(0xFF7B61FF), useMaterial3: true),
      home: MessagingPage(service: initialService),
    );
  }
}

class MessagingPage extends StatefulWidget {
  const MessagingPage({super.key, this.service});

  final MessagingService? service;

  @override
  State<MessagingPage> createState() => _MessagingPageState();
}

class _MessagingPageState extends State<MessagingPage> {
  late MessagingService _messaging;
  String _channel = 'sms';
  String? _error;
  final _recipient = TextEditingController(text: '+905550001234');
  final _body = TextEditingController(text: 'Your code is 1234');

  @override
  void initState() {
    super.initState();
    _messaging = widget.service ?? GetIt.instance<MessagingService>();
  }

  Future<void> _send() async {
    try {
      setState(() => _error = null);
      await _messaging.send(
        _channel,
        OutboundMessage(
          senderId: 'example-app',
          recipientId: _recipient.text.trim(),
          body: _body.text.trim(),
        ),
      );
      if (!mounted) return;
      ScaffoldMessenger.of(context)
          .showSnackBar(const SnackBar(content: Text('message sent')));
    } on MessagingException catch (error) {
      setState(() => _error = '${error.code}: ${error.message}');
    }
  }

  Future<void> _markRead(String messageId) async {
    final read = await _messaging.markRead(messageId);
    if (!read) {
      setState(() => _error = 'unknown_message: markRead returned false');
      return;
    }
    setState(() => _error = null);
  }

  @override
  void dispose() {
    _recipient.dispose();
    _body.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final messages = _messaging.history;
    return Scaffold(
      appBar: AppBar(title: const Text('zuraffa_messaging')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          if (_error != null)
            Card(
              color: Theme.of(context).colorScheme.errorContainer,
              child: Padding(
                padding: const EdgeInsets.all(12),
                child: Text(_error!, key: const Key('error-banner')),
              ),
            ),
          Card(
            child: Padding(
              padding: const EdgeInsets.all(12),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Transports',
                      style: Theme.of(context).textTheme.titleMedium),
                  const SizedBox(height: 4),
                  Text('registered channels: ${_messaging.channels.join(', ')}',
                      key: const Key('channels')),
                  const Text(
                      "send on 'email' to see the verbatim no_transport error"),
                ],
              ),
            ),
          ),
          Card(
            child: Padding(
              padding: const EdgeInsets.all(12),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Send message',
                      style: Theme.of(context).textTheme.titleMedium),
                  const SizedBox(height: 8),
                  DropdownButtonFormField<String>(
                    key: const Key('channel-picker'),
                    initialValue: _channel,
                    items: const [
                      DropdownMenuItem(value: 'sms', child: Text('sms')),
                      DropdownMenuItem(value: 'push', child: Text('push')),
                      DropdownMenuItem(value: 'email', child: Text('email (no transport)')),
                    ],
                    onChanged: (value) => setState(() => _channel = value!),
                    decoration: const InputDecoration(labelText: 'channel'),
                  ),
                  TextField(
                    key: const Key('field-recipient'),
                    controller: _recipient,
                    decoration: const InputDecoration(labelText: 'recipientId'),
                  ),
                  TextField(
                    key: const Key('field-body'),
                    controller: _body,
                    decoration: const InputDecoration(labelText: 'body'),
                  ),
                  const SizedBox(height: 8),
                  FilledButton(
                    key: const Key('send'),
                    onPressed: _send,
                    child: const Text('send'),
                  ),
                ],
              ),
            ),
          ),
          Card(
            child: Padding(
              padding: const EdgeInsets.all(12),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Sent history (${messages.length})',
                      style: Theme.of(context).textTheme.titleMedium),
                  const SizedBox(height: 8),
                  if (messages.isEmpty)
                    const Text('nothing sent yet'),
                  for (final message in messages.reversed)
                    ListTile(
                      key: Key('message-${message.id}'),
                      dense: true,
                      leading: Icon(
                        message.state == MessageDeliveryState.read
                            ? Icons.mark_email_read
                            : Icons.mark_email_unread,
                      ),
                      title: Text(message.body),
                      subtitle: Text(
                          '→ ${message.recipientId} · ${message.state.name}'),
                      trailing: message.state == MessageDeliveryState.read
                          ? null
                          : TextButton(
                              key: Key('mark-read-${message.id}'),
                              onPressed: () => _markRead(message.id),
                              child: const Text('markRead'),
                            ),
                    ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
150
points
72
downloads

Documentation

API reference

Publisher

verified publisherzuraffa.com

Weekly Downloads

Interface-based messaging for the Zuraffa ecosystem: pluggable transports behind one channel-routed facade, with send history, read receipts, and the versioned platform-channel contract the federated native adapters serve.

Homepage
Repository (GitHub)
View/report issues

Topics

#messaging #notifications #clean-architecture #zuraffa

License

MIT (license)

Dependencies

get_it, json_annotation, zorphy_annotation, zuraffa

More

Packages that depend on zuraffa_messaging