mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-10-31 10:03:18 +00:00 
			
		
		
		
	 bbe746c564
			
		
	
	
		bbe746c564
		
			
		
	
	
	
	
		
			
			* feat: support upload svg as icon * feat: support upload icon by pasting a link * feat: delete remote images when remove custon icons * chore: add testing for pasting image link as custon icon --------- Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
		
			
				
	
	
		
			145 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'dart:convert';
 | |
| import 'dart:io';
 | |
| 
 | |
| import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart';
 | |
| import 'package:appflowy/shared/icon_emoji_picker/flowy_icon_emoji_picker.dart';
 | |
| import 'package:appflowy/shared/icon_emoji_picker/icon_color_picker.dart';
 | |
| import 'package:appflowy/shared/icon_emoji_picker/icon_picker.dart';
 | |
| import 'package:appflowy/shared/icon_emoji_picker/icon_uploader.dart';
 | |
| import 'package:appflowy/shared/icon_emoji_picker/tab.dart';
 | |
| import 'package:appflowy/startup/startup.dart';
 | |
| import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/space_icon_popup.dart';
 | |
| import 'package:desktop_drop/desktop_drop.dart';
 | |
| import 'package:flowy_infra_ui/style_widget/primary_rounded_button.dart';
 | |
| import 'package:flowy_svg/flowy_svg.dart';
 | |
| import 'package:flutter/material.dart';
 | |
| import 'package:flutter/services.dart';
 | |
| import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
 | |
| import 'package:flutter_test/flutter_test.dart';
 | |
| 
 | |
| import 'base.dart';
 | |
| import 'common_operations.dart';
 | |
| 
 | |
| extension EmojiTestExtension on WidgetTester {
 | |
|   Future<void> tapEmoji(String emoji) async {
 | |
|     final emojiWidget = find.descendant(
 | |
|       of: find.byType(EmojiPicker),
 | |
|       matching: find.text(emoji),
 | |
|     );
 | |
|     await tapButton(emojiWidget);
 | |
|   }
 | |
| 
 | |
|   Future<void> tapIcon(EmojiIconData icon, {bool enableColor = true}) async {
 | |
|     final iconsData = IconsData.fromJson(jsonDecode(icon.emoji));
 | |
|     final pickTab = find.byType(PickerTab);
 | |
|     expect(pickTab, findsOneWidget);
 | |
|     await pumpAndSettle();
 | |
|     final iconTab = find.descendant(
 | |
|       of: pickTab,
 | |
|       matching: find.text(PickerTabType.icon.tr),
 | |
|     );
 | |
|     expect(iconTab, findsOneWidget);
 | |
|     await tapButton(iconTab);
 | |
|     final selectedSvg = find.descendant(
 | |
|       of: find.byType(FlowyIconPicker),
 | |
|       matching: find.byWidgetPredicate(
 | |
|         (w) => w is FlowySvg && w.svgString == iconsData.svgString,
 | |
|       ),
 | |
|     );
 | |
| 
 | |
|     await tapButton(selectedSvg.first);
 | |
|     if (enableColor) {
 | |
|       final colorPicker = find.byType(IconColorPicker);
 | |
|       expect(colorPicker, findsOneWidget);
 | |
|       final selectedColor = find.descendant(
 | |
|         of: colorPicker,
 | |
|         matching: find.byWidgetPredicate((w) {
 | |
|           if (w is Container) {
 | |
|             final d = w.decoration;
 | |
|             if (d is ShapeDecoration) {
 | |
|               if (d.color ==
 | |
|                   Color(
 | |
|                     int.parse(iconsData.color ?? builtInSpaceColors.first),
 | |
|                   )) {
 | |
|                 return true;
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|           return false;
 | |
|         }),
 | |
|       );
 | |
|       await tapButton(selectedColor);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> pickImage(EmojiIconData icon) async {
 | |
|     final pickTab = find.byType(PickerTab);
 | |
|     expect(pickTab, findsOneWidget);
 | |
|     await pumpAndSettle();
 | |
| 
 | |
|     /// switch to custom tab
 | |
|     final iconTab = find.descendant(
 | |
|       of: pickTab,
 | |
|       matching: find.text(PickerTabType.custom.tr),
 | |
|     );
 | |
|     expect(iconTab, findsOneWidget);
 | |
|     await tapButton(iconTab);
 | |
| 
 | |
|     /// mock for dragging image
 | |
|     final dropTarget = find.descendant(
 | |
|       of: find.byType(IconUploader),
 | |
|       matching: find.byType(DropTarget),
 | |
|     );
 | |
|     expect(dropTarget, findsOneWidget);
 | |
|     final dropTargetWidget = dropTarget.evaluate().first.widget as DropTarget;
 | |
|     dropTargetWidget.onDragDone?.call(
 | |
|       DropDoneDetails(
 | |
|         files: [DropItemFile(icon.emoji)],
 | |
|         localPosition: Offset.zero,
 | |
|         globalPosition: Offset.zero,
 | |
|       ),
 | |
|     );
 | |
|     await pumpAndSettle(const Duration(seconds: 3));
 | |
| 
 | |
|     /// confirm to upload
 | |
|     final confirmButton = find.descendant(
 | |
|       of: find.byType(IconUploader),
 | |
|       matching: find.byType(PrimaryRoundedButton),
 | |
|     );
 | |
|     await tapButton(confirmButton);
 | |
|   }
 | |
| 
 | |
|   Future<void> pasteImageLinkAsIcon(String link) async {
 | |
|     final pickTab = find.byType(PickerTab);
 | |
|     expect(pickTab, findsOneWidget);
 | |
|     await pumpAndSettle();
 | |
| 
 | |
|     /// switch to custom tab
 | |
|     final iconTab = find.descendant(
 | |
|       of: pickTab,
 | |
|       matching: find.text(PickerTabType.custom.tr),
 | |
|     );
 | |
|     expect(iconTab, findsOneWidget);
 | |
|     await tapButton(iconTab);
 | |
| 
 | |
|     // mock the clipboard
 | |
|     await getIt<ClipboardService>()
 | |
|         .setData(ClipboardServiceData(plainText: link));
 | |
| 
 | |
|     // paste the link
 | |
|     await simulateKeyEvent(
 | |
|       LogicalKeyboardKey.keyV,
 | |
|       isControlPressed: Platform.isLinux || Platform.isWindows,
 | |
|       isMetaPressed: Platform.isMacOS,
 | |
|     );
 | |
|     await pumpAndSettle(const Duration(seconds: 5));
 | |
| 
 | |
|     /// confirm to upload
 | |
|     final confirmButton = find.descendant(
 | |
|       of: find.byType(IconUploader),
 | |
|       matching: find.byType(PrimaryRoundedButton),
 | |
|     );
 | |
|     await tapButton(confirmButton);
 | |
|   }
 | |
| }
 |