Skip to main content

pilot_ui 0.0.13 copy "pilot_ui: ^0.0.13" to clipboard
pilot_ui: ^0.0.13 copied to clipboard

PlatformAndroid

A dynamic, theme-aware JSON UI rendering engine for Flutter with extensible parsers, action handlers, and ready-to-use smart dispatch & RTS action components.

Pilot UI 🚀 #

A powerful, dynamic, theme-aware JSON UI compilation and rendering engine for Flutter. Build interactive, responsive widget trees directly from JSON schemas or server-driven definitions, complete with state management, expression evaluation, extensible registries, and specialized UI components.


✨ Features #

  • 🧱 Server-Driven UI (SDUI): Render complete Flutter widget trees directly from JSON payloads.
  • ⚡ Extensible Registry: Register your own custom widget parsers and action handlers seamlessly via PilotRegistry.
  • 🔄 Reactive State Management: Built-in state context (PilotStateContext) and expression evaluator (${state.myValue}) for interactive UI flows.
  • 🎨 Theme-Aware & Responsive: Dynamic theme resolution (colors, typography, elevation) and responsive props adapting to device screen sizes and breakpoints.
  • 📝 Lightweight Markdown Engine: Built-in PilotMarkdownText supporting bold (**), italic (*), inline code (`), bullet lists (-), headers (#), and hyperlinks ([text](url)) without third-party dependencies.
  • 📦 Rich Widget Parser Suite:
    • Layout: Container, Column, Row, Flex, Stack, ListView, Expanded, Wrap, SafeArea
    • Display: Text, Markdown / MarkdownText, Icon, CachedImage, Card, Avatar, Badge, ProgressIndicator, GlassContainer
    • Inputs & Buttons: TextField, Checkbox, ElevatedButton, TextButton
    • Structure & Nav: AppBar, BottomNavigationBar, FloatingActionButton, PageView, TabView
  • 🎯 Action Routing: Declarative action handling for showDialog, showBottomSheet, setState, and custom event emission (emitEvent).
  • 🚚 Specialized Dispatch & Fleet Components:
    • RtsActionCard: Ready-to-use, interactive Return-to-Station request cards featuring animated countdown expiry progress bars, integrated driver contact bar, audio note player, dark mode support, markdown text formatting, expandable/collapsible animation, severity badges, interactive AI Insights callouts, header edit callbacks, and dynamic action buttons.
    • DriverContactBar: Direct calling interface with driver avatars, phone number formatting, native multi-app chooser support (Phone, Google Voice, Truecaller), and dark theme support.
    • PilotAudioPlayer: Sleek, seekable audio player for driver voice notes with play/pause controls, slider scrubbing, tabular time formatting, and stream handling.
    • DynamicActionButtons: Configurable action trigger buttons with icon matching, async loading states, dark theme palettes, and customizable colors.

📦 Installation #

Add pilot_ui to your pubspec.yaml dependencies:

dependencies:
  flutter:
    sdk: flutter
  pilot_ui: ^0.0.13

Or run:

flutter pub add pilot_ui

🚀 Quick Start #

1. Basic JSON Widget Rendering #

Use PilotBuilder to compile a JSON UI specification into live Flutter widgets:

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

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

  final Map<String, dynamic> jsonUi = const {
    "type": "container",
    "children": [
      {
        "type": "column",
        "children": [
          {
            "type": "text",
            "properties": {
              "text": "Hello, Pilot UI!",
              "style": {
                "fontSize": 22.0,
                "fontWeight": "bold",
                "color": "#7C4DFF"
              }
            }
          },
          {
            "type": "markdown",
            "properties": {
              "text": "Render **bold**, *italic*, `code`, and [links](https://flutter.dev) easily!"
            }
          },
          {
            "type": "elevated_button",
            "properties": {
              "label": "Click Me"
            },
            "actions": {
              "onTap": {
                "action": "showDialog",
                "params": {
                  "title": "Welcome",
                  "message": "Rendered dynamically from JSON!"
                }
              }
            }
          }
        ]
      }
    ]
  };

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Dynamic UI')),
      body: PilotBuilder(
        json: jsonUi,
        initialState: const {
          'user': 'Driver #42',
        },
        onEvent: (eventName, payload) {
          debugPrint('Event emitted: $eventName -> $payload');
        },
      ),
    );
  }
}

📝 Markdown Text: PilotMarkdownText #

Render markdown formatting in Flutter directly or via JSON without needing bulky markdown libraries. Hyperlinks ([label](url)) and raw URLs are automatically clickable and open in the default browser/external application:

import 'package:pilot_ui/pilot_ui.dart';

PilotMarkdownText(
  "Driver **Aaron Pouncy** requested *RTS*. Read the [guidelines](https://example.com).",
  style: const TextStyle(fontSize: 14, color: Colors.black87),
  // Optional custom link tap callback; if omitted, URLs launch automatically
  onLinkTap: (url) {
    debugPrint('Navigating to: $url');
  },
)

JSON definition:

{
  "type": "markdown",
  "properties": {
    "text": "### Notice\n- **Driver ID**: #42\n- **Status**: *En Route*\n- Visit [Support Portal](https://support.fleetglide.io)",
    "style": {
      "fontSize": 14.0,
      "color": "#1E293B"
    }
  }
}

📞 Driver Contact Bar: DriverContactBar #

Quickly connect dispatchers to drivers with phone number normalization, one-tap calling, and native multi-app chooser support:

import 'package:pilot_ui/pilot_ui.dart';

DriverContactBar(
  driverName: "Abas Ali",
  driverPhone: "+1 (555) 234-5678",
  isDarkMode: false,
  onCall: () {
    debugPrint('Initiating call to driver');
  },
)

Multi-App Calling Chooser (Android) #

On Android devices, tapping the Call button automatically triggers Android's system chooser dialog (Intent.createChooser with ACTION_DIAL), allowing users to pick from any installed calling or dialer application (e.g. Phone, Google Voice, Truecaller) rather than being locked to only the default dialer.

Android 11+ Configuration

To ensure Android allows querying installed calling apps under Android 11+ (API 30+) package visibility rules, add the following <queries> entries inside <manifest> in your android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <queries>
        <intent>
            <action android:name="android.intent.action.DIAL" />
            <data android:scheme="tel" />
        </intent>
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data android:scheme="tel" />
        </intent>
    </queries>
    ...
</manifest>

Multi-App Calling Chooser (iOS) #

On iOS, if Google Voice is installed on the user's device, tapping the Call button automatically presents a native CupertinoActionSheet prompting the user to choose between:

  • 📞 Phone (Default): Directly dials via Apple's native cellular dialer (tel:<phone>).
  • 🎙️ Google Voice: Copies the phone number to the iOS clipboard for effortless pasting and opens Google Voice (googlevoice://).

If Google Voice is not installed, it seamlessly places the call using the native Phone dialer without interrupting the user.

iOS Configuration

Add googlevoice and tel under LSApplicationQueriesSchemes in your ios/Runner/Info.plist:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>tel</string>
    <string>googlevoice</string>
</array>

🎵 Voice Note & Audio Player: PilotAudioPlayer #

Play voice notes and driver audio clips with seek scrubbing and streaming status:

import 'package:pilot_ui/pilot_ui.dart';

PilotAudioPlayer(
  audioUrl: "https://example.com/audio/driver_note.mp3",
  title: "Driver Voice Note",
  autoPlay: false,
)

🚚 Specialized Components: RtsActionCard #

pilot_ui includes high-fidelity operational components for logistics and dispatch feeds with countdown expiry timers, driver contact bars, audio note players, markdown formatting, AI Insights callouts, and dark theme support:

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

Widget buildEventCard(Map<String, dynamic> eventJson, BuildContext context) {
  return RtsActionCard(
    data: eventJson,
    initiallyExpanded: false, // Collapsed by default; tap to expand
    isDarkMode: Theme.of(context).brightness == Brightness.dark, // Optional manual dark mode override
    showEdit: true,
    onEdit: () => debugPrint('Edit card tapped'),
    onCallDriver: () => debugPrint('Driver call triggered'),
    onLinkTap: (url) => debugPrint('Tapped link in card: $url'),
    onButtonTap: (action) {
      debugPrint('Triggered: ${action?.actionType} with payload: ${action?.actionPayload}');
    },
  );
}

You can also render RtsActionCard dynamically inside your JSON definitions:

// Register specialized components before building
PilotComponents.registerAll();
{
  "type": "rts_action_card",
  "title": "**Driver RTS Request** - 50 Undeliverables",
  "severity": "warning",
  "status": "pending",
  "description": "Driver **Aaron** requested early return to station. Reason: `Heavy Traffic`.",
  "ai_diagnosis": "High volume of remaining packages. Recommend review.",
  "audio_url": "https://example.com/audio/voice_note.mp3",
  "expires_at": "2026-09-22T14:45:00Z",
  "expires_in_seconds": 900,
  "ui_schema": {
    "data": {
      "driver_name": "Aaron Pouncy",
      "driver_phone": "+1 (555) 019-2834"
    }
  },
  "actions": [
    {
      "action_type": "APPROVE_RTS",
      "action_label": "⚡ Approve Return to Station",
      "action_payload": {"status": "approved"}
    },
    {
      "action_type": "REJECT_RTS",
      "action_label": "❌ Reject Return",
      "action_payload": {"status": "rejected"}
    }
  ]
}

🛠️ Extending Pilot UI #

Registering Custom Widget Parsers #

Implement BaseWidgetParser and register it with PilotRegistry:

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

class CustomHeaderParser extends BaseWidgetParser {
  @override
  Widget parse(JsonWidgetData data, BuildContext context) {
    final title = data.props['title'] ?? '';
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: Colors.deepPurple.shade50,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(
        title,
        style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
      ),
    );
  }
}

// In your app initialization:
PilotRegistry.registerWidget('custom_header', CustomHeaderParser());

Registering Custom Action Handlers #

Implement BaseActionHandler and register it with PilotRegistry:

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

class AnalyticsActionHandler extends BaseActionHandler {
  @override
  void handle(ActionModel action, BuildContext context) {
    final eventName = action.params['event_name'];
    debugPrint('Analytics tracked: $eventName');
  }
}

// In your app initialization:
PilotRegistry.registerAction('trackAnalytics', AnalyticsActionHandler());

📂 Example App #

An interactive dashboard example is available in the example/ directory.

To run the example:

cd example
flutter run

📄 License #

This project is licensed under the MIT License.

1
likes
120
points
532
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A dynamic, theme-aware JSON UI rendering engine for Flutter with extensible parsers, action handlers, and ready-to-use smart dispatch & RTS action components.

Homepage

License

MIT (license)

Dependencies

android_intent_plus, audioplayers, cached_network_image, flutter, url_launcher

More

Packages that depend on pilot_ui