@@ -9,10 +9,15 @@ import 'package:file_picker/file_picker.dart';
9
9
import 'package:fluent_ui/fluent_ui.dart' ;
10
10
import 'package:flutter_svg/svg.dart' ;
11
11
import 'package:inference/importers/model_directory_importer.dart' ;
12
+ import 'package:inference/importers/model_manifest.dart' ;
13
+ import 'package:inference/project.dart' ;
12
14
import 'package:inference/providers/project_provider.dart' ;
15
+ import 'package:inference/public_models.dart' ;
13
16
import 'package:inference/theme_fluent.dart' ;
17
+ import 'package:inference/utils.dart' ;
14
18
import 'package:path/path.dart' show dirname;
15
19
import 'package:provider/provider.dart' ;
20
+ import 'package:uuid/uuid.dart' ;
16
21
17
22
class DirectoryImport extends StatefulWidget {
18
23
const DirectoryImport ({super .key});
@@ -23,6 +28,7 @@ class DirectoryImport extends StatefulWidget {
23
28
24
29
class _DirectoryImportState extends State <DirectoryImport > {
25
30
bool _showReleaseMessage = false ;
31
+ String ? selectedFolder;
26
32
27
33
void showReleaseMessage () {
28
34
setState (() => _showReleaseMessage = true );
@@ -43,7 +49,25 @@ class _DirectoryImportState extends State<DirectoryImport> {
43
49
44
50
Future <void > processFolder (String directory) async {
45
51
final importer = ModelDirImporter (directory);
46
- final project = await importer.generateProject ();
52
+ if (importer.containsProjectJson) {
53
+ final project = await importer.generateProject ();
54
+ importer.setupFiles ();
55
+ if (mounted) {
56
+ final projectsProvider = Provider .of <ProjectProvider >(context, listen: false );
57
+ projectsProvider.addProject (project);
58
+ Navigator .pop (context, [project]);
59
+ }
60
+ } else {
61
+ setState (() {
62
+ selectedFolder = directory;
63
+ });
64
+ }
65
+ }
66
+
67
+ Future <void > importProject (Project project) async {
68
+ final importer = ModelDirImporter (project.storagePath);
69
+ importer.project = project;
70
+ writeProjectJson (project);
47
71
importer.setupFiles ();
48
72
if (mounted) {
49
73
final projectsProvider = Provider .of <ProjectProvider >(context, listen: false );
@@ -78,31 +102,153 @@ class _DirectoryImportState extends State<DirectoryImport> {
78
102
},
79
103
onDragExited: (val) => hideReleaseMessage (),
80
104
onDragEntered: (val) => showReleaseMessage (),
105
+ child: Builder (
106
+ builder: (context) {
107
+ if (selectedFolder != null && ! _showReleaseMessage) {
108
+ return ModelImportPropertiesForm (
109
+ storagePath: selectedFolder! ,
110
+ onProjectImport: importProject,
111
+ onCancel: () {
112
+ setState (() => selectedFolder = null );
113
+ },
114
+ );
115
+ }
116
+ return Column (
117
+ mainAxisAlignment: MainAxisAlignment .center,
118
+ crossAxisAlignment: CrossAxisAlignment .center,
119
+ children: [
120
+ Text (text,
121
+ style: const TextStyle (
122
+ fontSize: 28 ,
123
+ )
124
+ ),
125
+ Padding (
126
+ padding: const EdgeInsets .all (24 ),
127
+ child: SvgPicture .asset ('images/drop_geti.svg' ),
128
+ ),
129
+ Padding (
130
+ padding: const EdgeInsets .only (top: 24 ),
131
+ child: FilledButton (
132
+ onPressed: () => selectFolder (),
133
+ child: const Text ("Select folder" ),
134
+ ),
135
+ )
136
+ ],
137
+ );
138
+ }
139
+ ),
140
+ );
141
+ }
142
+ )
143
+ );
144
+ }
145
+ }
146
+
147
+ class ModelImportPropertiesForm extends StatefulWidget {
148
+ final String storagePath;
149
+ final Function ? onCancel;
150
+ final Function (Project )? onProjectImport;
151
+ const ModelImportPropertiesForm ({
152
+ super .key,
153
+ required this .storagePath,
154
+ this .onProjectImport,
155
+ this .onCancel,
156
+ });
157
+
158
+ @override
159
+ State <ModelImportPropertiesForm > createState () => _ModelImportPropertiesFormState ();
160
+ }
161
+
162
+ class _ModelImportPropertiesFormState extends State <ModelImportPropertiesForm > {
163
+ ProjectType projectType = ProjectType .text;
164
+ final TextEditingController _controller = TextEditingController ();
165
+
166
+ void generateModelManifest () async {
167
+ final name = _controller.text;
168
+ final manifest = ModelManifest (
169
+ name: name,
170
+ id: const Uuid ().v4 ().toString (),
171
+ fileSize: calculateDiskUsage (widget.storagePath),
172
+ task: projectTypeToString (projectType),
173
+ author: "Unknown" ,
174
+ collection: "" ,
175
+ description: "Try out $name " ,
176
+ npuEnabled: false ,
177
+ contextWindow: 0 ,
178
+ optimizationPrecision: "" ,
179
+ );
180
+
181
+ widget.onProjectImport? .call (await PublicProject .fromModelManifest (manifest, widget.storagePath));
182
+ }
183
+
184
+ bool get validForm => _controller.text.isNotEmpty;
185
+
186
+ @override
187
+ void dispose () {
188
+ _controller.dispose ();
189
+ super .dispose ();
190
+ }
191
+
192
+ @override
193
+ Widget build (BuildContext context) {
194
+ return Padding (
195
+ padding: const EdgeInsets .all (20 ),
196
+ child: Column (
197
+ crossAxisAlignment: CrossAxisAlignment .start,
198
+ children: [
199
+ Expanded (
81
200
child: Column (
82
- mainAxisAlignment: MainAxisAlignment .center,
83
- crossAxisAlignment: CrossAxisAlignment .center,
201
+ crossAxisAlignment: CrossAxisAlignment .start,
84
202
children: [
85
- Text (text,
86
- style: const TextStyle (
87
- fontSize: 28 ,
203
+ const SizedBox (height: 10 ),
204
+ InfoLabel (
205
+ label: "Model name" ,
206
+ child: TextBox (
207
+ placeholder: "Name" ,
208
+ controller: _controller,
209
+ onChanged: (_) => setState (() {}),
88
210
)
89
211
),
90
- Padding (
91
- padding: const EdgeInsets .all (24 ),
92
- child: SvgPicture .asset ('images/drop_geti.svg' ),
212
+ const SizedBox (height: 10 ),
213
+ InfoLabel (
214
+ label: "Task" ,
215
+ child: ComboBox <ProjectType >(
216
+ value: projectType,
217
+ items: List <ComboBoxItem <ProjectType >>.from ([
218
+ ProjectType .text,
219
+ ProjectType .vlm,
220
+ ProjectType .textToImage,
221
+ ProjectType .speech,
222
+ ].map ((t) {
223
+ return ComboBoxItem <ProjectType >(
224
+ value: t,
225
+ child: Text (projectTypeToName (t)),
226
+ );
227
+ })),
228
+ placeholder: const Text ("Select model task" ),
229
+ onChanged: (t) => setState (() => projectType = t! ),
230
+ )
93
231
),
94
- Padding (
95
- padding: const EdgeInsets .only (top: 24 ),
96
- child: FilledButton (
97
- onPressed: () => selectFolder (),
98
- child: const Text ("Select folder" ),
99
- ),
100
- )
101
232
],
102
233
),
103
- );
104
- }
105
- )
234
+ ),
235
+ Row (
236
+ mainAxisAlignment: MainAxisAlignment .end,
237
+ children: [
238
+ Button (
239
+ onPressed: () => widget.onCancel? .call (),
240
+ child: const Text ("Cancel" ),
241
+ ),
242
+ const SizedBox (width: 10 ),
243
+ FilledButton (
244
+ onPressed: validForm ? () => generateModelManifest () : null ,
245
+ child: const Text ("Import" ),
246
+ ),
247
+ ],
248
+ )
249
+
250
+ ],
251
+ ),
106
252
);
107
253
}
108
254
}
0 commit comments