fyral_comms 0.4.2 copy "fyral_comms: ^0.4.2" to clipboard
fyral_comms: ^0.4.2 copied to clipboard

Communication feature package for Fleet Glide Admin

fyral_comms #

A premium, responsive, and interactive messaging and team communication package for Flutter applications. Built with modern aesthetics, dark mode adaptability, and native support for both mobile and tablet split-pane layouts.


Features #

  • 📢 Compact Broadcast Tile (broadcastCard / CommsPage): Dedicated compact Broadcast / Announcement header tile with customizable megaphone icon, title, unread counter badges, and tap handlers.
  • 🗂️ Redesigned Conversation Cards (conversationCard): Modern chat list tiles featuring synchronized 2-row layout (Title + Timestamp on Row 1, Message + Badge on Row 2), automatic 2-letter title initials avatar with gradient styling, soft drop shadows, and empty message handling.
  • ✨ Shimmer Skeleton Loading (ConversationShimmer): Smooth animated linear gradient sweep effect for message bubbles, avatars, and timestamps during initial conversation loading with responsive width handling across all screen sizes.
  • 📅 WhatsApp-Style Date Separators (DateSeparatorBadge): Centered floating date badges automatically grouping messages by calendar date ("Today", "Yesterday", and formatted calendar dates).
  • 🔄 Scroll-to-Top Pagination: Automatically triggers pagination callbacks (onLoadMoreMessages) when the user scrolls near the top of the chat history, with a sleek top loading indicator pill ("Loading earlier messages...").
  • 🔍 Fullscreen Interactive Media Viewer (FullscreenMediaViewer): Dedicated gallery viewer supporting images and videos. Features pinch-to-zoom and pan via InteractiveViewer, double-tap quick zoom toggle (1.0x $\leftrightarrow$ 2.5x), horizontal swipe navigation (PageView) with dynamic gesture resolution when zoomed, and integrated video playback controls (video_player).
  • 🌫️ BlurHash Placeholder Loading: Integrated flutter_blurhash to render smooth blurred placeholders during remote image network fetching.
  • 🎬 Automatic Video Thumbnail Previews (MediaGrid): Responsive multi-attachment grid (1, 2, 3, 4+ items) with automatic first-frame video extraction or explicit poster/thumbnail URLs and translucent play icon badges.
  • 📷 WhatsApp-Style Media Preview (MediaPreviewPage): Interactive fullscreen preview for selected or captured photos and videos. Includes pinch-to-zoom, live video preview with play/pause, multi-item swipe navigation, bottom thumbnail gallery strip, embedded Emoji Picker, and caption input.
  • 📎 Dual-Source Attachment Picker: Popup menu in MessageBox supporting both Camera (image_picker) and Gallery (wechat_assets_picker / pickMultipleMedia) with Android 13+ / 14+ runtime permission handling and automatic fallback.
  • 📱 Responsive Dual-Pane Split-Screen: Automatically adapts on tablet-sized displays ($\ge 600\text{px}$ in landscape, $\ge 900\text{px}$ in portrait) into a master-detail split-view with an active conversation sidebar and detail message viewport.
  • 💬 WhatsApp-Style Replies: Integrated reply preview card nested cleanly inside the message input pill with theme matching, borders, and dismiss controls.
  • 👥 Dynamic Mentions Suggestions Overlay: Typing @ displays a filtered user list overlay directly above the input container, presenting usernames and initials-based circular avatars.
  • 🎨 Rich-Text Mentions Highlighting: Automatically styles active mentions in bold accent text inside message bubbles and on-the-fly inside the text input field.
  • 🌓 Full Dark Mode Support: Theme-adaptive color palettes, borders, gradients, reaction badges, and backgrounds across all pages and widgets.

Getting Started #

1. Add Dependency #

Add fyral_comms to your pubspec.yaml:

dependencies:
  fyral_comms: ^0.4.1

Or run:

flutter pub add fyral_comms

2. Platform & WeChat Asset Picker Setup #

