like_devtool 1.0.2 copy "like_devtool: ^1.0.2" to clipboard
like_devtool: ^1.0.2 copied to clipboard

A developer tooling panel for the LIKE networking package. Provides an inspectable bottom sheet with logs, traffic inspector, and feature flags.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:like/like.dart';
import 'package:like_devtool/like_devtool.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const LikeDevToolExampleApp());
}

/// The root application widget demonstrating the LIKE DevTool panel.
class LikeDevToolExampleApp extends StatelessWidget {
  /// Creates the [LikeDevToolExampleApp].
  const LikeDevToolExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Like(
      baseUrl: 'https://jsonplaceholder.typicode.com',
      // Injects the LIKE DevTool overlay. The overlay FAB appears automatically
      // in debug builds and is stripped in release builds.
      devTool: (child) => LikeDevTool(child: child),
      child: MaterialApp(
        title: 'LIKE DevTool Example',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          useMaterial3: true,
          colorScheme: ColorScheme.fromSeed(
            seedColor: const Color(0xFF14B8A6),
            brightness: Brightness.dark,
          ),
          scaffoldBackgroundColor: const Color(0xFF0F1115),
          appBarTheme: const AppBarTheme(
            backgroundColor: Color(0xFF16181D),
            elevation: 0,
            centerTitle: true,
          ),
        ),
        home: const DevToolDemoScreen(),
      ),
    );
  }
}

/// The main demo screen showing various actions to trigger traffic and inspect details.
class DevToolDemoScreen extends StatefulWidget {
  /// Creates a [DevToolDemoScreen] widget.
  const DevToolDemoScreen({super.key});

  @override
  State<DevToolDemoScreen> createState() => _DevToolDemoScreenState();
}

class _DevToolDemoScreenState extends State<DevToolDemoScreen> {
  final ValueNotifier<LikeStateResponse<List<dynamic>>> _postsNotifier =
      ValueNotifier(LikeStateResponse.idle());

  @override
  void initState() {
    super.initState();
    _fetchDemoPosts();
  }

  @override
  void dispose() {
    _postsNotifier.dispose();
    super.dispose();
  }

  Future<void> _fetchDemoPosts() async {
    _postsNotifier.value = LikeStateResponse.loading();
    final result = await LikeClient().get(
      '/posts',
      ars: const ARS(staleWhileRevalidate: true),
    );
    _postsNotifier.value = LikeStateResponse.fromResult(result);
  }

