@@ -2,183 +2,47 @@ import 'package:flutter/material.dart';
22import 'package:flutter_riverpod/flutter_riverpod.dart' ;
33import 'package:miria/model/account.dart' ;
44import 'package:miria/providers.dart' ;
5- import 'package:miria/view/common/misskey_notes/network_image.dart' ;
6- import 'package:miria/view/common/pushable_listview.dart' ;
7- import 'package:miria/view/themes/app_theme.dart' ;
8- import 'package:misskey_dart/misskey_dart.dart' ;
9-
10- class DriveFileSelectDialog extends ConsumerStatefulWidget {
11- final Account account;
12- final bool allowMultiple;
5+ import 'package:miria/state_notifier/drive_page/drive_page_notifier.dart' ;
6+ import 'package:miria/view/drive_page/drive_page.dart' ;
137
8+ class DriveFileSelectDialog extends StatelessWidget {
149 const DriveFileSelectDialog ({
1510 super .key,
1611 required this .account,
17- this .allowMultiple = false ,
1812 });
1913
20- @override
21- ConsumerState <ConsumerStatefulWidget > createState () =>
22- DriveFileSelectDialogState ();
23- }
24-
25- class DriveFileSelectDialogState extends ConsumerState <DriveFileSelectDialog > {
26- final List <DriveFolder > path = [];
27- final List <DriveFile > files = [];
14+ final Account account;
2815
2916 @override
3017 Widget build (BuildContext context) {
31- return AlertDialog (
32- title: AppBar (
33- leading: IconButton (
34- onPressed: path.isEmpty
35- ? null
36- : () {
37- setState (() {
38- path.removeLast ();
39- });
40- },
41- icon: const Icon (Icons .arrow_back),
42- ),
43- title: path.isEmpty
44- ? const Text ("ファイルを選択" )
45- : Text (path.map ((e) => e.name).join ("/" )),
46- actions: [
47- if (files.isNotEmpty)
48- Center (
49- child: Text (
50- "(${files .length })" ,
51- style: Theme .of (context).textTheme.titleMedium,
52- ),
53- ),
54- if (widget.allowMultiple)
55- IconButton (
56- onPressed:
57- files.isEmpty ? null : () => Navigator .of (context).pop (files),
58- icon: const Icon (Icons .check),
59- ),
60- ],
61- backgroundColor: Colors .transparent,
62- ),
63- content: SizedBox (
64- width: MediaQuery .of (context).size.width * 0.8 ,
65- height: MediaQuery .of (context).size.height * 0.8 ,
66- child: SingleChildScrollView (
67- child: Column (
68- children: [
69- PushableListView (
70- shrinkWrap: true ,
71- physics: const NeverScrollableScrollPhysics (),
72- initializeFuture: () async {
73- final misskey = ref.read (misskeyProvider (widget.account));
74- final response = await misskey.drive.folders.folders (
75- DriveFoldersRequest (
76- folderId: path.isEmpty ? null : path.last.id));
77- return response.toList ();
78- },
79- nextFuture: (lastItem, _) async {
80- final misskey = ref.read (misskeyProvider (widget.account));
81- final response = await misskey.drive.folders.folders (
82- DriveFoldersRequest (
83- untilId: lastItem.id,
84- folderId: path.isEmpty ? null : path.last.id));
85- return response.toList ();
86- },
87- listKey: path.map ((e) => e.id).join ("/" ),
88- itemBuilder: (context, item) {
89- return ListTile (
90- leading: const Icon (Icons .folder),
91- title: Text (item.name ?? "" ),
92- onTap: () {
93- setState (() {
94- path.add (item);
95- });
96- },
97- );
98- }),
99- PushableListView (
100- shrinkWrap: true ,
101- physics: const NeverScrollableScrollPhysics (),
102- initializeFuture: () async {
103- final misskey = ref.read (misskeyProvider (widget.account));
104- final response = await misskey.drive.files.files (
105- DriveFilesRequest (
106- folderId: path.isEmpty ? null : path.last.id,
107- ),
108- );
109- return response.toList ();
110- },
111- nextFuture: (lastItem, _) async {
112- final misskey = ref.read (misskeyProvider (widget.account));
113- final response = await misskey.drive.files.files (
114- DriveFilesRequest (
115- untilId: lastItem.id,
116- folderId: path.isEmpty ? null : path.last.id,
117- ),
118- );
119- return response.toList ();
120- },
121- listKey: path.map ((e) => e.id).join ("/" ),
122- itemBuilder: (context, item) {
123- final isSelected = files.any ((file) => file.id == item.id);
124- return Padding (
125- padding: const EdgeInsets .symmetric (vertical: 2 ),
126- child: InkWell (
127- customBorder: RoundedRectangleBorder (
128- borderRadius: BorderRadius .circular (5 ),
129- ),
130- onTap: () {
131- if (widget.allowMultiple) {
132- setState (() {
133- if (isSelected) {
134- files.removeWhere ((file) => file.id == item.id);
135- } else {
136- files.add (item);
137- }
138- });
139- } else {
140- Navigator .of (context).pop (item);
141- }
142- },
143- child: Container (
144- padding: const EdgeInsets .all (10 ),
145- decoration: (widget.allowMultiple && isSelected)
146- ? BoxDecoration (
147- color: AppTheme .of (context)
148- .currentDisplayTabColor
149- .withOpacity (0.7 ),
150- borderRadius: BorderRadius .circular (5 ),
151- )
152- : null ,
153- child: Column (
154- crossAxisAlignment: CrossAxisAlignment .start,
155- children: [
156- SizedBox (
157- width: double .infinity,
158- height: 200 ,
159- child: item.thumbnailUrl == null
160- ? const SizedBox .shrink ()
161- : ClipRRect (
162- borderRadius: BorderRadius .circular (5 ),
163- child: NetworkImageView (
164- fit: BoxFit .cover,
165- url: item.thumbnailUrl! ,
166- type: ImageType .imageThumbnail,
167- ),
168- ),
169- ),
170- Text (item.name),
171- ],
172- ),
173- ),
174- ),
175- );
176- },
177- ),
178- ],
179- ),
18+ return ProviderScope (
19+ overrides: [
20+ drivePageNotifierProvider.overrideWith (DrivePageNotifier .new ),
21+ ],
22+ child: Dialog (
23+ child: DrivePage (
24+ account: account,
25+ title: const Text ("ファイルを選択" ),
26+ tapToSelect: true ,
27+ floatingActionButtonBuilder: (context) =>
28+ const DriveFileSelectDialogFloatingActionButton (),
18029 ),
18130 ),
18231 );
18332 }
18433}
34+
35+ class DriveFileSelectDialogFloatingActionButton extends ConsumerWidget {
36+ const DriveFileSelectDialogFloatingActionButton ({super .key});
37+
38+ @override
39+ Widget build (BuildContext context, WidgetRef ref) {
40+ final files = ref.watch (drivePageNotifierProvider).selectedFiles;
41+ return FloatingActionButton .extended (
42+ onPressed:
43+ files.isNotEmpty ? () => Navigator .of (context).pop (files) : null ,
44+ label: const Text ("選択" ),
45+ icon: const Icon (Icons .check),
46+ );
47+ }
48+ }
0 commit comments