11import 'dart:io' ;
22
33import 'package:appflowy/generated/locale_keys.g.dart' ;
4+ import 'package:appflowy/plugins/document/presentation/editor_drop_manager.dart' ;
45import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart' ;
56import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.dart' ;
67import 'package:appflowy/shared/appflowy_network_image.dart' ;
@@ -17,8 +18,7 @@ import 'package:desktop_drop/desktop_drop.dart';
1718import 'package:dotted_border/dotted_border.dart' ;
1819import 'package:easy_localization/easy_localization.dart' ;
1920import 'package:flowy_infra/file_picker/file_picker_service.dart' ;
20- import 'package:flowy_infra_ui/style_widget/primary_rounded_button.dart' ;
21- import 'package:flowy_infra_ui/style_widget/text.dart' ;
21+ import 'package:flowy_infra_ui/flowy_infra_ui.dart' ;
2222import 'package:flowy_svg/flowy_svg.dart' ;
2323import 'package:flutter/material.dart' ;
2424import 'package:flutter/services.dart' ;
@@ -45,6 +45,7 @@ class IconUploader extends StatefulWidget {
4545}
4646
4747class _IconUploaderState extends State <IconUploader > {
48+ bool isActive = false ;
4849 bool isHovering = false ;
4950 bool isUploading = false ;
5051
@@ -63,11 +64,17 @@ class _IconUploaderState extends State<IconUploader> {
6364 focusNode.requestFocus ();
6465 });
6566 }
67+ WidgetsBinding .instance.addPostFrameCallback ((_) {
68+ enableDocumentDragNotifier.value = false ;
69+ });
6670 }
6771
6872 @override
6973 void dispose () {
7074 super .dispose ();
75+ WidgetsBinding .instance.addPostFrameCallback ((_) {
76+ enableDocumentDragNotifier.value = true ;
77+ });
7178 focusNode.dispose ();
7279 }
7380
@@ -97,27 +104,35 @@ class _IconUploaderState extends State<IconUploader> {
97104 children: [
98105 Expanded (
99106 child: DropTarget (
100- /// there is an issue with multiple DropTargets
101- /// see https://github.com/MixinNetwork/flutter-plugins/issues/2
102- enable: false ,
103- onDragEntered: (_) => setState (() => isHovering = true ),
104- onDragExited: (_) => setState (() => isHovering = false ),
107+ onDragEntered: (_) => setState (() => isActive = true ),
108+ onDragExited: (_) => setState (() => isActive = false ),
105109 onDragDone: (details) => loadImage (details.files),
106110 child: MouseRegion (
107111 cursor: SystemMouseCursors .click,
112+ onEnter: (_) => setState (() => isHovering = true ),
113+ onExit: (_) => setState (() => isHovering = false ),
108114 child: GestureDetector (
109115 behavior: HitTestBehavior .opaque,
110- onTap: () => pickImage () ,
116+ onTap: pickImage,
111117 child: DottedBorder (
112118 dashPattern: const [3 , 3 ],
113119 radius: const Radius .circular (8 ),
114120 borderType: BorderType .RRect ,
115- color: isHovering
121+ color: isActive
116122 ? Theme .of (context).colorScheme.primary
117123 : Theme .of (context).hintColor,
118- child: Center (
124+ child: Container (
125+ alignment: Alignment .center,
126+ decoration: isHovering
127+ ? BoxDecoration (
128+ color: Color (0x0F1F2329 ),
129+ borderRadius: BorderRadius .circular (8 ),
130+ )
131+ : null ,
119132 child: pickedImages.isEmpty
120- ? dragHint ()
133+ ? (isActive
134+ ? hoveringWidget ()
135+ : dragHint (context))
121136 : previewImage (),
122137 ),
123138 ),
@@ -127,12 +142,21 @@ class _IconUploaderState extends State<IconUploader> {
127142 ),
128143 Padding (
129144 padding: const EdgeInsets .only (top: 16 ),
130- child: Align (
131- alignment: Alignment .centerRight,
132- child: _ConfirmButton (
133- onTap: uploadImage,
134- enable: pickedImages.isNotEmpty,
135- ),
145+ child: Row (
146+ children: [
147+ Spacer (),
148+ if (pickedImages.isNotEmpty)
149+ Padding (
150+ padding: EdgeInsets .only (right: 8 ),
151+ child: _ChangeIconButton (
152+ onTap: pickImage,
153+ ),
154+ ),
155+ _ConfirmButton (
156+ onTap: uploadImage,
157+ enable: pickedImages.isNotEmpty,
158+ ),
159+ ],
136160 ),
137161 ),
138162 ],
@@ -143,12 +167,49 @@ class _IconUploaderState extends State<IconUploader> {
143167 );
144168 }
145169
146- Widget dragHint () => FlowyText (
147- LocaleKeys .document_imageBlock_upload_placeholder.tr (),
148- fontSize: 14 ,
149- fontWeight: FontWeight .w500,
150- color: Theme .of (context).hintColor,
151- );
170+ Widget hoveringWidget () {
171+ return Container (
172+ color: Color (0xffE0F8FF ),
173+ child: Center (
174+ child: FlowyText (
175+ LocaleKeys .emojiIconPicker_iconUploader_dropToUpload.tr (),
176+ ),
177+ ),
178+ );
179+ }
180+
181+ Widget dragHint (BuildContext context) {
182+ final style = TextStyle (
183+ fontSize: 14 ,
184+ color: Color (0xff666D76 ),
185+ fontWeight: FontWeight .w500,
186+ );
187+ return Padding (
188+ padding: EdgeInsets .symmetric (horizontal: 32 ),
189+ child: RichText (
190+ textAlign: TextAlign .center,
191+ text: TextSpan (
192+ children: [
193+ TextSpan (
194+ text:
195+ LocaleKeys .emojiIconPicker_iconUploader_placeholderLeft.tr (),
196+ ),
197+ TextSpan (
198+ text: LocaleKeys .emojiIconPicker_iconUploader_placeholderUpload
199+ .tr (),
200+ style: style.copyWith (color: Color (0xff00BCF0 )),
201+ ),
202+ TextSpan (
203+ text:
204+ LocaleKeys .emojiIconPicker_iconUploader_placeholderRight.tr (),
205+ mouseCursor: SystemMouseCursors .click,
206+ ),
207+ ],
208+ style: style,
209+ ),
210+ ),
211+ );
212+ }
152213
153214 Widget previewImage () {
154215 final image = pickedImages.first;
@@ -285,6 +346,41 @@ class _IconUploaderState extends State<IconUploader> {
285346 }
286347}
287348
349+ class _ChangeIconButton extends StatelessWidget {
350+ const _ChangeIconButton ({required this .onTap});
351+
352+ final VoidCallback onTap;
353+
354+ @override
355+ Widget build (BuildContext context) {
356+ final isDark = Theme .of (context).brightness == Brightness .dark;
357+ return SizedBox (
358+ height: 32 ,
359+ width: 84 ,
360+ child: FlowyButton (
361+ text: FlowyText (
362+ LocaleKeys .emojiIconPicker_iconUploader_change.tr (),
363+ fontSize: 14.0 ,
364+ fontWeight: FontWeight .w500,
365+ figmaLineHeight: 20.0 ,
366+ color: isDark ? Colors .white : Color (0xff1F2329 ),
367+ textAlign: TextAlign .center,
368+ overflow: TextOverflow .ellipsis,
369+ ),
370+ margin: const EdgeInsets .symmetric (horizontal: 14.0 ),
371+ backgroundColor: Theme .of (context).colorScheme.surface,
372+ hoverColor:
373+ (isDark ? Colors .white : Color (0xffD1D8E0 )).withValues (alpha: 0.9 ),
374+ decoration: BoxDecoration (
375+ border: Border .all (color: isDark ? Colors .white : Color (0xffD1D8E0 )),
376+ borderRadius: BorderRadius .circular (10 ),
377+ ),
378+ onTap: onTap,
379+ ),
380+ );
381+ }
382+ }
383+
288384class _ConfirmButton extends StatelessWidget {
289385 const _ConfirmButton ({required this .onTap, this .enable = true });
290386
@@ -299,6 +395,7 @@ class _ConfirmButton extends StatelessWidget {
299395 opacity: enable ? 1.0 : 0.5 ,
300396 child: PrimaryRoundedButton (
301397 text: LocaleKeys .button_confirm.tr (),
398+ figmaLineHeight: 20.0 ,
302399 onTap: enable ? onTap : null ,
303400 ),
304401 ),
0 commit comments