fyral_comms uses wechat_assets_picker for multi-media gallery selection with WeChat UI aesthetics, alongside image_picker for camera captures. Configure your host application for smooth operation:

Android Configuration (android/app/src/main/AndroidManifest.xml)

Add the required permissions and application settings to your AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Storage & Media Permissions -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />

    <!-- Camera Permission for photo & video captures -->
    <uses-permission android:name="android.permission.CAMERA" />

    <application
        ...
        android:enableOnBackInvokedCallback="true">
        <!-- ... -->
    </application>
</manifest>

Note:

  • Predictive Back Navigation: android:enableOnBackInvokedCallback="true" is required in your <application> tag for Android 13+ (API 33+) to properly support predictive back gestures and prevent back navigation issues when dismissing wechat_assets_picker gallery screens.
  • Ensure your android/app/build.gradle has compileSdkVersion set to 33 or higher.

iOS Configuration (ios/Runner/Info.plist)

Add the permission keys to your Info.plist:

<key>NSPhotoLibraryUsageDescription</key>
<string>Requires photo library access to pick photos and videos to share in conversations.</string>
<key>NSCameraUsageDescription</key>
<string>Requires camera access to capture photos and videos for messaging.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Requires microphone access to record videos with audio.</string>

wechat_assets_picker relies on Flutter's localization system to render gallery UI labels (e.g. "Cancel", "Preview", "Send"). Add flutter_localizations to your pubspec.yaml and configure your MaterialApp:

dependencies:
  flutter_localizations:
    sdk: flutter
import 'package:flutter_localizations/flutter_localizations.dart';

MaterialApp(
  localizationsDelegates: const [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: const [
    Locale('en', ''),
    // Add additional supported locales as needed
  ],
  // ...
);

Automatic Fallback Mechanism

If photo library permissions are restricted or denied on Android/iOS, fyral_comms automatically falls back to the system photo picker (image_picker / pickMultipleMedia()), ensuring an uninterrupted user experience.


Usage Guide #

1. Conversation List View (CommsPage) #

Embed CommsPage in your application route (e.g. using GoRouter or standard Navigator) with optional Broadcast card support at the top:

import 'package:fyral_comms/comms.dart';

CommsPage(
  currentUserId: 2,
  conversations: conversationGroups,
  onConversationSelected: (conversation) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => ConversationDetailPage(
          title: conversation.name,
          // pass parameters or state
        ),
      ),
    );
  },
  // Optional Broadcast Card at top of the conversation list:
  showBroadcast: true,
  broadcastTitle: 'Broadcast',
  broadcastMessage: 'Company-wide announcement: All routes updated',
  broadcastTime: '10:30 AM',
  broadcastUnreadCount: 2,
  onBroadcastTap: () {
    // Handle broadcast tap
  },
)

CommsPage Properties

Property Type Description
conversations List<CommsGroup>? List of conversation groups to render.
currentUserId int? ID of the current user to resolve personal unread counts.
onConversationSelected Function(CommsGroup)? Callback when a conversation card is tapped.
showBroadcast bool? (default: false) Displays a pinned Broadcast card at index 0.
broadcastTitle String? (default: 'Broadcast') Title on the Broadcast card.
broadcastMessage String? Subtitle message content on the Broadcast card.
broadcastTime String? Formatted timestamp string for the Broadcast card.
broadcastUnreadCount int? (default: 0) Unread badge counter for Broadcasts.
broadcastIcon IconData? (default: Icons.campaign_rounded) Avatar icon for the Broadcast card.
broadcastIconColor Color? (default: Color(0xFFF97316)) Icon tint and avatar background color.
onBroadcastTap VoidCallback? Tap callback handler for the Broadcast card.
broadcastWidget Widget? Custom widget override for the Broadcast card.
noDataIcon IconData? Icon displayed when there are no conversations.
emptyWidget List<Widget>? Custom widget list for the empty state.

2. Conversation Detail View (ConversationDetailPage) #

ConversationDetailPage supports both Controlled (stateless style for BLoC/Riverpod/Redux) and Uncontrolled (stateful fallback) modes.

