feat: update workspace icon style on desktop (#6452)

* feat: update workspace icon style on desktop

* fix: unable to insert two referenced link at the same doc
This commit is contained in:
Lucas 2024-10-03 09:39:52 +08:00 committed by GitHub
parent cb2b933a90
commit 5de716b19d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 95 additions and 143 deletions

View File

@ -60,6 +60,57 @@ void main() {
); );
}); });
testWidgets('insert multiple referenced boards', (tester) async {
await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton();
// create a new grid
final id = uuid();
final name = '${ViewLayoutPB.Board.name}_$id';
await tester.createNewPageWithNameUnderParent(
name: name,
layout: ViewLayoutPB.Board,
openAfterCreated: false,
);
// create a new document
await tester.createNewPageWithNameUnderParent(
name: 'insert_a_reference_${ViewLayoutPB.Board.name}',
);
// tap the first line of the document
await tester.editor.tapLineOfEditorAt(0);
// insert a referenced view
await tester.editor.showSlashMenu();
await tester.editor.tapSlashMenuItemWithName(
ViewLayoutPB.Board.slashMenuLinkedName,
);
final referencedDatabase1 = find.descendant(
of: find.byType(InlineActionsHandler),
matching: find.findTextInFlowyText(name),
);
expect(referencedDatabase1, findsOneWidget);
await tester.tapButton(referencedDatabase1);
await tester.editor.tapLineOfEditorAt(1);
await tester.editor.showSlashMenu();
await tester.editor.tapSlashMenuItemWithName(
ViewLayoutPB.Board.slashMenuLinkedName,
);
final referencedDatabase2 = find.descendant(
of: find.byType(InlineActionsHandler),
matching: find.findTextInFlowyText(name),
);
expect(referencedDatabase2, findsOneWidget);
await tester.tapButton(referencedDatabase2);
expect(
find.descendant(
of: find.byType(AppFlowyEditor),
matching: find.byType(DesktopBoardPage),
),
findsNWidgets(2),
);
});
testWidgets('insert a referenced calendar', (tester) async { testWidgets('insert a referenced calendar', (tester) async {
await tester.initializeAppFlowy(); await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton(); await tester.tapAnonymousSignInButton();

View File

@ -121,7 +121,7 @@ class _MobileWorkspace extends StatelessWidget {
}, },
child: Row( child: Row(
children: [ children: [
WorkspaceIconV2( WorkspaceIcon(
workspace: currentWorkspace, workspace: currentWorkspace,
iconSize: 36, iconSize: 36,
fontSize: 18.0, fontSize: 18.0,

View File

@ -272,7 +272,7 @@ class _WorkspaceMenuItemIcon extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0), padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: WorkspaceIconV2( child: WorkspaceIcon(
enableEdit: false, enableEdit: false,
iconSize: 36, iconSize: 36,
emojiSize: 24.0, emojiSize: 24.0,

View File

@ -1,5 +1,3 @@
import 'package:flutter/material.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/inline_actions/handlers/inline_page_reference.dart'; import 'package:appflowy/plugins/inline_actions/handlers/inline_page_reference.dart';
import 'package:appflowy/plugins/inline_actions/inline_actions_menu.dart'; import 'package:appflowy/plugins/inline_actions/inline_actions_menu.dart';
@ -8,6 +6,7 @@ import 'package:appflowy/plugins/inline_actions/inline_actions_service.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
InlineActionsMenuService? _actionsMenuService; InlineActionsMenuService? _actionsMenuService;
Future<void> showLinkToPageMenu( Future<void> showLinkToPageMenu(
@ -15,6 +14,8 @@ Future<void> showLinkToPageMenu(
SelectionMenuService menuService, SelectionMenuService menuService,
ViewLayoutPB pageType, ViewLayoutPB pageType,
) async { ) async {
keepEditorFocusNotifier.increase();
menuService.dismiss(); menuService.dismiss();
_actionsMenuService?.dismiss(); _actionsMenuService?.dismiss();
@ -27,7 +28,7 @@ Future<void> showLinkToPageMenu(
context: rootContext, context: rootContext,
handlers: [ handlers: [
InlinePageReferenceService( InlinePageReferenceService(
currentViewId: "", currentViewId: '',
viewLayout: pageType, viewLayout: pageType,
customTitle: titleFromPageType(pageType), customTitle: titleFromPageType(pageType),
insertPage: pageType != ViewLayoutPB.Document, insertPage: pageType != ViewLayoutPB.Document,

View File

@ -1,9 +1,8 @@
import 'package:flutter/material.dart';
import 'package:appflowy/plugins/inline_actions/inline_actions_result.dart'; import 'package:appflowy/plugins/inline_actions/inline_actions_result.dart';
import 'package:appflowy/plugins/inline_actions/inline_actions_service.dart'; import 'package:appflowy/plugins/inline_actions/inline_actions_service.dart';
import 'package:appflowy/plugins/inline_actions/widgets/inline_actions_handler.dart'; import 'package:appflowy/plugins/inline_actions/widgets/inline_actions_handler.dart';
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
abstract class InlineActionsMenuService { abstract class InlineActionsMenuService {
InlineActionsMenuStyle get style; InlineActionsMenuStyle get style;
@ -40,6 +39,7 @@ class InlineActionsMenu extends InlineActionsMenuService {
if (_menuEntry != null) { if (_menuEntry != null) {
editorState.service.keyboardService?.enable(); editorState.service.keyboardService?.enable();
editorState.service.scrollService?.enable(); editorState.service.scrollService?.enable();
keepEditorFocusNotifier.decrease();
} }
_menuEntry?.remove(); _menuEntry?.remove();

View File

@ -1,5 +1,3 @@
import 'dart:math';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/base/emoji/emoji_picker_screen.dart'; import 'package:appflowy/plugins/base/emoji/emoji_picker_screen.dart';
import 'package:appflowy/shared/icon_emoji_picker/flowy_icon_emoji_picker.dart'; import 'package:appflowy/shared/icon_emoji_picker/flowy_icon_emoji_picker.dart';
@ -24,96 +22,6 @@ class WorkspaceIcon extends StatefulWidget {
this.emojiSize, this.emojiSize,
this.alignment, this.alignment,
required this.figmaLineHeight, required this.figmaLineHeight,
});
final UserWorkspacePB workspace;
final double iconSize;
final bool enableEdit;
final double fontSize;
final double? emojiSize;
final void Function(EmojiPickerResult) onSelected;
final double borderRadius;
final Alignment? alignment;
final double figmaLineHeight;
@override
State<WorkspaceIcon> createState() => _WorkspaceIconState();
}
class _WorkspaceIconState extends State<WorkspaceIcon> {
final controller = PopoverController();
@override
Widget build(BuildContext context) {
Widget child = widget.workspace.icon.isNotEmpty
? Container(
width: widget.iconSize,
alignment: widget.alignment ?? Alignment.center,
child: FlowyText.emoji(
widget.workspace.icon,
fontSize: widget.emojiSize ?? widget.iconSize,
figmaLineHeight: widget.figmaLineHeight,
optimizeEmojiAlign: true,
),
)
: Container(
alignment: Alignment.center,
width: widget.iconSize,
height: min(widget.iconSize, 24),
decoration: BoxDecoration(
color: ColorGenerator(widget.workspace.name).toColor(),
borderRadius: BorderRadius.circular(widget.borderRadius),
border: Border.all(
color: const Color(0xa1717171),
width: 0.5,
),
),
child: FlowyText.semibold(
widget.workspace.name.isEmpty
? ''
: widget.workspace.name.substring(0, 1),
fontSize: widget.fontSize,
color: Colors.black,
),
);
if (widget.enableEdit) {
child = AppFlowyPopover(
offset: const Offset(0, 8),
controller: controller,
direction: PopoverDirection.bottomWithLeftAligned,
constraints: BoxConstraints.loose(const Size(364, 356)),
clickHandler: PopoverClickHandler.gestureDetector,
margin: const EdgeInsets.all(0),
popupBuilder: (_) => FlowyIconEmojiPicker(
onSelectedEmoji: (result) {
widget.onSelected(result);
controller.close();
},
),
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
),
);
}
return child;
}
}
// The v2 supports the built-in color set
class WorkspaceIconV2 extends StatefulWidget {
const WorkspaceIconV2({
super.key,
required this.workspace,
required this.enableEdit,
required this.iconSize,
required this.fontSize,
required this.onSelected,
this.borderRadius = 4,
this.emojiSize,
this.alignment,
required this.figmaLineHeight,
this.showBorder = true, this.showBorder = true,
}); });
@ -129,10 +37,10 @@ class WorkspaceIconV2 extends StatefulWidget {
final bool showBorder; final bool showBorder;
@override @override
State<WorkspaceIconV2> createState() => _WorkspaceIconV2State(); State<WorkspaceIcon> createState() => _WorkspaceIconState();
} }
class _WorkspaceIconV2State extends State<WorkspaceIconV2> { class _WorkspaceIconState extends State<WorkspaceIcon> {
final controller = PopoverController(); final controller = PopoverController();
@override @override
@ -178,7 +86,7 @@ class _WorkspaceIconV2State extends State<WorkspaceIconV2> {
Widget _buildEditableIcon(Widget child) { Widget _buildEditableIcon(Widget child) {
if (UniversalPlatform.isDesktopOrWeb) { if (UniversalPlatform.isDesktopOrWeb) {
AppFlowyPopover( return AppFlowyPopover(
offset: const Offset(0, 8), offset: const Offset(0, 8),
controller: controller, controller: controller,
direction: PopoverDirection.bottomWithLeftAligned, direction: PopoverDirection.bottomWithLeftAligned,

View File

@ -153,31 +153,22 @@ class _WorkspaceMenuItemState extends State<WorkspaceMenuItem> {
} }
Widget _buildLeftIcon(BuildContext context) { Widget _buildLeftIcon(BuildContext context) {
return Container( return FlowyTooltip(
width: 32.0, message: LocaleKeys.document_plugins_cover_changeIcon.tr(),
height: 32.0, child: WorkspaceIcon(
decoration: BoxDecoration( workspace: widget.workspace,
borderRadius: BorderRadius.circular(8), iconSize: 36,
border: Border.all( emojiSize: 24.0,
color: const Color(0x01717171).withOpacity(0.12), fontSize: 18.0,
width: 0.8, figmaLineHeight: 26.0,
), borderRadius: 12.0,
), enableEdit: true,
child: FlowyTooltip( onSelected: (result) => context.read<UserWorkspaceBloc>().add(
message: LocaleKeys.document_plugins_cover_changeIcon.tr(), UserWorkspaceEvent.updateWorkspaceIcon(
child: WorkspaceIcon( widget.workspace.workspaceId,
workspace: widget.workspace, result.emoji,
iconSize: 22,
fontSize: 16,
figmaLineHeight: 32.0,
enableEdit: true,
onSelected: (result) => context.read<UserWorkspaceBloc>().add(
UserWorkspaceEvent.updateWorkspaceIcon(
widget.workspace.workspaceId,
result.emoji,
),
), ),
), ),
), ),
); );
} }
@ -321,8 +312,10 @@ class _CreateWorkspaceButton extends StatelessWidget {
text: Row( text: Row(
children: [ children: [
_buildLeftIcon(context), _buildLeftIcon(context),
const HSpace(10.0), const HSpace(8.0),
FlowyText.regular(LocaleKeys.workspace_create.tr()), FlowyText.regular(
LocaleKeys.workspace_create.tr(),
),
], ],
), ),
), ),
@ -331,11 +324,11 @@ class _CreateWorkspaceButton extends StatelessWidget {
Widget _buildLeftIcon(BuildContext context) { Widget _buildLeftIcon(BuildContext context) {
return Container( return Container(
width: 32.0, width: 36.0,
height: 32.0, height: 36.0,
padding: const EdgeInsets.all(7.0), padding: const EdgeInsets.all(7.0),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(12),
border: Border.all( border: Border.all(
color: const Color(0x01717171).withOpacity(0.12), color: const Color(0x01717171).withOpacity(0.12),
width: 0.8, width: 0.8,

View File

@ -273,12 +273,13 @@ class _SideBarSwitchWorkspaceButtonChild extends StatelessWidget {
const HSpace(4.0), const HSpace(4.0),
WorkspaceIcon( WorkspaceIcon(
workspace: currentWorkspace, workspace: currentWorkspace,
iconSize: 24, iconSize: 26,
fontSize: 16, fontSize: 16,
emojiSize: 18, emojiSize: 20,
enableEdit: false, enableEdit: false,
borderRadius: 8.0, borderRadius: 8.0,
figmaLineHeight: 21.0, figmaLineHeight: 18.0,
showBorder: false,
onSelected: (result) => context.read<UserWorkspaceBloc>().add( onSelected: (result) => context.read<UserWorkspaceBloc>().add(
UserWorkspaceEvent.updateWorkspaceIcon( UserWorkspaceEvent.updateWorkspaceIcon(
currentWorkspace.workspaceId, currentWorkspace.workspaceId,
@ -286,7 +287,7 @@ class _SideBarSwitchWorkspaceButtonChild extends StatelessWidget {
), ),
), ),
), ),
const HSpace(8), const HSpace(6),
Flexible( Flexible(
child: FlowyText.medium( child: FlowyText.medium(
currentWorkspace.name, currentWorkspace.name,

View File

@ -345,20 +345,18 @@ class _WorkspaceIconSetting extends StatelessWidget {
); );
} }
return Container( return SizedBox(
height: 64, height: 64,
width: 64, width: 64,
decoration: BoxDecoration(
border: Border.all(color: Theme.of(context).colorScheme.outline),
borderRadius: BorderRadius.circular(8),
),
child: Padding( child: Padding(
padding: const EdgeInsets.all(1), padding: const EdgeInsets.all(1),
child: WorkspaceIcon( child: WorkspaceIcon(
workspace: workspace!, workspace: workspace!,
iconSize: workspace!.icon.isNotEmpty == true ? 46 : 20, iconSize: 36,
fontSize: 16.0, emojiSize: 24.0,
figmaLineHeight: 46, fontSize: 24.0,
figmaLineHeight: 26.0,
borderRadius: 18.0,
enableEdit: true, enableEdit: true,
onSelected: (r) => context onSelected: (r) => context
.read<WorkspaceSettingsBloc>() .read<WorkspaceSettingsBloc>()