  Future<void> _triggerPostRequest() async {
    // Generate a POST request to show up in the devtool traffic inspector
    await LikeClient().post(
      '/posts',
      body: {
        'title': 'Testing LIKE DevTool',
        'body': 'This request was captured by the traffic inspector!',
        'userId': 1,
      },
    );
    if (!mounted) return;
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('POST request triggered! Open DevTool to inspect.'),
        backgroundColor: Color(0xFF14B8A6),
      ),
    );
  }

  Future<void> _triggerErrorRequest() async {
    // Generate a failing request to demonstrate error handling and red indicators
    await LikeClient().get('/invalid-endpoint-for-error-testing');
    if (!mounted) return;
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('Failed GET request triggered! Open DevTool to inspect.'),
        backgroundColor: Colors.redAccent,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          'LIKE DEVTOOL DEMO',
          style: TextStyle(
            fontWeight: FontWeight.bold,
            letterSpacing: 1.2,
            fontSize: 16,
          ),
        ),
      ),
      body: Column(
        children: [
          // Control Actions Panel
          Container(
            padding: const EdgeInsets.all(16.0),
            color: const Color(0xFF16181D),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                const Text(
                  'INTERACT & GENERATE TRAFFIC',
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: Color(0xFF14B8A6),
                    fontSize: 11,
                    fontWeight: FontWeight.bold,
                    letterSpacing: 1.5,
                  ),
                ),
                const SizedBox(height: 12),
                Row(
                  children: [
                    Expanded(
                      child: ElevatedButton.icon(
                        style: ElevatedButton.styleFrom(
                          backgroundColor: const Color(0xFF1E2128),
                          foregroundColor: Colors.white,
                        ),
                        onPressed: _triggerPostRequest,
                        icon: const Icon(Icons.send_rounded, size: 16),
                        label: const Text('POST Req'),
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      child: ElevatedButton.icon(
                        style: ElevatedButton.styleFrom(
                          backgroundColor: const Color(0xFF1E2128),
                          foregroundColor: Colors.white,
                        ),
                        onPressed: _triggerErrorRequest,
                        icon: const Icon(Icons.error_outline_rounded, size: 16),
                        label: const Text('Fail Req'),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
          // List of posts from jsonplaceholder
          Expanded(
            child: ValueListenableBuilder<LikeStateResponse<List<dynamic>>>(
              valueListenable: _postsNotifier,
              builder: (context, state, _) {
                return LikeBuilder<List<dynamic>>(
                  observe: () => state,
                  onLoading: () => const Center(
                    child: CircularProgressIndicator(
                      valueColor: AlwaysStoppedAnimation(Color(0xFF14B8A6)),
                    ),
                  ),
                  onSuccess: (posts, isRefreshing, isFromSWR) {
                    final displayPosts = posts.take(10).toList();
                    return Stack(
                      children: [
                        RefreshIndicator(
                          onRefresh: _fetchDemoPosts,
                          color: const Color(0xFF14B8A6),
                          child: ListView.builder(
                            padding: const EdgeInsets.all(12),
                            itemCount: displayPosts.length,
                            itemBuilder: (context, index) {
                              final post = displayPosts[index];
                              return Card(
                                color: const Color(0xFF16181D),
                                margin: const EdgeInsets.only(bottom: 10),
                                shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(12),
                                ),
                                child: ListTile(
                                  leading: CircleAvatar(
                                    backgroundColor: const Color(0xFF1E2128),
                                    foregroundColor: const Color(0xFF14B8A6),
                                    child: Text(post['id'].toString()),
                                  ),
                                  title: Text(
                                    post['title'],
                                    maxLines: 1,
                                    overflow: TextOverflow.ellipsis,
                                    style: const TextStyle(
                                      fontWeight: FontWeight.bold,
                                      color: Colors.white,
                                    ),
                                  ),
                                  subtitle: Text(
                                    post['body'],
                                    maxLines: 2,
                                    overflow: TextOverflow.ellipsis,
                                    style: TextStyle(
                                      color: Colors.white.withValues(
                                        alpha: 0.7,
                                      ),
                                    ),
                                  ),
                                ),
                              );
                            },
                          ),
                        ),
                        if (isRefreshing)
                          const Positioned(
                            top: 0,
                            left: 0,
                            right: 0,
                            child: LinearProgressIndicator(
                              minHeight: 2,
                              valueColor: AlwaysStoppedAnimation(
                                Color(0xFF14B8A6),
                              ),
                              backgroundColor: Colors.transparent,
                            ),
                          ),
                      ],
                    );
                  },
                  onError: (error) => Center(
                    child: Padding(
                      padding: const EdgeInsets.all(24.0),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          const Icon(
                            Icons.cloud_off_rounded,
                            size: 48,
                            color: Colors.redAccent,
                          ),
                          const SizedBox(height: 12),
                          Text(
                            'Failed to fetch posts: ${error.message}',
                            textAlign: TextAlign.center,
                            style: const TextStyle(color: Colors.white70),
                          ),
                          const SizedBox(height: 16),
                          ElevatedButton(
                            onPressed: _fetchDemoPosts,
                            child: const Text('Retry'),
                          ),
                        ],
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        backgroundColor: const Color(0xFF14B8A6),
        foregroundColor: Colors.white,
        onPressed: _fetchDemoPosts,
        child: const Icon(Icons.refresh_rounded),
      ),
    );
  }
}
1
likes
0
points
272
downloads

Publisher

unverified uploader

Weekly Downloads

A developer tooling panel for the LIKE networking package. Provides an inspectable bottom sheet with logs, traffic inspector, and feature flags.

Repository (GitHub)
View/report issues

Topics

#devtools #networking #debugging #flutter

License

unknown (license)

Dependencies

connectivity_plus, device_info_plus, flutter, hive, hive_flutter, like, network_info_plus, package_info_plus, path_provider

More

Packages that depend on like_devtool