Uncontrolled Mode (Self-Contained)

ConversationDetailPage(
  title: 'Operations Room',
)

Controlled Mode (State-Driven)

ConversationDetailPage(
  title: 'Operations Room',
  messages: state.messages,
  isLoading: state.isLoadingMessages, // Displays ConversationShimmer
  isLoadingMore: state.isLoadingMore, // Displays top pagination spinner
  hasMoreMessages: state.hasMore,
  onLoadMoreMessages: () async {
    await context.read<ChatCubit>().loadEarlierMessages();
  },
  showDateSeparators: true,
  isSearching: state.isSearching,
  searchQuery: state.searchQuery,
  showEmojiPicker: state.showEmojiPicker,
  messageController: _messageController,
  searchController: _searchController,
  focusNode: _focusNode,
  mentionableUsers: [
    {'id': '1', 'name': 'Sarah Connor'},
    {'id': '2', 'name': 'John Doe'},
  ],
  onSendMessage: () => bloc.add(SendMessageEvent()),
  onSearchQueryChanged: (query) => bloc.add(SearchChangedEvent(query)),
  onToggleEmojiPicker: () => bloc.add(ToggleEmojiEvent()),
  onToggleSearch: () => bloc.add(ToggleSearchEvent()),
  onClearSearch: () => bloc.add(ClearSearchEvent()),
  onMediaPicked: (List<File> files) => bloc.add(MediaPickedEvent(files)),
  onBackPressed: () => Navigator.pop(context),
)

ConversationDetailPage Key Properties

Property Type Description
title String Header title of the conversation.
messages List<dynamic>? List of messages to display.
isLoading bool (default: false) Displays ConversationShimmer during initial message load.
isLoadingMore bool (default: false) Shows top pagination indicator while loading history.
hasMoreMessages bool (default: true) Enables/disables scroll-to-top pagination triggers.
onLoadMoreMessages Future<void> Function()? Callback triggered when user scrolls near the top.
showDateSeparators bool (default: true) Groups messages by date with DateSeparatorBadge.
mentionableUsers List<Map<String, dynamic>>? Users suggested when typing @ in the input box.
emptyTitle String? (default: 'No messages yet') Title in empty chat state.
emptySubtitle String? Subtitle in empty chat state.
emptyIcon IconData? Icon in empty chat state.
emptyPlaceholder Widget? Custom empty placeholder widget override.
shimmerPlaceholder Widget? Custom shimmer placeholder widget override.
onMediaPicked ValueChanged<List<File>>? Invoked with selected media files from gallery/camera.
showMediaPicker bool? (default: true) Toggles attachment button visibility in MessageBox.
showBackButton bool? Controls back button visibility (true to force show on tablet/desktop, false to hide, null for responsive auto).
forceShowBackButton bool? Alias for showBackButton: true to guarantee back button display on tablet viewports.
showAppBar bool (default: true) Set to false when embedding inside custom layouts.
addDemoData bool (default: true) Whether to populate mock messages in uncontrolled mode.

3. Fullscreen Media Viewer (FullscreenMediaViewer) #

Displays an interactive fullscreen image and video gallery:

import 'package:fyral_comms/comms.dart';

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => FullscreenMediaViewer(
      attachments: message.attachments, // URLs, Files, or CommsAttachment objects
      initialIndex: 0,
    ),
  ),
);
  • Pinch-to-zoom & pan: Uses InteractiveViewer with smooth double-tap zoom (1.0x $\leftrightarrow$ 2.5x).
  • Dynamic gesture handling: Resolves swipe conflicts so horizontal panning inside zoomed images does not trigger page swipes.
  • Video playback: Built-in player with tap-to-play, center play/pause overlay, and format detection (network, file, assets).

4. Responsive Attachment Grid (MediaGrid) #

Renders 1 to 4+ image and video thumbnails inside chat bubbles with BlurHash support:

import 'package:fyral_comms/comms.dart';

