Apparence-io / CamerAwesome

📸 Embedding a camera experience within your own app shouldn't be that hard. A flutter plugin to integrate awesome Android / iOS camera experience.
https://ApparenceKit.dev
MIT License
906 stars 199 forks source link

onMediaCaptureEvent triggers duplicate PreviewScreen instances upon navigation #454

Closed CikaTom closed 2 months ago

CikaTom commented 3 months ago

Steps to Reproduce

Describe how to reproduce the error

Expected results

The expected behavior is a single navigation event to the PreviewScreen.

What it should be

Actual results

Contrary to expectations, the system navigates twice to the PreviewScreen, creating a duplicate instance.

About your device

Both Android and iOS

Your flutter version

Run this in your command line flutter --version

Flutter 3.16.3 • channel stable • https://github.com/flutter/flutter.git Framework • revision b0366e0a3f (3 months ago) • 2023-12-05 19:46:39 -0800 Engine • revision 54a7145303 Tools • Dart 3.2.3 • DevTools 2.28.4

Camera Screen

import 'package:accounting_app/camera/camera_overlay.dart';

import 'package:camerawesome/camerawesome_plugin.dart';
import 'package:flutter/material.dart';

import 'preview_screen.dart';

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

  @override
  CameraPageState createState() => CameraPageState();
}

class CameraPageState extends State<CameraScreen> {
  @override
  void dispose() {
    super.dispose();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          'Camera',
          style: TextStyle(color: Colors.white),
        ),
        backgroundColor: Colors.amber,
      ),
      body: CameraAwesomeBuilder.awesome(
        previewDecoratorBuilder: (state, previewRect) {
          return OverlayPreview(
            previewRect: previewRect.rect,
          );
        },
        topActionsBuilder: (state) => AwesomeTopActions(
          padding: EdgeInsets.zero,
          state: state,
          children: [
            AwesomeFlashButton(
              state: state,
            ),
          ],
        ),
        middleContentBuilder: (state) {
          return Column(
            mainAxisAlignment: MainAxisAlignment.end,
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [],
          );
        },
        bottomActionsBuilder: (state) => AwesomeBottomActions(
          state: state,
          padding: const EdgeInsets.only(
            bottom: 10,
            left: 8,
            right: 8,
          ),
          captureButton: AwesomeCaptureButton(
            state: state,
          ),
        ),
        onMediaCaptureEvent: (event) {
          event.captureRequest.when(
            single: (single) async {
              final filePath = event.captureRequest.when(
                single: (single) => single.file!.path,
              );

              await Navigator.push<MaterialPageRoute>(
                context,
                MaterialPageRoute(
                  builder: (context) => PreviewScreen(
                    key: UniqueKey(),
                    imagePath: filePath,
                  ),
                ),
              );
            },
          );
        },
        saveConfig: SaveConfig.photo(),
        sensorConfig: SensorConfig.single(
          sensor: Sensor.position(SensorPosition.back),
          aspectRatio: CameraAspectRatios.ratio_16_9,
          flashMode: FlashMode.auto,
        ),
        enablePhysicalButton: true,
        previewFit: CameraPreviewFit.cover,
      ),
    );
  }
}

Preview Screen

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
import 'package:accounting_app/bloc/document_bloc/document_cubit.dart';
import 'package:accounting_app/bloc/document_bloc/document_state.dart';
import 'package:accounting_app/custom_icons.dart';
import 'package:accounting_app/repository/pages_repository.dart';

class PreviewScreen extends StatefulWidget {
  const PreviewScreen({
    super.key,
    required this.imagePath,
  });

  final String imagePath;

  @override
  _PreviewScreenState createState() => _PreviewScreenState();
}

class _PreviewScreenState extends State<PreviewScreen> {
  @override
  void initState() {
    super.initState();

    print('Key + ${widget.key}');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(
            CustomIcons.arrow_left,
            size: 15,
            color: Colors.grey,
          ),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
        backgroundColor: Colors.white,
        title: const Text(
          'Preview',
          style: TextStyle(color: Colors.black),
        ),
      ),
      body: BlocBuilder<DocumentCubit, DocumentState>(
        builder: (context, state) {
          return Consumer<PagesRepository>(
            builder: (context, pagesRepo, child) {
              return Column(
                children: <Widget>[
                  Expanded(
                    child: Container(
                      color: Colors.grey,
                      padding: const EdgeInsets.fromLTRB(8, 8, 8, 8),
                      child: SizedBox(
                          height: 350,
                          width: MediaQuery.of(context).size.width,
                          child: PageView.builder(
                            itemBuilder: (context, pagePosition) {
                              return Center(
                                child: Container(
                                  margin: const EdgeInsets.all(
                                    10,
                                  ),
                                  child: Image.asset(widget.imagePath),
                                ),
                              );
                            },
                          )),
                    ),
                  ),
                ],
              );
            },
          );
        },
      ),
    );
  }
}

Madnex commented 2 months ago

How did you get onMediaCaptureEvent already? It is not in the latest versino on pub dev, is it?

CikaTom commented 2 months ago

You can use master version, put this in your pubsbec

  camerawesome:
    git:
      url: https://github.com/Apparence-io/CamerAwesome
Madnex commented 2 months ago

Thanks i managed indeed :) BTW I had the same issue like you. Hava a look at their example. You need to make sure to only filter out the MediaCaptureStatus.success (line 54 in that example). The onMediaCaptureEventfires already at the capturing state (and then again after success).

CikaTom commented 2 months ago

That's a good catch. I missed it at that time. Thanks for a heads up ;)