mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-07-28 11:31:54 +00:00

* 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);
|
|
}
|
|
}
|