MediaGrid(
  attachments: [
    'https://example.com/photo1.jpg',
    'https://example.com/video1.mp4',
  ],
  isSender: false,
)

5. Media Preview Page (MediaPreviewPage) #

Launches a WhatsApp-style media review and caption screen before sending:

import 'package:fyral_comms/comms.dart';

final MediaPreviewResult? result = await Navigator.push<MediaPreviewResult>(
  context,
  MaterialPageRoute(
    builder: (context) => MediaPreviewPage(
      filePaths: ['/path/to/image.png', '/path/to/video.mp4'],
      initialCaption: 'Check out these updates',
    ),
  ),
);

if (result != null) {
  print('Files to send: ${result.files}');
  print('Caption: ${result.caption}');
}

6. Conversation Card Tile (conversationCard) #

Stand-alone WhatsApp-style conversation tile widget with automatic two-letter initials avatar:

import 'package:fyral_comms/comms.dart';

conversationCard(
  title: 'Operations Group',
  message: 'Meeting starts at 10 AM',
  time: '9:45 AM',
  avatarIconColor: Colors.blueAccent,
  unreadCount: 3,
  isUnread: true,
  onTap: () => openConversation(),
);

7. Broadcast Header Tile (broadcastCard) #

Compact single-line broadcast and announcements banner:

import 'package:fyral_comms/comms.dart';

broadcastCard(
  context,
  broadcastTitle: 'Broadcast',
  broadcastIcon: Icons.campaign_rounded,
  broadcastIconColor: const Color(0xFFF97316),
  onBroadcastTap: () => openBroadcastChannel(),
);

8. Standalone Shimmer Skeleton (ConversationShimmer) #

import 'package:fyral_comms/comms.dart';

ConversationShimmer(
  itemCount: 8,
  padding: EdgeInsets.symmetric(horizontal: 14, vertical: 16),
)

8. Date Separator Badge (DateSeparatorBadge) #

import 'package:fyral_comms/comms.dart';

DateSeparatorBadge(
  dateText: 'Today',
)

9. Domain Models #

fyral_comms includes strongly typed models with built-in JSON deserialization and serialization:

  • CommsGroup: Represents a conversation group or topic, with id, name, groupType, participants, lastMessage, and unreadCount.
  • CommsParticipant: Participant details, unreadCount, and lastReadMessageId.
  • CommsUser: User metadata (id, name, email, role).
  • CommsMessage / CommsMessageResponse: Rich message model with text, reactions, attachments, reply references, and delivery/read statuses.
  • CommsAttachment: Attachment metadata including fileUrl, fileType, fileName, fileSize, thumbnailUrl, and blurhash.

Theming & Dark Mode #

fyral_comms automatically adapts to ThemeData.light() and ThemeData.dark(). For optimal appearance, you can provide custom color schemes:

MaterialApp(
  theme: ThemeData(
    brightness: Brightness.light,
    colorScheme: ColorScheme.fromSeed(
      seedColor: const Color(0xFFF97316),
      brightness: Brightness.light,
    ),
  ),
  darkTheme: ThemeData(
    brightness: Brightness.dark,
    scaffoldBackgroundColor: const Color(0xFF0B1120),
    colorScheme: ColorScheme.fromSeed(
      seedColor: const Color(0xFFF97316),
      brightness: Brightness.dark,
    ),
  ),
  // ...
);

Example App #

A full demonstration app showing conversation lists, broadcast cards, split-screen tablet navigation, media previews, mentions, shimmer loaders, and theme switching is available in the example/ directory.

To run the example:

cd example
flutter run

Additional Information #

  • Repository: Source code and issue tracking on GitHub.
  • Contributing: Pull requests, bug reports, and feature suggestions are always welcome!
1
likes
150
points
1.33k
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Communication feature package for Fleet Glide Admin

Repository (GitHub)

License

MIT (license)

Dependencies

animated_emoji, emoji_picker_flutter, flutter, flutter_blurhash, image_picker, intl, video_player, wechat_assets_picker

More

Packages that depend on fyral_comms