mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: add ... button in mobile toolbar (#3970)
* feat: add ... button in mobile toolbar * fix: the title state should be reset when canceling * fix: reset hover status after picking emoji * fix: some emojis missing on linux and android * fix: unable to press enter key to rename page
This commit is contained in:
parent
a7364e1f4a
commit
412f34c72a
@ -2,6 +2,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
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/widgets/flowy_mobile_state_container.dart';
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||
import 'package:appflowy/plugins/document/document_page.dart';
|
||||
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
@ -120,8 +121,8 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (icon != null)
|
||||
FlowyText(
|
||||
'$icon ',
|
||||
EmojiText(
|
||||
emoji: '$icon ',
|
||||
fontSize: 22.0,
|
||||
),
|
||||
Expanded(
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_data_pb_extension.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||
import 'package:appflowy/workspace/application/doc/doc_listener.dart';
|
||||
@ -108,8 +109,8 @@ class _MobileRecentViewState extends State<MobileRecentView> {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 4),
|
||||
child: icon.isNotEmpty
|
||||
? FlowyText(
|
||||
icon,
|
||||
? EmojiText(
|
||||
emoji: icon,
|
||||
fontSize: 30.0,
|
||||
)
|
||||
: SizedBox.square(
|
||||
|
@ -3,6 +3,7 @@ import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_add_new_page.dart';
|
||||
import 'package:appflowy/mobile/presentation/page_item/mobile_view_item_add_button.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||
@ -355,8 +356,8 @@ class _SingleMobileInnerViewItemState extends State<SingleMobileInnerViewItem> {
|
||||
|
||||
Widget _buildViewIconButton() {
|
||||
final icon = widget.view.icon.value.isNotEmpty
|
||||
? FlowyText(
|
||||
widget.view.icon.value,
|
||||
? EmojiText(
|
||||
emoji: widget.view.icon.value,
|
||||
fontSize: 24.0,
|
||||
)
|
||||
: SizedBox.square(
|
||||
|
@ -1,9 +1,12 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_picker_header.dart';
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_search_bar.dart';
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_skin_tone.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
// use a global value to store the selected emoji to prevent reloading every time.
|
||||
EmojiData? _cachedEmojiData;
|
||||
@ -24,6 +27,7 @@ class FlowyEmojiPicker extends StatefulWidget {
|
||||
|
||||
class _FlowyEmojiPickerState extends State<FlowyEmojiPicker> {
|
||||
EmojiData? emojiData;
|
||||
List<String>? fallbackFontFamily;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -42,6 +46,13 @@ class _FlowyEmojiPickerState extends State<FlowyEmojiPicker> {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (Platform.isAndroid || Platform.isLinux) {
|
||||
final notoColorEmoji = GoogleFonts.notoColorEmoji().fontFamily;
|
||||
if (notoColorEmoji != null) {
|
||||
fallbackFontFamily = [notoColorEmoji];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -77,6 +88,7 @@ class _FlowyEmojiPickerState extends State<FlowyEmojiPicker> {
|
||||
icon: FlowyText(
|
||||
emoji,
|
||||
fontSize: 28.0,
|
||||
fallbackFontFamily: fallbackFontFamily,
|
||||
),
|
||||
onPressed: () => callback(emojiId, emoji),
|
||||
);
|
||||
|
@ -0,0 +1,42 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
// used to prevent loading font from google fonts every time
|
||||
List<String>? _cachedFallbackFontFamily;
|
||||
|
||||
// Some emojis are not supported by the default font on Android or Linux, fallback to noto color emoji
|
||||
class EmojiText extends StatelessWidget {
|
||||
const EmojiText({
|
||||
super.key,
|
||||
required this.emoji,
|
||||
required this.fontSize,
|
||||
this.textAlign,
|
||||
});
|
||||
|
||||
final String emoji;
|
||||
final double fontSize;
|
||||
final TextAlign? textAlign;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_loadFallbackFontFamily();
|
||||
return FlowyText(
|
||||
emoji,
|
||||
fontSize: fontSize,
|
||||
textAlign: textAlign,
|
||||
fallbackFontFamily: _cachedFallbackFontFamily,
|
||||
);
|
||||
}
|
||||
|
||||
void _loadFallbackFontFamily() {
|
||||
if (Platform.isLinux || Platform.isAndroid) {
|
||||
final notoColorEmoji = GoogleFonts.notoColorEmoji().fontFamily;
|
||||
if (notoColorEmoji != null) {
|
||||
_cachedFallbackFontFamily = [notoColorEmoji];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_picker.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||
@ -119,6 +120,9 @@ class _FlowyIconPickerState extends State<FlowyIconPicker>
|
||||
}
|
||||
|
||||
int _getEmojiPerLine() {
|
||||
if (PlatformExtension.isDesktopOrWeb) {
|
||||
return 9;
|
||||
}
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
return width ~/ 46.0; // the size of the emoji
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ List<MobileToolbarItem> getMobileToolbarItems() {
|
||||
mobileOutdentToolbarItem,
|
||||
undoMobileToolbarItem,
|
||||
redoMobileToolbarItem,
|
||||
mobileBlockSettingsToolbarItem,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class EmojiIconWidget extends StatefulWidget {
|
||||
@ -32,8 +32,8 @@ class _EmojiIconWidgetState extends State<EmojiIconWidget> {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: FlowyText(
|
||||
widget.emoji,
|
||||
child: EmojiText(
|
||||
emoji: widget.emoji,
|
||||
fontSize: widget.emojiSize,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
|
@ -0,0 +1,106 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.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:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
enum MobileBlockActionType {
|
||||
delete,
|
||||
duplicate,
|
||||
insertAbove,
|
||||
insertBelow,
|
||||
color;
|
||||
|
||||
static List<MobileBlockActionType> get standard => [
|
||||
MobileBlockActionType.delete,
|
||||
MobileBlockActionType.duplicate,
|
||||
MobileBlockActionType.insertAbove,
|
||||
MobileBlockActionType.insertBelow,
|
||||
];
|
||||
|
||||
static MobileBlockActionType fromActionString(String actionString) {
|
||||
return MobileBlockActionType.values.firstWhere(
|
||||
(e) => e.actionString == actionString,
|
||||
orElse: () => throw Exception('Unknown action string: $actionString'),
|
||||
);
|
||||
}
|
||||
|
||||
String get actionString => toString();
|
||||
|
||||
FlowySvgData get icon {
|
||||
return switch (this) {
|
||||
MobileBlockActionType.delete => FlowySvgs.m_delete_m,
|
||||
MobileBlockActionType.duplicate => FlowySvgs.m_duplicate_m,
|
||||
MobileBlockActionType.insertAbove => FlowySvgs.arrow_up_s,
|
||||
MobileBlockActionType.insertBelow => FlowySvgs.arrow_down_s,
|
||||
MobileBlockActionType.color => FlowySvgs.m_color_m,
|
||||
};
|
||||
}
|
||||
|
||||
String get i18n {
|
||||
return switch (this) {
|
||||
MobileBlockActionType.delete => LocaleKeys.button_delete.tr(),
|
||||
MobileBlockActionType.duplicate => LocaleKeys.button_duplicate.tr(),
|
||||
MobileBlockActionType.insertAbove => LocaleKeys.button_insertAbove.tr(),
|
||||
MobileBlockActionType.insertBelow => LocaleKeys.button_insertBelow.tr(),
|
||||
MobileBlockActionType.color =>
|
||||
LocaleKeys.document_plugins_optionAction_color.tr(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class MobileBlockSettingsScreen extends StatelessWidget {
|
||||
static const routeName = '/block_settings';
|
||||
|
||||
// the action string comes from the enum MobileBlockActionType
|
||||
// example: MobileBlockActionType.delete.actionString, MobileBlockActionType.duplicate.actionString, etc.
|
||||
static const supportedActions = 'actions';
|
||||
|
||||
const MobileBlockSettingsScreen({
|
||||
super.key,
|
||||
required this.actions,
|
||||
});
|
||||
|
||||
final List<MobileBlockActionType> actions;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
titleSpacing: 0,
|
||||
title: FlowyText.semibold(
|
||||
LocaleKeys.titleBar_actions.tr(),
|
||||
fontSize: 14.0,
|
||||
),
|
||||
leading: AppBarBackButton(
|
||||
onTap: () => context.pop(),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: ListView.separated(
|
||||
itemCount: actions.length,
|
||||
itemBuilder: (context, index) {
|
||||
final action = actions[index];
|
||||
return FlowyButton(
|
||||
text: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 18.0,
|
||||
),
|
||||
child: FlowyText(action.i18n),
|
||||
),
|
||||
leftIcon: FlowySvg(action.icon),
|
||||
leftIconSize: const Size.square(24),
|
||||
onTap: () {},
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => const Divider(
|
||||
height: 1.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_block_action_widget.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
final mobileBlockSettingsToolbarItem = MobileToolbarItem.action(
|
||||
itemIconBuilder: (_, editorState, __) {
|
||||
return onlyShowInSingleSelectionAndTextType(editorState)
|
||||
? const FlowySvg(FlowySvgs.three_dots_s)
|
||||
: null;
|
||||
},
|
||||
actionHandler: (_, editorState) async {
|
||||
// show the settings page
|
||||
final selection = editorState.selection;
|
||||
if (selection == null || !selection.isCollapsed) {
|
||||
return;
|
||||
}
|
||||
final node = editorState.getNodeAtPath(selection.start.path);
|
||||
final context = node?.context;
|
||||
if (node == null || context == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final result = await showFlowyMobileBottomSheet<bool>(
|
||||
context,
|
||||
title: LocaleKeys.document_plugins_action.tr(),
|
||||
builder: (context) {
|
||||
return BlockActionBottomSheet(
|
||||
onAction: (action) async {
|
||||
context.pop(true);
|
||||
|
||||
final transaction = editorState.transaction;
|
||||
switch (action) {
|
||||
case BlockActionBottomSheetType.delete:
|
||||
transaction.deleteNode(node);
|
||||
break;
|
||||
case BlockActionBottomSheetType.duplicate:
|
||||
transaction.insertNode(
|
||||
node.path.next,
|
||||
node.copyWith(),
|
||||
);
|
||||
break;
|
||||
case BlockActionBottomSheetType.insertAbove:
|
||||
case BlockActionBottomSheetType.insertBelow:
|
||||
final path = action == BlockActionBottomSheetType.insertAbove
|
||||
? node.path
|
||||
: node.path.next;
|
||||
transaction
|
||||
..insertNode(
|
||||
path,
|
||||
paragraphNode(),
|
||||
)
|
||||
..afterSelection = Selection.collapsed(
|
||||
Position(
|
||||
path: path,
|
||||
),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
if (transaction.operations.isNotEmpty) {
|
||||
await editorState.apply(transaction);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (result != true) {
|
||||
// restore the selection
|
||||
editorState.selection = selection;
|
||||
}
|
||||
},
|
||||
);
|
@ -28,8 +28,9 @@ export 'math_equation/math_equation_block_component.dart';
|
||||
export 'math_equation/mobile_math_equation_toolbar_item.dart';
|
||||
export 'mobile_toolbar_item/mobile_add_block_toolbar_item.dart';
|
||||
export 'mobile_toolbar_item/mobile_align_toolbar_item.dart';
|
||||
export 'mobile_toolbar_item/mobile_block_settings_toolbar_item.dart';
|
||||
export 'mobile_toolbar_item/mobile_convert_block_toolbar_item.dart';
|
||||
export 'mobile_toolbar_item/mobile_indent_toolbar_items.dart';
|
||||
export 'mobile_toolbar_item/mobile_indent_toolbar_item.dart';
|
||||
export 'mobile_toolbar_item/mobile_text_decoration_item.dart';
|
||||
export 'openai/widgets/auto_completion_node_widget.dart';
|
||||
export 'openai/widgets/smart_edit_node_widget.dart';
|
||||
|
@ -13,6 +13,7 @@ import 'package:appflowy/plugins/base/emoji/emoji_picker_screen.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/code_block/code_language_screen.dart';
|
||||
import 'package:appflowy/plugins/database_view/grid/application/row/row_detail_bloc.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_picker_screen.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/mobile_block_settings_screen.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/startup/tasks/app_widget.dart';
|
||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||
@ -72,6 +73,7 @@ GoRouter generateRouter(Widget child) {
|
||||
_mobileCodeLanguagePickerPageRoute(),
|
||||
_mobileLanguagePickerPageRoute(),
|
||||
_mobileFontPickerPageRoute(),
|
||||
_mobileBlockSettingsPageRoute(),
|
||||
],
|
||||
|
||||
// Desktop and Mobile
|
||||
@ -225,6 +227,26 @@ GoRoute _mobileHomeTrashPageRoute() {
|
||||
);
|
||||
}
|
||||
|
||||
GoRoute _mobileBlockSettingsPageRoute() {
|
||||
return GoRoute(
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
path: MobileBlockSettingsScreen.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
final actionsString =
|
||||
state.uri.queryParameters[MobileBlockSettingsScreen.supportedActions];
|
||||
final actions = actionsString
|
||||
?.split(',')
|
||||
.map(MobileBlockActionType.fromActionString)
|
||||
.toList();
|
||||
return MaterialPage(
|
||||
child: MobileBlockSettingsScreen(
|
||||
actions: actions ?? MobileBlockActionType.standard,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
GoRoute _mobileEmojiPickerPageRoute() {
|
||||
return GoRoute(
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||
import 'package:appflowy/plugins/base/icon/icon_picker.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
||||
@ -301,7 +302,7 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
|
||||
style: HoverStyle(
|
||||
hoverColor: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
resetHoverOnRebuild: widget.showActions,
|
||||
resetHoverOnRebuild: widget.showActions || !isIconPickerOpened,
|
||||
buildWhenOnHover: () =>
|
||||
!widget.showActions && !_isDragging && !isIconPickerOpened,
|
||||
builder: (_, onHover) => _buildViewItem(onHover),
|
||||
@ -356,8 +357,8 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
|
||||
|
||||
Widget _buildViewIconButton() {
|
||||
final icon = widget.view.icon.value.isNotEmpty
|
||||
? FlowyText(
|
||||
widget.view.icon.value,
|
||||
? EmojiText(
|
||||
emoji: widget.view.icon.value,
|
||||
fontSize: 18.0,
|
||||
)
|
||||
: SizedBox.square(
|
||||
@ -419,6 +420,7 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
|
||||
|
||||
// + button
|
||||
Widget _buildViewAddButton(BuildContext context) {
|
||||
final viewBloc = context.read<ViewBloc>();
|
||||
return FlowyTooltip(
|
||||
message: LocaleKeys.menuAppHeader_addPageTooltip.tr(),
|
||||
child: ViewAddButton(
|
||||
@ -438,20 +440,20 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
|
||||
_convertLayoutToHintText(pluginBuilder.layoutType!),
|
||||
(viewName) {
|
||||
if (viewName.isNotEmpty) {
|
||||
context.read<ViewBloc>().add(
|
||||
ViewEvent.createView(
|
||||
viewName,
|
||||
pluginBuilder.layoutType!,
|
||||
openAfterCreated: openAfterCreated,
|
||||
),
|
||||
);
|
||||
viewBloc.add(
|
||||
ViewEvent.createView(
|
||||
viewName,
|
||||
pluginBuilder.layoutType!,
|
||||
openAfterCreated: openAfterCreated,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
context.read<ViewBloc>().add(
|
||||
const ViewEvent.setIsExpanded(true),
|
||||
);
|
||||
viewBloc.add(
|
||||
const ViewEvent.setIsExpanded(true),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/emoji_picker_button.dart';
|
||||
import 'package:appflowy/startup/tasks/app_window_size_manager.dart';
|
||||
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
||||
@ -95,12 +96,15 @@ class _ViewTitleBarState extends State<ViewTitleBar> {
|
||||
continue;
|
||||
}
|
||||
children.add(
|
||||
_ViewTitle(
|
||||
view: view,
|
||||
behavior: i == views.length - 1
|
||||
? _ViewTitleBehavior.editable // only the last one is editable
|
||||
: _ViewTitleBehavior.uneditable, // others are not editable
|
||||
onUpdated: () => setState(() => _reloadAncestors()),
|
||||
FlowyTooltip(
|
||||
message: view.name,
|
||||
child: _ViewTitle(
|
||||
view: view,
|
||||
behavior: i == views.length - 1
|
||||
? _ViewTitleBehavior.editable // only the last one is editable
|
||||
: _ViewTitleBehavior.uneditable, // others are not editable
|
||||
onUpdated: () => setState(() => _reloadAncestors()),
|
||||
),
|
||||
),
|
||||
);
|
||||
if (i != views.length - 1) {
|
||||
@ -190,26 +194,23 @@ class _ViewTitleState extends State<_ViewTitle> {
|
||||
);
|
||||
}
|
||||
|
||||
final child = FlowyTooltip(
|
||||
message: name,
|
||||
child: Row(
|
||||
children: [
|
||||
FlowyText.regular(
|
||||
icon,
|
||||
fontSize: 18.0,
|
||||
final child = Row(
|
||||
children: [
|
||||
EmojiText(
|
||||
emoji: icon,
|
||||
fontSize: 18.0,
|
||||
),
|
||||
const HSpace(2.0),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: widget.maxTitleWidth,
|
||||
),
|
||||
const HSpace(2.0),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: widget.maxTitleWidth,
|
||||
),
|
||||
child: FlowyText.regular(
|
||||
name,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
child: FlowyText.regular(
|
||||
name,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
if (widget.behavior == _ViewTitleBehavior.uneditable) {
|
||||
@ -232,6 +233,7 @@ class _ViewTitleState extends State<_ViewTitle> {
|
||||
offset: const Offset(0, 18),
|
||||
popupBuilder: (context) {
|
||||
// icon + textfield
|
||||
_resetTextEditingController();
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@ -261,8 +263,8 @@ class _ViewTitleState extends State<_ViewTitle> {
|
||||
viewId: widget.view.id,
|
||||
name: text,
|
||||
);
|
||||
popoverController.close();
|
||||
}
|
||||
popoverController.close();
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -11,6 +11,7 @@ class FlowyText extends StatelessWidget {
|
||||
final TextDecoration? decoration;
|
||||
final bool selectable;
|
||||
final String? fontFamily;
|
||||
final List<String>? fallbackFontFamily;
|
||||
|
||||
const FlowyText(
|
||||
this.text, {
|
||||
@ -23,6 +24,7 @@ class FlowyText extends StatelessWidget {
|
||||
this.decoration,
|
||||
this.selectable = false,
|
||||
this.fontFamily,
|
||||
this.fallbackFontFamily,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -36,6 +38,7 @@ class FlowyText extends StatelessWidget {
|
||||
this.decoration,
|
||||
this.selectable = false,
|
||||
this.fontFamily,
|
||||
this.fallbackFontFamily,
|
||||
Key? key,
|
||||
}) : fontWeight = FontWeight.w400,
|
||||
super(key: key);
|
||||
@ -50,6 +53,7 @@ class FlowyText extends StatelessWidget {
|
||||
this.decoration,
|
||||
this.selectable = false,
|
||||
this.fontFamily,
|
||||
this.fallbackFontFamily,
|
||||
Key? key,
|
||||
}) : fontWeight = FontWeight.w500,
|
||||
super(key: key);
|
||||
@ -64,10 +68,27 @@ class FlowyText extends StatelessWidget {
|
||||
this.decoration,
|
||||
this.selectable = false,
|
||||
this.fontFamily,
|
||||
this.fallbackFontFamily,
|
||||
Key? key,
|
||||
}) : fontWeight = FontWeight.w600,
|
||||
super(key: key);
|
||||
|
||||
// Some emojis are not supported on Linux and Android, fallback to noto color emoji
|
||||
const FlowyText.emoji(
|
||||
this.text, {
|
||||
this.fontSize,
|
||||
this.overflow,
|
||||
this.color,
|
||||
this.textAlign,
|
||||
this.maxLines = 1,
|
||||
this.decoration,
|
||||
this.selectable = false,
|
||||
Key? key,
|
||||
}) : fontWeight = FontWeight.w400,
|
||||
fontFamily = 'noto color emoji',
|
||||
fallbackFontFamily = null,
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (selectable) {
|
||||
@ -81,6 +102,7 @@ class FlowyText extends StatelessWidget {
|
||||
color: color,
|
||||
decoration: decoration,
|
||||
fontFamily: fontFamily,
|
||||
fontFamilyFallback: fallbackFontFamily,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@ -95,6 +117,7 @@ class FlowyText extends StatelessWidget {
|
||||
color: color,
|
||||
decoration: decoration,
|
||||
fontFamily: fontFamily,
|
||||
fontFamilyFallback: fallbackFontFamily,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1091,6 +1091,7 @@
|
||||
"titleBar": {
|
||||
"pageIcon": "Page icon",
|
||||
"language": "Language",
|
||||
"font": "Font"
|
||||
"font": "Font",
|
||||
"actions": "Actions"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user