Last active
January 28, 2020 18:33
-
-
Save ggichure/565d44af75e48609803784da9e022c16 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class CameraThumb extends StatefulWidget { | |
| const CameraThumb({Key key}) : super(key: key); | |
| @override | |
| CameraThumbState createState() => CameraThumbState(); | |
| } | |
| class CameraThumbState extends State<CameraThumb> | |
| with AutomaticKeepAliveClientMixin, SingleTickerProviderStateMixin { | |
| CameraController _controller; | |
| List<CameraDescription> _cameras; | |
| final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); | |
| bool _isRecordingMode = false; | |
| bool _isRecording = false; | |
| // final _timerKey = GlobalKey<VideoTimerState>(); | |
| Future<void> _initCamera() async { | |
| _cameras = await availableCameras(); | |
| _controller = CameraController(_cameras[0], ResolutionPreset.max); | |
| _controller.initialize().then((_) { | |
| if (!mounted) { | |
| return; | |
| } | |
| setState(() {}); | |
| }); | |
| } | |
| @override | |
| void dispose() { | |
| _controller?.dispose(); | |
| controller.dispose(); | |
| super.dispose(); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| super.build(context); | |
| if (_controller != null) { | |
| if (!_controller.value.isInitialized) { | |
| return Container(); | |
| } | |
| } else { | |
| return const Center( | |
| child: SizedBox( | |
| width: 32, | |
| height: 32, | |
| child: CircularProgressIndicator(), | |
| ), | |
| ); | |
| } | |
| if (!_controller.value.isInitialized) { | |
| return Container(); | |
| } | |
| return Scaffold( | |
| backgroundColor: Theme.of(context).backgroundColor, | |
| key: _scaffoldKey, | |
| extendBody: true, | |
| body: Stack( | |
| children: <Widget>[ | |
| _buildCameraPreview(), | |
| ], | |
| ), | |
| ) | |
| //////////// | |
| /// | |
| /// | |
| /// | |
| /// | |
| ], | |
| ), | |
| bottomNavigationBar: _buildBottomNavigationBar(), | |
| ); | |
| } | |
| ; | |
| } | |
| Widget _buildCameraPreview() { | |
| final size = MediaQuery.of(context).size; | |
| return ClipRect( | |
| child: Container( | |
| child: Transform.scale( | |
| scale: _controller.value.aspectRatio / size.aspectRatio, | |
| child: Center( | |
| child: AspectRatio( | |
| aspectRatio: _controller.value.aspectRatio, | |
| child: CameraPreview(_controller), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ) | |
| Widget _buildBottomNavigationBar() { | |
| return Container( | |
| color: Colors.transparent, | |
| height: 100.0, | |
| width: double.infinity, | |
| child: Row( | |
| mainAxisAlignment: MainAxisAlignment.spaceAround, | |
| children: <Widget>[ | |
| FutureBuilder( | |
| future: getLastImage(), | |
| builder: (context, snapshot) { | |
| if (snapshot.data == null) { | |
| return Container( | |
| width: 60.0, | |
| height: 60.0, | |
| ); | |
| } | |
| return GestureDetector( | |
| onTap: () => Navigator.push( | |
| context, | |
| MaterialPageRoute( | |
| builder: (context) => Gallery(), | |
| ), | |
| ), | |
| child: Container( | |
| padding: EdgeInsets.all(2), | |
| decoration: BoxDecoration( | |
| border: | |
| Border.all(color: Colors.purple[200], width: 2.0)), | |
| width: 80.0, | |
| height: 100.0, | |
| child: ClipRRect( | |
| borderRadius: BorderRadius.circular(4.0), | |
| child: Image.file( | |
| snapshot.data, | |
| fit: BoxFit.cover, | |
| ), | |
| ), | |
| ), | |
| ); | |
| }, | |
| ), | |
| CircleAvatar( | |
| backgroundColor: Colors.white, | |
| radius: 28.0, | |
| child: IconButton( | |
| icon: Icon( | |
| (_isRecordingMode) | |
| ? (_isRecording) ? Icons.stop : Icons.videocam | |
| : Icons.camera_alt, | |
| size: 28.0, | |
| color: (_isRecording) ? Colors.red : Colors.black, | |
| ), | |
| onPressed: () { | |
| if (!_isRecordingMode) { | |
| _captureImage(); | |
| } else { | |
| if (_isRecording) { | |
| stopVideoRecording(); | |
| } else { | |
| startVideoRecording(); | |
| } | |
| } | |
| }, | |
| ), | |
| ), | |
| SizedBox( | |
| width: 40, | |
| ), | |
| /* IconButton( | |
| icon: Icon( | |
| (_isRecordingMode) ? Icons.camera_alt : Icons.videocam, | |
| color: Colors.white, | |
| ), | |
| onPressed: () { | |
| setState(() { | |
| _isRecordingMode = !_isRecordingMode; | |
| }); | |
| }, | |
| ),*/ | |
| ], | |
| ), | |
| ); | |
| } | |
| Future<FileSystemEntity> getLastImage() async { | |
| final Directory extDir = await getApplicationDocumentsDirectory(); | |
| final String dirPath = '${extDir.path}/media'; | |
| final myDir = Directory(dirPath); | |
| List<FileSystemEntity> _images; | |
| _images = myDir.listSync(recursive: true, followLinks: false); | |
| _images.sort((a, b) { | |
| return b.path.compareTo(a.path); | |
| }); | |
| var lastFile = _images[0]; | |
| var extension = path.extension(lastFile.path); | |
| if (extension == '.jpeg') { | |
| return lastFile; | |
| } else {} | |
| } | |
| Future<void> _onCameraSwitch() async { | |
| final CameraDescription cameraDescription = | |
| (_controller.description == _cameras[0]) ? _cameras[1] : _cameras[0]; | |
| if (_controller != null) { | |
| await _controller.dispose(); | |
| } | |
| _controller = CameraController(cameraDescription, ResolutionPreset.medium); | |
| _controller.addListener(() { | |
| if (mounted) setState(() {}); | |
| if (_controller.value.hasError) { | |
| showInSnackBar('Camera error ${_controller.value.errorDescription}'); | |
| } | |
| }); | |
| try { | |
| await _controller.initialize(); | |
| } on CameraException catch (e) { | |
| _showCameraException(e); | |
| } | |
| if (mounted) { | |
| setState(() {}); | |
| } | |
| } | |
| void _captureImage() async { | |
| print('_captureImage'); | |
| if (_controller.value.isInitialized) { | |
| SystemSound.play(SystemSoundType.click); | |
| final Directory extDir = await getApplicationDocumentsDirectory(); | |
| final String dirPath = '${extDir.path}/media'; | |
| await Directory(dirPath).create(recursive: true); | |
| final String filePath = '$dirPath/${_timestamp()}.jpeg'; | |
| print('path: $filePath'); | |
| await _controller.takePicture(filePath); | |
| setState(() {}); | |
| Navigator.of(context).pushNamed(/gallery); | |
| } | |
| } | |
| Future<String> startVideoRecording() async { | |
| print('startVideoRecording'); | |
| if (!_controller.value.isInitialized) { | |
| return null; | |
| } | |
| setState(() { | |
| _isRecording = true; | |
| }); | |
| //_timerKey.currentState.startTimer(); | |
| final Directory extDir = await getApplicationDocumentsDirectory(); | |
| final String dirPath = '${extDir.path}/media'; | |
| await Directory(dirPath).create(recursive: true); | |
| final String filePath = '$dirPath/${_timestamp()}.mp4'; | |
| if (_controller.value.isRecordingVideo) { | |
| // A recording is already started, do nothing. | |
| return null; | |
| } | |
| try { | |
| // videoPath = filePath; | |
| await _controller.startVideoRecording(filePath); | |
| } on CameraException catch (e) { | |
| _showCameraException(e); | |
| return null; | |
| } | |
| return filePath; | |
| } | |
| Future<void> stopVideoRecording() async { | |
| if (!_controller.value.isRecordingVideo) { | |
| return null; | |
| } | |
| // _timerKey.currentState.stopTimer(); | |
| setState(() { | |
| _isRecording = false; | |
| }); | |
| try { | |
| await _controller.stopVideoRecording(); | |
| } on CameraException catch (e) { | |
| _showCameraException(e); | |
| return null; | |
| } | |
| } | |
| String _timestamp() => DateTime.now().millisecondsSinceEpoch.toString(); | |
| void _showCameraException(CameraException e) { | |
| logError(e.code, e.description); | |
| showInSnackBar('Error: ${e.code}\n${e.description}'); | |
| } | |
| void showInSnackBar(String message) { | |
| _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message))); | |
| } | |
| void logError(String code, String message) => | |
| print('Error: $code\nError Message: $message'); | |
| @override | |
| bool get wantKeepAlive => true; | |
| } | |
| class Gallery extends StatefulWidget { | |
| @override | |
| _GalleryState createState() => _GalleryState(); | |
| } | |
| class _GalleryState extends State<Gallery> { | |
| String currentFilePath; | |
| String currentUser; | |
| Firestore _fs = Firestore.instance; | |
| RecordData recordData; | |
| String imageName; | |
| String imgUrl; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| getCurrentFirebaseUser(); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| backgroundColor: Colors.white, | |
| appBar: null, | |
| body: FutureBuilder( | |
| future: _getAllImages(), | |
| builder: (context, AsyncSnapshot<List<FileSystemEntity>> snapshot) { | |
| if (!snapshot.hasData || snapshot.data.isEmpty) { | |
| return Container(); | |
| } | |
| print('${snapshot.data.length} ${snapshot.data}'); | |
| if (snapshot.data.length == 0) { | |
| return Center( | |
| child: Text('No images found.'), | |
| ); | |
| } | |
| return PageView.builder( | |
| itemCount: snapshot.data.length, | |
| itemBuilder: (context, index) { | |
| currentFilePath = snapshot.data[index].path; | |
| var extension = path.extension(snapshot.data[index].path); | |
| if (extension == '.jpeg') { | |
| return Column( | |
| children: <Widget>[ | |
| Container( | |
| height: MediaQuery.of(context).size.height * .94, | |
| width: MediaQuery.of(context).size.width * 1, | |
| padding: const EdgeInsets.only(bottom: 3.0), | |
| child: Container( | |
| child: Image.file( | |
| File(snapshot.data[index].path), | |
| fit: BoxFit.fill, | |
| ), | |
| )), | |
| ], | |
| ); | |
| } else { | |
| return Center( | |
| child: Text("no images found"), | |
| ); | |
| } | |
| }, | |
| ); | |
| }, | |
| ), | |
| bottomNavigationBar: BottomAppBar( | |
| child: Container( | |
| color: Colors.purple[200], | |
| height: 56.0, | |
| child: Row( | |
| mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |
| children: <Widget>[ | |
| /* IconButton( | |
| icon: Icon(Icons.share), | |
| onPressed: () => _shareFile(), | |
| ),*/ | |
| IconButton( | |
| iconSize: 30, | |
| icon: Icon(Icons.cancel), | |
| onPressed: _deleteFile, | |
| ), | |
| IconButton( | |
| iconSize: 30, | |
| icon: Icon(Icons.check), | |
| onPressed: () { | |
| var image = File(currentFilePath).readAsBytesSync(); | |
| uploadImageFs(image); | |
| }) | |
| ], | |
| ), | |
| ), | |
| ), | |
| ); | |
| } | |
| _shareFile() async { | |
| var extension = path.extension(currentFilePath); | |
| await Share.file( | |
| 'image', | |
| (extension == '.jpeg') ? 'image.jpeg' : ' video.mp4', | |
| File(currentFilePath).readAsBytesSync(), | |
| (extension == '.jpeg') ? 'image/jpeg' : ' video/mp4', | |
| ); | |
| // var image=File(currentFilePath).readAsBytesSync(); | |
| // uploadImageFs(image); | |
| } | |
| _deleteFile() { | |
| final dir = Directory(currentFilePath); | |
| dir.deleteSync(recursive: true); | |
| print('deleted'); | |
| setState(() {}); | |
| } | |
| Future<List<FileSystemEntity>> _getAllImages() async { | |
| final Directory extDir = await getApplicationDocumentsDirectory(); | |
| final String dirPath = '${extDir.path}/media'; | |
| final myDir = Directory(dirPath); | |
| List<FileSystemEntity> _images; | |
| _images = myDir.listSync(recursive: true, followLinks: false); | |
| _images.sort((a, b) { | |
| return b.path.compareTo(a.path); | |
| }); | |
| return _images; | |
| } | |
| Future<FirebaseUser> getCurrentFirebaseUser() async { | |
| FirebaseUser user = await FirebaseAuth.instance.currentUser(); | |
| currentUser = user.uid; | |
| return user; | |
| } | |
| Future uploadImageFs(var asset) async { | |
| setState(() { | |
| imageName = DateTime.now().millisecondsSinceEpoch.toString(); | |
| }); | |
| final StorageReference storageReference = FirebaseStorage.instance | |
| .ref() | |
| .child("images") | |
| .child("$currentUser/$imageName"); | |
| StorageUploadTask uploadTask = storageReference.putData(asset); | |
| final StreamSubscription<StorageTaskEvent> streamSubscription = | |
| uploadTask.events.listen((event) { | |
| // You can use this to notify yourself or your user in any kind of way. | |
| // For example: you could use the uploadTask.events stream in a StreamBuilder instead | |
| // to show your user what the current status is. In that case, you would not need to cancel any | |
| // subscription as StreamBuilder handles this automatically. | |
| CircularProgressIndicator(); | |
| Fluttertoast.showToast( | |
| msg: "Uploading...", | |
| backgroundColor: Colors.green, | |
| textColor: Colors.white, | |
| toastLength: Toast.LENGTH_LONG, | |
| timeInSecForIos: 2, | |
| gravity: ToastGravity.BOTTOM); | |
| // Here, every StorageTaskEvent concerning the upload is printed to the logs. | |
| print('EVENT ${event.type}'); | |
| }); | |
| await uploadTask.onComplete; | |
| streamSubscription.cancel(); | |
| String docUrl = await (await uploadTask.onComplete).ref.getDownloadURL(); | |
| setState(() { | |
| imgUrl = docUrl; | |
| }); | |
| DocumentReference doc = await Firestore.instance | |
| .collection("users") | |
| ... | |
| }); | |
| String recordId = doc.documentID.toString(); | |
| //save to url to firestore | |
| _deleteFile(); | |
| Fluttertoast.showToast(msg: "done "); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment