mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: optimize editor toolbar tooltip (#5889)
* chore: improve icon picker dark mode color * feat: optimize editor toolbar tooltip style * feat: customize markdown item tooltip message * chore: find the tooltip by rich message * feat: add hover effect in toolbar item * feat: add hover effect in toolbar item * chore: optimize hover color in light mode * chore: fix integration test * chore: optimize align & font toolbar item * chore: fix integration test
This commit is contained in:
parent
a798b037db
commit
e279ad1cc7
@ -33,7 +33,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// tap the inline math equation button
|
// tap the inline math equation button
|
||||||
final inlineMathEquationButton = find.byTooltip(
|
final inlineMathEquationButton = find.findFlowyTooltip(
|
||||||
LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
||||||
);
|
);
|
||||||
await tester.tapButton(inlineMathEquationButton);
|
await tester.tapButton(inlineMathEquationButton);
|
||||||
@ -78,7 +78,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// tap the inline math equation button
|
// tap the inline math equation button
|
||||||
var inlineMathEquationButton = find.byTooltip(
|
var inlineMathEquationButton = find.findFlowyTooltip(
|
||||||
LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
||||||
);
|
);
|
||||||
await tester.tapButton(inlineMathEquationButton);
|
await tester.tapButton(inlineMathEquationButton);
|
||||||
@ -93,11 +93,11 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// expect to the see the inline math equation button is highlighted
|
// expect to the see the inline math equation button is highlighted
|
||||||
inlineMathEquationButton = find.byWidgetPredicate(
|
inlineMathEquationButton = find.descendant(
|
||||||
(widget) =>
|
of: find.findFlowyTooltip(
|
||||||
widget is SVGIconItemWidget &&
|
LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
||||||
widget.tooltip ==
|
),
|
||||||
LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
matching: find.byType(SVGIconItemWidget),
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
tester.widget<SVGIconItemWidget>(inlineMathEquationButton).isHighlight,
|
tester.widget<SVGIconItemWidget>(inlineMathEquationButton).isHighlight,
|
||||||
|
@ -1,113 +0,0 @@
|
|||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart';
|
|
||||||
import 'package:appflowy/startup/startup.dart';
|
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
|
||||||
import 'package:appflowy_editor/src/render/toolbar/toolbar_widget.dart';
|
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:integration_test/integration_test.dart';
|
|
||||||
|
|
||||||
import '../../shared/mock/mock_openai_repository.dart';
|
|
||||||
import '../../shared/util.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
const service = TestWorkspaceService(TestWorkspace.aiWorkSpace);
|
|
||||||
|
|
||||||
group('integration tests for open-ai smart menu', () {
|
|
||||||
setUpAll(() async => service.setUpAll());
|
|
||||||
setUp(() async => service.setUp());
|
|
||||||
|
|
||||||
testWidgets('testing selection on open-ai smart menu replace',
|
|
||||||
(tester) async {
|
|
||||||
final appFlowyEditor = await setUpOpenAITesting(tester);
|
|
||||||
final editorState = appFlowyEditor.editorState;
|
|
||||||
|
|
||||||
editorState.service.selectionService.updateSelection(
|
|
||||||
Selection(
|
|
||||||
start: Position(path: [1], offset: 4),
|
|
||||||
end: Position(path: [1], offset: 10),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
expect(find.byType(ToolbarWidget), findsAtLeastNWidgets(1));
|
|
||||||
|
|
||||||
await tester.tap(find.byTooltip('AI Assistants'));
|
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
||||||
|
|
||||||
await tester.tap(find.text('Summarize'));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
await tester
|
|
||||||
.tap(find.byType(FlowyRichTextButton, skipOffstage: false).first);
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
expect(
|
|
||||||
editorState.service.selectionService.currentSelection.value,
|
|
||||||
Selection(
|
|
||||||
start: Position(path: [1], offset: 4),
|
|
||||||
end: Position(path: [1], offset: 84),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
testWidgets('testing selection on open-ai smart menu insert',
|
|
||||||
(tester) async {
|
|
||||||
final appFlowyEditor = await setUpOpenAITesting(tester);
|
|
||||||
final editorState = appFlowyEditor.editorState;
|
|
||||||
|
|
||||||
editorState.service.selectionService.updateSelection(
|
|
||||||
Selection(
|
|
||||||
start: Position(path: [1]),
|
|
||||||
end: Position(path: [1], offset: 5),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(find.byType(ToolbarWidget), findsAtLeastNWidgets(1));
|
|
||||||
|
|
||||||
await tester.tap(find.byTooltip('AI Assistants'));
|
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
|
||||||
|
|
||||||
await tester.tap(find.text('Summarize'));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
await tester
|
|
||||||
.tap(find.byType(FlowyRichTextButton, skipOffstage: false).at(1));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
expect(
|
|
||||||
editorState.service.selectionService.currentSelection.value,
|
|
||||||
Selection(
|
|
||||||
start: Position(path: [2]),
|
|
||||||
end: Position(path: [3]),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<AppFlowyEditor> setUpOpenAITesting(WidgetTester tester) async {
|
|
||||||
await tester.initializeAppFlowy();
|
|
||||||
await mockOpenAIRepository();
|
|
||||||
|
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.controlLeft);
|
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.backslash);
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
final Finder editor = find.byType(AppFlowyEditor);
|
|
||||||
await tester.tap(editor);
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
return tester.state(editor).widget as AppFlowyEditor;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> mockOpenAIRepository() async {
|
|
||||||
await getIt.unregister<AIRepository>();
|
|
||||||
getIt.registerFactoryAsync<AIRepository>(
|
|
||||||
() => Future.value(
|
|
||||||
MockOpenAIRepository(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
@ -1,9 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/env/cloud_env.dart';
|
import 'package:appflowy/env/cloud_env.dart';
|
||||||
import 'package:appflowy/env/cloud_env_test.dart';
|
import 'package:appflowy/env/cloud_env_test.dart';
|
||||||
import 'package:appflowy/startup/entry_point.dart';
|
import 'package:appflowy/startup/entry_point.dart';
|
||||||
@ -16,6 +13,8 @@ import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widget
|
|||||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||||
import 'package:flowy_infra/uuid.dart';
|
import 'package:flowy_infra/uuid.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
@ -231,6 +230,16 @@ extension AppFlowyFinderTestBase on CommonFinders {
|
|||||||
(widget) => widget is FlowyText && widget.text == text,
|
(widget) => widget is FlowyText && widget.text == text,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Finder findFlowyTooltip(String richMessage, {bool skipOffstage = true}) {
|
||||||
|
return byWidgetPredicate(
|
||||||
|
(widget) =>
|
||||||
|
widget is FlowyTooltip &&
|
||||||
|
widget.richMessage != null &&
|
||||||
|
widget.richMessage!.toPlainText().contains(richMessage),
|
||||||
|
skipOffstage: skipOffstage,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> useTestSupabaseCloud() async {
|
Future<void> useTestSupabaseCloud() async {
|
||||||
|
@ -3,7 +3,7 @@ import 'dart:ui';
|
|||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_picker.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_picker.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_skin_tone.dart';
|
import 'package:appflowy/shared/icon_emoji_picker/emoji_skin_tone.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/actions/block_action_add_button.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/actions/block_action_add_button.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/actions/block_action_option_button.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/actions/block_action_option_button.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/header/cover_editor.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/header/cover_editor.dart';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:appflowy/plugins/base/emoji/emoji_picker_header.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_picker_header.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_skin_tone.dart';
|
import 'package:appflowy/shared/icon_emoji_picker/emoji_skin_tone.dart';
|
||||||
import 'package:appflowy/shared/icon_emoji_picker/emoji_search_bar.dart';
|
import 'package:appflowy/shared/icon_emoji_picker/emoji_search_bar.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
@ -387,6 +387,8 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
editorScrollController: editorScrollController,
|
editorScrollController: editorScrollController,
|
||||||
textDirection: textDirection,
|
textDirection: textDirection,
|
||||||
|
tooltipBuilder: (context, id, message, child) => widget.styleCustomizer
|
||||||
|
.buildToolbarItemTooltip(context, id, message, child,),
|
||||||
child: editor,
|
child: editor,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -9,12 +9,13 @@ import 'package:flutter/material.dart';
|
|||||||
const String leftAlignmentKey = 'left';
|
const String leftAlignmentKey = 'left';
|
||||||
const String centerAlignmentKey = 'center';
|
const String centerAlignmentKey = 'center';
|
||||||
const String rightAlignmentKey = 'right';
|
const String rightAlignmentKey = 'right';
|
||||||
|
const String kAlignToolbarItemId = 'editor.align';
|
||||||
|
|
||||||
final alignToolbarItem = ToolbarItem(
|
final alignToolbarItem = ToolbarItem(
|
||||||
id: 'editor.align',
|
id: kAlignToolbarItemId,
|
||||||
group: 4,
|
group: 4,
|
||||||
isActive: onlyShowInTextType,
|
isActive: onlyShowInTextType,
|
||||||
builder: (context, editorState, highlightColor, _) {
|
builder: (context, editorState, highlightColor, _, tooltipBuilder) {
|
||||||
final selection = editorState.selection!;
|
final selection = editorState.selection!;
|
||||||
final nodes = editorState.getNodesInSelection(selection);
|
final nodes = editorState.getNodesInSelection(selection);
|
||||||
|
|
||||||
@ -37,35 +38,37 @@ final alignToolbarItem = ToolbarItem(
|
|||||||
data = FlowySvgs.toolbar_align_right_s;
|
data = FlowySvgs.toolbar_align_right_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
final child = FlowySvg(
|
Widget child = FlowySvg(
|
||||||
data,
|
data,
|
||||||
size: const Size.square(16),
|
size: const Size.square(16),
|
||||||
color: isHighlight ? highlightColor : Colors.white,
|
color: isHighlight ? highlightColor : Colors.white,
|
||||||
);
|
);
|
||||||
|
|
||||||
return MouseRegion(
|
child = _AlignmentButtons(
|
||||||
cursor: SystemMouseCursors.click,
|
child: child,
|
||||||
child: FlowyTooltip(
|
onAlignChanged: (align) async {
|
||||||
message: LocaleKeys.document_plugins_optionAction_align.tr(),
|
await editorState.updateNode(
|
||||||
child: Padding(
|
selection,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
(node) => node.copyWith(
|
||||||
child: _AlignmentButtons(
|
attributes: {
|
||||||
child: child,
|
...node.attributes,
|
||||||
onAlignChanged: (align) async {
|
blockComponentAlign: align,
|
||||||
await editorState.updateNode(
|
|
||||||
selection,
|
|
||||||
(node) => node.copyWith(
|
|
||||||
attributes: {
|
|
||||||
...node.attributes,
|
|
||||||
blockComponentAlign: align,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (tooltipBuilder != null) {
|
||||||
|
child = tooltipBuilder(
|
||||||
|
context,
|
||||||
|
kAlignToolbarItemId,
|
||||||
|
LocaleKeys.document_plugins_optionAction_align.tr(),
|
||||||
|
child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -83,13 +86,15 @@ class _AlignmentButtons extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _AlignmentButtonsState extends State<_AlignmentButtons> {
|
class _AlignmentButtonsState extends State<_AlignmentButtons> {
|
||||||
|
final controller = PopoverController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
windowPadding: const EdgeInsets.all(0),
|
windowPadding: const EdgeInsets.all(0),
|
||||||
margin: const EdgeInsets.all(4),
|
margin: const EdgeInsets.symmetric(vertical: 2.0),
|
||||||
direction: PopoverDirection.bottomWithCenterAligned,
|
direction: PopoverDirection.bottomWithCenterAligned,
|
||||||
offset: const Offset(0, 10),
|
offset: const Offset(0, 12),
|
||||||
decorationColor: Theme.of(context).colorScheme.onTertiary,
|
decorationColor: Theme.of(context).colorScheme.onTertiary,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||||
popupBuilder: (_) {
|
popupBuilder: (_) {
|
||||||
@ -99,7 +104,12 @@ class _AlignmentButtonsState extends State<_AlignmentButtons> {
|
|||||||
onClose: () {
|
onClose: () {
|
||||||
keepEditorFocusNotifier.decrease();
|
keepEditorFocusNotifier.decrease();
|
||||||
},
|
},
|
||||||
child: widget.child,
|
child: FlowyButton(
|
||||||
|
useIntrinsicWidth: true,
|
||||||
|
text: widget.child,
|
||||||
|
hoverColor: Colors.grey.withOpacity(0.3),
|
||||||
|
onTap: () => controller.show(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,7 +124,7 @@ class _AlignButtons extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 32,
|
height: 28,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@ -156,17 +166,16 @@ class _AlignButton extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MouseRegion(
|
return FlowyButton(
|
||||||
cursor: SystemMouseCursors.click,
|
useIntrinsicWidth: true,
|
||||||
child: GestureDetector(
|
hoverColor: Colors.grey.withOpacity(0.3),
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: FlowyTooltip(
|
text: FlowyTooltip(
|
||||||
message: tooltips,
|
message: tooltips,
|
||||||
child: FlowySvg(
|
child: FlowySvg(
|
||||||
icon,
|
icon,
|
||||||
size: const Size.square(16),
|
size: const Size.square(16),
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -179,7 +188,7 @@ class _Divider extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(4),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 1,
|
width: 1,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||||
@ -9,6 +6,7 @@ import 'package:appflowy/util/font_family_extension.dart';
|
|||||||
import 'package:appflowy/util/levenshtein.dart';
|
import 'package:appflowy/util/levenshtein.dart';
|
||||||
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/shared/setting_list_tile.dart';
|
import 'package:appflowy/workspace/presentation/settings/shared/setting_list_tile.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/shared/setting_value_dropdown.dart';
|
import 'package:appflowy/workspace/presentation/settings/shared/setting_value_dropdown.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
@ -20,56 +18,66 @@ import 'package:flowy_infra/theme_extension.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text_field.dart';
|
import 'package:flowy_infra_ui/style_widget/text_field.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
const kFontToolbarItemId = 'editor.font';
|
||||||
|
|
||||||
final customizeFontToolbarItem = ToolbarItem(
|
final customizeFontToolbarItem = ToolbarItem(
|
||||||
id: 'editor.font',
|
id: kFontToolbarItemId,
|
||||||
group: 4,
|
group: 4,
|
||||||
isActive: onlyShowInTextType,
|
isActive: onlyShowInTextType,
|
||||||
builder: (context, editorState, highlightColor, _) {
|
builder: (context, editorState, highlightColor, _, tooltipBuilder) {
|
||||||
final selection = editorState.selection!;
|
final selection = editorState.selection!;
|
||||||
final popoverController = PopoverController();
|
final popoverController = PopoverController();
|
||||||
final String? currentFontFamily = editorState
|
final String? currentFontFamily = editorState
|
||||||
.getDeltaAttributeValueInSelection(AppFlowyRichTextKeys.fontFamily);
|
.getDeltaAttributeValueInSelection(AppFlowyRichTextKeys.fontFamily);
|
||||||
return MouseRegion(
|
|
||||||
cursor: SystemMouseCursors.click,
|
Widget child = FontFamilyDropDown(
|
||||||
child: FontFamilyDropDown(
|
currentFontFamily: currentFontFamily ?? '',
|
||||||
currentFontFamily: currentFontFamily ?? '',
|
offset: const Offset(0, 12),
|
||||||
offset: const Offset(0, 12),
|
popoverController: popoverController,
|
||||||
popoverController: popoverController,
|
onOpen: () => keepEditorFocusNotifier.increase(),
|
||||||
onOpen: () => keepEditorFocusNotifier.increase(),
|
onClose: () => keepEditorFocusNotifier.decrease(),
|
||||||
onClose: () => keepEditorFocusNotifier.decrease(),
|
showResetButton: true,
|
||||||
showResetButton: true,
|
onFontFamilyChanged: (fontFamily) async {
|
||||||
onFontFamilyChanged: (fontFamily) async {
|
popoverController.close();
|
||||||
popoverController.close();
|
try {
|
||||||
try {
|
await editorState.formatDelta(selection, {
|
||||||
await editorState.formatDelta(selection, {
|
AppFlowyRichTextKeys.fontFamily: fontFamily,
|
||||||
AppFlowyRichTextKeys.fontFamily: fontFamily,
|
});
|
||||||
});
|
} catch (e) {
|
||||||
} catch (e) {
|
Log.error('Failed to set font family: $e');
|
||||||
Log.error('Failed to set font family: $e');
|
}
|
||||||
}
|
},
|
||||||
},
|
onResetFont: () async {
|
||||||
onResetFont: () async {
|
popoverController.close();
|
||||||
popoverController.close();
|
await editorState
|
||||||
await editorState
|
.formatDelta(selection, {AppFlowyRichTextKeys.fontFamily: null});
|
||||||
.formatDelta(selection, {AppFlowyRichTextKeys.fontFamily: null});
|
},
|
||||||
},
|
child: FlowyButton(
|
||||||
child: Padding(
|
useIntrinsicWidth: true,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
hoverColor: Colors.grey.withOpacity(0.3),
|
||||||
child: FlowyTooltip(
|
onTap: () => popoverController.show(),
|
||||||
message: LocaleKeys.document_plugins_fonts.tr(),
|
text: const FlowySvg(
|
||||||
child: const FlowySvg(
|
FlowySvgs.font_family_s,
|
||||||
FlowySvgs.font_family_s,
|
size: Size.square(16.0),
|
||||||
size: Size.square(16.0),
|
color: Colors.white,
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (tooltipBuilder != null) {
|
||||||
|
child = tooltipBuilder(
|
||||||
|
context,
|
||||||
|
kFontToolbarItemId,
|
||||||
|
LocaleKeys.document_plugins_fonts.tr(),
|
||||||
|
child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -5,11 +5,13 @@ 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';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
const _kInlineMathEquationToolbarItemId = 'editor.inline_math_equation';
|
||||||
|
|
||||||
final ToolbarItem inlineMathEquationItem = ToolbarItem(
|
final ToolbarItem inlineMathEquationItem = ToolbarItem(
|
||||||
id: 'editor.inline_math_equation',
|
id: _kInlineMathEquationToolbarItemId,
|
||||||
group: 2,
|
group: 2,
|
||||||
isActive: onlyShowInSingleSelectionAndTextType,
|
isActive: onlyShowInSingleSelectionAndTextType,
|
||||||
builder: (context, editorState, highlightColor, _) {
|
builder: (context, editorState, highlightColor, _, tooltipBuilder) {
|
||||||
final selection = editorState.selection!;
|
final selection = editorState.selection!;
|
||||||
final nodes = editorState.getNodesInSelection(selection);
|
final nodes = editorState.getNodesInSelection(selection);
|
||||||
final isHighlight = nodes.allSatisfyInSelection(selection, (delta) {
|
final isHighlight = nodes.allSatisfyInSelection(selection, (delta) {
|
||||||
@ -17,7 +19,7 @@ final ToolbarItem inlineMathEquationItem = ToolbarItem(
|
|||||||
(attributes) => attributes[InlineMathEquationKeys.formula] != null,
|
(attributes) => attributes[InlineMathEquationKeys.formula] != null,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return SVGIconItemWidget(
|
final child = SVGIconItemWidget(
|
||||||
iconBuilder: (_) => FlowySvg(
|
iconBuilder: (_) => FlowySvg(
|
||||||
FlowySvgs.math_lg,
|
FlowySvgs.math_lg,
|
||||||
size: const Size.square(16),
|
size: const Size.square(16),
|
||||||
@ -25,7 +27,6 @@ final ToolbarItem inlineMathEquationItem = ToolbarItem(
|
|||||||
),
|
),
|
||||||
isHighlight: isHighlight,
|
isHighlight: isHighlight,
|
||||||
highlightColor: highlightColor,
|
highlightColor: highlightColor,
|
||||||
tooltip: LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final selection = editorState.selection;
|
final selection = editorState.selection;
|
||||||
if (selection == null || selection.isCollapsed) {
|
if (selection == null || selection.isCollapsed) {
|
||||||
@ -71,5 +72,16 @@ final ToolbarItem inlineMathEquationItem = ToolbarItem(
|
|||||||
await editorState.apply(transaction);
|
await editorState.apply(transaction);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (tooltipBuilder != null) {
|
||||||
|
return tooltipBuilder(
|
||||||
|
context,
|
||||||
|
_kInlineMathEquationToolbarItemId,
|
||||||
|
LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
||||||
|
child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -11,12 +11,15 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
const _kSmartEditToolbarItemId = 'appflowy.editor.smart_edit';
|
||||||
|
|
||||||
final ToolbarItem smartEditItem = ToolbarItem(
|
final ToolbarItem smartEditItem = ToolbarItem(
|
||||||
id: 'appflowy.editor.smart_edit',
|
id: _kSmartEditToolbarItemId,
|
||||||
group: 0,
|
group: 0,
|
||||||
isActive: onlyShowInSingleSelectionAndTextType,
|
isActive: onlyShowInSingleSelectionAndTextType,
|
||||||
builder: (context, editorState, _, __) => SmartEditActionList(
|
builder: (context, editorState, _, __, tooltipBuilder) => SmartEditActionList(
|
||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
|
tooltipBuilder: tooltipBuilder,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -24,9 +27,11 @@ class SmartEditActionList extends StatefulWidget {
|
|||||||
const SmartEditActionList({
|
const SmartEditActionList({
|
||||||
super.key,
|
super.key,
|
||||||
required this.editorState,
|
required this.editorState,
|
||||||
|
this.tooltipBuilder,
|
||||||
});
|
});
|
||||||
|
|
||||||
final EditorState editorState;
|
final EditorState editorState;
|
||||||
|
final ToolbarTooltipBuilder? tooltipBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SmartEditActionList> createState() => _SmartEditActionListState();
|
State<SmartEditActionList> createState() => _SmartEditActionListState();
|
||||||
@ -60,11 +65,8 @@ class _SmartEditActionListState extends State<SmartEditActionList> {
|
|||||||
onClosed: () => keepEditorFocusNotifier.decrease(),
|
onClosed: () => keepEditorFocusNotifier.decrease(),
|
||||||
buildChild: (controller) {
|
buildChild: (controller) {
|
||||||
keepEditorFocusNotifier.increase();
|
keepEditorFocusNotifier.increase();
|
||||||
return FlowyIconButton(
|
final child = FlowyIconButton(
|
||||||
hoverColor: Colors.transparent,
|
hoverColor: Colors.transparent,
|
||||||
tooltipText: isAIEnabled
|
|
||||||
? LocaleKeys.document_plugins_smartEdit.tr()
|
|
||||||
: LocaleKeys.document_plugins_appflowyAIEditDisabled.tr(),
|
|
||||||
preferBelow: false,
|
preferBelow: false,
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.lightbulb_outline,
|
Icons.lightbulb_outline,
|
||||||
@ -83,6 +85,19 @@ class _SmartEditActionListState extends State<SmartEditActionList> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (widget.tooltipBuilder != null) {
|
||||||
|
return widget.tooltipBuilder!(
|
||||||
|
context,
|
||||||
|
_kSmartEditToolbarItemId,
|
||||||
|
isAIEnabled
|
||||||
|
? LocaleKeys.document_plugins_smartEdit.tr()
|
||||||
|
: LocaleKeys.document_plugins_appflowyAIEditDisabled.tr(),
|
||||||
|
child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
},
|
},
|
||||||
onSelected: (action, controller) {
|
onSelected: (action, controller) {
|
||||||
controller.close();
|
controller.close();
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:appflowy/core/helpers/url_launcher.dart';
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart';
|
import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart';
|
||||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/font_colors.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/font_colors.dart';
|
||||||
@ -13,7 +16,10 @@ import 'package:appflowy/workspace/application/settings/appearance/appearance_cu
|
|||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -394,4 +400,83 @@ class EditorStyleCustomizer {
|
|||||||
after,
|
after,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildToolbarItemTooltip(
|
||||||
|
BuildContext context,
|
||||||
|
String id,
|
||||||
|
String message,
|
||||||
|
Widget child,
|
||||||
|
) {
|
||||||
|
final tooltipMessage = _buildTooltipMessage(id, message);
|
||||||
|
child = FlowyTooltip(
|
||||||
|
richMessage: tooltipMessage,
|
||||||
|
preferBelow: false,
|
||||||
|
verticalOffset: 20,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
|
||||||
|
// the align/font toolbar item doesn't need the hover effect
|
||||||
|
final toolbarItemsWithoutHover = {
|
||||||
|
kFontToolbarItemId,
|
||||||
|
kAlignToolbarItemId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!toolbarItemsWithoutHover.contains(id)) {
|
||||||
|
child = Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
child: FlowyHover(
|
||||||
|
style: HoverStyle(
|
||||||
|
hoverColor: Colors.grey.withOpacity(0.3),
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextSpan _buildTooltipMessage(String id, String message) {
|
||||||
|
final markdownItemTooltips = {
|
||||||
|
'underline': (LocaleKeys.toolbar_underline.tr(), 'U'),
|
||||||
|
'bold': (LocaleKeys.toolbar_bold.tr(), 'B'),
|
||||||
|
'italic': (LocaleKeys.toolbar_italic.tr(), 'I'),
|
||||||
|
'strikethrough': (LocaleKeys.toolbar_strike.tr(), 'Shift+S'),
|
||||||
|
'code': (LocaleKeys.toolbar_inlineCode.tr(), 'E'),
|
||||||
|
};
|
||||||
|
|
||||||
|
final markdownItemIds = markdownItemTooltips.keys.toSet();
|
||||||
|
// the items without shortcuts
|
||||||
|
if (!markdownItemIds.contains(id)) {
|
||||||
|
return TextSpan(
|
||||||
|
text: message,
|
||||||
|
style: context.tooltipTextStyle(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final tooltip = markdownItemTooltips[id];
|
||||||
|
if (tooltip == null) {
|
||||||
|
return TextSpan(
|
||||||
|
text: message,
|
||||||
|
style: context.tooltipTextStyle(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final textSpan = TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: '${tooltip.$1}\n',
|
||||||
|
style: context.tooltipTextStyle(),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: (Platform.isMacOS ? '⌘+' : 'Ctrl+\\') + tooltip.$2,
|
||||||
|
style: context
|
||||||
|
.tooltipTextStyle()
|
||||||
|
?.copyWith(color: Theme.of(context).hintColor),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return textSpan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
import 'package:appflowy/util/theme_extension.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
extension PickerColors on BuildContext {
|
||||||
|
Color get pickerTextColor {
|
||||||
|
return Theme.of(this).isLightMode
|
||||||
|
? const Color(0x80171717)
|
||||||
|
: Colors.white.withOpacity(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color get pickerIconColor {
|
||||||
|
return Theme.of(this).isLightMode ? const Color(0xFF171717) : Colors.white;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color get pickerSearchBarBorderColor {
|
||||||
|
return Theme.of(this).isLightMode
|
||||||
|
? const Color(0x1E171717)
|
||||||
|
: Colors.white.withOpacity(0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color get pickerButtonBoarderColor {
|
||||||
|
return Theme.of(this).isLightMode
|
||||||
|
? const Color(0x1E171717)
|
||||||
|
: Colors.white.withOpacity(0.12);
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,14 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_skin_tone.dart';
|
import 'package:appflowy/shared/icon_emoji_picker/emoji_skin_tone.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:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
||||||
|
|
||||||
|
import 'colors.dart';
|
||||||
|
|
||||||
typedef EmojiKeywordChangedCallback = void Function(String keyword);
|
typedef EmojiKeywordChangedCallback = void Function(String keyword);
|
||||||
typedef EmojiSkinToneChanged = void Function(EmojiSkinTone skinTone);
|
typedef EmojiSkinToneChanged = void Function(EmojiSkinTone skinTone);
|
||||||
|
|
||||||
@ -82,7 +84,7 @@ class _RandomEmojiButton extends StatelessWidget {
|
|||||||
height: 36,
|
height: 36,
|
||||||
decoration: ShapeDecoration(
|
decoration: ShapeDecoration(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
side: const BorderSide(color: Color(0x1E171717)),
|
side: BorderSide(color: context.pickerButtonBoarderColor),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -141,7 +143,7 @@ class _SearchTextFieldState extends State<_SearchTextField> {
|
|||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
),
|
),
|
||||||
enableBorderColor: const Color(0x1E171717),
|
enableBorderColor: context.pickerSearchBarBorderColor,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
onChanged: widget.onKeywordChanged,
|
onChanged: widget.onKeywordChanged,
|
||||||
prefixIcon: const Padding(
|
prefixIcon: const Padding(
|
||||||
|
@ -5,6 +5,8 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
||||||
|
|
||||||
|
import 'colors.dart';
|
||||||
|
|
||||||
// use a temporary global value to store last selected skin tone
|
// use a temporary global value to store last selected skin tone
|
||||||
EmojiSkinTone? lastSelectedEmojiSkinTone;
|
EmojiSkinTone? lastSelectedEmojiSkinTone;
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ class _FlowyEmojiSkinToneSelectorState
|
|||||||
width: 36,
|
width: 36,
|
||||||
height: 36,
|
height: 36,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: const Color(0x1E171717)),
|
border: Border.all(color: context.pickerButtonBoarderColor),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: FlowyButton(
|
child: FlowyButton(
|
@ -13,6 +13,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|||||||
import 'package:flutter/material.dart' hide Icon;
|
import 'package:flutter/material.dart' hide Icon;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'colors.dart';
|
||||||
import 'icon_color_picker.dart';
|
import 'icon_color_picker.dart';
|
||||||
|
|
||||||
// cache the icon groups to avoid loading them multiple times
|
// cache the icon groups to avoid loading them multiple times
|
||||||
@ -200,7 +201,7 @@ class _IconPickerState extends State<IconPicker> {
|
|||||||
iconGroup.displayName,
|
iconGroup.displayName,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
figmaLineHeight: 18.0,
|
figmaLineHeight: 18.0,
|
||||||
color: const Color(0x80171717),
|
color: context.pickerTextColor,
|
||||||
),
|
),
|
||||||
const VSpace(4.0),
|
const VSpace(4.0),
|
||||||
Wrap(
|
Wrap(
|
||||||
@ -252,7 +253,7 @@ class _Icon extends StatelessWidget {
|
|||||||
child: FlowySvg.string(
|
child: FlowySvg.string(
|
||||||
icon.content,
|
icon.content,
|
||||||
size: const Size.square(20),
|
size: const Size.square(20),
|
||||||
color: const Color(0xFF171717),
|
color: context.pickerIconColor,
|
||||||
opacity: 0.7,
|
opacity: 0.7,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -6,6 +6,8 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
||||||
|
|
||||||
|
import 'colors.dart';
|
||||||
|
|
||||||
typedef IconKeywordChangedCallback = void Function(String keyword);
|
typedef IconKeywordChangedCallback = void Function(String keyword);
|
||||||
typedef EmojiSkinToneChanged = void Function(EmojiSkinTone skinTone);
|
typedef EmojiSkinToneChanged = void Function(EmojiSkinTone skinTone);
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ class _RandomIconButton extends StatelessWidget {
|
|||||||
height: 36,
|
height: 36,
|
||||||
decoration: ShapeDecoration(
|
decoration: ShapeDecoration(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
side: const BorderSide(color: Color(0x1E171717)),
|
side: BorderSide(color: context.pickerButtonBoarderColor),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -123,7 +125,7 @@ class _SearchTextFieldState extends State<_SearchTextField> {
|
|||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
),
|
),
|
||||||
enableBorderColor: const Color(0x1E171717),
|
enableBorderColor: context.pickerSearchBarBorderColor,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
onChanged: widget.onKeywordChanged,
|
onChanged: widget.onKeywordChanged,
|
||||||
prefixIcon: const Padding(
|
prefixIcon: const Padding(
|
||||||
|
@ -10,6 +10,7 @@ class FlowyTooltip extends StatelessWidget {
|
|||||||
this.preferBelow,
|
this.preferBelow,
|
||||||
this.showDuration,
|
this.showDuration,
|
||||||
this.margin,
|
this.margin,
|
||||||
|
this.verticalOffset,
|
||||||
this.child,
|
this.child,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ class FlowyTooltip extends StatelessWidget {
|
|||||||
final Duration? showDuration;
|
final Duration? showDuration;
|
||||||
final EdgeInsetsGeometry? margin;
|
final EdgeInsetsGeometry? margin;
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
|
final double? verticalOffset;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -28,16 +30,14 @@ class FlowyTooltip extends StatelessWidget {
|
|||||||
|
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
margin: margin,
|
margin: margin,
|
||||||
verticalOffset: 16.0,
|
verticalOffset: verticalOffset ?? 16.0,
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.symmetric(
|
||||||
left: 12.0,
|
horizontal: 12.0,
|
||||||
right: 12.0,
|
vertical: 8.0,
|
||||||
top: 5.0,
|
|
||||||
bottom: 8.0,
|
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: context.tooltipBackgroundColor(),
|
color: context.tooltipBackgroundColor(),
|
||||||
borderRadius: BorderRadius.circular(12.0),
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
),
|
),
|
||||||
waitDuration: _tooltipWaitDuration,
|
waitDuration: _tooltipWaitDuration,
|
||||||
message: message,
|
message: message,
|
||||||
@ -50,7 +50,7 @@ class FlowyTooltip extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension FlowyToolTipExtension on BuildContext {
|
extension FlowyToolTipExtension on BuildContext {
|
||||||
double tooltipFontSize() => 13.0;
|
double tooltipFontSize() => 14.0;
|
||||||
double tooltipHeight() => 18.0 / tooltipFontSize();
|
double tooltipHeight() => 18.0 / tooltipFontSize();
|
||||||
Color tooltipFontColor() => Theme.of(this).brightness == Brightness.light
|
Color tooltipFontColor() => Theme.of(this).brightness == Brightness.light
|
||||||
? Colors.white
|
? Colors.white
|
||||||
|
@ -53,8 +53,8 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: c064543
|
ref: "4536488faf458ab45e304c1715850d4d1ae517ee"
|
||||||
resolved-ref: c064543e0e40f862f1db2db36725d48465a8aea5
|
resolved-ref: "4536488faf458ab45e304c1715850d4d1ae517ee"
|
||||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||||
source: git
|
source: git
|
||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
|
@ -199,7 +199,7 @@ dependency_overrides:
|
|||||||
appflowy_editor:
|
appflowy_editor:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||||
ref: "c064543"
|
ref: "4536488faf458ab45e304c1715850d4d1ae517ee"
|
||||||
|
|
||||||
appflowy_editor_plugins:
|
appflowy_editor_plugins:
|
||||||
git:
|
git:
|
||||||
|
Loading…
Reference in New Issue
Block a user