Skip to content

Commit 0ef6327

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

File tree

4 files changed

+138
-26
lines changed

4 files changed

+138
-26
lines changed

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

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_p
44
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart';
55
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
66
import 'package:appflowy/shared/patterns/file_type_patterns.dart';
7+
import 'package:appflowy/startup/startup.dart';
78
import 'package:appflowy/workspace/presentation/widgets/draggable_item/draggable_item.dart';
89
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
910
import 'package:appflowy_editor/appflowy_editor.dart';
@@ -66,12 +67,22 @@ class EditorDropHandler extends StatelessWidget {
6667
return true;
6768
},
6869
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,
70+
builder: (context, _, __) => ChangeNotifierProvider(
71+
create: (_) => getIt.get<EditorDropManagerState>(),
72+
builder: (context, _) {
73+
final topLevelEditorDropManagerState =
74+
Provider.of<EditorDropManagerState>(context);
75+
return DropTarget(
76+
enable: dropState.isDropEnabled &&
77+
topLevelEditorDropManagerState.isDropEnabled,
78+
onDragExited: (_) =>
79+
editorState.selectionService.removeDropTarget(),
80+
onDragUpdated: (details) =>
81+
_onDragUpdated(details.globalPosition),
82+
onDragDone: _onDragDone,
83+
child: child,
84+
);
85+
},
7586
),
7687
),
7788
);

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

Lines changed: 110 additions & 20 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';
@@ -50,6 +50,8 @@ class _IconUploaderState extends State<IconUploader> {
5050

5151
final List<_Image> pickedImages = [];
5252
final FocusNode focusNode = FocusNode();
53+
final topEditorDropManagerState = getIt.get<EditorDropManagerState>();
54+
final iconUploaderType = 'iconUploaderType';
5355

5456
@override
5557
void initState() {
@@ -63,11 +65,17 @@ class _IconUploaderState extends State<IconUploader> {
6365
focusNode.requestFocus();
6466
});
6567
}
68+
WidgetsBinding.instance.addPostFrameCallback((_) {
69+
topEditorDropManagerState.add(iconUploaderType);
70+
});
6671
}
6772

6873
@override
6974
void dispose() {
7075
super.dispose();
76+
WidgetsBinding.instance.addPostFrameCallback((_) {
77+
topEditorDropManagerState.remove(iconUploaderType);
78+
});
7179
focusNode.dispose();
7280
}
7381

