diff --git a/assets/images/doc.png b/assets/images/doc.png new file mode 100644 index 00000000..e7418db8 Binary files /dev/null and b/assets/images/doc.png differ diff --git a/assets/images/excel.png b/assets/images/excel.png new file mode 100644 index 00000000..470e1be5 Binary files /dev/null and b/assets/images/excel.png differ diff --git a/assets/images/pdf.png b/assets/images/pdf.png new file mode 100644 index 00000000..3102284f Binary files /dev/null and b/assets/images/pdf.png differ diff --git a/assets/subtitles/ar_subtitle.json b/assets/subtitles/ar_subtitle.json index b9a51fd7..e419c327 100644 --- a/assets/subtitles/ar_subtitle.json +++ b/assets/subtitles/ar_subtitle.json @@ -201,5 +201,6 @@ "floor": "طابق", "department": "قسم", "room": "غرفه", - "actions": "اجراءات" + "actions": "اجراءات", + "deviceFiles": "ملفات الجهاز" } \ No newline at end of file diff --git a/assets/subtitles/en_subtitle.json b/assets/subtitles/en_subtitle.json index fc57c444..33ff94b5 100644 --- a/assets/subtitles/en_subtitle.json +++ b/assets/subtitles/en_subtitle.json @@ -201,5 +201,6 @@ "floor": "Floor", "department": "Department", "room": "Room", - "actions": "Actions" + "actions": "Actions", + "deviceFiles": "Asset Files" } \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 86b0405c..4d661d08 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -36,6 +36,10 @@ This app requires permission to access photo gallery to allow user to attach images NSSpeechRecognitionUsageDescription This app requires permission for Speech Recognition for speech to text functionality. + LSSupportsOpeningDocumentsInPlace + + UISupportsDocumentBrowser + UIBackgroundModes fetch diff --git a/lib/models/subtitle.dart b/lib/models/subtitle.dart index 6786ddd1..fe71b3c3 100644 --- a/lib/models/subtitle.dart +++ b/lib/models/subtitle.dart @@ -84,6 +84,7 @@ class Subtitle { String hospital; String device; String deviceImages; + String deviceFiles; String pickDevice; String maintenanceIssue; String create; @@ -359,6 +360,7 @@ class Subtitle { @required this.createServiceRequest, @required this.delete, @required this.deviceImages, + @required this.deviceFiles, @required this.deviceRequired, @required this.general, @required this.maintenanceIssueRequired, @@ -520,6 +522,7 @@ class Subtitle { device: parsedJson["device"], deviceArName: parsedJson["deviceArName"], deviceImages: parsedJson["deviceImages"], + deviceFiles: parsedJson["deviceFiles"], deviceModel: parsedJson["deviceModel"], deviceName: parsedJson["deviceName"], deviceRequired: parsedJson["deviceRequired"], diff --git a/lib/views/pages/user/requests/create_request.dart b/lib/views/pages/user/requests/create_request.dart index 4aaf65bc..9201149b 100644 --- a/lib/views/pages/user/requests/create_request.dart +++ b/lib/views/pages/user/requests/create_request.dart @@ -291,9 +291,9 @@ class CreateRequestPageState extends State { enable: widget.serviceRequest != null ? false : true, ), 12.height, - MultiImagesPicker( - label: _subtitle.deviceImages, - images: _deviceImages, + MultiFilesPicker( + label: _subtitle.deviceFiles, + files: _deviceImages, enabled: widget.serviceRequest == null ? true : false, ), 12.height, diff --git a/lib/views/pages/user/requests/report/edit_service_report.dart b/lib/views/pages/user/requests/report/edit_service_report.dart index b783e5a6..828e6b11 100644 --- a/lib/views/pages/user/requests/report/edit_service_report.dart +++ b/lib/views/pages/user/requests/report/edit_service_report.dart @@ -754,9 +754,9 @@ class _EditServiceReportState extends State with TickerProvid const SizedBox( height: 4, ), - MultiImagesPicker( + MultiFilesPicker( label: "", - images: _images, + files: _images, ), // AMiniOneImagePicker( // //error: _validate && _serviceReport.image == null, diff --git a/lib/views/widgets/images/multi_image_picker.dart b/lib/views/widgets/images/multi_image_picker.dart index fe200bd9..784c42b2 100644 --- a/lib/views/widgets/images/multi_image_picker.dart +++ b/lib/views/widgets/images/multi_image_picker.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:file_picker/file_picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -13,31 +14,31 @@ import 'package:test_sa/views/widgets/buttons/app_flat_button.dart'; import 'multi_image_picker_item.dart'; -class MultiImagesPicker extends StatefulWidget { +class MultiFilesPicker extends StatefulWidget { final String label; final bool error; - final List images; + final List files; final bool enabled; - const MultiImagesPicker({Key key, this.images, this.label, this.error = false, this.enabled = true}) : super(key: key); + const MultiFilesPicker({Key key, this.files, this.label, this.error = false, this.enabled = true}) : super(key: key); @override - _MultiImagesPickerState createState() => _MultiImagesPickerState(); + _MultiFilesPickerState createState() => _MultiFilesPickerState(); } -class _MultiImagesPickerState extends State with TickerProviderStateMixin { +class _MultiFilesPickerState extends State with TickerProviderStateMixin { Size _size; @override Widget build(BuildContext context) { _size = MediaQuery.of(context).size; - Subtitle _subtitle = AppLocalization.of(context).subtitle; + Subtitle subtitle = AppLocalization.of(context).subtitle; return Container( - padding: EdgeInsets.all(12), + padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: Color(0xfff5f5f5), + color: const Color(0xfff5f5f5), border: Border.all( - color: Color(0xffefefef), + color: const Color(0xffefefef), ), borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), ), @@ -49,7 +50,7 @@ class _MultiImagesPickerState extends State with TickerProvid children: [ Expanded( child: Text( - widget.label ?? _subtitle.images, + widget.label ?? subtitle.images, style: Theme.of(context).textTheme.headline6.copyWith( fontSize: 14, ), @@ -57,10 +58,11 @@ class _MultiImagesPickerState extends State with TickerProvid ), ), AFlatButton( - text: _subtitle.add, + text: subtitle.add, onPressed: widget.enabled ? () { - onImagePick(_subtitle); + // onImagePick(_subtitle); + onFilePicker(subtitle); } : null, ), @@ -68,14 +70,14 @@ class _MultiImagesPickerState extends State with TickerProvid ), 12.height, AnimatedSize( - duration: Duration(milliseconds: 400), + duration: const Duration(milliseconds: 400), child: !widget.error - ? SizedBox.shrink() + ? const SizedBox.shrink() : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - _subtitle.imagesRequired, + subtitle.imagesRequired, style: Theme.of(context).textTheme.headline6.copyWith( fontSize: 14, color: AColors.red, @@ -89,9 +91,9 @@ class _MultiImagesPickerState extends State with TickerProvid ), ), AnimatedSwitcher( - duration: Duration(milliseconds: 400), + duration: const Duration(milliseconds: 400), child: Container( - key: ValueKey(widget.images.length), + key: ValueKey(widget.files.length), width: _size.width, height: 200 * AppStyle.getScaleFactor(context), padding: EdgeInsets.all( @@ -102,16 +104,17 @@ class _MultiImagesPickerState extends State with TickerProvid border: Border.all(color: Theme.of(context).primaryColor, width: 2), borderRadius: BorderRadius.circular(8 * AppStyle.getScaleFactor(context)), ), - child: widget.images.isEmpty + child: widget.files.isEmpty ? MaterialButton( onPressed: widget.enabled ? () { - onImagePick(_subtitle); + // onImagePick(_subtitle); + onFilePicker(subtitle); } : null, child: Center( child: Icon( - Icons.add_a_photo_outlined, + Icons.file_upload, size: 48 * AppStyle.getScaleFactor(context), color: Theme.of(context).primaryColor, )), @@ -122,12 +125,12 @@ class _MultiImagesPickerState extends State with TickerProvid scrollDirection: Axis.horizontal, mainAxisSpacing: 10, crossAxisSpacing: 10, - children: List.generate(widget.images.length, (index) { - File _image = widget.images[index]; - return MultiImagesPickerItem( - image: _image, + children: List.generate(widget.files.length, (index) { + File _image = widget.files[index]; + return MultiFilesPickerItem( + file: _image, onRemoveTap: (image) { - widget.images.remove(image); + widget.files.remove(image); setState(() {}); }, ); @@ -140,9 +143,23 @@ class _MultiImagesPickerState extends State with TickerProvid ); } - onImagePick(Subtitle _subtitle) async { - if (widget.images.length >= 5) { - Fluttertoast.showToast(msg: _subtitle.maxImagesNumberIs5); + onFilePicker(Subtitle subtitle) async { + FilePickerResult result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowMultiple: true, + allowedExtensions: ['jpg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'], + ); + if (result != null) { + for (var path in result.paths) { + widget.files.insert(0, File(path)); + } + setState(() {}); + } + } + + onImagePick(Subtitle subtitle) async { + if (widget.files.length >= 5) { + Fluttertoast.showToast(msg: subtitle.maxImagesNumberIs5); return; } ImageSource source = await showDialog( @@ -150,13 +167,13 @@ class _MultiImagesPickerState extends State with TickerProvid builder: (dialogContext) => CupertinoAlertDialog( actions: [ TextButton( - child: Text(_subtitle.pickFromCamera), + child: Text(subtitle.pickFromCamera), onPressed: () { Navigator.of(dialogContext).pop(ImageSource.camera); }, ), TextButton( - child: Text(_subtitle.pickFromGallery), + child: Text(subtitle.pickFromGallery), onPressed: () { Navigator.of(dialogContext).pop(ImageSource.gallery); }, @@ -168,9 +185,9 @@ class _MultiImagesPickerState extends State with TickerProvid final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); if (pickedFile != null) { - File _fileImage = File(pickedFile.path); - if (_fileImage != null) { - widget.images.insert(0, _fileImage); + File fileImage = File(pickedFile.path); + if (fileImage != null) { + widget.files.insert(0, fileImage); setState(() {}); } } diff --git a/lib/views/widgets/images/multi_image_picker_item.dart b/lib/views/widgets/images/multi_image_picker_item.dart index e540cc2b..3f1d5805 100644 --- a/lib/views/widgets/images/multi_image_picker_item.dart +++ b/lib/views/widgets/images/multi_image_picker_item.dart @@ -5,54 +5,67 @@ import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; -class MultiImagesPickerItem extends StatelessWidget { - final File image; +class MultiFilesPickerItem extends StatelessWidget { + final File file; final Function(File) onRemoveTap; - const MultiImagesPickerItem({Key key, this.image, this.onRemoveTap}) : super(key: key); + const MultiFilesPickerItem({Key key, this.file, this.onRemoveTap}) : super(key: key); @override Widget build(BuildContext context) { + var isImage = file.path.split(".").last.toLowerCase() == "png" || file.path.split(".").last.toLowerCase() == "jpg"; + var isPdf = file.path.split(".").last.toLowerCase() == "pdf"; + var isExcel = file.path.split(".").last.toLowerCase() == "xlsx"; return Container( width: 80 * AppStyle.getScaleFactor(context), height: 80 * AppStyle.getScaleFactor(context), - decoration: - BoxDecoration(boxShadow: [BoxShadow(color: Colors.black38, blurRadius: 2)], image: DecorationImage(image: FileImage(image), fit: BoxFit.cover), borderRadius: BorderRadius.circular(8)), + decoration: BoxDecoration( + boxShadow: [BoxShadow(color: isImage ? Colors.black38 : AColors.cyan.withOpacity(0.5), blurRadius: 2)], + image: DecorationImage( + image: isImage + ? FileImage(file) + : AssetImage("assets/images/${isPdf ? "pdf" : isExcel ? "excel" : "doc"}.png"), + fit: BoxFit.cover, + ), + borderRadius: BorderRadius.circular(8), + ), child: MaterialButton( padding: EdgeInsets.zero, onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => Scaffold( - body: SafeArea( - child: Stack( - children: [ - Center( - child: InteractiveViewer( - child: Image( - image: FileImage(image), - )), - ), - ABackButton(), - ], - ), + if (isImage) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => Scaffold( + body: SafeArea( + child: Stack( + children: [ + Center(child: isImage ? InteractiveViewer(child: Image(image: FileImage(file))) : const SizedBox.shrink()), + const ABackButton(), + ], ), - ))); + ), + ), + ), + ); + } }, child: Align( - alignment: Alignment.topRight, - child: IconButton( - padding: const EdgeInsets.all(2.0), - icon: Container( - padding: EdgeInsets.all(1), - decoration: BoxDecoration(color: Theme.of(context).scaffoldBackgroundColor.withOpacity(.3), borderRadius: BorderRadius.circular(8)), - child: Icon( - Icons.remove_circle, - color: AColors.red, - )), - onPressed: () { - onRemoveTap(image); - }, - )), + alignment: Alignment.topRight, + child: IconButton( + padding: const EdgeInsets.all(2.0), + icon: Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration(color: Theme.of(context).scaffoldBackgroundColor.withOpacity(.3), borderRadius: BorderRadius.circular(8)), + child: const Icon( + Icons.remove_circle, + color: AColors.red, + ), + ), + onPressed: () { + onRemoveTap(file); + }, + ), + ), ), ); } diff --git a/pubspec.yaml b/pubspec.yaml index 4f82161b..076379b6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -61,7 +61,7 @@ dependencies: flare_flutter: ^3.0.2 signature: ^5.3.0 flutter_svg: ^1.1.6 - + file_picker: ^5.2.5 dev_dependencies: flutter_test: