cameraShutterWidget function

Widget cameraShutterWidget({
  1. required void takePicture(),
  2. required Fr<CameraTimingMsg> shutterTiming,
  3. required TickerProvider tickerProvider,
  4. required DspReg disposers,
})

Implementation

Widget cameraShutterWidget({
  required void Function() takePicture,
  required Fr<CameraTimingMsg> shutterTiming,
  required TickerProvider tickerProvider,
  required DspReg disposers,
}) {
  final timer = fw<double?>(null);

  final shootingFr = fr(() => timer() != null);

  var latestDisposers = DspImpl();
  disposers.add(() => latestDisposers.dispose());

  void shutterClicked(TickerProvider tickers) {
    final shutterDelayMilliseconds =
        shutterTiming.read().shutterDelayMilliseconds;

    if (shutterDelayMilliseconds <= 0) {
      timer.value = 0;
      takePicture();
    } else {
      timer.value = 1;

      late final Ticker ticker;

      latestDisposers = DspImpl()..add(() => ticker.dispose());

      ticker = tickers.createTicker(
        (elapsed) {
          final time = 1 - elapsed.inMilliseconds / shutterDelayMilliseconds;
          timer.value = time;
          if (time <= 0) {
            latestDisposers.dispose();
            try {
              takePicture();
            } catch (e, st) {
              _logger.e(e, st);
              rethrow;
            }
          }
        },
      )..start();
    }
  }

  late final shootingWidget = Container(
    decoration: BoxDecoration(
      color: Colors.black.withOpacity(0.5),
      borderRadius: BorderRadius.circular(8),
    ),
    child: Padding(
      padding: const EdgeInsets.all(8.0),
      child: Text(
        'Hold still!',
        style: TextStyle(
          color: Colors.white,
        ),
      ),
    ),
  );

  return Stack(
    fit: StackFit.expand,
    children: [
      flcFrr(() {
        final shooting = shootingFr();

        if (shooting) return nullWidget;

        final button = flcCameraOverlayButton(
          onPressed: () {
            shutterClicked(tickerProvider);
          },
        );

        return SafeArea(
          child: Align(
            alignment: Alignment.bottomCenter,
            child: button,
          ),
        );
      }),
      flcFrr(() {
        final time = timer();

        if (time == null) {
          return nullWidget;
        }

        return Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              SizedBox(
                height: 150.0,
                width: 150.0,
                child: CircularProgressIndicator(
                  value: time,
                  strokeWidth: 20,
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(32.0),
                child: shootingWidget,
              ),
            ],
          ),
        );
      }),
    ],
  );
}