Multiple types of attachments

main_design2.0
zaid_daoud 3 years ago
parent 591e1513a2
commit a3264f4f1c

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

@ -201,5 +201,6 @@
"floor": "طابق", "floor": "طابق",
"department": "قسم", "department": "قسم",
"room": "غرفه", "room": "غرفه",
"actions": "اجراءات" "actions": "اجراءات",
"deviceFiles": "ملفات الجهاز"
} }

@ -201,5 +201,6 @@
"floor": "Floor", "floor": "Floor",
"department": "Department", "department": "Department",
"room": "Room", "room": "Room",
"actions": "Actions" "actions": "Actions",
"deviceFiles": "Asset Files"
} }

@ -36,6 +36,10 @@
<string>This app requires permission to access photo gallery to allow user to attach images</string> <string>This app requires permission to access photo gallery to allow user to attach images</string>
<key>NSSpeechRecognitionUsageDescription</key> <key>NSSpeechRecognitionUsageDescription</key>
<string>This app requires permission for Speech Recognition for speech to text functionality.</string> <string>This app requires permission for Speech Recognition for speech to text functionality.</string>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UISupportsDocumentBrowser</key>
<true/>
<key>UIBackgroundModes</key> <key>UIBackgroundModes</key>
<array> <array>
<string>fetch</string> <string>fetch</string>

