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

Flutter SDK for AssetFlux — manage remote image assets with automatic density selection, CDN caching, and gradual rollout support.

example/lib/main.dart

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize AssetFlux SDK
  try {
    await AssetFlux.init(
      // Replace with your project credentials from the AssetFlux dashboard
      // Get these from Settings > API Keys (use an SDK key with afk_ prefix)
      projectId: 'af_00000000000000000000000000000000',
      apiKey: 'afk_0000000000000000000000000000000000000000000000000000000000000000',
      config: const AssetFluxConfig(
        debug: true,
        // Remove instanceConfig for production — defaults to https://api.assetflux.io
        // instanceConfig: InstanceConfig(baseUrl: 'https://api.dev.assetflux.io'),
      ),
    );
  } catch (e) {
    debugPrint('Failed to initialize AssetFlux: $e');
  }

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'AssetFlux Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final List<String> _exampleAssets = [
    'home.hero.banner',
    'home.logo',
    'profile.avatar',
    'product.thumbnail',
  ];

  @override
  void initState() {
    super.initState();
    // Prefetch critical assets on app start
    _prefetchAssets();
  }

  Future<void> _prefetchAssets() async {
    if (!AssetFlux.isInitialized) return;

    try {
      await AssetFlux.prefetchPattern('home.*');
      debugPrint('Prefetched home assets');
    } catch (e) {
      debugPrint('Prefetch failed: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('AssetFlux Example'),
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildInfoCard(),
          const SizedBox(height: 24),
          _buildAssetsSection(),
          const SizedBox(height: 24),
          _buildActionsSection(),
        ],
      ),
    );
  }

  Widget _buildInfoCard() {
    if (!AssetFlux.isInitialized) {
      return const Card(
        child: Padding(
          padding: EdgeInsets.all(16),
          child: Text(
            'SDK not initialized. Please check your configuration.',
            style: TextStyle(color: Colors.red),
          ),
        ),
      );
    }

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              'SDK Status',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
              ),
            ),
            const SizedBox(height: 12),
            _buildInfoRow('Environment', AssetFlux.environment.name),
            _buildInfoRow('Project ID', AssetFlux.projectId),
            _buildInfoRow('Offline Mode', AssetFlux.isOfflineMode.toString()),
            _buildInfoRow('Identifier', AssetFlux.identifier ?? 'Not set'),
          ],
        ),
      ),
    );
  }

  Widget _buildInfoRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        children: [
          SizedBox(
            width: 120,
            child: Text(
              '$label:',
              style: const TextStyle(fontWeight: FontWeight.w500),
            ),
          ),
          Expanded(
            child: Text(
              value,
              style: const TextStyle(color: Colors.grey),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildAssetsSection() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const Text(
          'Example Assets',
          style: TextStyle(
            fontSize: 18,
            fontWeight: FontWeight.bold,
          ),
        ),
        const SizedBox(height: 12),
        ..._exampleAssets.map(_buildAssetCard),
      ],
    );
  }

  Widget _buildAssetCard(String assetKey) {
    return Card(
      margin: const EdgeInsets.only(bottom: 12),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              assetKey,
              style: const TextStyle(
                fontWeight: FontWeight.w500,
                fontSize: 16,
              ),
            ),
            const SizedBox(height: 12),
            SizedBox(
              height: 200,
              child: RemoteImage(
                assetKey,
                fit: BoxFit.cover,
                placeholder: const ShimmerPlaceholder(),
                errorWidget: const Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.error_outline, size: 48, color: Colors.grey),
                      SizedBox(height: 8),
                      Text(
                        'Asset not found',
                        style: TextStyle(color: Colors.grey),
                      ),
                    ],
                  ),
                ),
                fallbackAsset: 'assets/images/placeholder.png',
              ),
            ),
            const SizedBox(height: 8),
            ElevatedButton.icon(
              onPressed: () => _showDebugInfo(assetKey),
              icon: const Icon(Icons.info_outline, size: 16),
              label: const Text('Debug Info'),
              style: ElevatedButton.styleFrom(
                minimumSize: const Size.fromHeight(36),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildActionsSection() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        const Text(
          'Actions',
          style: TextStyle(
            fontSize: 18,
            fontWeight: FontWeight.bold,
          ),
        ),
        const SizedBox(height: 12),
        ElevatedButton.icon(
          onPressed: _refreshManifest,
          icon: const Icon(Icons.refresh),
          label: const Text('Refresh Manifest'),
        ),
        const SizedBox(height: 8),
        ElevatedButton.icon(
          onPressed: _clearCache,
          icon: const Icon(Icons.delete_outline),
          label: const Text('Clear Cache'),
        ),
        const SizedBox(height: 8),
        ElevatedButton.icon(
          onPressed: _prefetchAll,
          icon: const Icon(Icons.download),
          label: const Text('Prefetch All'),
        ),
      ],
    );
  }

  void _showDebugInfo(String assetKey) {
    if (!AssetFlux.isInitialized) return;

    final debugInfo = AssetFlux.getDebugInfo(assetKey);

    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Debug Info: $assetKey'),
        content: SingleChildScrollView(
          child: Text(
            debugInfo.entries
                .map((e) => '${e.key}: ${e.value}')
                .join('\n'),
            style: const TextStyle(fontFamily: 'monospace'),
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Close'),
          ),
        ],
      ),
    );
  }

  Future<void> _refreshManifest() async {
    try {
      await AssetFlux.refreshManifest();
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Manifest refreshed')),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Failed to refresh: $e')),
        );
      }
    }
  }

  Future<void> _clearCache() async {
    try {
      await AssetFlux.clearCache();
      if (mounted) {
        setState(() {});
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Cache cleared')),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Failed to clear cache: $e')),
        );
      }
    }
  }

  Future<void> _prefetchAll() async {
    try {
      await AssetFlux.prefetchAll(_exampleAssets);
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Assets prefetched')),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Failed to prefetch: $e')),
        );
      }
    }
  }
}
3
likes
160
points
213
downloads

Publisher

verified publisherassetflux.io

Weekly Downloads

Flutter SDK for AssetFlux — manage remote image assets with automatic density selection, CDN caching, and gradual rollout support.

Homepage
Repository (GitHub)
View/report issues

Topics

#assets #images #cdn #remote-config

Documentation

Documentation
API reference

License

BSD-3-Clause (license)

Dependencies

crypto, device_info_plus, flutter, flutter_cache_manager, http, path_provider, shared_preferences

More

Packages that depend on assetflux_flutter