@@ -14,10 +14,11 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
1414/// by the [FormBuilderFilePicker] .
1515///
1616/// [filesSetter] can be used to update the value of [FormBuilderFilePicker] .
17- typedef FileViewerBuilder = Widget Function (
18- List <PlatformFile >? files,
19- FormFieldSetter <List <PlatformFile >> filesSetter,
20- );
17+ typedef FileViewerBuilder =
18+ Widget Function (
19+ List <PlatformFile >? files,
20+ FormFieldSetter <List <PlatformFile >> filesSetter,
21+ );
2122
2223class TypeSelector {
2324 final FileType type;
@@ -77,73 +78,89 @@ class FormBuilderFilePicker
7778 final Widget Function (List <Widget > types)? customTypeViewerBuilder;
7879
7980 /// Creates field for image(s) from user device storage
80- FormBuilderFilePicker (
81- {
82- //From Super
83- super .key,
84- required super .name,
85- super .validator,
86- super .initialValue,
87- super .decoration,
88- super .onChanged,
89- super .valueTransformer,
90- super .enabled,
91- super .onSaved,
92- super .autovalidateMode = AutovalidateMode .disabled,
93- super .onReset,
94- super .focusNode,
95- this .maxFiles,
96- this .withData = kIsWeb,
97- this .withReadStream = false ,
98- this .allowMultiple = false ,
99- this .previewImages = true ,
100- this .typeSelectors = const [
101- TypeSelector (type: FileType .any, selector: Icon (Icons .add_circle))
102- ],
103- this .allowedExtensions,
104- this .onFileLoading,
105- this .allowCompression = true ,
106- this .compressionQuality = 30 ,
107- this .customFileViewerBuilder,
108- this .customTypeViewerBuilder})
109- : super (
110- builder: (FormFieldState <List <PlatformFile >?> field) {
111- final state = field as _FormBuilderFilePickerState ;
112-
113- return InputDecorator (
114- decoration: state.decoration.copyWith (
115- counterText: maxFiles != null
116- ? '${state ._files .length } / $maxFiles '
117- : null ),
118- child: Column (
119- children: < Widget > [
120- customTypeViewerBuilder != null
121- ? customTypeViewerBuilder (
122- state.getTypeSelectorActions (typeSelectors, field))
123- : Row (
124- mainAxisAlignment: MainAxisAlignment .spaceBetween,
125- children: state.getTypeSelectorActions (
126- typeSelectors, field),
127- ),
128- const SizedBox (height: 3 ),
129- customFileViewerBuilder != null
130- ? customFileViewerBuilder.call (state._files,
131- (files) => state._setFiles (files ?? [], field))
132- : state.defaultFileViewer (state._files,
133- (files) => state._setFiles (files ?? [], field)),
134- ],
135- ),
136- );
137- },
138- );
81+ FormBuilderFilePicker ({
82+ //From Super
83+ super .key,
84+ required super .name,
85+ super .validator,
86+ super .initialValue,
87+ super .decoration,
88+ super .onChanged,
89+ super .valueTransformer,
90+ super .enabled,
91+ super .onSaved,
92+ super .autovalidateMode = AutovalidateMode .disabled,
93+ super .onReset,
94+ super .focusNode,
95+ this .maxFiles,
96+ this .withData = kIsWeb,
97+ this .withReadStream = false ,
98+ this .allowMultiple = false ,
99+ this .previewImages = true ,
100+ this .typeSelectors = const [
101+ TypeSelector (type: FileType .any, selector: Icon (Icons .add_circle)),
102+ ],
103+ this .allowedExtensions,
104+ this .onFileLoading,
105+ @Deprecated (
106+ 'allowCompression is deprecated and will be removed in the next major version. '
107+ 'Use compressionQuality instead.' ,
108+ )
109+ this .allowCompression = true ,
110+ this .compressionQuality = 0 ,
111+ this .customFileViewerBuilder,
112+ this .customTypeViewerBuilder,
113+ }) : super (
114+ builder: (FormFieldState <List <PlatformFile >?> field) {
115+ final state = field as _FormBuilderFilePickerState ;
116+
117+ return InputDecorator (
118+ decoration: state.decoration.copyWith (
119+ counterText:
120+ maxFiles != null
121+ ? '${state ._files .length } / $maxFiles '
122+ : null ,
123+ ),
124+ child: Column (
125+ children: < Widget > [
126+ customTypeViewerBuilder != null
127+ ? customTypeViewerBuilder (
128+ state.getTypeSelectorActions (typeSelectors, field),
129+ )
130+ : Row (
131+ mainAxisAlignment: MainAxisAlignment .spaceBetween,
132+ children: state.getTypeSelectorActions (
133+ typeSelectors,
134+ field,
135+ ),
136+ ),
137+ const SizedBox (height: 3 ),
138+ customFileViewerBuilder != null
139+ ? customFileViewerBuilder.call (
140+ state._files,
141+ (files) => state._setFiles (files ?? [], field),
142+ )
143+ : state.defaultFileViewer (
144+ state._files,
145+ (files) => state._setFiles (files ?? [], field),
146+ ),
147+ ],
148+ ),
149+ );
150+ },
151+ );
139152
140153 @override
141154 FormBuilderFieldDecorationState <FormBuilderFilePicker , List <PlatformFile >>
142- createState () => _FormBuilderFilePickerState ();
155+ createState () => _FormBuilderFilePickerState ();
143156}
144157
145- class _FormBuilderFilePickerState extends FormBuilderFieldDecorationState <
146- FormBuilderFilePicker , List <PlatformFile >> {
158+ class _FormBuilderFilePickerState
159+ extends
160+ FormBuilderFieldDecorationState <
161+ FormBuilderFilePicker ,
162+ List <PlatformFile >
163+ > {
147164 /// Image File Extensions.
148165 ///
149166 /// Note that images may be previewed.
@@ -175,14 +192,15 @@ class _FormBuilderFilePickerState extends FormBuilderFieldDecorationState<
175192 }
176193
177194 Future <void > pickFiles (
178- FormFieldState <List <PlatformFile >?> field, FileType fileType) async {
195+ FormFieldState <List <PlatformFile >?> field,
196+ FileType fileType,
197+ ) async {
179198 FilePickerResult ? resultList;
180199
181200 try {
182201 resultList = await FilePicker .platform.pickFiles (
183202 type: fileType,
184203 allowedExtensions: widget.allowedExtensions,
185- allowCompression: widget.allowCompression,
186204 compressionQuality: widget.compressionQuality,
187205 onFileLoading: widget.onFileLoading,
188206 allowMultiple: widget.allowMultiple,
@@ -205,7 +223,9 @@ class _FormBuilderFilePickerState extends FormBuilderFieldDecorationState<
205223 }
206224
207225 void _setFiles (
208- List <PlatformFile > files, FormFieldState <List <PlatformFile >?> field) {
226+ List <PlatformFile > files,
227+ FormFieldState <List <PlatformFile >?> field,
228+ ) {
209229 setState (() => _files = files);
210230 field.didChange (_files);
211231 }
@@ -216,7 +236,9 @@ class _FormBuilderFilePickerState extends FormBuilderFieldDecorationState<
216236 }
217237
218238 Widget defaultFileViewer (
219- List <PlatformFile > files, FormFieldSetter <List <PlatformFile >> setter) {
239+ List <PlatformFile > files,
240+ FormFieldSetter <List <PlatformFile >> setter,
241+ ) {
220242 final theme = Theme .of (context);
221243
222244 return LayoutBuilder (
@@ -230,27 +252,31 @@ class _FormBuilderFilePickerState extends FormBuilderFieldDecorationState<
230252 runAlignment: WrapAlignment .start,
231253 runSpacing: 10 ,
232254 spacing: 10 ,
233- children: List .generate (
234- files.length,
235- (index) {
236- return Container (
237- height: itemSize,
238- width: itemSize,
239- margin: const EdgeInsets .only (right: 2 ),
240- child: Stack (
241- alignment: Alignment .bottomCenter,
242- children: < Widget > [
243- Container (
244- alignment: Alignment .center,
245- child: (imageFileExts.contains (
246- files[index].extension ! .toLowerCase ()) &&
247- widget.previewImages)
248- ? widget.withData
249- ? Image .memory (files[index].bytes! ,
250- fit: BoxFit .cover)
251- : Image .file (File (files[index].path! ),
252- fit: BoxFit .cover)
253- : Container (
255+ children: List .generate (files.length, (index) {
256+ return Container (
257+ height: itemSize,
258+ width: itemSize,
259+ margin: const EdgeInsets .only (right: 2 ),
260+ child: Stack (
261+ alignment: Alignment .bottomCenter,
262+ children: < Widget > [
263+ Container (
264+ alignment: Alignment .center,
265+ child:
266+ (imageFileExts.contains (
267+ files[index].extension ! .toLowerCase (),
268+ ) &&
269+ widget.previewImages)
270+ ? widget.withData
271+ ? Image .memory (
272+ files[index].bytes! ,
273+ fit: BoxFit .cover,
274+ )
275+ : Image .file (
276+ File (files[index].path! ),
277+ fit: BoxFit .cover,
278+ )
279+ : Container (
254280 alignment: Alignment .center,
255281 color: theme.primaryColor,
256282 child: Icon (
@@ -259,63 +285,65 @@ class _FormBuilderFilePickerState extends FormBuilderFieldDecorationState<
259285 size: 56 ,
260286 ),
261287 ),
288+ ),
289+ Container (
290+ padding: const EdgeInsets .symmetric (horizontal: 2 ),
291+ width: double .infinity,
292+ color: Colors .white.withValues (alpha: .8 ),
293+ child: Text (
294+ files[index].name,
295+ style: theme.textTheme.bodySmall,
296+ maxLines: 2 ,
297+ overflow: TextOverflow .clip,
262298 ),
263- Container (
264- padding: const EdgeInsets .symmetric (horizontal: 2 ),
265- width: double .infinity,
266- color: Colors .white.withValues (alpha: .8 ),
267- child: Text (
268- files[index].name,
269- style: theme.textTheme.bodySmall,
270- maxLines: 2 ,
271- overflow: TextOverflow .clip,
272- ),
273- ),
274- if (enabled)
275- Positioned (
276- top: 0 ,
277- right: 0 ,
278- child: InkWell (
279- onTap: () {
280- files.removeAt (index);
281- setter.call ([...files]);
282- },
283- child: Container (
284- margin: const EdgeInsets .all (3 ),
285- decoration: BoxDecoration (
286- color: Colors .grey.withValues (alpha: .7 ),
287- shape: BoxShape .circle,
288- ),
289- alignment: Alignment .center,
290- height: 22 ,
291- width: 22 ,
292- child: const Icon (
293- Icons .close,
294- size: 18 ,
295- color: Colors .white,
296- ),
299+ ),
300+ if (enabled)
301+ Positioned (
302+ top: 0 ,
303+ right: 0 ,
304+ child: InkWell (
305+ onTap: () {
306+ files.removeAt (index);
307+ setter.call ([...files]);
308+ },
309+ child: Container (
310+ margin: const EdgeInsets .all (3 ),
311+ decoration: BoxDecoration (
312+ color: Colors .grey.withValues (alpha: .7 ),
313+ shape: BoxShape .circle,
314+ ),
315+ alignment: Alignment .center,
316+ height: 22 ,
317+ width: 22 ,
318+ child: const Icon (
319+ Icons .close,
320+ size: 18 ,
321+ color: Colors .white,
297322 ),
298323 ),
299324 ),
300- ] ,
301- ) ,
302- );
303- },
304- ),
325+ ) ,
326+ ] ,
327+ ),
328+ );
329+ } ),
305330 );
306331 },
307332 );
308333 }
309334
310- List <Widget > getTypeSelectorActions (List <TypeSelector > typeSelectors,
311- FormFieldState <List <PlatformFile >?> field) {
335+ List <Widget > getTypeSelectorActions (
336+ List <TypeSelector > typeSelectors,
337+ FormFieldState <List <PlatformFile >?> field,
338+ ) {
312339 return < Widget > [
313340 ...typeSelectors.map (
314341 (typeSelector) => InkWell (
315- onTap: enabled &&
316- (null == _remainingItemCount || _remainingItemCount! > 0 )
317- ? () => pickFiles (field, typeSelector.type)
318- : null ,
342+ onTap:
343+ enabled &&
344+ (null == _remainingItemCount || _remainingItemCount! > 0 )
345+ ? () => pickFiles (field, typeSelector.type)
346+ : null ,
319347 child: typeSelector.selector,
320348 ),
321349 ),
0 commit comments