mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: some UI issues were present in version 0.3.1. (#3401)
This commit is contained in:
parent
fe55452c79
commit
26a2bffcd1
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database_view/board/presentation/board_page.dart';
|
import 'package:appflowy/plugins/database_view/board/presentation/board_page.dart';
|
||||||
import 'package:appflowy/plugins/database_view/calendar/presentation/calendar_page.dart';
|
import 'package:appflowy/plugins/database_view/calendar/presentation/calendar_page.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/presentation/grid_page.dart';
|
import 'package:appflowy/plugins/database_view/grid/presentation/grid_page.dart';
|
||||||
@ -7,7 +8,7 @@ import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
|
|||||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_more_action_button.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/view/view_more_action_button.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:integration_test/integration_test.dart';
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
@ -22,14 +23,11 @@ void main() {
|
|||||||
await tester.tapGoButton();
|
await tester.tapGoButton();
|
||||||
|
|
||||||
// create a new page
|
// create a new page
|
||||||
const name = 'Hello AppFlowy';
|
|
||||||
await tester.tapNewPageButton();
|
await tester.tapNewPageButton();
|
||||||
await tester.enterText(find.byType(TextFormField), name);
|
|
||||||
await tester.tapOKButton();
|
|
||||||
|
|
||||||
// expect to see a new document
|
// expect to see a new document
|
||||||
tester.expectToSeePageName(
|
tester.expectToSeePageName(
|
||||||
name,
|
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||||
);
|
);
|
||||||
// and with one paragraph block
|
// and with one paragraph block
|
||||||
expect(find.byType(TextBlockComponentWidget), findsOneWidget);
|
expect(find.byType(TextBlockComponentWidget), findsOneWidget);
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:appflowy/startup/entry_point.dart';
|
import 'package:appflowy/startup/entry_point.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
|
import 'package:appflowy/user/presentation/presentation.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||||
import 'package:flowy_infra/uuid.dart';
|
import 'package:flowy_infra/uuid.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
@ -9,8 +11,8 @@ import 'package:flutter/gestures.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
class FlowyTestContext {
|
class FlowyTestContext {
|
||||||
FlowyTestContext({
|
FlowyTestContext({
|
||||||
@ -39,8 +41,8 @@ extension AppFlowyTestBase on WidgetTester {
|
|||||||
IntegrationMode.integrationTest,
|
IntegrationMode.integrationTest,
|
||||||
);
|
);
|
||||||
|
|
||||||
await wait(3000);
|
await waitUntilSignInPageShow();
|
||||||
await pumpAndSettle(const Duration(seconds: 2));
|
|
||||||
return FlowyTestContext(
|
return FlowyTestContext(
|
||||||
applicationDataDirectory: directory,
|
applicationDataDirectory: directory,
|
||||||
);
|
);
|
||||||
@ -78,6 +80,27 @@ extension AppFlowyTestBase on WidgetTester {
|
|||||||
return directory.path;
|
return directory.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> waitUntilSignInPageShow() async {
|
||||||
|
final finder = find.byType(GoButton);
|
||||||
|
await pumpUntilFound(finder);
|
||||||
|
expect(finder, findsOneWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> pumpUntilFound(
|
||||||
|
Finder finder, {
|
||||||
|
Duration timeout = const Duration(seconds: 10),
|
||||||
|
}) async {
|
||||||
|
bool timerDone = false;
|
||||||
|
final timer = Timer(timeout, () => timerDone = true);
|
||||||
|
while (timerDone != true) {
|
||||||
|
await pump();
|
||||||
|
if (any(finder)) {
|
||||||
|
timerDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> tapButton(
|
Future<void> tapButton(
|
||||||
Finder finder, {
|
Finder finder, {
|
||||||
int? pointer,
|
int? pointer,
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
|
import 'package:appflowy/core/config/kv.dart';
|
||||||
|
import 'package:appflowy/core/config/kv_keys.dart';
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/share/share_button.dart';
|
import 'package:appflowy/plugins/document/presentation/share/share_button.dart';
|
||||||
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/user/presentation/screens/screens.dart';
|
import 'package:appflowy/user/presentation/screens/screens.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_new_page_button.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_new_page_button.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/view/draggable_view_item.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/view/draggable_view_item.dart';
|
||||||
@ -279,7 +282,14 @@ extension CommonOperations on WidgetTester {
|
|||||||
// create a new page
|
// create a new page
|
||||||
await tapAddViewButton(name: parentName ?? gettingStarted);
|
await tapAddViewButton(name: parentName ?? gettingStarted);
|
||||||
await tapButtonWithName(layout.menuName);
|
await tapButtonWithName(layout.menuName);
|
||||||
|
final settingsOrFailure = await getIt<KeyValueStorage>().getWithFormat(
|
||||||
|
KVKeys.showRenameDialogWhenCreatingNewFile,
|
||||||
|
(value) => bool.parse(value),
|
||||||
|
);
|
||||||
|
final showRenameDialog = settingsOrFailure.fold((l) => false, (r) => r);
|
||||||
|
if (showRenameDialog) {
|
||||||
await tapOKButton();
|
await tapOKButton();
|
||||||
|
}
|
||||||
await pumpAndSettle();
|
await pumpAndSettle();
|
||||||
|
|
||||||
// hover on it and change it's name
|
// hover on it and change it's name
|
||||||
|
@ -7,6 +7,10 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||||||
abstract class KeyValueStorage {
|
abstract class KeyValueStorage {
|
||||||
Future<void> set(String key, String value);
|
Future<void> set(String key, String value);
|
||||||
Future<Either<FlowyError, String>> get(String key);
|
Future<Either<FlowyError, String>> get(String key);
|
||||||
|
Future<Either<FlowyError, T>> getWithFormat<T>(
|
||||||
|
String key,
|
||||||
|
T Function(String value) formatter,
|
||||||
|
);
|
||||||
Future<void> remove(String key);
|
Future<void> remove(String key);
|
||||||
Future<void> clear();
|
Future<void> clear();
|
||||||
}
|
}
|
||||||
@ -26,6 +30,18 @@ class DartKeyValue implements KeyValueStorage {
|
|||||||
return Left(FlowyError());
|
return Left(FlowyError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Either<FlowyError, T>> getWithFormat<T>(
|
||||||
|
String key,
|
||||||
|
T Function(String value) formatter,
|
||||||
|
) async {
|
||||||
|
final value = await get(key);
|
||||||
|
return value.fold(
|
||||||
|
(l) => left(l),
|
||||||
|
(r) => right(formatter(r)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> remove(String key) async {
|
Future<void> remove(String key) async {
|
||||||
await _initSharedPreferencesIfNeeded();
|
await _initSharedPreferencesIfNeeded();
|
||||||
@ -71,6 +87,18 @@ class RustKeyValue implements KeyValueStorage {
|
|||||||
return response.swap().map((r) => r.value);
|
return response.swap().map((r) => r.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Either<FlowyError, T>> getWithFormat<T>(
|
||||||
|
String key,
|
||||||
|
T Function(String value) formatter,
|
||||||
|
) async {
|
||||||
|
final value = await get(key);
|
||||||
|
return value.fold(
|
||||||
|
(l) => left(l),
|
||||||
|
(r) => right(formatter(r)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> remove(String key) async {
|
Future<void> remove(String key) async {
|
||||||
await ConfigEventRemoveKeyValue(
|
await ConfigEventRemoveKeyValue(
|
||||||
|
@ -43,4 +43,10 @@ class KVKeys {
|
|||||||
/// The value is a json string with the following format:
|
/// The value is a json string with the following format:
|
||||||
/// {'SidebarFolderCategoryType.value': true}
|
/// {'SidebarFolderCategoryType.value': true}
|
||||||
static const String expandedFolders = 'expandedFolders';
|
static const String expandedFolders = 'expandedFolders';
|
||||||
|
|
||||||
|
/// The key for saving if showing the rename dialog when creating a new file
|
||||||
|
///
|
||||||
|
/// The value is a boolean string.
|
||||||
|
static const String showRenameDialogWhenCreatingNewFile =
|
||||||
|
'showRenameDialogWhenCreatingNewFile';
|
||||||
}
|
}
|
||||||
|
@ -34,11 +34,13 @@ class TransactionAdapter {
|
|||||||
final DocumentService documentService;
|
final DocumentService documentService;
|
||||||
final String documentId;
|
final String documentId;
|
||||||
|
|
||||||
final bool _enableDebug = false;
|
final bool _enableDebug = true;
|
||||||
|
|
||||||
Future<void> apply(Transaction transaction, EditorState editorState) async {
|
Future<void> apply(Transaction transaction, EditorState editorState) async {
|
||||||
final stopwatch = Stopwatch()..start();
|
final stopwatch = Stopwatch()..start();
|
||||||
|
if (_enableDebug) {
|
||||||
Log.debug('transaction => ${transaction.toJson()}');
|
Log.debug('transaction => ${transaction.toJson()}');
|
||||||
|
}
|
||||||
final actions = transaction.operations
|
final actions = transaction.operations
|
||||||
.map((op) => op.toBlockAction(editorState, documentId))
|
.map((op) => op.toBlockAction(editorState, documentId))
|
||||||
.whereNotNull()
|
.whereNotNull()
|
||||||
@ -58,16 +60,20 @@ class TransactionAdapter {
|
|||||||
textId: payload.textId,
|
textId: payload.textId,
|
||||||
delta: payload.delta,
|
delta: payload.delta,
|
||||||
);
|
);
|
||||||
|
if (_enableDebug) {
|
||||||
Log.debug('create external text: ${payload.delta}');
|
Log.debug('create external text: ${payload.delta}');
|
||||||
|
}
|
||||||
} else if (type == TextDeltaType.update) {
|
} else if (type == TextDeltaType.update) {
|
||||||
await documentService.updateExternalText(
|
await documentService.updateExternalText(
|
||||||
documentId: payload.documentId,
|
documentId: payload.documentId,
|
||||||
textId: payload.textId,
|
textId: payload.textId,
|
||||||
delta: payload.delta,
|
delta: payload.delta,
|
||||||
);
|
);
|
||||||
|
if (_enableDebug) {
|
||||||
Log.debug('update external text: ${payload.delta}');
|
Log.debug('update external text: ${payload.delta}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
final blockActions =
|
final blockActions =
|
||||||
actions.map((e) => e.blockActionPB).toList(growable: false);
|
actions.map((e) => e.blockActionPB).toList(growable: false);
|
||||||
await documentService.applyAction(
|
await documentService.applyAction(
|
||||||
|
@ -40,12 +40,16 @@ class BlockOptionButton extends StatelessWidget {
|
|||||||
return PopoverActionList<PopoverAction>(
|
return PopoverActionList<PopoverAction>(
|
||||||
direction: PopoverDirection.leftWithCenterAligned,
|
direction: PopoverDirection.leftWithCenterAligned,
|
||||||
actions: popoverActions,
|
actions: popoverActions,
|
||||||
onPopupBuilder: () => blockComponentState.alwaysShowActions = true,
|
onPopupBuilder: () {
|
||||||
|
keepEditorFocusNotifier.value += 1;
|
||||||
|
blockComponentState.alwaysShowActions = true;
|
||||||
|
},
|
||||||
onClosed: () {
|
onClosed: () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
editorState.selectionType = null;
|
editorState.selectionType = null;
|
||||||
editorState.selection = null;
|
editorState.selection = null;
|
||||||
blockComponentState.alwaysShowActions = false;
|
blockComponentState.alwaysShowActions = false;
|
||||||
|
keepEditorFocusNotifier.value -= 1;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSelected: (action, controller) {
|
onSelected: (action, controller) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.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/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@ -31,12 +33,18 @@ final alignToolbarItem = ToolbarItem(
|
|||||||
data = FlowySvgs.toolbar_align_right_s;
|
data = FlowySvgs.toolbar_align_right_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
final child = FlowySvg(
|
final child = MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
child: FlowySvg(
|
||||||
data,
|
data,
|
||||||
size: const Size.square(16),
|
size: const Size.square(20),
|
||||||
color: isHighlight ? highlightColor : Colors.white,
|
color: isHighlight ? highlightColor : Colors.white,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return _AlignmentButtons(
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
|
child: _AlignmentButtons(
|
||||||
child: child,
|
child: child,
|
||||||
onAlignChanged: (align) async {
|
onAlignChanged: (align) async {
|
||||||
await editorState.updateNode(
|
await editorState.updateNode(
|
||||||
@ -49,6 +57,7 @@ final alignToolbarItem = ToolbarItem(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -71,11 +80,15 @@ class _AlignmentButtonsState extends State<_AlignmentButtons> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
windowPadding: const EdgeInsets.all(0),
|
windowPadding: const EdgeInsets.all(0),
|
||||||
margin: const EdgeInsets.all(0),
|
margin: const EdgeInsets.all(4),
|
||||||
direction: PopoverDirection.bottomWithCenterAligned,
|
direction: PopoverDirection.bottomWithCenterAligned,
|
||||||
offset: const Offset(0, 10),
|
offset: const Offset(0, 10),
|
||||||
child: widget.child,
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.onTertiary,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||||
|
),
|
||||||
popupBuilder: (_) => _AlignButtons(onAlignChanged: widget.onAlignChanged),
|
popupBuilder: (_) => _AlignButtons(onAlignChanged: widget.onAlignChanged),
|
||||||
|
child: widget.child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,16 +110,19 @@ class _AlignButtons extends StatelessWidget {
|
|||||||
const HSpace(4),
|
const HSpace(4),
|
||||||
_AlignButton(
|
_AlignButton(
|
||||||
icon: FlowySvgs.toolbar_align_left_s,
|
icon: FlowySvgs.toolbar_align_left_s,
|
||||||
|
tooltips: LocaleKeys.document_plugins_optionAction_left.tr(),
|
||||||
onTap: () => onAlignChanged('left'),
|
onTap: () => onAlignChanged('left'),
|
||||||
),
|
),
|
||||||
const _Divider(),
|
const _Divider(),
|
||||||
_AlignButton(
|
_AlignButton(
|
||||||
icon: FlowySvgs.toolbar_align_center_s,
|
icon: FlowySvgs.toolbar_align_center_s,
|
||||||
|
tooltips: LocaleKeys.document_plugins_optionAction_center.tr(),
|
||||||
onTap: () => onAlignChanged('center'),
|
onTap: () => onAlignChanged('center'),
|
||||||
),
|
),
|
||||||
const _Divider(),
|
const _Divider(),
|
||||||
_AlignButton(
|
_AlignButton(
|
||||||
icon: FlowySvgs.toolbar_align_right_s,
|
icon: FlowySvgs.toolbar_align_right_s,
|
||||||
|
tooltips: LocaleKeys.document_plugins_optionAction_right.tr(),
|
||||||
onTap: () => onAlignChanged('right'),
|
onTap: () => onAlignChanged('right'),
|
||||||
),
|
),
|
||||||
const HSpace(4),
|
const HSpace(4),
|
||||||
@ -119,19 +135,25 @@ class _AlignButtons extends StatelessWidget {
|
|||||||
class _AlignButton extends StatelessWidget {
|
class _AlignButton extends StatelessWidget {
|
||||||
const _AlignButton({
|
const _AlignButton({
|
||||||
required this.icon,
|
required this.icon,
|
||||||
|
required this.tooltips,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
});
|
});
|
||||||
|
|
||||||
final FlowySvgData icon;
|
final FlowySvgData icon;
|
||||||
|
final String tooltips;
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
|
child: Tooltip(
|
||||||
|
message: tooltips,
|
||||||
child: FlowySvg(
|
child: FlowySvg(
|
||||||
icon,
|
icon,
|
||||||
size: const Size.square(16),
|
size: const Size.square(16),
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ class OutlineItemWidget extends StatelessWidget {
|
|||||||
hoverColor: Theme.of(context).hoverColor,
|
hoverColor: Theme.of(context).hoverColor,
|
||||||
),
|
),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => updateBlockSelection(context),
|
onTap: () => scrollToBlock(context),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.only(left: node.leftIndent),
|
padding: EdgeInsets.only(left: node.leftIndent),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -180,14 +180,14 @@ class OutlineItemWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateBlockSelection(BuildContext context) async {
|
void scrollToBlock(BuildContext context) {
|
||||||
final editorState = context.read<EditorState>();
|
final editorState = context.read<EditorState>();
|
||||||
editorState.selectionType = SelectionType.block;
|
final editorScrollController = context.read<EditorScrollController>();
|
||||||
|
editorScrollController.itemScrollController.jumpTo(index: node.path.first);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
editorState.selection = Selection.collapsed(
|
editorState.selection = Selection.collapsed(
|
||||||
Position(path: node.path, offset: node.delta?.length ?? 0),
|
Position(path: node.path, offset: node.delta?.length ?? 0),
|
||||||
);
|
);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
|
||||||
editorState.selectionType = null;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,10 @@ class _ToggleListBlockComponentWidgetState
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildComponent(BuildContext context) {
|
Widget buildComponent(
|
||||||
|
BuildContext context, {
|
||||||
|
bool withBackgroundColor = false,
|
||||||
|
}) {
|
||||||
final textDirection = calculateTextDirection(
|
final textDirection = calculateTextDirection(
|
||||||
layoutDirection: Directionality.maybeOf(context),
|
layoutDirection: Directionality.maybeOf(context),
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
import 'package:appflowy/core/config/kv.dart';
|
||||||
|
import 'package:appflowy/core/config/kv_keys.dart';
|
||||||
|
import 'package:appflowy/startup/startup.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class CreateFileSettingsCubit extends Cubit<bool> {
|
||||||
|
CreateFileSettingsCubit(super.initialState) {
|
||||||
|
getInitialSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> toggle({bool? value}) async {
|
||||||
|
await getIt<KeyValueStorage>().set(
|
||||||
|
KVKeys.showRenameDialogWhenCreatingNewFile,
|
||||||
|
(value ?? !state).toString(),
|
||||||
|
);
|
||||||
|
emit(value ?? !state);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getInitialSettings() async {
|
||||||
|
final settingsOrFailure = await getIt<KeyValueStorage>().getWithFormat(
|
||||||
|
KVKeys.showRenameDialogWhenCreatingNewFile,
|
||||||
|
(value) => bool.parse(value),
|
||||||
|
);
|
||||||
|
settingsOrFailure.fold(
|
||||||
|
(_) => emit(false),
|
||||||
|
(settings) => emit(settings),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
export 'settings_dialog_bloc.dart';
|
|
||||||
export 'application_data_storage.dart';
|
export 'application_data_storage.dart';
|
||||||
|
export 'create_file_settings_cubit.dart';
|
||||||
|
export 'settings_dialog_bloc.dart';
|
||||||
|
@ -4,8 +4,8 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
|||||||
import 'package:appflowy/workspace/application/menu/menu_bloc.dart';
|
import 'package:appflowy/workspace/application/menu/menu_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/rename_view_dialog.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
@ -118,14 +118,14 @@ class _PersonalFolderHeaderState extends State<PersonalFolderHeader> {
|
|||||||
width: iconSize,
|
width: iconSize,
|
||||||
icon: const FlowySvg(FlowySvgs.add_s),
|
icon: const FlowySvg(FlowySvgs.add_s),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
NavigatorTextFieldDialog(
|
createViewAndShowRenameDialogIfNeeded(
|
||||||
title: LocaleKeys.newPageText.tr(),
|
context,
|
||||||
value: '',
|
LocaleKeys.newPageText.tr(),
|
||||||
confirm: (value) {
|
(viewName) {
|
||||||
if (value.isNotEmpty) {
|
if (viewName.isNotEmpty) {
|
||||||
context.read<MenuBloc>().add(
|
context.read<MenuBloc>().add(
|
||||||
MenuEvent.createApp(
|
MenuEvent.createApp(
|
||||||
value,
|
viewName,
|
||||||
index: 0,
|
index: 0,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -133,7 +133,7 @@ class _PersonalFolderHeaderState extends State<PersonalFolderHeader> {
|
|||||||
widget.onAdded();
|
widget.onAdded();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
).show(context);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:appflowy/core/config/kv.dart';
|
||||||
|
import 'package:appflowy/core/config/kv_keys.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/startup/startup.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Creates a new view and shows the rename dialog if needed.
|
||||||
|
///
|
||||||
|
/// If the user has enabled the setting to show the rename dialog when creating a new view,
|
||||||
|
/// this function will show the rename dialog.
|
||||||
|
///
|
||||||
|
/// Otherwise, it will just create the view with default name.
|
||||||
|
Future<void> createViewAndShowRenameDialogIfNeeded(
|
||||||
|
BuildContext context,
|
||||||
|
String dialogTitle,
|
||||||
|
void Function(String viewName) createView,
|
||||||
|
) async {
|
||||||
|
final value = await getIt<KeyValueStorage>().getWithFormat(
|
||||||
|
KVKeys.showRenameDialogWhenCreatingNewFile,
|
||||||
|
(value) => bool.parse(value),
|
||||||
|
);
|
||||||
|
final showRenameDialog = value.fold((l) => false, (r) => r);
|
||||||
|
if (context.mounted && showRenameDialog) {
|
||||||
|
NavigatorTextFieldDialog(
|
||||||
|
title: dialogTitle,
|
||||||
|
value: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||||
|
autoSelectAllText: true,
|
||||||
|
confirm: createView,
|
||||||
|
).show(context);
|
||||||
|
} else {
|
||||||
|
createView(LocaleKeys.menuAppHeader_defaultNewPageName.tr());
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/application/menu/menu_bloc.dart';
|
import 'package:appflowy/workspace/application/menu/menu_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/rename_view_dialog.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flowy_infra_ui/style_widget/extension.dart';
|
import 'package:flowy_infra_ui/style_widget/extension.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class SidebarNewPageButton extends StatelessWidget {
|
class SidebarNewPageButton extends StatelessWidget {
|
||||||
@ -20,7 +20,15 @@ class SidebarNewPageButton extends StatelessWidget {
|
|||||||
fillColor: Colors.transparent,
|
fillColor: Colors.transparent,
|
||||||
hoverColor: Colors.transparent,
|
hoverColor: Colors.transparent,
|
||||||
fontColor: Theme.of(context).colorScheme.tertiary,
|
fontColor: Theme.of(context).colorScheme.tertiary,
|
||||||
onPressed: () async => await _showCreatePageDialog(context),
|
onPressed: () async => await createViewAndShowRenameDialogIfNeeded(
|
||||||
|
context,
|
||||||
|
LocaleKeys.newPageText.tr(),
|
||||||
|
(viewName) {
|
||||||
|
if (viewName.isNotEmpty) {
|
||||||
|
context.read<MenuBloc>().add(MenuEvent.createApp(viewName));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
heading: Container(
|
heading: Container(
|
||||||
width: 16,
|
width: 16,
|
||||||
height: 16,
|
height: 16,
|
||||||
@ -44,16 +52,4 @@ class SidebarNewPageButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _showCreatePageDialog(BuildContext context) async {
|
|
||||||
return NavigatorTextFieldDialog(
|
|
||||||
title: LocaleKeys.newPageText.tr(),
|
|
||||||
value: '',
|
|
||||||
confirm: (value) {
|
|
||||||
if (value.isNotEmpty) {
|
|
||||||
context.read<MenuBloc>().add(MenuEvent.createApp(value));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).show(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
|||||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/rename_view_dialog.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/view/draggable_view_item.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/view/draggable_view_item.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_action_type.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/view/view_action_type.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_add_button.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/view/view_add_button.dart';
|
||||||
@ -350,22 +351,21 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
|
|||||||
createNewView,
|
createNewView,
|
||||||
) {
|
) {
|
||||||
if (createNewView) {
|
if (createNewView) {
|
||||||
NavigatorTextFieldDialog(
|
createViewAndShowRenameDialogIfNeeded(
|
||||||
title: _convertLayoutToHintText(pluginBuilder.layoutType!),
|
context,
|
||||||
value: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
_convertLayoutToHintText(pluginBuilder.layoutType!),
|
||||||
autoSelectAllText: true,
|
(viewName) {
|
||||||
confirm: (value) {
|
if (viewName.isNotEmpty) {
|
||||||
if (value.isNotEmpty) {
|
|
||||||
context.read<ViewBloc>().add(
|
context.read<ViewBloc>().add(
|
||||||
ViewEvent.createView(
|
ViewEvent.createView(
|
||||||
value,
|
viewName,
|
||||||
pluginBuilder.layoutType!,
|
pluginBuilder.layoutType!,
|
||||||
openAfterCreated: openAfterCreated,
|
openAfterCreated: openAfterCreated,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
).show(context);
|
);
|
||||||
}
|
}
|
||||||
context.read<ViewBloc>().add(
|
context.read<ViewBloc>().add(
|
||||||
const ViewEvent.setIsExpanded(true),
|
const ViewEvent.setIsExpanded(true),
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/theme_setting_entry_template.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
bool _prevSetting = false;
|
||||||
|
|
||||||
|
class CreateFileSettings extends StatelessWidget {
|
||||||
|
CreateFileSettings({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final cubit = CreateFileSettingsCubit(_prevSetting);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ThemeSettingEntryTemplateWidget(
|
||||||
|
label: 'Show rename dialog when creating a new file',
|
||||||
|
trailing: [
|
||||||
|
BlocProvider.value(
|
||||||
|
value: cubit,
|
||||||
|
child: BlocBuilder<CreateFileSettingsCubit, bool>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return Switch(
|
||||||
|
value: state,
|
||||||
|
onChanged: (value) {
|
||||||
|
cubit.toggle(value: value);
|
||||||
|
_prevSetting = value;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:appflowy/workspace/application/appearance.dart';
|
import 'package:appflowy/workspace/application/appearance.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/create_file_setting.dart';
|
||||||
import 'package:flowy_infra/plugins/bloc/dynamic_plugin_bloc.dart';
|
import 'package:flowy_infra/plugins/bloc/dynamic_plugin_bloc.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -34,6 +35,7 @@ class SettingsAppearanceView extends StatelessWidget {
|
|||||||
TextDirectionSetting(
|
TextDirectionSetting(
|
||||||
currentTextDirection: state.textDirection,
|
currentTextDirection: state.textDirection,
|
||||||
),
|
),
|
||||||
|
CreateFileSettings(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||||
import 'package:flowy_infra_ui/widget/dialog/dialog_size.dart';
|
import 'package:flowy_infra_ui/widget/dialog/dialog_size.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
extension IntoDialog on Widget {
|
extension IntoDialog on Widget {
|
||||||
Future<dynamic> show(BuildContext context) async {
|
Future<dynamic> show(BuildContext context) async {
|
||||||
@ -71,7 +72,7 @@ class StyledDialog extends StatelessWidget {
|
|||||||
maxWidth: maxWidth ?? double.infinity,
|
maxWidth: maxWidth ?? double.infinity,
|
||||||
),
|
),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius ?? BorderRadius.zero,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
physics: StyledScrollPhysics(),
|
physics: StyledScrollPhysics(),
|
||||||
//https://medium.com/saugo360/https-medium-com-saugo360-flutter-using-overlay-to-display-floating-widgets-2e6d0e8decb9
|
//https://medium.com/saugo360/https-medium-com-saugo360-flutter-using-overlay-to-display-floating-widgets-2e6d0e8decb9
|
||||||
|
@ -54,8 +54,8 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: "6d68f90"
|
ref: a97c816
|
||||||
resolved-ref: "6d68f9003fa023d215dc5f20e8900f985c2cdaa1"
|
resolved-ref: a97c816c1d8cfbc5644a8be49deae334c47261e3
|
||||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||||
source: git
|
source: git
|
||||||
version: "1.3.0"
|
version: "1.3.0"
|
||||||
@ -1430,6 +1430,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.0"
|
||||||
|
string_validator:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: string_validator
|
||||||
|
sha256: b419cf5d21d608522e6e7cafed4deb34b6f268c43df866e63c320bab98a08cf6
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
styled_widget:
|
styled_widget:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -47,7 +47,7 @@ dependencies:
|
|||||||
appflowy_editor:
|
appflowy_editor:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||||
ref: 6d68f90
|
ref: a97c816
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
path: packages/appflowy_popover
|
path: packages/appflowy_popover
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user