@@ -97,27 +105,27 @@ class _IconUploaderState extends State<IconUploader> {
97105
children: [
98106
Expanded(
99107
child: DropTarget(
100-
/// there is an issue with multiple DropTargets
101-
/// see https://github.com/MixinNetwork/flutter-plugins/issues/2
102-
enable: false,
103108
onDragEntered: (_) => setState(() => isHovering = true),
104109
onDragExited: (_) => setState(() => isHovering = false),
105110
onDragDone: (details) => loadImage(details.files),
106111
child: MouseRegion(
107112
cursor: SystemMouseCursors.click,
108113
child: GestureDetector(
109114
behavior: HitTestBehavior.opaque,
110-
onTap: () => pickImage(),
115+
onTap: pickImage,
111116
child: DottedBorder(
112117
dashPattern: const [3, 3],
113118
radius: const Radius.circular(8),
114119
borderType: BorderType.RRect,
115120
color: isHovering
116121
? Theme.of(context).colorScheme.primary
117122
: Theme.of(context).hintColor,
118-
child: Center(
123+
child: Container(
124+
alignment: Alignment.center,
119125
child: pickedImages.isEmpty
120-
? dragHint()
126+
? (isHovering
127+
? hoveringWidget()
128+
: dragHint(context))
121129
: previewImage(),
122130
),
123131
),
@@ -127,12 +135,21 @@ class _IconUploaderState extends State<IconUploader> {
127135
),
128136
Padding(
129137
padding: const EdgeInsets.only(top: 16),
130-
child: Align(
131-
alignment: Alignment.centerRight,
132-
child: _ConfirmButton(
133-
onTap: uploadImage,
134-
enable: pickedImages.isNotEmpty,
135-
),
138+
child: Row(
139+
children: [
140+
Spacer(),
141+
if (pickedImages.isNotEmpty)
142+
Padding(
143+
padding: EdgeInsets.only(right: 8),
144+
child: _ChangeIconButton(
145+
onTap: pickImage,
146+
),
147+
),
148+
_ConfirmButton(
149+
onTap: uploadImage,
150+
enable: pickedImages.isNotEmpty,
151+
),
152+
],
136153
),
137154
),
138155
],
@@ -143,12 +160,49 @@ class _IconUploaderState extends State<IconUploader> {
143160
);
144161
}
145162

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-
);
163+
Widget hoveringWidget() {
164+
return Container(
165+
color: Color(0xffE0F8FF),
166+
child: Center(
167+
child: FlowyText(
168+
LocaleKeys.emojiIconPicker_iconUploader_dropToUpload.tr(),
169+
),
170+
),
171+
);
172+
}
173+
174+
Widget dragHint(BuildContext context) {
175+
final style = TextStyle(
176+
fontSize: 14,
177+
color: Color(0xff666D76),
178+
fontWeight: FontWeight.w500,
179+
);
180+
return Padding(
181+
padding: EdgeInsets.symmetric(horizontal: 32),
182+
child: RichText(
183+
textAlign: TextAlign.center,
184+
text: TextSpan(
185+
children: [
186+
TextSpan(
187+
text:
188+
LocaleKeys.emojiIconPicker_iconUploader_placeholderLeft.tr(),
189+
),
190+
TextSpan(
191+
text: LocaleKeys.emojiIconPicker_iconUploader_placeholderUpload
192+
.tr(),
193+
style: style.copyWith(color: Color(0xff00BCF0)),
194+
),
195+
TextSpan(
196+
text:
197+
LocaleKeys.emojiIconPicker_iconUploader_placeholderRight.tr(),
198+
mouseCursor: SystemMouseCursors.click,
199+
),
200+
],
201+
style: style,
202+
),
203+
),
204+
);
205+
}
152206

153207
Widget previewImage() {
154208
final image = pickedImages.first;
@@ -285,6 +339,41 @@ class _IconUploaderState extends State<IconUploader> {
285339
}
286340
}
287341

342+
class _ChangeIconButton extends StatelessWidget {
343+
const _ChangeIconButton({required this.onTap});
344+
345+
final VoidCallback onTap;
346+
347+
@override
348+
Widget build(BuildContext context) {
349+
final isDark = Theme.of(context).brightness == Brightness.dark;
350+
return SizedBox(
351+
height: 32,
352+
width: 84,
353+
child: FlowyButton(
354+
text: FlowyText(
355+
LocaleKeys.emojiIconPicker_iconUploader_change.tr(),
356+
fontSize: 14.0,
357+
fontWeight: FontWeight.w500,
358+
figmaLineHeight: 20.0,
359+
color: isDark ? Colors.white : Color(0xff1F2329),
360+
textAlign: TextAlign.center,
361+
overflow: TextOverflow.ellipsis,
362+
),
363+
margin: const EdgeInsets.symmetric(horizontal: 14.0),
364+
backgroundColor: Theme.of(context).colorScheme.surface,
365+
hoverColor:
366+
(isDark ? Colors.white : Color(0xffD1D8E0)).withValues(alpha: 0.9),
367+
decoration: BoxDecoration(
368+
border: Border.all(color: isDark ? Colors.white : Color(0xffD1D8E0)),
369+
borderRadius: BorderRadius.circular(10),
370+
),
371+
onTap: onTap,
372+
),
373+
);
374+
}
375+
}
376+
288377
class _ConfirmButton extends StatelessWidget {
289378
const _ConfirmButton({required this.onTap, this.enable = true});
290379

@@ -299,6 +388,7 @@ class _ConfirmButton extends StatelessWidget {
299388
opacity: enable ? 1.0 : 0.5,
300389
child: PrimaryRoundedButton(
301390
text: LocaleKeys.button_confirm.tr(),
391+
figmaLineHeight: 20.0,
302392
onTap: enable ? onTap : null,
303393
),
304394
),

frontend/appflowy_flutter/lib/startup/startup.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:async';
22
import 'dart:io';
33

44
import 'package:appflowy/env/cloud_env.dart';
5+
import 'package:appflowy/plugins/document/presentation/editor_drop_manager.dart';
56
import 'package:appflowy/util/expand_views.dart';
67
import 'package:appflowy/workspace/application/settings/prelude.dart';
78
import 'package:appflowy_backend/appflowy_backend.dart';
@@ -185,6 +186,7 @@ Future<void> initGetIt(
185186
);
186187
getIt.registerSingleton<PluginSandbox>(PluginSandbox());
187188
getIt.registerSingleton<ViewExpanderRegistry>(ViewExpanderRegistry());
189+
getIt.registerSingleton<EditorDropManagerState>(EditorDropManagerState());
188190

189191
await DependencyResolver.resolve(getIt, mode);
190192
}

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)