mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: legacy bugs on mobile (#4927)
This commit is contained in:
parent
fdc105a3e8
commit
7375349626
@ -77,7 +77,7 @@ class AppBarDoneButton extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppBarButton(
|
return AppBarButton(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
padding: const EdgeInsets.fromLTRB(12, 12, 8, 12),
|
padding: const EdgeInsets.all(12),
|
||||||
child: FlowyText(
|
child: FlowyText(
|
||||||
LocaleKeys.button_done.tr(),
|
LocaleKeys.button_done.tr(),
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
@ -93,7 +93,7 @@ class AppBarSaveButton extends StatelessWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
this.enable = true,
|
this.enable = true,
|
||||||
this.padding = const EdgeInsets.fromLTRB(12, 12, 8, 12),
|
this.padding = const EdgeInsets.all(12),
|
||||||
});
|
});
|
||||||
|
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
@ -165,7 +165,7 @@ class AppBarMoreButton extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppBarButton(
|
return AppBarButton(
|
||||||
padding: const EdgeInsets.fromLTRB(12, 12, 8, 12),
|
padding: const EdgeInsets.all(12),
|
||||||
onTap: () => onTap(context),
|
onTap: () => onTap(context),
|
||||||
child: const FlowySvg(FlowySvgs.three_dots_s),
|
child: const FlowySvg(FlowySvgs.three_dots_s),
|
||||||
);
|
);
|
||||||
|
@ -4,7 +4,7 @@ import 'package:appflowy/mobile/presentation/base/app_bar_actions.dart';
|
|||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
import 'package:appflowy/mobile/presentation/widgets/flowy_mobile_state_container.dart';
|
import 'package:appflowy/mobile/presentation/widgets/flowy_mobile_state_container.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||||
import 'package:appflowy/plugins/document/document_page.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_notification.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
||||||
@ -144,6 +144,8 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
Widget _buildAppBarMoreButton(ViewPB view) {
|
Widget _buildAppBarMoreButton(ViewPB view) {
|
||||||
return AppBarMoreButton(
|
return AppBarMoreButton(
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
|
EditorNotification.exitEditing().post();
|
||||||
|
|
||||||
showMobileBottomSheet(
|
showMobileBottomSheet(
|
||||||
context,
|
context,
|
||||||
showDragHandle: true,
|
showDragHandle: true,
|
||||||
@ -183,14 +185,12 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
context.read<FavoriteBloc>().add(FavoriteEvent.toggle(view));
|
context.read<FavoriteBloc>().add(FavoriteEvent.toggle(view));
|
||||||
break;
|
break;
|
||||||
case MobileViewBottomSheetBodyAction.undo:
|
case MobileViewBottomSheetBodyAction.undo:
|
||||||
context.dispatchNotification(
|
EditorNotification.undo().post();
|
||||||
const EditorNotification(type: EditorNotificationType.redo),
|
|
||||||
);
|
|
||||||
context.pop();
|
context.pop();
|
||||||
break;
|
break;
|
||||||
case MobileViewBottomSheetBodyAction.redo:
|
case MobileViewBottomSheetBodyAction.redo:
|
||||||
|
EditorNotification.redo().post();
|
||||||
context.pop();
|
context.pop();
|
||||||
context.dispatchNotification(EditorNotification.redo());
|
|
||||||
break;
|
break;
|
||||||
case MobileViewBottomSheetBodyAction.helpCenter:
|
case MobileViewBottomSheetBodyAction.helpCenter:
|
||||||
// unimplemented
|
// unimplemented
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class BottomSheetCloseButton extends StatelessWidget {
|
||||||
|
const BottomSheetCloseButton({
|
||||||
|
super.key,
|
||||||
|
this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onTap ?? () => Navigator.pop(context),
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
child: FlowySvg(
|
||||||
|
FlowySvgs.m_bottom_sheet_close_m,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BottomSheetDoneButton extends StatelessWidget {
|
||||||
|
const BottomSheetDoneButton({
|
||||||
|
super.key,
|
||||||
|
this.onDone,
|
||||||
|
});
|
||||||
|
|
||||||
|
final VoidCallback? onDone;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onDone ?? () => Navigator.pop(context),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12.0),
|
||||||
|
child: FlowyText(
|
||||||
|
LocaleKeys.button_done.tr(),
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BottomSheetBackButton extends StatelessWidget {
|
||||||
|
const BottomSheetBackButton({
|
||||||
|
super.key,
|
||||||
|
this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onTap ?? () => Navigator.pop(context),
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
child: FlowySvg(
|
||||||
|
FlowySvgs.m_app_bar_back_s,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,4 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_buttons.dart';
|
||||||
import 'package:appflowy/mobile/presentation/base/app_bar_actions.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';
|
||||||
|
|
||||||
@ -26,7 +24,7 @@ class BottomSheetHeader extends StatelessWidget {
|
|||||||
left: 0,
|
left: 0,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: AppBarCloseButton(
|
child: BottomSheetCloseButton(
|
||||||
onTap: onClose,
|
onTap: onClose,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -41,19 +39,8 @@ class BottomSheetHeader extends StatelessWidget {
|
|||||||
if (onDone != null)
|
if (onDone != null)
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: FlowyButton(
|
child: BottomSheetDoneButton(
|
||||||
useIntrinsicWidth: true,
|
onDone: onDone,
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
|
||||||
color: Color(0xFF00BCF0),
|
|
||||||
),
|
|
||||||
text: FlowyText.medium(
|
|
||||||
LocaleKeys.button_done.tr(),
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 16.0,
|
|
||||||
),
|
|
||||||
onTap: onDone,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:appflowy/mobile/presentation/base/app_bar_actions.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_buttons.dart';
|
||||||
import 'package:appflowy/plugins/base/drag_handler.dart';
|
import 'package:appflowy/plugins/base/drag_handler.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart' hide WidgetBuilder;
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart' hide WidgetBuilder;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -195,12 +195,12 @@ class BottomSheetHeader extends StatelessWidget {
|
|||||||
if (showBackButton)
|
if (showBackButton)
|
||||||
const Align(
|
const Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: AppBarBackButton(),
|
child: BottomSheetBackButton(),
|
||||||
),
|
),
|
||||||
if (showCloseButton)
|
if (showCloseButton)
|
||||||
const Align(
|
const Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: AppBarCloseButton(),
|
child: BottomSheetCloseButton(),
|
||||||
),
|
),
|
||||||
Align(
|
Align(
|
||||||
child: FlowyText(
|
child: FlowyText(
|
||||||
@ -212,8 +212,8 @@ class BottomSheetHeader extends StatelessWidget {
|
|||||||
if (showDoneButton)
|
if (showDoneButton)
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: AppBarDoneButton(
|
child: BottomSheetDoneButton(
|
||||||
onTap: () => Navigator.pop(context),
|
onDone: () => Navigator.pop(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -43,6 +43,7 @@ class MobileSettingItem extends StatelessWidget {
|
|||||||
trailing: trailing,
|
trailing: trailing,
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
|
contentPadding: const EdgeInsets.only(left: 8.0),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
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/document/application/doc_bloc.dart';
|
import 'package:appflowy/plugins/document/application/doc_bloc.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/banner.dart';
|
import 'package:appflowy/plugins/document/presentation/banner.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_notification.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_page.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_page.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
||||||
@ -15,24 +14,9 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
|||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
enum EditorNotificationType {
|
|
||||||
undo,
|
|
||||||
redo,
|
|
||||||
}
|
|
||||||
|
|
||||||
class EditorNotification extends Notification {
|
|
||||||
const EditorNotification({
|
|
||||||
required this.type,
|
|
||||||
});
|
|
||||||
|
|
||||||
EditorNotification.undo() : type = EditorNotificationType.undo;
|
|
||||||
EditorNotification.redo() : type = EditorNotificationType.redo;
|
|
||||||
|
|
||||||
final EditorNotificationType type;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DocumentPage extends StatefulWidget {
|
class DocumentPage extends StatefulWidget {
|
||||||
const DocumentPage({
|
const DocumentPage({
|
||||||
super.key,
|
super.key,
|
||||||
@ -50,12 +34,23 @@ class DocumentPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DocumentPageState extends State<DocumentPage> {
|
class _DocumentPageState extends State<DocumentPage> {
|
||||||
|
EditorState? editorState;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
// The appflowy editor use Intl as localization, set the default language as fallback.
|
// The appflowy editor use Intl as localization, set the default language as fallback.
|
||||||
Intl.defaultLocale = 'en_US';
|
Intl.defaultLocale = 'en_US';
|
||||||
|
|
||||||
|
EditorNotification.addListener(_onEditorNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
EditorNotification.removeListener(_onEditorNotification);
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -75,6 +70,7 @@ class _DocumentPageState extends State<DocumentPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final editorState = state.editorState;
|
final editorState = state.editorState;
|
||||||
|
this.editorState = editorState;
|
||||||
final error = state.error;
|
final error = state.error;
|
||||||
if (error != null || editorState == null) {
|
if (error != null || editorState == null) {
|
||||||
Log.error(error);
|
Log.error(error);
|
||||||
@ -149,20 +145,19 @@ class _DocumentPageState extends State<DocumentPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Future<void> _exportPage(DocumentDataPB data) async {
|
void _onEditorNotification(EditorNotificationType type) {
|
||||||
// final picker = getIt<FilePickerService>();
|
final editorState = this.editorState;
|
||||||
// final dir = await picker.getDirectoryPath();
|
if (editorState == null) {
|
||||||
// if (dir == null) {
|
return;
|
||||||
// return;
|
}
|
||||||
// }
|
if (type == EditorNotificationType.undo) {
|
||||||
// final path = p.join(dir, '${documentBloc.view.name}.json');
|
undoCommand.execute(editorState);
|
||||||
// const encoder = JsonEncoder.withIndent(' ');
|
} else if (type == EditorNotificationType.redo) {
|
||||||
// final json = encoder.convert(data.toProto3Json());
|
redoCommand.execute(editorState);
|
||||||
// await File(path).writeAsString(json.base64.base64);
|
} else if (type == EditorNotificationType.exitEditing) {
|
||||||
// if (mounted) {
|
editorState.selection = null;
|
||||||
// showSnackBarMessage(context, 'Export success to $path');
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
void _onNotificationAction(
|
void _onNotificationAction(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
enum EditorNotificationType {
|
||||||
|
none,
|
||||||
|
undo,
|
||||||
|
redo,
|
||||||
|
exitEditing,
|
||||||
|
}
|
||||||
|
|
||||||
|
class EditorNotification {
|
||||||
|
const EditorNotification({
|
||||||
|
required this.type,
|
||||||
|
});
|
||||||
|
|
||||||
|
EditorNotification.undo() : type = EditorNotificationType.undo;
|
||||||
|
EditorNotification.redo() : type = EditorNotificationType.redo;
|
||||||
|
EditorNotification.exitEditing() : type = EditorNotificationType.exitEditing;
|
||||||
|
|
||||||
|
static final PropertyValueNotifier<EditorNotificationType> _notifier =
|
||||||
|
PropertyValueNotifier(
|
||||||
|
EditorNotificationType.none,
|
||||||
|
);
|
||||||
|
|
||||||
|
final EditorNotificationType type;
|
||||||
|
|
||||||
|
void post() {
|
||||||
|
_notifier.value = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addListener(ValueChanged<EditorNotificationType> listener) {
|
||||||
|
_notifier.addListener(() {
|
||||||
|
listener(_notifier.value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void removeListener(ValueChanged<EditorNotificationType> listener) {
|
||||||
|
_notifier.removeListener(() {
|
||||||
|
listener(_notifier.value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dispose() {
|
||||||
|
_notifier.dispose();
|
||||||
|
}
|
||||||
|
}
|
@ -197,7 +197,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
|
|
||||||
_initEditorL10n();
|
_initEditorL10n();
|
||||||
_initializeShortcuts();
|
_initializeShortcuts();
|
||||||
appFlowyEditorAutoScrollEdgeOffset = 250;
|
appFlowyEditorAutoScrollEdgeOffset = 220;
|
||||||
indentableBlockTypes.add(ToggleListBlockKeys.type);
|
indentableBlockTypes.add(ToggleListBlockKeys.type);
|
||||||
convertibleBlockTypes.add(ToggleListBlockKeys.type);
|
convertibleBlockTypes.add(ToggleListBlockKeys.type);
|
||||||
slashMenuItems = _customSlashMenuItems();
|
slashMenuItems = _customSlashMenuItems();
|
||||||
@ -317,19 +317,12 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
editorScrollController: editorScrollController,
|
editorScrollController: editorScrollController,
|
||||||
toolbarBuilder: (context, anchor, closeToolbar) {
|
toolbarBuilder: (context, anchor, closeToolbar) {
|
||||||
return AdaptiveTextSelectionToolbar.editable(
|
return AdaptiveTextSelectionToolbar.buttonItems(
|
||||||
clipboardStatus: ClipboardStatus.pasteable,
|
buttonItems: buildMobileFloatingToolbarItems(
|
||||||
onCopy: () {
|
editorState,
|
||||||
customCopyCommand.execute(editorState);
|
anchor,
|
||||||
closeToolbar();
|
closeToolbar,
|
||||||
},
|
),
|
||||||
onCut: () => customCutCommand.execute(editorState),
|
|
||||||
onPaste: () => customPasteCommand.execute(editorState),
|
|
||||||
onSelectAll: () => selectAllCommand.execute(editorState),
|
|
||||||
onLiveTextInput: null,
|
|
||||||
onLookUp: null,
|
|
||||||
onSearchWeb: null,
|
|
||||||
onShare: null,
|
|
||||||
anchors: TextSelectionToolbarAnchors(
|
anchors: TextSelectionToolbarAnchors(
|
||||||
primaryAnchor: anchor,
|
primaryAnchor: anchor,
|
||||||
),
|
),
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
List<ContextMenuButtonItem> buildMobileFloatingToolbarItems(
|
||||||
|
EditorState editorState,
|
||||||
|
Offset offset,
|
||||||
|
Function closeToolbar,
|
||||||
|
) {
|
||||||
|
// copy, paste, select, select all, cut
|
||||||
|
final selection = editorState.selection;
|
||||||
|
if (selection == null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
final toolbarItems = <ContextMenuButtonItem>[];
|
||||||
|
|
||||||
|
if (!selection.isCollapsed) {
|
||||||
|
toolbarItems.add(
|
||||||
|
ContextMenuButtonItem(
|
||||||
|
label: LocaleKeys.editor_copy.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
copyCommand.execute(editorState);
|
||||||
|
closeToolbar();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbarItems.add(
|
||||||
|
ContextMenuButtonItem(
|
||||||
|
label: LocaleKeys.editor_paste.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
pasteCommand.execute(editorState);
|
||||||
|
closeToolbar();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!selection.isCollapsed) {
|
||||||
|
toolbarItems.add(
|
||||||
|
ContextMenuButtonItem(
|
||||||
|
label: LocaleKeys.editor_cut.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
cutCommand.execute(editorState);
|
||||||
|
closeToolbar();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbarItems.add(
|
||||||
|
ContextMenuButtonItem(
|
||||||
|
label: LocaleKeys.editor_select.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
editorState.selectWord(offset);
|
||||||
|
closeToolbar();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
toolbarItems.add(
|
||||||
|
ContextMenuButtonItem(
|
||||||
|
label: LocaleKeys.editor_selectAll.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
selectAllCommand.execute(editorState);
|
||||||
|
closeToolbar();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return toolbarItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension on EditorState {
|
||||||
|
void selectWord(Offset offset) {
|
||||||
|
final node = service.selectionService.getNodeInOffset(offset);
|
||||||
|
final selection = node?.selectable?.getWordBoundaryInOffset(offset);
|
||||||
|
if (selection == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateSelectionWithReason(selection);
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,8 @@ import 'package:flowy_infra/size.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';
|
||||||
|
|
||||||
|
const _count = 6;
|
||||||
|
|
||||||
Future<void> showTextColorAndBackgroundColorPicker(
|
Future<void> showTextColorAndBackgroundColorPicker(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
required EditorState editorState,
|
required EditorState editorState,
|
||||||
@ -26,7 +28,7 @@ Future<void> showTextColorAndBackgroundColorPicker(
|
|||||||
backgroundColor: theme.toolbarMenuBackgroundColor,
|
backgroundColor: theme.toolbarMenuBackgroundColor,
|
||||||
elevation: 20,
|
elevation: 20,
|
||||||
title: LocaleKeys.grid_selectOption_colorPanelTitle.tr(),
|
title: LocaleKeys.grid_selectOption_colorPanelTitle.tr(),
|
||||||
padding: const EdgeInsets.fromLTRB(18, 4, 18, 8),
|
padding: const EdgeInsets.fromLTRB(10, 4, 10, 8),
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return _TextColorAndBackgroundColor(
|
return _TextColorAndBackgroundColor(
|
||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
@ -79,6 +81,7 @@ class _TextColorAndBackgroundColorState
|
|||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const VSpace(6.0),
|
||||||
_TextColors(
|
_TextColors(
|
||||||
selectedColor: selectedTextColor?.tryToColor(),
|
selectedColor: selectedTextColor?.tryToColor(),
|
||||||
onSelectedColor: (textColor) async {
|
onSelectedColor: (textColor) async {
|
||||||
@ -115,6 +118,7 @@ class _TextColorAndBackgroundColorState
|
|||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const VSpace(6.0),
|
||||||
_BackgroundColors(
|
_BackgroundColors(
|
||||||
selectedColor: selectedBackgroundColor?.tryToColor(),
|
selectedColor: selectedBackgroundColor?.tryToColor(),
|
||||||
onSelectedColor: (backgroundColor) async {
|
onSelectedColor: (backgroundColor) async {
|
||||||
@ -202,7 +206,7 @@ class _BackgroundColors extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GridView.count(
|
return GridView.count(
|
||||||
crossAxisCount: 6,
|
crossAxisCount: _count,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
children: colors.mapIndexed(
|
children: colors.mapIndexed(
|
||||||
@ -236,9 +240,7 @@ class _BackgroundColorItem extends StatelessWidget {
|
|||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.all(
|
margin: const EdgeInsets.all(6.0),
|
||||||
6.0,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color,
|
color: color,
|
||||||
borderRadius: Corners.s12Border,
|
borderRadius: Corners.s12Border,
|
||||||
@ -283,7 +285,7 @@ class _TextColors extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GridView.count(
|
return GridView.count(
|
||||||
crossAxisCount: 6,
|
crossAxisCount: _count,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
@ -317,9 +319,7 @@ class _TextColorItem extends StatelessWidget {
|
|||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.all(
|
margin: const EdgeInsets.all(6.0),
|
||||||
6.0,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: Corners.s12Border,
|
borderRadius: Corners.s12Border,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
|
@ -29,6 +29,7 @@ export 'link_preview/link_preview_cache.dart';
|
|||||||
export 'link_preview/link_preview_menu.dart';
|
export 'link_preview/link_preview_menu.dart';
|
||||||
export 'math_equation/math_equation_block_component.dart';
|
export 'math_equation/math_equation_block_component.dart';
|
||||||
export 'math_equation/mobile_math_equation_toolbar_item.dart';
|
export 'math_equation/mobile_math_equation_toolbar_item.dart';
|
||||||
|
export 'mobile_floating_toolbar/custom_mobile_floating_toolbar.dart';
|
||||||
export 'mobile_toolbar_v3/aa_toolbar_item.dart';
|
export 'mobile_toolbar_v3/aa_toolbar_item.dart';
|
||||||
export 'mobile_toolbar_v3/add_block_toolbar_item.dart';
|
export 'mobile_toolbar_v3/add_block_toolbar_item.dart';
|
||||||
export 'mobile_toolbar_v3/appflowy_mobile_toolbar.dart';
|
export 'mobile_toolbar_v3/appflowy_mobile_toolbar.dart';
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="关闭_close 1">
|
||||||
|
<path id="Union" d="M4.13807 3.19526C3.87772 2.93491 3.45561 2.93491 3.19526 3.19526C2.93491 3.45561 2.93491 3.87772 3.19526 4.13807L8.05719 9L3.19526 13.8619C2.93491 14.1223 2.93491 14.5444 3.19526 14.8047C3.45561 15.0651 3.87772 15.0651 4.13807 14.8047L9 9.94281L13.8619 14.8047C14.1223 15.0651 14.5444 15.0651 14.8047 14.8047C15.0651 14.5444 15.0651 14.1223 14.8047 13.8619L9.94281 9L14.8047 4.13807C15.0651 3.87772 15.0651 3.45561 14.8047 3.19526C14.5444 2.93491 14.1223 2.93491 13.8619 3.19526L9 8.05719L4.13807 3.19526Z" fill="#1F2329" stroke="#1F2329" stroke-width="0.24" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 790 B |
@ -0,0 +1,5 @@
|
|||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="关闭_close 1">
|
||||||
|
<path id="Union" d="M4.13807 3.19526C3.87772 2.93491 3.45561 2.93491 3.19526 3.19526C2.93491 3.45561 2.93491 3.87772 3.19526 4.13807L8.05719 9L3.19526 13.8619C2.93491 14.1223 2.93491 14.5444 3.19526 14.8047C3.45561 15.0651 3.87772 15.0651 4.13807 14.8047L9 9.94281L13.8619 14.8047C14.1223 15.0651 14.5444 15.0651 14.8047 14.8047C15.0651 14.5444 15.0651 14.1223 14.8047 13.8619L9.94281 9L14.8047 4.13807C15.0651 3.87772 15.0651 3.45561 14.8047 3.19526C14.5444 2.93491 14.1223 2.93491 13.8619 3.19526L9 8.05719L4.13807 3.19526Z" fill="#1F2329" stroke="#1F2329" stroke-width="0.24" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 790 B |
@ -1309,6 +1309,8 @@
|
|||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
"paste": "Paste",
|
"paste": "Paste",
|
||||||
"find": "Find",
|
"find": "Find",
|
||||||
|
"select": "Select",
|
||||||
|
"selectAll": "Select all",
|
||||||
"previousMatch": "Previous match",
|
"previousMatch": "Previous match",
|
||||||
"nextMatch": "Next match",
|
"nextMatch": "Next match",
|
||||||
"closeFind": "Close",
|
"closeFind": "Close",
|
||||||
|
Loading…
Reference in New Issue
Block a user