Multiple types of attachments

main_design2.0
zaid_daoud 2 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": "طابق",
"department": "قسم",
"room": "غرفه",
"actions": "اجراءات"
"actions": "اجراءات",
"deviceFiles": "ملفات الجهاز"
}

@ -201,5 +201,6 @@
"floor": "Floor",
"department": "Department",
"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>
<key>NSSpeechRecognitionUsageDescription</key>
<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>
<array>
<string>fetch</string>

@ -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"],

@ -291,9 +291,9 @@ class CreateRequestPageState extends State<CreateRequestPage> {
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,

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

@ -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<File> images;
final List<File> 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<MultiImagesPicker> with TickerProviderStateMixin {
class _MultiFilesPickerState extends State<MultiFilesPicker> 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<MultiImagesPicker> 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<MultiImagesPicker> 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<MultiImagesPicker> 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<MultiImagesPicker> 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<MultiImagesPicker> 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<MultiImagesPicker> 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<MultiImagesPicker> 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<MultiImagesPicker> with TickerProvid
builder: (dialogContext) => CupertinoAlertDialog(
actions: <Widget>[
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<MultiImagesPicker> 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(() {});
}
}

@ -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);
},
),
),
),
);
}

@ -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:

Loading…
Cancel
Save