@ -84,6 +84,7 @@ class Subtitle {
String hospital; String hospital;
String device; String device;
String deviceImages; String deviceImages;
String deviceFiles;
String pickDevice; String pickDevice;
String maintenanceIssue; String maintenanceIssue;
String create; String create;
@ -359,6 +360,7 @@ class Subtitle {
@required this.createServiceRequest, @required this.createServiceRequest,
@required this.delete, @required this.delete,
@required this.deviceImages, @required this.deviceImages,
@required this.deviceFiles,
@required this.deviceRequired, @required this.deviceRequired,
@required this.general, @required this.general,
@required this.maintenanceIssueRequired, @required this.maintenanceIssueRequired,
@ -520,6 +522,7 @@ class Subtitle {
device: parsedJson["device"], device: parsedJson["device"],
deviceArName: parsedJson["deviceArName"], deviceArName: parsedJson["deviceArName"],
deviceImages: parsedJson["deviceImages"], deviceImages: parsedJson["deviceImages"],
deviceFiles: parsedJson["deviceFiles"],
deviceModel: parsedJson["deviceModel"], deviceModel: parsedJson["deviceModel"],
deviceName: parsedJson["deviceName"], deviceName: parsedJson["deviceName"],
deviceRequired: parsedJson["deviceRequired"], deviceRequired: parsedJson["deviceRequired"],

@ -291,9 +291,9 @@ class CreateRequestPageState extends State<CreateRequestPage> {
enable: widget.serviceRequest != null ? false : true, enable: widget.serviceRequest != null ? false : true,
), ),
12.height, 12.height,
MultiImagesPicker( MultiFilesPicker(
label: _subtitle.deviceImages, label: _subtitle.deviceFiles,
images: _deviceImages, files: _deviceImages,
enabled: widget.serviceRequest == null ? true : false, enabled: widget.serviceRequest == null ? true : false,
), ),
12.height, 12.height,

@ -754,9 +754,9 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
const SizedBox( const SizedBox(
height: 4, height: 4,
), ),
MultiImagesPicker( MultiFilesPicker(
label: "", label: "",
images: _images, files: _images,
), ),
// AMiniOneImagePicker( // AMiniOneImagePicker(
// //error: _validate && _serviceReport.image == null, // //error: _validate && _serviceReport.image == null,

@ -1,5 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.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'; import 'multi_image_picker_item.dart';
class MultiImagesPicker extends StatefulWidget { class MultiFilesPicker extends StatefulWidget {
final String label; final String label;
final bool error; final bool error;
final List<File> images; final List<File> files;
final bool enabled; 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 @override
_MultiImagesPickerState createState() => _MultiImagesPickerState(); _MultiFilesPickerState createState() => _MultiFilesPickerState();
} }
class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProviderStateMixin { class _MultiFilesPickerState extends State<MultiFilesPicker> with TickerProviderStateMixin {
Size _size; Size _size;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_size = MediaQuery.of(context).size; _size = MediaQuery.of(context).size;
Subtitle _subtitle = AppLocalization.of(context).subtitle; Subtitle subtitle = AppLocalization.of(context).subtitle;
return Container( return Container(
padding: EdgeInsets.all(12), padding: const EdgeInsets.all(12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color(0xfff5f5f5), color: const Color(0xfff5f5f5),
border: Border.all( border: Border.all(
color: Color(0xffefefef), color: const Color(0xffefefef),
), ),
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
), ),
@ -49,7 +50,7 @@ class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProvid
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
widget.label ?? _subtitle.images, widget.label ?? subtitle.images,
style: Theme.of(context).textTheme.headline6.copyWith( style: Theme.of(context).textTheme.headline6.copyWith(
fontSize: 14, fontSize: 14,
), ),
@ -57,10 +58,11 @@ class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProvid
), ),
), ),
AFlatButton( AFlatButton(
text: _subtitle.add, text: subtitle.add,
onPressed: widget.enabled onPressed: widget.enabled
? () { ? () {
onImagePick(_subtitle); // onImagePick(_subtitle);
onFilePicker(subtitle);
} }
: null, : null,
), ),
@ -68,14 +70,14 @@ class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProvid
), ),
12.height, 12.height,
AnimatedSize( AnimatedSize(
duration: Duration(milliseconds: 400), duration: const Duration(milliseconds: 400),
child: !widget.error child: !widget.error
? SizedBox.shrink() ? const SizedBox.shrink()
: Column( : Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
_subtitle.imagesRequired, subtitle.imagesRequired,
style: Theme.of(context).textTheme.headline6.copyWith( style: Theme.of(context).textTheme.headline6.copyWith(
fontSize: 14, fontSize: 14,
color: AColors.red, color: AColors.red,
@ -89,9 +91,9 @@ class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProvid
), ),
), ),
AnimatedSwitcher( AnimatedSwitcher(
duration: Duration(milliseconds: 400), duration: const Duration(milliseconds: 400),
child: Container( child: Container(
key: ValueKey(widget.images.length), key: ValueKey(widget.files.length),
width: _size.width, width: _size.width,
height: 200 * AppStyle.getScaleFactor(context), height: 200 * AppStyle.getScaleFactor(context),
padding: EdgeInsets.all( padding: EdgeInsets.all(
@ -102,16 +104,17 @@ class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProvid
border: Border.all(color: Theme.of(context).primaryColor, width: 2), border: Border.all(color: Theme.of(context).primaryColor, width: 2),
borderRadius: BorderRadius.circular(8 * AppStyle.getScaleFactor(context)), borderRadius: BorderRadius.circular(8 * AppStyle.getScaleFactor(context)),
), ),
child: widget.images.isEmpty child: widget.files.isEmpty
? MaterialButton( ? MaterialButton(
onPressed: widget.enabled onPressed: widget.enabled
? () { ? () {
onImagePick(_subtitle); // onImagePick(_subtitle);
onFilePicker(subtitle);
} }
: null, : null,
child: Center( child: Center(
child: Icon( child: Icon(
Icons.add_a_photo_outlined, Icons.file_upload,
size: 48 * AppStyle.getScaleFactor(context), size: 48 * AppStyle.getScaleFactor(context),
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
)), )),
@ -122,12 +125,12 @@ class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProvid
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
mainAxisSpacing: 10, mainAxisSpacing: 10,
crossAxisSpacing: 10, crossAxisSpacing: 10,
children: List.generate(widget.images.length, (index) { children: List.generate(widget.files.length, (index) {
File _image = widget.images[index]; File _image = widget.files[index];
return MultiImagesPickerItem( return MultiFilesPickerItem(
image: _image, file: _image,
onRemoveTap: (image) { onRemoveTap: (image) {
widget.images.remove(image); widget.files.remove(image);
setState(() {}); setState(() {});
}, },
); );
@ -140,9 +143,23 @@ class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProvid
); );
} }
onImagePick(Subtitle _subtitle) async { onFilePicker(Subtitle subtitle) async {
if (widget.images.length >= 5) { FilePickerResult result = await FilePicker.platform.pickFiles(
Fluttertoast.showToast(msg: _subtitle.maxImagesNumberIs5); 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; return;
} }
ImageSource source = await showDialog( ImageSource source = await showDialog(
@ -150,13 +167,13 @@ class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProvid
builder: (dialogContext) => CupertinoAlertDialog( builder: (dialogContext) => CupertinoAlertDialog(
actions: <Widget>[ actions: <Widget>[
TextButton( TextButton(
child: Text(_subtitle.pickFromCamera), child: Text(subtitle.pickFromCamera),
onPressed: () { onPressed: () {
Navigator.of(dialogContext).pop(ImageSource.camera); Navigator.of(dialogContext).pop(ImageSource.camera);
}, },
), ),
TextButton( TextButton(
child: Text(_subtitle.pickFromGallery), child: Text(subtitle.pickFromGallery),
onPressed: () { onPressed: () {
Navigator.of(dialogContext).pop(ImageSource.gallery); Navigator.of(dialogContext).pop(ImageSource.gallery);
}, },
@ -168,9 +185,9 @@ class _MultiImagesPickerState extends State<MultiImagesPicker> with TickerProvid
final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);
if (pickedFile != null) { if (pickedFile != null) {
File _fileImage = File(pickedFile.path); File fileImage = File(pickedFile.path);
if (_fileImage != null) { if (fileImage != null) {
widget.images.insert(0, _fileImage); widget.files.insert(0, fileImage);
setState(() {}); setState(() {});
} }
} }

@ -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/app_style/sizing.dart';
import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart';
class MultiImagesPickerItem extends StatelessWidget { class MultiFilesPickerItem extends StatelessWidget {
final File image; final File file;
final Function(File) onRemoveTap; 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 @override
Widget build(BuildContext context) { 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( return Container(
width: 80 * AppStyle.getScaleFactor(context), width: 80 * AppStyle.getScaleFactor(context),
height: 80 * AppStyle.getScaleFactor(context), height: 80 * AppStyle.getScaleFactor(context),
decoration: decoration: BoxDecoration(
BoxDecoration(boxShadow: [BoxShadow(color: Colors.black38, blurRadius: 2)], image: DecorationImage(image: FileImage(image), fit: BoxFit.cover), borderRadius: BorderRadius.circular(8)), 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( child: MaterialButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () { onPressed: () {
Navigator.of(context).push(MaterialPageRoute( if (isImage) {
builder: (_) => Scaffold( Navigator.of(context).push(
body: SafeArea( MaterialPageRoute(
child: Stack( builder: (_) => Scaffold(
children: [ body: SafeArea(
Center( child: Stack(
child: InteractiveViewer( children: [
child: Image( Center(child: isImage ? InteractiveViewer(child: Image(image: FileImage(file))) : const SizedBox.shrink()),
image: FileImage(image), const ABackButton(),
)), ],
),
ABackButton(),
],
),
), ),
))); ),
),
),
);
}
}, },
child: Align( child: Align(
alignment: Alignment.topRight, alignment: Alignment.topRight,
child: IconButton( child: IconButton(
padding: const EdgeInsets.all(2.0), padding: const EdgeInsets.all(2.0),
icon: Container( icon: Container(
padding: EdgeInsets.all(1), padding: const EdgeInsets.all(1),
decoration: BoxDecoration(color: Theme.of(context).scaffoldBackgroundColor.withOpacity(.3), borderRadius: BorderRadius.circular(8)), decoration: BoxDecoration(color: Theme.of(context).scaffoldBackgroundColor.withOpacity(.3), borderRadius: BorderRadius.circular(8)),
child: Icon( child: const Icon(
Icons.remove_circle, Icons.remove_circle,
color: AColors.red, color: AColors.red,
)), ),
onPressed: () { ),
onRemoveTap(image); onPressed: () {
}, onRemoveTap(file);
)), },
),
),
), ),
); );
} }

@ -61,7 +61,7 @@ dependencies:
flare_flutter: ^3.0.2 flare_flutter: ^3.0.2
signature: ^5.3.0 signature: ^5.3.0
flutter_svg: ^1.1.6 flutter_svg: ^1.1.6
file_picker: ^5.2.5
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save