2022-12-29 08:45:28 +03:00
|
|
|
import 'package:flutter/material.dart';
|
2022-12-30 05:18:18 +03:00
|
|
|
// ignore: depend_on_referenced_packages
|
2022-12-29 08:45:28 +03:00
|
|
|
import 'package:gallery_picker/gallery_picker.dart';
|
2022-12-30 05:18:18 +03:00
|
|
|
// ignore: depend_on_referenced_packages
|
2022-12-29 08:45:28 +03:00
|
|
|
import 'package:camera/camera.dart';
|
|
|
|
import 'package:gallery_picker_example/examples/multiple_medias.dart';
|
|
|
|
|
|
|
|
class WhatsappPickPhoto extends StatefulWidget {
|
|
|
|
const WhatsappPickPhoto({super.key});
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<WhatsappPickPhoto> createState() => _WhatsappPickPhotoState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _WhatsappPickPhotoState extends State<WhatsappPickPhoto> {
|
|
|
|
CameraController? cameraController;
|
|
|
|
GalleryMedia? gallery;
|
|
|
|
List<MediaFile> selectedMedias = [];
|
|
|
|
List<CameraDescription>? cameras;
|
2023-01-20 09:58:21 +03:00
|
|
|
CameraLensDirection cameraLensDirection = CameraLensDirection.back;
|
2022-12-29 08:45:28 +03:00
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
initCamera();
|
|
|
|
fetchMedias();
|
|
|
|
GalleryPicker.listenSelectedFiles.listen((medias) {
|
|
|
|
selectedMedias = medias;
|
2023-01-20 09:58:21 +03:00
|
|
|
if (mounted) {
|
|
|
|
setState(() {});
|
|
|
|
}
|
2022-12-29 08:45:28 +03:00
|
|
|
});
|
|
|
|
super.initState();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> fetchMedias() async {
|
2023-01-20 09:58:21 +03:00
|
|
|
gallery = await GalleryPicker.initializeGallery;
|
2022-12-29 08:45:28 +03:00
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> initCamera() async {
|
|
|
|
cameraController = null;
|
|
|
|
setState(() {});
|
|
|
|
cameras ??= await availableCameras();
|
|
|
|
cameraController = CameraController(
|
|
|
|
cameras!.firstWhere(
|
|
|
|
(camera) => camera.lensDirection == cameraLensDirection),
|
|
|
|
ResolutionPreset.max);
|
|
|
|
cameraController!.initialize().then((_) {
|
|
|
|
if (!mounted) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setState(() {});
|
|
|
|
}).catchError((Object e) {
|
|
|
|
if (e is CameraException) {
|
|
|
|
switch (e.code) {
|
|
|
|
case 'CameraAccessDenied':
|
|
|
|
// Handle access errors here.
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// Handle other errors here.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isRecording = false;
|
|
|
|
bool anyProcess = false;
|
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
cameraController!.dispose();
|
|
|
|
GalleryPicker.disposeSelectedFilesListener();
|
|
|
|
super.dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2023-01-20 09:58:21 +03:00
|
|
|
return PickerScaffold(
|
2022-12-29 08:45:28 +03:00
|
|
|
backgroundColor: Colors.transparent,
|
2023-01-20 09:58:21 +03:00
|
|
|
onSelect: (List<MediaFile> selectedMedias) {
|
|
|
|
this.selectedMedias = selectedMedias;
|
|
|
|
if (mounted) {
|
2022-12-29 08:45:28 +03:00
|
|
|
setState(() {});
|
2023-01-20 09:58:21 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
initSelectedMedia: selectedMedias,
|
|
|
|
config: Config(mode: Mode.dark),
|
|
|
|
body: Stack(
|
|
|
|
children: [
|
|
|
|
if (cameraController != null && cameraController!.value.isInitialized)
|
|
|
|
SizedBox(
|
|
|
|
height: MediaQuery.of(context).size.height,
|
|
|
|
child: CameraPreview(
|
|
|
|
cameraController!,
|
2022-12-29 08:45:28 +03:00
|
|
|
),
|
2023-01-20 09:58:21 +03:00
|
|
|
),
|
|
|
|
if (gallery != null && gallery!.recent != null)
|
|
|
|
Positioned(
|
|
|
|
bottom: 100,
|
|
|
|
child: SizedBox(
|
|
|
|
width: MediaQuery.of(context).size.width,
|
|
|
|
height: 65,
|
|
|
|
child: ListView(
|
|
|
|
scrollDirection: Axis.horizontal,
|
|
|
|
children: [
|
|
|
|
for (var media in gallery!.recent!.files)
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 5),
|
|
|
|
child: GestureDetector(
|
|
|
|
onTap: () {
|
|
|
|
if (selectedMedias.isEmpty) {
|
|
|
|
Navigator.push(
|
|
|
|
context,
|
|
|
|
MaterialPageRoute(
|
|
|
|
builder: (context) =>
|
|
|
|
MultipleMediasView([media])),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
selectedMedias
|
|
|
|
.any((element) => element.id == media.id)
|
|
|
|
? selectedMedias.removeWhere(
|
|
|
|
(element) => element.id == media.id)
|
|
|
|
: selectedMedias.add(media);
|
2022-12-29 08:45:28 +03:00
|
|
|
setState(() {});
|
2023-01-20 09:58:21 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
onLongPress: () {
|
|
|
|
if (selectedMedias
|
|
|
|
.any((element) => element.id == media.id)) {
|
|
|
|
selectedMedias.removeWhere(
|
|
|
|
(element) => element.id == media.id);
|
|
|
|
} else {
|
|
|
|
selectedMedias.add(media);
|
|
|
|
}
|
|
|
|
setState(() {});
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
width: 65,
|
|
|
|
height: 65,
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
border: Border.all(
|
|
|
|
width: 2,
|
|
|
|
color: selectedMedias.any((element) =>
|
|
|
|
element.id == media.id)
|
|
|
|
? Colors.red
|
|
|
|
: Colors.black)),
|
|
|
|
child: Stack(
|
|
|
|
children: [
|
|
|
|
SizedBox(
|
|
|
|
width: 65,
|
|
|
|
height: 65,
|
|
|
|
child: ThumbnailMedia(
|
|
|
|
media: media,
|
2022-12-29 08:45:28 +03:00
|
|
|
),
|
2023-01-20 09:58:21 +03:00
|
|
|
),
|
|
|
|
if (selectedMedias
|
|
|
|
.any((element) => element.id == media.id))
|
|
|
|
Container(
|
|
|
|
color: Colors.black.withOpacity(0.3),
|
|
|
|
alignment: Alignment.center,
|
|
|
|
child: const Icon(
|
|
|
|
Icons.check,
|
|
|
|
size: 30,
|
|
|
|
color: Colors.white,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
2022-12-29 08:45:28 +03:00
|
|
|
),
|
|
|
|
),
|
2023-01-20 09:58:21 +03:00
|
|
|
),
|
|
|
|
if (selectedMedias.isNotEmpty)
|
2022-12-29 08:45:28 +03:00
|
|
|
Positioned(
|
2023-01-20 09:58:21 +03:00
|
|
|
bottom: 150,
|
|
|
|
right: 10,
|
|
|
|
child: FloatingActionButton(
|
|
|
|
onPressed: () {
|
|
|
|
Navigator.push(
|
|
|
|
context,
|
|
|
|
MaterialPageRoute(
|
|
|
|
builder: (context) =>
|
|
|
|
MultipleMediasView(selectedMedias)),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
mini: true,
|
|
|
|
child: const Icon(
|
|
|
|
Icons.check,
|
|
|
|
color: Colors.white,
|
|
|
|
),
|
|
|
|
)),
|
|
|
|
Positioned(
|
|
|
|
bottom: 20,
|
|
|
|
child: SizedBox(
|
|
|
|
width: MediaQuery.of(context).size.width,
|
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
|
|
children: [
|
|
|
|
TextButton(
|
|
|
|
onPressed: () {
|
|
|
|
GalleryPicker.openSheet();
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: Colors.black.withOpacity(0.5),
|
|
|
|
shape: BoxShape.circle),
|
|
|
|
padding: const EdgeInsets.all(8),
|
|
|
|
child: const Icon(
|
|
|
|
Icons.image,
|
|
|
|
size: 20,
|
|
|
|
color: Colors.white,
|
2022-12-29 08:45:28 +03:00
|
|
|
),
|
|
|
|
),
|
2023-01-20 09:58:21 +03:00
|
|
|
),
|
|
|
|
GestureDetector(
|
|
|
|
onTap: () async {
|
|
|
|
setState(() {
|
|
|
|
anyProcess = true;
|
|
|
|
});
|
|
|
|
Future.delayed(const Duration(milliseconds: 100))
|
|
|
|
.then((value) => setState(() {
|
|
|
|
anyProcess = false;
|
|
|
|
}));
|
|
|
|
},
|
|
|
|
onLongPressStart: (value) {
|
|
|
|
setState(() {
|
|
|
|
isRecording = true;
|
|
|
|
anyProcess = true;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
onLongPressEnd: (value) async {
|
|
|
|
setState(() {
|
|
|
|
isRecording = false;
|
|
|
|
anyProcess = false;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
padding: const EdgeInsets.all(4),
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
shape: BoxShape.circle,
|
|
|
|
border: Border.all(width: 2, color: Colors.white)),
|
|
|
|
width: isRecording ? 80 : 65,
|
|
|
|
height: isRecording ? 80 : 65,
|
2022-12-29 08:45:28 +03:00
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
2023-01-20 09:58:21 +03:00
|
|
|
color: anyProcess ? Colors.red : Colors.transparent,
|
|
|
|
shape: BoxShape.circle,
|
2022-12-29 08:45:28 +03:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
2023-01-20 09:58:21 +03:00
|
|
|
),
|
|
|
|
TextButton(
|
|
|
|
onPressed: () {
|
|
|
|
if (cameraLensDirection == CameraLensDirection.front) {
|
|
|
|
cameraLensDirection = CameraLensDirection.back;
|
|
|
|
} else {
|
|
|
|
cameraLensDirection = CameraLensDirection.front;
|
|
|
|
}
|
|
|
|
initCamera();
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: Colors.black.withOpacity(0.5),
|
|
|
|
shape: BoxShape.circle),
|
|
|
|
padding: const EdgeInsets.all(8),
|
|
|
|
child: const Icon(
|
|
|
|
Icons.cameraswitch,
|
|
|
|
size: 20,
|
|
|
|
color: Colors.white,
|
2022-12-29 08:45:28 +03:00
|
|
|
),
|
|
|
|
),
|
2023-01-20 09:58:21 +03:00
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
))
|
|
|
|
],
|
2022-12-29 08:45:28 +03:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|