cloud_media 0.0.6 copy "cloud_media: ^0.0.6" to clipboard
cloud_media: ^0.0.6 copied to clipboard

A complete Firebase-native media management Flutter package. One line to pick. Everything else automated.

example/lib/main.dart

// Hide SyncStatusIndicator from riverpod_offline_sync to avoid conflict
// with cloud_media's own SyncStatusIndicator widget.
import 'package:riverpod_offline_sync/riverpod_offline_sync.dart'
    hide SyncStatusIndicator;

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:permission_handler_package/permission_handler_package.dart';
import 'package:cloud_media/cloud_media.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await PermissionHandler.initialize();
  await OfflineSyncLayer.instance.initialize(
    config: const SyncConfig(
      autoSyncOnReconnect: true,
      syncImmediately: true,
      maxConcurrentOperations: 2,
      enableMetrics: true,
      syncOnWiFiOnly: false,
      maxRetries: 5,
      initialRetryDelay: Duration(seconds: 2),
      maxQueueSize: 500,
    ),
  );
  await CloudMedia.initialize(
    config: const CloudMediaConfig(
      imageQuality: 85,
      maxSelection: 20,
      enableOfflineSync: true,
      enableLogging: true,
    ),
  );
  runApp(const ProviderScope(child: ExampleApp()));
}

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

  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: const Size(375, 812),
      minTextAdapt: true,
      builder: (context, child) {
        return MaterialApp(
          title: 'CloudMedia Example',
          theme: ThemeData(
              primarySwatch: Colors.blue,
              useMaterial3: true),
          home: child,
          debugShowCheckedModeBanner: false,
        );
      },
      child: const ExampleScreen(),
    );
  }
}

class ExampleScreen extends ConsumerStatefulWidget {
  const ExampleScreen({super.key});

  @override
  ConsumerState<ExampleScreen> createState() =>
      _ExampleScreenState();
}

class _ExampleScreenState
    extends ConsumerState<ExampleScreen> {
  List<CloudMediaItem> _items = [];
  bool _loading = false;

  Future<void> _pickImage() async {
    try {
      final items =
          await CloudMedia.pick(type: CloudMediaType.image);
      setState(() => _items = [..._items, ...items]);
      _snack('Picked ${items.length} image(s)');
    } catch (e) {
      _snack('Error: $e', error: true);
    }
  }

  Future<void> _loadAll() async {
    setState(() => _loading = true);
    try {
      final items = await CloudMedia.list();
      setState(() => _items = items);
    } catch (e) {
      _snack('Error: $e', error: true);
    } finally {
      setState(() => _loading = false);
    }
  }

  void _snack(String msg, {bool error = false}) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text(msg),
      backgroundColor: error ? Colors.red : Colors.green,
    ));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('CloudMedia Example'),
        // SyncStatusIndicator from cloud_media (not riverpod_offline_sync)
        actions: [
          SyncStatusIndicator(showLabel: false),
        ],
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Wrap(
              spacing: 8,
              children: [
                ElevatedButton.icon(
                  onPressed: _pickImage,
                  icon: const Icon(Icons.image),
                  label: const Text('Pick Image'),
                ),
                ElevatedButton.icon(
                  onPressed: _loadAll,
                  icon: const Icon(Icons.refresh),
                  label: const Text('Load All'),
                ),
              ],
            ),
          ),
          Expanded(
            child: _loading
                ? const Center(
                    child: CircularProgressIndicator())
                : _items.isEmpty
                    ? const Center(
                        child: Text('No media yet'))
                    : MediaGrid(
                        mediaItems: _items,
                        onItemTap: (item) =>
                            CloudMedia.share(item.id),
                        onItemLongPress: (item) async {
                          await CloudMedia.delete(item.id);
                          setState(() => _items.removeWhere(
                              (i) => i.id == item.id));
                        },
                      ),
          ),
        ],
      ),
      floatingActionButton: PermissionAwareMediaPicker(
        mediaType: CloudMediaType.image,
        maxCount: 5,
        onMediaSelected: (_) => _loadAll(),
        child: FloatingActionButton(
          onPressed: () {},
          child: const Icon(Icons.add_photo_alternate),
        ),
      ),
    );
  }
}