Skip to main content

endpoint_lens 0.2.1 copy "endpoint_lens: ^0.2.1" to clipboard
endpoint_lens: ^0.2.1 copied to clipboard

Inspect recent API calls in debug builds, and in internal QA releases when you opt in. Attach Dio once, then long-press anywhere.

example/lib/main.dart

import 'package:dio/dio.dart';
import 'package:endpoint_lens/endpoint_lens.dart';
import 'package:flutter/material.dart';

import 'example_api.dart';

/// The same Dio client the example screens call.
///
/// The bearer value is fake so a debug long press can show that API Lens
/// redacts it.
final Dio exampleDio = Dio(
  BaseOptions(
    baseUrl: 'https://api.example.com/v1',
    headers: const <String, dynamic>{
      'Authorization': 'Bearer demo-secret-token',
    },
  ),
);

/// Example client created after [ApiLens.init] attaches [exampleDio].
late ExampleApi exampleApi;

void main() {
  ApiLens.init(dio: exampleDio);
  exampleApi = ExampleApi(exampleDio);
  runApp(const ExampleApp());
}

/// Three screens plus one advanced exact-mapping page.
class ExampleApp extends StatelessWidget {
  /// Creates the example app.
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    const seed = Color(0xFF0B6E4F);
    return MaterialApp(
      title: 'API Lens example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: seed),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: seed,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      navigatorObservers: [ApiLensNavigatorObserver()],
      initialRoute: 'Home',
      routes: {
        'Home': (_) => const HomeScreen(),
        'Products': (_) => const ProductsScreen(),
        'Profile': (_) => const ProfileScreen(),
        'Advanced': (_) => const AdvancedScreen(),
      },
    );
  }
}

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  void initState() {
    super.initState();
    exampleApi.loadHome();
  }

  @override
  Widget build(BuildContext context) {
    return _Page(
      index: 0,
      title: 'Home',
      child: const Text('Long press anywhere to inspect recent API activity.'),
    );
  }
}

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

  @override
  State<ProductsScreen> createState() => _ProductsScreenState();
}

class _ProductsScreenState extends State<ProductsScreen> {
  late final Future<List<DemoProduct>> _products = exampleApi.loadProducts();

  @override
  Widget build(BuildContext context) {
    return _Page(
      index: 1,
      title: 'Products',
      child: FutureBuilder<List<DemoProduct>>(
        future: _products,
        builder: (context, snapshot) {
          final products = snapshot.data ?? const <DemoProduct>[];
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              for (final product in products)
                Text('${product.name} · \$${product.price}'),
            ],
          );
        },
      ),
    );
  }
}

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

  @override
  State<ProfileScreen> createState() => _ProfileScreenState();
}

class _ProfileScreenState extends State<ProfileScreen> {
  late final Future<DemoProfile> _profile = exampleApi.loadProfile();

  @override
  Widget build(BuildContext context) {
    return _Page(
      index: 2,
      title: 'Profile',
      child: FutureBuilder<DemoProfile>(
        future: _profile,
        builder: (context, snapshot) {
          final profile = snapshot.data;
          if (profile == null) return const Text('Loading profile');
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(profile.name),
              Text(profile.email),
              for (final post in profile.posts) Text(post.title),
              TextButton(
                onPressed: () => Navigator.pushNamed(context, 'Advanced'),
                child: const Text('Advanced exact mapping'),
              ),
            ],
          );
        },
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Advanced')),
      body: Center(
        child: ApiLensWidget(
          feature: 'avatar',
          child: Padding(
            padding: const EdgeInsets.all(24),
            child: FilledButton(
              onPressed: exampleApi.loadAvatar,
              child: const Text('Load avatar'),
            ),
          ),
        ),
      ),
    );
  }
}

class _Page extends StatelessWidget {
  const _Page({required this.index, required this.title, required this.child});

  final int index;
  final String title;
  final Widget child;

  static const _routes = <String>['Home', 'Products', 'Profile'];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Padding(padding: const EdgeInsets.all(24), child: child),
      bottomNavigationBar: NavigationBar(
        selectedIndex: index,
        onDestinationSelected: (next) {
          if (next == index) return;
          Navigator.pushReplacementNamed(context, _routes[next]);
        },
        destinations: const [
          NavigationDestination(icon: Icon(Icons.home_outlined), label: 'Home'),
          NavigationDestination(
            icon: Icon(Icons.shopping_bag_outlined),
            label: 'Products',
          ),
          NavigationDestination(
            icon: Icon(Icons.person_outline),
            label: 'Profile',
          ),
        ],
      ),
    );
  }
}
0
likes
160
points
575
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Inspect recent API calls in debug builds, and in internal QA releases when you opt in. Attach Dio once, then long-press anywhere.

Repository (GitHub)
View/report issues

Topics

#flutter #debugging #api #dio #developer-tools

License

MIT (license)

Dependencies

dio, flutter

More

Packages that depend on endpoint_lens