Skip to content

Commit 0044b6f

Browse files
committed
feat: add change button for icon uploader
1 parent 4e3d085 commit 0044b6f

File tree

6 files changed

+147
-29
lines changed

6 files changed

+147
-29
lines changed

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_drop_handler.dart

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,20 @@ class EditorDropHandler extends StatelessWidget {
6666
return true;
6767
},
6868
onAcceptWithDetails: _onDragViewDone,
69-
builder: (context, _, __) => DropTarget(
70-
enable: dropState.isDropEnabled,
71-
onDragExited: (_) => editorState.selectionService.removeDropTarget(),
72-
onDragUpdated: (details) => _onDragUpdated(details.globalPosition),
73-
onDragDone: _onDragDone,
74-
child: child,
69+
builder: (context, _, __) => ValueListenableBuilder(
70+
valueListenable: enableDocumentDragNotifier,
71+
builder: (context, value, _) {
72+
final enableDocumentDrag = value;
73+
return DropTarget(
74+
enable: dropState.isDropEnabled && enableDocumentDrag,
75+
onDragExited: (_) =>
76+
editorState.selectionService.removeDropTarget(),
77+
onDragUpdated: (details) =>
78+
_onDragUpdated(details.globalPosition),
79+
onDragDone: _onDragDone,
80+
child: child,
81+
);
82+
},
7583
),
7684
),
7785
);

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_drop_manager.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ class EditorDropManagerState extends ChangeNotifier {
1515

1616
bool get isDropEnabled => _draggedTypes.isEmpty;
1717
}
18+
19+
final enableDocumentDragNotifier = ValueNotifier(true);

frontend/appflowy_flutter/lib/shared/icon_emoji_picker/icon_uploader.dart

Lines changed: 120 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:io';
22

33
import 'package:appflowy/generated/locale_keys.g.dart';
4+
import 'package:appflowy/plugins/document/presentation/editor_drop_manager.dart';
45
import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart';
56
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.dart';
67
import 'package:appflowy/shared/appflowy_network_image.dart';
@@ -17,8 +18,7 @@ import 'package:desktop_drop/desktop_drop.dart';
1718
import 'package:dotted_border/dotted_border.dart';
1819
import 'package:easy_localization/easy_localization.dart';
1920
import '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';
2222
import 'package:flowy_svg/flowy_svg.dart';
2323
import 'package:flutter/material.dart';
2424
import 'package:flutter/services.dart';
@@ -45,6 +45,7 @@ class IconUploader extends StatefulWidget {
4545
}
4646

4747
class _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+
288384
class _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
),

frontend/appflowy_flutter/macos/build/ios/XCBuildData/PIFCache/project/PROJECT@v11_mod=a7fbf46937053896f73cc7c7ec6baefb_hash=bfdfe7dc352907fc980b868725387e98plugins=1OJSG6M1FOV3XYQCBH7Z29RZ0FPR9XDE1-json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"guid":"dc4b70c03e8043e50e38f2068887b1d4","name":"Pods","path":"/Users/morn/dev/samples/AppFlowy/frontend/appflowy_flutter/ios/Pods/Pods.xcodeproj/project.xcworkspace","projects":["PROJECT@v11_mod=a7fbf46937053896f73cc7c7ec6baefb_hash=bfdfe7dc352907fc980b868725387e98plugins=1OJSG6M1FOV3XYQCBH7Z29RZ0FPR9XDE1"]}

frontend/resources/translations/en.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,15 @@
161161
"csv": "CSV",
162162
"database": "Database"
163163
},
164+
"emojiIconPicker": {
165+
"iconUploader": {
166+
"placeholderLeft": "Drag & drop a file, click to ",
167+
"placeholderUpload": "Upload",
168+
"placeholderRight": ", or paste an image link.",
169+
"dropToUpload": "Drop a file to upload",
170+
"change": "Change"
171+
}
172+
},
164173
"disclosureAction": {
165174
"rename": "Rename",
166175
"delete": "Delete",

0 commit comments

Comments
 (0)