mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: word and char count (#4705)
* feat: word and char count * chore: lints after merge * feat: add create time of view in more action * fix: missing comma lint * feat: add duplicate/delete + database view more * fix: dispose logic * feat: code cleanup * fix: add false for isDocument in databases * feat: register view info bloc on plugin basis * fix: accidental removal * chore: clean up * fix: add ViewInfoBloc above Row Document Editor * chore: final clean up
This commit is contained in:
parent
93af6e69a1
commit
609557c357
@ -1,10 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/font_size_slider.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/more_view_actions/widgets/font_size_stepper.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../setting.dart';
|
||||
|
@ -1,12 +1,13 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
@ -1,16 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/plugins/database/application/database_controller.dart';
|
||||
import 'package:appflowy/plugins/database/application/tab_bar_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/share_button.dart';
|
||||
import 'package:appflowy/plugins/util.dart';
|
||||
import 'package:appflowy/startup/plugin/plugin.dart';
|
||||
import 'package:appflowy/workspace/application/view_info/view_info_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/more_view_actions/more_view_actions.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/tab_bar_item.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/view_title_bar.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'desktop/tab_bar_header.dart';
|
||||
@ -183,7 +187,9 @@ class DatabaseTabBarViewPlugin extends Plugin {
|
||||
|
||||
@override
|
||||
final ViewPluginNotifier notifier;
|
||||
|
||||
final PluginType _pluginType;
|
||||
late final ViewInfoBloc _viewInfoBloc;
|
||||
|
||||
/// Used to open a Row on plugin load
|
||||
///
|
||||
@ -191,6 +197,7 @@ class DatabaseTabBarViewPlugin extends Plugin {
|
||||
|
||||
@override
|
||||
PluginWidgetBuilder get widgetBuilder => DatabasePluginWidgetBuilder(
|
||||
bloc: _viewInfoBloc,
|
||||
notifier: notifier,
|
||||
initialRowId: initialRowId,
|
||||
);
|
||||
@ -200,11 +207,28 @@ class DatabaseTabBarViewPlugin extends Plugin {
|
||||
|
||||
@override
|
||||
PluginType get pluginType => _pluginType;
|
||||
|
||||
@override
|
||||
void init() {
|
||||
_viewInfoBloc = ViewInfoBloc(view: notifier.view)
|
||||
..add(const ViewInfoEvent.started());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_viewInfoBloc.close();
|
||||
notifier.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class DatabasePluginWidgetBuilder extends PluginWidgetBuilder {
|
||||
DatabasePluginWidgetBuilder({required this.notifier, this.initialRowId});
|
||||
DatabasePluginWidgetBuilder({
|
||||
required this.bloc,
|
||||
required this.notifier,
|
||||
this.initialRowId,
|
||||
});
|
||||
|
||||
final ViewInfoBloc bloc;
|
||||
final ViewPluginNotifier notifier;
|
||||
|
||||
/// Used to open a Row on plugin load
|
||||
@ -225,6 +249,7 @@ class DatabasePluginWidgetBuilder extends PluginWidgetBuilder {
|
||||
context?.onDeleted(notifier.view, deletedView.index);
|
||||
}
|
||||
});
|
||||
|
||||
return DatabaseTabBarView(
|
||||
key: ValueKey(notifier.view.id),
|
||||
view: notifier.view,
|
||||
@ -238,9 +263,16 @@ class DatabasePluginWidgetBuilder extends PluginWidgetBuilder {
|
||||
|
||||
@override
|
||||
Widget? get rightBarItem {
|
||||
return DatabaseShareButton(
|
||||
key: ValueKey(notifier.view.id),
|
||||
view: notifier.view,
|
||||
final view = notifier.view;
|
||||
return BlocProvider<ViewInfoBloc>.value(
|
||||
value: bloc,
|
||||
child: Row(
|
||||
children: [
|
||||
DatabaseShareButton(key: ValueKey(view.id), view: view),
|
||||
const HSpace(4),
|
||||
MoreViewActions(view: view, isDocument: false),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/startup/plugin/plugin.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_listener.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DatabaseViewWidget extends StatefulWidget {
|
||||
const DatabaseViewWidget({
|
||||
@ -28,11 +30,13 @@ class _DatabaseViewWidgetState extends State<DatabaseViewWidget> {
|
||||
/// The view will be updated by the [ViewListener].
|
||||
late ViewPB view;
|
||||
|
||||
late Plugin viewPlugin;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
view = widget.view;
|
||||
viewPlugin = view.plugin()..init();
|
||||
_listenOnViewUpdated();
|
||||
}
|
||||
|
||||
@ -40,6 +44,7 @@ class _DatabaseViewWidgetState extends State<DatabaseViewWidget> {
|
||||
void dispose() {
|
||||
_layoutTypeChangeNotifier.dispose();
|
||||
_listener.stop();
|
||||
viewPlugin.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@ -47,12 +52,9 @@ class _DatabaseViewWidgetState extends State<DatabaseViewWidget> {
|
||||
Widget build(BuildContext context) {
|
||||
return ValueListenableBuilder<ViewLayoutPB>(
|
||||
valueListenable: _layoutTypeChangeNotifier,
|
||||
builder: (_, __, ___) {
|
||||
return view
|
||||
.plugin()
|
||||
.widgetBuilder
|
||||
.buildWidget(shrinkWrap: widget.shrinkWrap);
|
||||
},
|
||||
builder: (_, __, ___) => viewPlugin.widgetBuilder.buildWidget(
|
||||
shrinkWrap: widget.shrinkWrap,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/grid/application/row/row_document_bloc.dart';
|
||||
import 'package:appflowy/plugins/document/application/doc_bloc.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_page.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
||||
import 'package:appflowy/workspace/application/view_info/view_info_bloc.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class RowDocument extends StatelessWidget {
|
||||
@ -107,22 +109,25 @@ class _RowEditorState extends State<RowEditor> {
|
||||
howToFix: LocaleKeys.errorDialog_howToFixFallback.tr(),
|
||||
);
|
||||
}
|
||||
|
||||
return IntrinsicHeight(
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(minHeight: 300),
|
||||
child: AppFlowyEditorPage(
|
||||
shrinkWrap: true,
|
||||
autoFocus: false,
|
||||
editorState: editorState,
|
||||
// scrollController: widget.scrollController,
|
||||
styleCustomizer: EditorStyleCustomizer(
|
||||
context: context,
|
||||
padding: const EdgeInsets.only(left: 16, right: 54),
|
||||
child: BlocProvider<ViewInfoBloc>(
|
||||
create: (context) => ViewInfoBloc(view: widget.viewPB),
|
||||
child: AppFlowyEditorPage(
|
||||
shrinkWrap: true,
|
||||
autoFocus: false,
|
||||
editorState: editorState,
|
||||
styleCustomizer: EditorStyleCustomizer(
|
||||
context: context,
|
||||
padding: const EdgeInsets.only(left: 16, right: 54),
|
||||
),
|
||||
showParagraphPlaceholder: (editorState, node) =>
|
||||
editorState.document.isEmpty,
|
||||
placeholderText: (node) =>
|
||||
LocaleKeys.cardDetails_notesPlaceholder.tr(),
|
||||
),
|
||||
showParagraphPlaceholder: (editorState, node) =>
|
||||
editorState.document.isEmpty,
|
||||
placeholderText: (node) =>
|
||||
LocaleKeys.cardDetails_notesPlaceholder.tr(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -1,10 +1,11 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/core/config/kv_keys.dart';
|
||||
import 'package:appflowy/util/color_to_hex_string.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class DocumentAppearance {
|
@ -1,22 +1,24 @@
|
||||
library document_plugin;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.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/document_page.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/favorite/favorite_button.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/more_button.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/share/share_button.dart';
|
||||
import 'package:appflowy/plugins/util.dart';
|
||||
import 'package:appflowy/startup/plugin/plugin.dart';
|
||||
import 'package:appflowy/workspace/application/view_info/view_info_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/more_view_actions/more_view_actions.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/tab_bar_item.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/view_title_bar.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.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:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class DocumentPluginBuilder extends PluginBuilder {
|
||||
@ -52,6 +54,7 @@ class DocumentPlugin extends Plugin<int> {
|
||||
}
|
||||
|
||||
late PluginType _pluginType;
|
||||
late final ViewInfoBloc _viewInfoBloc;
|
||||
|
||||
@override
|
||||
final ViewPluginNotifier notifier;
|
||||
@ -60,6 +63,7 @@ class DocumentPlugin extends Plugin<int> {
|
||||
|
||||
@override
|
||||
PluginWidgetBuilder get widgetBuilder => DocumentPluginWidgetBuilder(
|
||||
bloc: _viewInfoBloc,
|
||||
notifier: notifier,
|
||||
initialSelection: initialSelection,
|
||||
);
|
||||
@ -69,15 +73,29 @@ class DocumentPlugin extends Plugin<int> {
|
||||
|
||||
@override
|
||||
PluginId get id => notifier.view.id;
|
||||
|
||||
@override
|
||||
void init() {
|
||||
_viewInfoBloc = ViewInfoBloc(view: notifier.view)
|
||||
..add(const ViewInfoEvent.started());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_viewInfoBloc.close();
|
||||
notifier.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
|
||||
with NavigationItem {
|
||||
DocumentPluginWidgetBuilder({
|
||||
required this.bloc,
|
||||
required this.notifier,
|
||||
this.initialSelection,
|
||||
});
|
||||
|
||||
final ViewInfoBloc bloc;
|
||||
final ViewPluginNotifier notifier;
|
||||
ViewPB get view => notifier.view;
|
||||
int? deletedViewIndex;
|
||||
@ -95,12 +113,15 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
|
||||
}
|
||||
});
|
||||
|
||||
return BlocBuilder<DocumentAppearanceCubit, DocumentAppearance>(
|
||||
builder: (_, state) => DocumentPage(
|
||||
key: ValueKey(view.id),
|
||||
view: view,
|
||||
onDeleted: () => context?.onDeleted(view, deletedViewIndex),
|
||||
initialSelection: initialSelection,
|
||||
return BlocProvider<ViewInfoBloc>.value(
|
||||
value: bloc,
|
||||
child: BlocBuilder<DocumentAppearanceCubit, DocumentAppearance>(
|
||||
builder: (_, state) => DocumentPage(
|
||||
key: ValueKey(view.id),
|
||||
view: view,
|
||||
onDeleted: () => context?.onDeleted(view, deletedViewIndex),
|
||||
initialSelection: initialSelection,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -113,17 +134,20 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
|
||||
|
||||
@override
|
||||
Widget? get rightBarItem {
|
||||
return Row(
|
||||
children: [
|
||||
DocumentShareButton(key: ValueKey(view.id), view: view),
|
||||
const HSpace(4),
|
||||
DocumentFavoriteButton(
|
||||
key: ValueKey('favorite_button_${view.id}'),
|
||||
view: view,
|
||||
),
|
||||
const HSpace(4),
|
||||
const DocumentMoreButton(),
|
||||
],
|
||||
return BlocProvider<ViewInfoBloc>.value(
|
||||
value: bloc,
|
||||
child: Row(
|
||||
children: [
|
||||
DocumentShareButton(key: ValueKey(view.id), view: view),
|
||||
const HSpace(4),
|
||||
DocumentFavoriteButton(
|
||||
key: ValueKey('favorite_button_${view.id}'),
|
||||
view: view,
|
||||
),
|
||||
const HSpace(4),
|
||||
MoreViewActions(view: view),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:appflowy/plugins/document/application/doc_bloc.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_configuration.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/align_toolbar_item/custom_text_align_command.dart';
|
||||
@ -14,13 +17,12 @@ import 'package:appflowy/plugins/inline_actions/inline_actions_command.dart';
|
||||
import 'package:appflowy/plugins/inline_actions/inline_actions_service.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/settings/shortcuts/settings_shortcuts_service.dart';
|
||||
import 'package:appflowy/workspace/application/view_info/view_info_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
final List<CommandShortcutEvent> commandShortcutEvents = [
|
||||
@ -176,6 +178,8 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
|
||||
late final EditorScrollController editorScrollController;
|
||||
|
||||
late final ViewInfoBloc viewInfoBloc = context.read<ViewInfoBloc>();
|
||||
|
||||
Future<bool> showSlashMenu(editorState) async => customSlashCommand(
|
||||
slashMenuItems,
|
||||
shouldInsertSlash: false,
|
||||
@ -186,6 +190,12 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
viewInfoBloc.add(
|
||||
ViewInfoEvent.registerEditorState(
|
||||
editorState: widget.editorState,
|
||||
),
|
||||
);
|
||||
|
||||
_initEditorL10n();
|
||||
_initializeShortcuts();
|
||||
indentableBlockTypes.add(ToggleListBlockKeys.type);
|
||||
@ -224,6 +234,10 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (!viewInfoBloc.isClosed) {
|
||||
viewInfoBloc.add(const ViewInfoEvent.unregisterEditorState());
|
||||
}
|
||||
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
|
||||
if (widget.scrollController == null) {
|
||||
|
@ -5,8 +5,8 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||
import 'package:appflowy/plugins/base/drag_handler.dart';
|
||||
import 'package:appflowy/plugins/document/application/doc_bloc.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
||||
import 'package:appflowy/user/application/reminder/reminder_extension.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
|
@ -1,12 +1,13 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/util/google_font_family_extension.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -1,9 +1,12 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/inline_actions/inline_actions_menu.dart';
|
||||
import 'package:appflowy/util/google_font_family_extension.dart';
|
||||
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
||||
@ -11,8 +14,6 @@ import 'package:appflowy/workspace/application/settings/appearance/appearance_cu
|
||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
@ -1,85 +0,0 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/font_size_slider.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class DocumentMoreButton extends StatelessWidget {
|
||||
const DocumentMoreButton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppFlowyPopover(
|
||||
constraints: BoxConstraints.loose(const Size(200, 400)),
|
||||
offset: const Offset(0, 30),
|
||||
popupBuilder: (_) {
|
||||
final actions = [
|
||||
AppFlowyPopover(
|
||||
direction: PopoverDirection.leftWithCenterAligned,
|
||||
constraints: const BoxConstraints(maxHeight: 40, maxWidth: 240),
|
||||
offset: const Offset(-10, 0),
|
||||
popupBuilder: (context) {
|
||||
return BlocBuilder<DocumentAppearanceCubit, DocumentAppearance>(
|
||||
builder: (context, state) {
|
||||
return FontSizeStepper(
|
||||
minimumValue: 10,
|
||||
maximumValue: 24,
|
||||
value: state.fontSize,
|
||||
divisions: 8,
|
||||
onChanged: (newFontSize) {
|
||||
context
|
||||
.read<DocumentAppearanceCubit>()
|
||||
.syncFontSize(newFontSize);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: FlowyButton(
|
||||
text: FlowyText.regular(
|
||||
LocaleKeys.moreAction_fontSize.tr(),
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
),
|
||||
leftIcon: Icon(
|
||||
Icons.format_size_sharp,
|
||||
color: Theme.of(context).iconTheme.color,
|
||||
size: 18,
|
||||
),
|
||||
leftIconSize: const Size(18, 18),
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: actions.length,
|
||||
separatorBuilder: (_, __) => const VSpace(4),
|
||||
physics: StyledScrollPhysics(),
|
||||
itemBuilder: (_, index) => actions[index],
|
||||
);
|
||||
},
|
||||
child: FlowyTooltip(
|
||||
message: LocaleKeys.moreAction_moreOptions.tr(),
|
||||
child: FlowyHover(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(6),
|
||||
child: FlowySvg(
|
||||
FlowySvgs.details_s,
|
||||
size: const Size(18, 18),
|
||||
color: Theme.of(context).iconTheme.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
library flowy_plugin;
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/startup/plugin/plugin.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
export "./src/sandbox.dart";
|
||||
|
||||
@ -29,6 +30,8 @@ abstract class Plugin<T> {
|
||||
|
||||
PluginType get pluginType;
|
||||
|
||||
void init() {}
|
||||
|
||||
void dispose() {
|
||||
notifier?.dispose();
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
||||
import 'package:appflowy/user/application/user_settings_service.dart';
|
||||
@ -18,8 +21,6 @@ import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
|
@ -0,0 +1,87 @@
|
||||
import 'package:appflowy/util/int64_extension.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'view_info_bloc.freezed.dart';
|
||||
|
||||
class ViewInfoBloc extends Bloc<ViewInfoEvent, ViewInfoState> {
|
||||
ViewInfoBloc({required this.view}) : super(ViewInfoState.initial()) {
|
||||
on<ViewInfoEvent>((event, emit) {
|
||||
event.when(
|
||||
started: () {
|
||||
emit(state.copyWith(createdAt: view.createTime.toDateTime()));
|
||||
},
|
||||
unregisterEditorState: () {
|
||||
_clearWordCountService();
|
||||
emit(state.copyWith(documentCounters: null));
|
||||
},
|
||||
registerEditorState: (editorState) {
|
||||
_clearWordCountService();
|
||||
_wordCountService = WordCountService(editorState: editorState)
|
||||
..addListener(_onWordCountChanged)
|
||||
..register();
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
documentCounters: _wordCountService!.documentCounters,
|
||||
),
|
||||
);
|
||||
},
|
||||
wordCountChanged: () {
|
||||
emit(
|
||||
state.copyWith(
|
||||
documentCounters: _wordCountService?.documentCounters,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
final ViewPB view;
|
||||
|
||||
WordCountService? _wordCountService;
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
_clearWordCountService();
|
||||
await super.close();
|
||||
}
|
||||
|
||||
void _onWordCountChanged() => add(const ViewInfoEvent.wordCountChanged());
|
||||
|
||||
void _clearWordCountService() {
|
||||
_wordCountService
|
||||
?..removeListener(_onWordCountChanged)
|
||||
..dispose();
|
||||
_wordCountService = null;
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ViewInfoEvent with _$ViewInfoEvent {
|
||||
const factory ViewInfoEvent.started() = _Started;
|
||||
|
||||
const factory ViewInfoEvent.unregisterEditorState() = _UnregisterEditorState;
|
||||
|
||||
const factory ViewInfoEvent.registerEditorState({
|
||||
required EditorState editorState,
|
||||
}) = _RegisterEditorState;
|
||||
|
||||
const factory ViewInfoEvent.wordCountChanged() = _WordCountChanged;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ViewInfoState with _$ViewInfoState {
|
||||
const factory ViewInfoState({
|
||||
required Counters? documentCounters,
|
||||
required DateTime? createdAt,
|
||||
}) = _ViewInfoState;
|
||||
|
||||
factory ViewInfoState.initial() => const ViewInfoState(
|
||||
documentCounters: null,
|
||||
createdAt: null,
|
||||
);
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/core/frameless_window.dart';
|
||||
import 'package:appflowy/plugins/blank/blank.dart';
|
||||
import 'package:appflowy/startup/plugin/plugin.dart';
|
||||
@ -10,7 +12,6 @@ import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:time/time.dart';
|
||||
@ -175,6 +176,7 @@ class PageNotifier extends ChangeNotifier {
|
||||
/// No need compare the old plugin with the new plugin. Just set it.
|
||||
set plugin(Plugin newPlugin) {
|
||||
_plugin.dispose();
|
||||
newPlugin.init();
|
||||
|
||||
/// Set the plugin view as the latest view.
|
||||
FolderEventSetLatestView(ViewIdPB(value: newPlugin.id)).send();
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||
import 'package:appflowy/workspace/application/menu/menu_user_bloc.dart';
|
||||
|
@ -1,11 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'theme_setting_entry_template.dart';
|
||||
|
@ -1,12 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/document_color_setting_button.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/theme_setting_entry_template.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class DocumentCursorColorSetting extends StatelessWidget {
|
||||
|
@ -1,12 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/document_color_setting_button.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/theme_setting_entry_template.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class DocumentSelectionColorSetting extends StatelessWidget {
|
||||
|
@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/util/google_font_family_extension.dart';
|
||||
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
@ -8,7 +10,6 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
|
@ -0,0 +1,119 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/view_info/view_info_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/more_view_actions/widgets/common_view_action.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/more_view_actions/widgets/font_size_action.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/more_view_actions/widgets/view_meta_info.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/date_time.pbenum.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.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';
|
||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class MoreViewActions extends StatefulWidget {
|
||||
const MoreViewActions({
|
||||
super.key,
|
||||
required this.view,
|
||||
this.isDocument = true,
|
||||
});
|
||||
|
||||
/// The view to show the actions for.
|
||||
final ViewPB view;
|
||||
|
||||
/// If false the view is a Database, otherwise it is a Document.
|
||||
final bool isDocument;
|
||||
|
||||
@override
|
||||
State<MoreViewActions> createState() => _MoreViewActionsState();
|
||||
}
|
||||
|
||||
class _MoreViewActionsState extends State<MoreViewActions> {
|
||||
late final List<Widget> viewActions;
|
||||
late final UserDateFormatPB dateFormat;
|
||||
final popoverMutex = PopoverMutex();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
dateFormat = context.read<AppearanceSettingsCubit>().state.dateFormat;
|
||||
viewActions = ViewActionType.values
|
||||
.map(
|
||||
(type) => ViewAction(
|
||||
type: type,
|
||||
view: widget.view,
|
||||
mutex: popoverMutex,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
popoverMutex.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<ViewInfoBloc, ViewInfoState>(
|
||||
builder: (context, state) {
|
||||
return AppFlowyPopover(
|
||||
mutex: popoverMutex,
|
||||
constraints: BoxConstraints.loose(const Size(200, 400)),
|
||||
offset: const Offset(0, 30),
|
||||
popupBuilder: (_) {
|
||||
final actions = [
|
||||
if (widget.isDocument) ...[
|
||||
const FontSizeAction(),
|
||||
const Divider(height: 4),
|
||||
],
|
||||
...viewActions,
|
||||
if (state.documentCounters != null ||
|
||||
state.createdAt != null) ...[
|
||||
const Divider(height: 4),
|
||||
ViewMetaInfo(
|
||||
dateFormat: dateFormat,
|
||||
documentCounters: state.documentCounters,
|
||||
createdAt: state.createdAt,
|
||||
),
|
||||
],
|
||||
];
|
||||
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: actions.length,
|
||||
separatorBuilder: (_, __) => const VSpace(4),
|
||||
physics: StyledScrollPhysics(),
|
||||
itemBuilder: (_, index) => actions[index],
|
||||
);
|
||||
},
|
||||
child: FlowyTooltip(
|
||||
message: LocaleKeys.moreAction_moreOptions.tr(),
|
||||
child: FlowyHover(
|
||||
style: HoverStyle(
|
||||
foregroundColorOnHover: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
builder: (context, isHovering) => Padding(
|
||||
padding: const EdgeInsets.all(6),
|
||||
child: FlowySvg(
|
||||
FlowySvgs.details_s,
|
||||
size: const Size(18, 18),
|
||||
color: isHovering
|
||||
? Theme.of(context).colorScheme.onPrimary
|
||||
: Theme.of(context).iconTheme.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
|
||||
enum ViewActionType {
|
||||
delete,
|
||||
duplicate;
|
||||
|
||||
String get label => switch (this) {
|
||||
ViewActionType.delete => LocaleKeys.moreAction_deleteView.tr(),
|
||||
ViewActionType.duplicate => LocaleKeys.moreAction_duplicateView.tr(),
|
||||
};
|
||||
|
||||
FlowySvgData get icon => switch (this) {
|
||||
ViewActionType.delete => FlowySvgs.delete_s,
|
||||
ViewActionType.duplicate => FlowySvgs.m_duplicate_s,
|
||||
};
|
||||
|
||||
ViewEvent get actionEvent => switch (this) {
|
||||
ViewActionType.delete => const ViewEvent.delete(),
|
||||
ViewActionType.duplicate => const ViewEvent.duplicate(),
|
||||
};
|
||||
}
|
||||
|
||||
class ViewAction extends StatelessWidget {
|
||||
const ViewAction({
|
||||
super.key,
|
||||
required this.type,
|
||||
required this.view,
|
||||
this.mutex,
|
||||
});
|
||||
|
||||
final ViewActionType type;
|
||||
final ViewPB view;
|
||||
final PopoverMutex? mutex;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FlowyButton(
|
||||
onTap: () {
|
||||
getIt<ViewBloc>(param1: view).add(type.actionEvent);
|
||||
mutex?.close();
|
||||
},
|
||||
text: FlowyText.regular(
|
||||
type.label,
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
),
|
||||
leftIcon: FlowySvg(
|
||||
type.icon,
|
||||
color: Theme.of(context).iconTheme.color,
|
||||
size: const Size.square(18),
|
||||
),
|
||||
leftIconSize: const Size(18, 18),
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/more_view_actions/widgets/font_size_stepper.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class FontSizeAction extends StatelessWidget {
|
||||
const FontSizeAction({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppFlowyPopover(
|
||||
direction: PopoverDirection.leftWithCenterAligned,
|
||||
constraints: const BoxConstraints(maxHeight: 40, maxWidth: 240),
|
||||
offset: const Offset(-10, 0),
|
||||
popupBuilder: (context) {
|
||||
return BlocBuilder<DocumentAppearanceCubit, DocumentAppearance>(
|
||||
builder: (_, state) => FontSizeStepper(
|
||||
minimumValue: 10,
|
||||
maximumValue: 24,
|
||||
value: state.fontSize,
|
||||
divisions: 8,
|
||||
onChanged: (newFontSize) => context
|
||||
.read<DocumentAppearanceCubit>()
|
||||
.syncFontSize(newFontSize),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: FlowyButton(
|
||||
text: FlowyText.regular(
|
||||
LocaleKeys.moreAction_fontSize.tr(),
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
),
|
||||
leftIcon: Icon(
|
||||
Icons.format_size_sharp,
|
||||
color: Theme.of(context).iconTheme.color,
|
||||
size: 18,
|
||||
),
|
||||
leftIconSize: const Size(18, 18),
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FontSizeStepper extends StatefulWidget {
|
||||
const FontSizeStepper({
|
||||
@ -53,10 +54,7 @@ class _FontSizeStepperState extends State<FontSizeStepper> {
|
||||
max: widget.maximumValue,
|
||||
divisions: widget.divisions,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_value = value;
|
||||
});
|
||||
|
||||
setState(() => _value = value);
|
||||
widget.onChanged(value);
|
||||
},
|
||||
),
|
@ -0,0 +1,59 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/workspace/application/settings/date_time/date_format_ext.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/date_time.pbenum.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
|
||||
class ViewMetaInfo extends StatelessWidget {
|
||||
const ViewMetaInfo({
|
||||
super.key,
|
||||
required this.dateFormat,
|
||||
this.documentCounters,
|
||||
this.createdAt,
|
||||
});
|
||||
|
||||
final UserDateFormatPB dateFormat;
|
||||
final Counters? documentCounters;
|
||||
final DateTime? createdAt;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// If more info is added to this Widget, use a separated ListView
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (documentCounters != null) ...[
|
||||
FlowyText.regular(
|
||||
LocaleKeys.moreAction_wordCount.tr(
|
||||
args: [documentCounters!.wordCount.toString()],
|
||||
),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
const VSpace(2),
|
||||
FlowyText.regular(
|
||||
LocaleKeys.moreAction_charCount.tr(
|
||||
args: [documentCounters!.charCount.toString()],
|
||||
),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
],
|
||||
if (createdAt != null) ...[
|
||||
if (documentCounters != null) const VSpace(2),
|
||||
FlowyText.regular(
|
||||
LocaleKeys.moreAction_createdAt.tr(
|
||||
args: [dateFormat.formatDate(createdAt!, false)],
|
||||
),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import 'package:appflowy/core/config/kv_keys.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:appflowy/core/config/kv_keys.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
@ -1,9 +1,10 @@
|
||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/plugins/document/application/document_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/widgets/settings_appearance/font_family_setting.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
@ -78,7 +78,12 @@
|
||||
"large": "large",
|
||||
"fontSize": "Font size",
|
||||
"import": "Import",
|
||||
"moreOptions": "More options"
|
||||
"moreOptions": "More options",
|
||||
"wordCount": "Word count: {}",
|
||||
"charCount": "Character count: {}",
|
||||
"createdAt": "Created at: {}",
|
||||
"deleteView": "Delete",
|
||||
"duplicateView": "Duplicate"
|
||||
},
|
||||
"importPanel": {
|
||||
"textAndMarkdown": "Text & Markdown",
|
||||
@ -1285,4 +1290,4 @@
|
||||
"userIcon": "User icon"
|
||||
},
|
||||
"noLogFiles": "There're no log files"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user