duplicate_images_plugin 0.0.2 copy "duplicate_images_plugin: ^0.0.2" to clipboard
duplicate_images_plugin: ^0.0.2 copied to clipboard

Get duplicate images from gallery.

example/lib/main.dart

import 'package:duplicate_images_plugin_example/picture_item.dart';
import 'package:flutter/material.dart';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:duplicate_images_plugin/duplicate_images_plugin.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _platformVersion = 'Unknown';
  final _duplicateImagesPlugin = DuplicateImagesPlugin();
  Map<String, List<String>> duplicateGroups = {};

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

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      platformVersion = await _duplicateImagesPlugin.getPlatformVersion() ?? 'Unknown platform version';
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _platformVersion = platformVersion;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: SingleChildScrollView(
          child: Column(
            children: [
              Center(
                child: Text('Running on: $_platformVersion\n'),
              ),
              InkWell(
                onTap: () async {
                  print('START');
                  var now = DateTime.now();
                  if (await Permission.photos.isGranted) {
                    final duplicates = await _duplicateImagesPlugin.findAndListDuplicates();
                    setState(() {
                      duplicateGroups = duplicates;
                    });
                    print("Time taken: ${DateTime.now().difference(now).inSeconds} $duplicates");
                  } else {
                    Permission.photos.request().then((rs) async {
                      final duplicates = await _duplicateImagesPlugin.findAndListDuplicates();
                      setState(() {
                        duplicateGroups = duplicates;
                      });
                      print("Time taken: ${DateTime.now().difference(now).inSeconds} $duplicates");
                    }).catchError((onError) {
                      print(" Permission.photos.request err: $onError");
                    });
                  }
                },
                child: const Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text('Find and list duplicates'),
                ),
              ),
              ListView.builder(
                physics: NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                itemCount: duplicateGroups.length,
                itemBuilder: (context, index) {
                  String key = duplicateGroups.keys.elementAt(index);
                  List<String> assets = duplicateGroups[key]!;
                  return Container(
                    child: Column(
                      children: [
                        Text('Group Key: $key'),
                        Container(
                          height: 200,
                          width: MediaQuery.sizeOf(context).width,
                          child: ListView.separated(
                            scrollDirection: Axis.horizontal,
                            shrinkWrap: true,
                            itemCount: assets.length,
                            itemBuilder: (context, index) {
                              return PictureItem(imageId: assets[index]);
                            }, separatorBuilder: (BuildContext context, int index) {
                              return const SizedBox(width: 10);
                          },
                          ),
                        ),
                      ],
                    )
                  );
                  return ExpansionTile(
                    title: Text('Group Key: ${assets.length}'),
                    children: assets.map((asset) {
                      return PictureItem(imageId: asset);
                    }).toList(),
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}