|
|
|
// SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru>
|
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
import 'dart:io';
|
|
|
|
|
|
|
|
import 'package:camera/camera.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_example_packages/theme/colors.dart';
|
|
|
|
import 'package:flutter_example_packages/widgets/base/export.dart';
|
|
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
|
|
|
|
|
|
class CameraControlPanel extends AppStatefulWidget {
|
|
|
|
const CameraControlPanel({
|
|
|
|
super.key,
|
|
|
|
required this.disable,
|
|
|
|
required this.controller,
|
|
|
|
required this.photo,
|
|
|
|
required this.onRecordingStart,
|
|
|
|
required this.onRecordingStop,
|
|
|
|
required this.onRecordingPause,
|
|
|
|
required this.onRecordingResume,
|
|
|
|
required this.onTakePhoto,
|
|
|
|
required this.onClearPhoto,
|
|
|
|
});
|
|
|
|
|
|
|
|
final bool disable;
|
|
|
|
final CameraController? controller;
|
|
|
|
final File? photo;
|
|
|
|
final void Function() onRecordingStart;
|
|
|
|
final void Function() onRecordingStop;
|
|
|
|
final void Function() onRecordingPause;
|
|
|
|
final void Function() onRecordingResume;
|
|
|
|
final void Function() onTakePhoto;
|
|
|
|
final void Function() onClearPhoto;
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<CameraControlPanel> createState() => _CameraControlPanelState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _CameraControlPanelState extends AppState<CameraControlPanel> {
|
|
|
|
@override
|
|
|
|
Widget buildWide(
|
|
|
|
BuildContext context,
|
|
|
|
MediaQueryData media,
|
|
|
|
AppLocalizations l10n,
|
|
|
|
) {
|
|
|
|
final isPhoto = widget.photo != null;
|
|
|
|
final isRecordingVideo = widget.controller?.value.isRecordingVideo ?? false;
|
|
|
|
final isRecordingPaused =
|
|
|
|
widget.controller?.value.isRecordingPaused ?? false;
|
|
|
|
|
|
|
|
return Visibility(
|
|
|
|
visible: widget.controller != null,
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
ClipOval(
|
|
|
|
child: Material(
|
|
|
|
child: IconButton(
|
|
|
|
icon: Icon(
|
|
|
|
isRecordingVideo ? Icons.stop_circle : Icons.videocam,
|
|
|
|
color: AppColors.primary.withOpacity(isPhoto ||
|
|
|
|
widget.disable ||
|
|
|
|
true /* @todo disable video record */
|
|
|
|
? 0.5
|
|
|
|
: 1),
|
|
|
|
),
|
|
|
|
onPressed: isPhoto ||
|
|
|
|
widget.disable ||
|
|
|
|
true // @todo disable video record
|
|
|
|
? null
|
|
|
|
: () {
|
|
|
|
if (isRecordingVideo) {
|
|
|
|
widget.onRecordingStop.call();
|
|
|
|
} else {
|
|
|
|
widget.onRecordingStart.call();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
if (isRecordingVideo)
|
|
|
|
ClipOval(
|
|
|
|
child: Material(
|
|
|
|
child: IconButton(
|
|
|
|
icon: Icon(
|
|
|
|
isRecordingPaused
|
|
|
|
? Icons.play_circle
|
|
|
|
: Icons.pause_circle,
|
|
|
|
color: AppColors.primary,
|
|
|
|
),
|
|
|
|
onPressed: () {
|
|
|
|
if (isRecordingPaused) {
|
|
|
|
widget.onRecordingResume.call();
|
|
|
|
} else {
|
|
|
|
widget.onRecordingPause.call();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
const Spacer(),
|
|
|
|
ClipOval(
|
|
|
|
child: Material(
|
|
|
|
child: IconButton(
|
|
|
|
icon: Icon(
|
|
|
|
isPhoto ? Icons.image_not_supported : Icons.photo_camera,
|
|
|
|
color: AppColors.primary.withOpacity(
|
|
|
|
isRecordingVideo || widget.disable ? 0.5 : 1),
|
|
|
|
),
|
|
|
|
onPressed: isRecordingVideo || widget.disable
|
|
|
|
? null
|
|
|
|
: () {
|
|
|
|
if (isPhoto) {
|
|
|
|
widget.onClearPhoto.call();
|
|
|
|
} else {
|
|
|
|
widget.onTakePhoto.call();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|