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

Get duplicate images from gallery.

example/lib/main.dart

import 'dart:async';
import 'dart:isolate';
import 'package:flutter/material.dart';
import 'package:duplicate_images_plugin/duplicate_images_plugin.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:flutter_isolate/flutter_isolate.dart';
import 'background_task.dart'; // Import the background task

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DuplicateImagesScreen(),
    );
  }
}

class DuplicateImagesScreen extends StatefulWidget {
  @override
  _DuplicateImagesScreenState createState() => _DuplicateImagesScreenState();
}

class _DuplicateImagesScreenState extends State<DuplicateImagesScreen> {
  Map<String, List<String>> duplicateGroups = {};
  bool isLoading = true;
  StreamController<Map<String, List<String>>>? _streamController;

  @override
  void initState() {
    super.initState();
    _streamController = StreamController();
    _streamController!.stream.listen((data) {
      setState(() {
        duplicateGroups.addAll(data);
        isLoading = false;
      });
    });
  }

  @override
  void dispose() {
    _streamController?.close();
    super.dispose();
  }

  Future<void> findAndListDuplicates() async {
    setState(() {
      isLoading = true;
    });

    ReceivePort receivePort = ReceivePort();
    await FlutterIsolate.spawn(backgroundTask, receivePort.sendPort);

    receivePort.listen((message) {
      if (message is Map<String, dynamic> && message.containsKey("error")) {
        print("Error finding duplicates: ${message['error']}");
      } else if (message is Map<String, List<String>>) {
        _streamController?.add(message);
      }
    });
  }




  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: InkWell(child: Text('Duplicate Images'),onTap: (){
print("THE TAP");
          findAndListDuplicates();
        },),
      ),
      body: isLoading
          ? Center(child: SingleChildScrollView(
            child: ListView(
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
              children: [
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                Text('data', style: TextStyle(fontSize: 100),),
                CircularProgressIndicator(),
              ],
            ),
          ))
          : ListView.builder(
        itemCount: duplicateGroups.keys.length,
        itemBuilder: (context, index) {
          String key = duplicateGroups.keys.elementAt(index);
          List<String> assets = duplicateGroups[key]!;
          return ExpansionTile(
            title: Text('Group Key: $key'),
            children: assets.map((asset) => AssetImageView(assetId: asset)).toList(),
          );
        },
      ),
    );
  }
}

class AssetImageView extends StatelessWidget {
  final String assetId;

  const AssetImageView({Key? key, required this.assetId}) : super(key: key);

  Future<Widget> _loadImage() async {
    final asset = await AssetEntity.fromId(assetId);
    if (asset == null) {
      return Text('Image not found');
    }

    final thumb = await asset.thumbnailDataWithSize(ThumbnailSize(300, 300));
    if (thumb == null) {
      return Text('Image not available');
    }

    return Image.memory(thumb, fit: BoxFit.cover);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<Widget>(
      future: _loadImage(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return CircularProgressIndicator();
        } else if (snapshot.hasError) {
          return Text('Error loading image');
        } else {
          return snapshot.data!;
        }
      },
    );
  }
}