mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: merge with main
This commit is contained in:
2
.github/workflows/android_ci.yaml.bak
vendored
2
.github/workflows/android_ci.yaml.bak
vendored
@ -19,7 +19,7 @@
|
||||
|
||||
# env:
|
||||
# CARGO_TERM_COLOR: always
|
||||
# FLUTTER_VERSION: "3.19.0"
|
||||
# FLUTTER_VERSION: "3.22.0"
|
||||
# RUST_TOOLCHAIN: "1.77.2"
|
||||
# CARGO_MAKE_VERSION: "0.36.6"
|
||||
|
||||
|
2
.github/workflows/flutter_ci.yaml
vendored
2
.github/workflows/flutter_ci.yaml
vendored
@ -25,7 +25,7 @@ on:
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
FLUTTER_VERSION: "3.19.0"
|
||||
FLUTTER_VERSION: "3.22.0"
|
||||
RUST_TOOLCHAIN: "1.77.2"
|
||||
CARGO_MAKE_VERSION: "0.36.6"
|
||||
|
||||
|
2
.github/workflows/ios_ci.yaml
vendored
2
.github/workflows/ios_ci.yaml
vendored
@ -20,7 +20,7 @@ on:
|
||||
- "!frontend/appflowy_web_app/**"
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.19.0"
|
||||
FLUTTER_VERSION: "3.22.0"
|
||||
RUST_TOOLCHAIN: "1.77.2"
|
||||
|
||||
concurrency:
|
||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -6,7 +6,7 @@ on:
|
||||
- "*"
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: "3.19.0"
|
||||
FLUTTER_VERSION: "3.22.0"
|
||||
RUST_TOOLCHAIN: "1.77.2"
|
||||
|
||||
jobs:
|
||||
|
2
.github/workflows/rust_coverage.yml
vendored
2
.github/workflows/rust_coverage.yml
vendored
@ -10,7 +10,7 @@ on:
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
FLUTTER_VERSION: "3.19.0"
|
||||
FLUTTER_VERSION: "3.22.0"
|
||||
RUST_TOOLCHAIN: "1.77.2"
|
||||
|
||||
jobs:
|
||||
|
19
CHANGELOG.md
19
CHANGELOG.md
@ -1,4 +1,21 @@
|
||||
# Release Notes
|
||||
## Version 0.5.8 - 05/20/2024
|
||||
### New Features
|
||||
- Improvement to the Callout block to insert new lines
|
||||
- New settings page "Manage data" replaced the "Files" page
|
||||
- New settings page "Workspace" replaced the "Appearance" and "Language" pages
|
||||
- A custom implementation of a title bar for Windows users
|
||||
- Added support for selecting Cards in kanban and performing grouped keyboard shortcuts
|
||||
- Added support for default system font family
|
||||
- Support for scaling the application up/down using a keyboard shortcut (CMD/CTRL + PLUS/MINUS)
|
||||
|
||||
### Bug Fixes
|
||||
- Resolved and refined the UI on Mobile
|
||||
- Resolved issue with text editing in database
|
||||
- Improved appearance of empty text cells in kanban/calendar
|
||||
- Resolved an issue where a page's more actions (delete, duplicate) did not work properly
|
||||
- Resolved and inconsistency in padding on get started screen on Desktop
|
||||
|
||||
## Version 0.5.7 - 05/10/2024
|
||||
### Bug Fixes
|
||||
- Resolved page opening issue on Android.
|
||||
@ -88,7 +105,7 @@
|
||||
- Fixed a bug where newly created rows were not being automatically sorted.
|
||||
- Fixed issues related to deleting a sorting field or sort not removing existing sorts properly.
|
||||
### Notes
|
||||
- Windows 7, Windows 8, and iOS 11 are not yet supported due to the upgrade to Flutter 3.19.0.
|
||||
- Windows 7, Windows 8, and iOS 11 are not yet supported due to the upgrade to Flutter 3.22.0.
|
||||
|
||||
## Version 0.4.9 - 02/17/2024
|
||||
### Bug Fixes
|
||||
|
@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
||||
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
||||
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
||||
LIB_NAME = "dart_ffi"
|
||||
APPFLOWY_VERSION = "0.5.7"
|
||||
APPFLOWY_VERSION = "0.5.8"
|
||||
FLUTTER_DESKTOP_FEATURES = "dart"
|
||||
PRODUCT_NAME = "AppFlowy"
|
||||
MACOSX_DEPLOYMENT_TARGET = "11.0"
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/env/cloud_env.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart';
|
||||
@ -12,14 +10,15 @@ import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/application/auth/af_cloud_mock_auth_service.dart';
|
||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_workspace.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_actions.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_menu.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/sidebar_workspace.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/user_avatar.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/uuid.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
@ -0,0 +1,37 @@
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import '../../shared/database_test_op.dart';
|
||||
import '../../shared/util.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('board field test', () {
|
||||
testWidgets('change field type whithin card #5360', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
|
||||
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Board);
|
||||
const name = 'Card 1';
|
||||
final card1 = find.text(name);
|
||||
await tester.tapButton(card1);
|
||||
|
||||
const fieldName = "test change field";
|
||||
await tester.createField(
|
||||
FieldType.RichText,
|
||||
fieldName,
|
||||
layout: ViewLayoutPB.Board,
|
||||
);
|
||||
await tester.tapButton(card1);
|
||||
await tester.changeFieldTypeOfFieldWithName(
|
||||
fieldName,
|
||||
FieldType.Checkbox,
|
||||
layout: ViewLayoutPB.Board,
|
||||
);
|
||||
await tester.hoverOnWidget(find.text('Card 2'));
|
||||
});
|
||||
});
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'board_row_test.dart' as board_row_test;
|
||||
import 'board_add_row_test.dart' as board_add_row_test;
|
||||
import 'board_group_test.dart' as board_group_test;
|
||||
import 'board_row_test.dart' as board_row_test;
|
||||
|
||||
void startTesting() {
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Board integration tests
|
||||
|
@ -66,6 +66,7 @@ void main() {
|
||||
LogicalKeyboardKey.keyR,
|
||||
],
|
||||
tester: tester,
|
||||
withKeyUp: true,
|
||||
);
|
||||
expect(first.attributes[blockComponentAlign], rightAlignmentKey);
|
||||
|
||||
@ -77,6 +78,7 @@ void main() {
|
||||
LogicalKeyboardKey.keyE,
|
||||
],
|
||||
tester: tester,
|
||||
withKeyUp: true,
|
||||
);
|
||||
expect(first.attributes[blockComponentAlign], centerAlignmentKey);
|
||||
|
||||
@ -88,6 +90,7 @@ void main() {
|
||||
LogicalKeyboardKey.keyL,
|
||||
],
|
||||
tester: tester,
|
||||
withKeyUp: true,
|
||||
);
|
||||
expect(first.attributes[blockComponentAlign], leftAlignmentKey);
|
||||
});
|
||||
|
@ -111,6 +111,7 @@ Future<void> triggerReferenceDocumentBySlashMenu(WidgetTester tester) async {
|
||||
LogicalKeyboardKey.enter,
|
||||
],
|
||||
tester: tester,
|
||||
withKeyUp: true,
|
||||
);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
@ -129,6 +130,7 @@ Future<void> enterDocumentText(WidgetTester tester) async {
|
||||
LogicalKeyboardKey.keyT,
|
||||
],
|
||||
tester: tester,
|
||||
withKeyUp: true,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import '../../shared/util.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('MoreViewActions', () {
|
||||
testWidgets('can duplicate and delete from menu', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final pageFinder = find.byType(ViewItem);
|
||||
expect(pageFinder, findsNWidgets(1));
|
||||
|
||||
// Duplicate
|
||||
await tester.openMoreViewActions();
|
||||
await tester.duplicateByMoreViewActions();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(pageFinder, findsNWidgets(2));
|
||||
|
||||
// Delete
|
||||
await tester.openMoreViewActions();
|
||||
await tester.deleteByMoreViewActions();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(pageFinder, findsNWidgets(1));
|
||||
});
|
||||
});
|
||||
}
|
@ -6,6 +6,9 @@ import 'document_copy_and_paste_test.dart' as document_copy_and_paste_test;
|
||||
import 'document_create_and_delete_test.dart'
|
||||
as document_create_and_delete_test;
|
||||
import 'document_option_action_test.dart' as document_option_action_test;
|
||||
import 'document_inline_page_reference_test.dart'
|
||||
as document_inline_page_reference_test;
|
||||
import 'document_more_actions_test.dart' as document_more_actions_test;
|
||||
import 'document_text_direction_test.dart' as document_text_direction_test;
|
||||
import 'document_with_cover_image_test.dart' as document_with_cover_image_test;
|
||||
import 'document_with_database_test.dart' as document_with_database_test;
|
||||
@ -16,8 +19,6 @@ import 'document_with_inline_page_test.dart' as document_with_inline_page_test;
|
||||
import 'document_with_outline_block_test.dart' as document_with_outline_block;
|
||||
import 'document_with_toggle_list_test.dart' as document_with_toggle_list_test;
|
||||
import 'edit_document_test.dart' as document_edit_test;
|
||||
import 'document_inline_page_reference_test.dart'
|
||||
as document_inline_page_reference_test;
|
||||
|
||||
void startTesting() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
@ -38,4 +39,5 @@ void startTesting() {
|
||||
document_option_action_test.main();
|
||||
document_with_image_block_test.main();
|
||||
document_inline_page_reference_test.main();
|
||||
document_more_actions_test.main();
|
||||
}
|
||||
|
@ -130,24 +130,24 @@ void main() {
|
||||
final searchEmojiTextField = find.byWidgetPredicate(
|
||||
(widget) =>
|
||||
widget is TextField &&
|
||||
widget.decoration!.hintText == LocaleKeys.emoji_search.tr(),
|
||||
widget.decoration!.hintText == LocaleKeys.search_label.tr(),
|
||||
);
|
||||
await tester.enterText(
|
||||
searchEmojiTextField,
|
||||
'hand',
|
||||
'punch',
|
||||
);
|
||||
|
||||
// change skin tone
|
||||
await tester.editor.changeEmojiSkinTone(EmojiSkinTone.dark);
|
||||
|
||||
// select an icon with skin tone
|
||||
const hand = '👋🏿';
|
||||
await tester.tapEmoji(hand);
|
||||
tester.expectToSeeDocumentIcon(hand);
|
||||
const punch = '👊🏿';
|
||||
await tester.tapEmoji(punch);
|
||||
tester.expectToSeeDocumentIcon(punch);
|
||||
tester.expectViewHasIcon(
|
||||
gettingStarted,
|
||||
ViewLayoutPB.Document,
|
||||
hand,
|
||||
punch,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_folder.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_folder.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -12,8 +12,8 @@ void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('sidebar expand test', () {
|
||||
bool isExpanded({required FolderCategoryType type}) {
|
||||
if (type == FolderCategoryType.private) {
|
||||
bool isExpanded({required FolderSpaceType type}) {
|
||||
if (type == FolderSpaceType.private) {
|
||||
return find
|
||||
.descendant(
|
||||
of: find.byType(PrivateSectionFolder),
|
||||
@ -30,19 +30,19 @@ void main() {
|
||||
await tester.tapAnonymousSignInButton();
|
||||
|
||||
// first time is expanded
|
||||
expect(isExpanded(type: FolderCategoryType.private), true);
|
||||
expect(isExpanded(type: FolderSpaceType.private), true);
|
||||
|
||||
// collapse the personal folder
|
||||
await tester.tapButton(
|
||||
find.byTooltip(LocaleKeys.sideBar_clickToHidePrivate.tr()),
|
||||
);
|
||||
expect(isExpanded(type: FolderCategoryType.private), false);
|
||||
expect(isExpanded(type: FolderSpaceType.private), false);
|
||||
|
||||
// expand the personal folder
|
||||
await tester.tapButton(
|
||||
find.byTooltip(LocaleKeys.sideBar_clickToHidePrivate.tr()),
|
||||
);
|
||||
expect(isExpanded(type: FolderCategoryType.private), true);
|
||||
expect(isExpanded(type: FolderSpaceType.private), true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/folder/_favorite_folder.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/favorites/favorite_folder.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||
@ -46,7 +46,7 @@ void main() {
|
||||
await tester.favoriteViewByName(names[1]);
|
||||
expect(
|
||||
tester.findFavoritePageName(names[1]),
|
||||
findsNWidgets(2),
|
||||
findsNWidgets(1),
|
||||
);
|
||||
|
||||
await tester.unfavoriteViewByName(gettingStarted);
|
||||
@ -120,9 +120,9 @@ void main() {
|
||||
(widget) =>
|
||||
widget is SingleInnerViewItem &&
|
||||
widget.view.isFavorite &&
|
||||
widget.categoryType == FolderCategoryType.favorite,
|
||||
widget.spaceType == FolderSpaceType.favorite,
|
||||
),
|
||||
findsNWidgets(6),
|
||||
findsNWidgets(3),
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(
|
||||
@ -135,7 +135,7 @@ void main() {
|
||||
|
||||
expect(
|
||||
tester.findAllFavoritePages(),
|
||||
findsNWidgets(3),
|
||||
findsNWidgets(2),
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(
|
||||
@ -168,7 +168,7 @@ void main() {
|
||||
widget.isSelected != null &&
|
||||
widget.isSelected!(),
|
||||
),
|
||||
findsNWidgets(2),
|
||||
findsNWidgets(1),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import 'sidebar_favorites_test.dart' as sidebar_favorite_test;
|
||||
import 'sidebar_icon_test.dart' as sidebar_icon_test;
|
||||
import 'sidebar_test.dart' as sidebar_test;
|
||||
|
||||
void startTesting() {
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Sidebar integration tests
|
||||
|
@ -27,7 +27,7 @@ Future<void> runIntegration3OnDesktop() async {
|
||||
settings_test_runner.main();
|
||||
share_markdown_test.main();
|
||||
import_files_test.main();
|
||||
sidebar_test_runner.startTesting();
|
||||
board_test_runner.startTesting();
|
||||
sidebar_test_runner.main();
|
||||
board_test_runner.main();
|
||||
tabs_test.main();
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import 'package:appflowy/shared/feature_flags.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/presentation/screens/screens.dart';
|
||||
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_new_page_button.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_workspace.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_new_page_button.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_menu.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/sidebar_workspace.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_add_button.dart';
|
||||
@ -22,6 +22,8 @@ import 'package:appflowy/workspace/presentation/notifications/widgets/flowy_tab.
|
||||
import 'package:appflowy/workspace/presentation/notifications/widgets/notification_button.dart';
|
||||
import 'package:appflowy/workspace/presentation/notifications/widgets/notification_tab_bar.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_body.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/more_view_actions/more_view_actions.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/more_view_actions/widgets/common_view_action.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/view_title_bar.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
@ -57,6 +59,7 @@ extension CommonOperations on WidgetTester {
|
||||
/// Tap the + button on the home page.
|
||||
Future<void> tapAddViewButton({
|
||||
String name = gettingStarted,
|
||||
ViewLayoutPB layout = ViewLayoutPB.Document,
|
||||
}) async {
|
||||
await hoverOnPageName(
|
||||
name,
|
||||
@ -276,7 +279,7 @@ extension CommonOperations on WidgetTester {
|
||||
bool openAfterCreated = true,
|
||||
}) async {
|
||||
// create a new page
|
||||
await tapAddViewButton(name: parentName ?? gettingStarted);
|
||||
await tapAddViewButton(name: parentName ?? gettingStarted, layout: layout);
|
||||
await tapButtonWithName(layout.menuName);
|
||||
final settingsOrFailure = await getIt<KeyValueStorage>().getWithFormat(
|
||||
KVKeys.showRenameDialogWhenCreatingNewFile,
|
||||
@ -564,6 +567,44 @@ extension CommonOperations on WidgetTester {
|
||||
);
|
||||
await tapButton(button);
|
||||
}
|
||||
|
||||
Future<void> openMoreViewActions() async {
|
||||
final button = find.byType(MoreViewActions);
|
||||
await tap(button);
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
/// Presses on the Duplicate ViewAction in the [MoreViewActions] popup.
|
||||
///
|
||||
/// [openMoreViewActions] must be called beforehand!
|
||||
///
|
||||
Future<void> duplicateByMoreViewActions() async {
|
||||
final button = find.descendant(
|
||||
of: find.byType(ListView),
|
||||
matching: find.byWidgetPredicate(
|
||||
(widget) =>
|
||||
widget is ViewAction && widget.type == ViewActionType.duplicate,
|
||||
),
|
||||
);
|
||||
await tap(button);
|
||||
await pump();
|
||||
}
|
||||
|
||||
/// Presses on the Delete ViewAction in the [MoreViewActions] popup.
|
||||
///
|
||||
/// [openMoreViewActions] must be called beforehand!
|
||||
///
|
||||
Future<void> deleteByMoreViewActions() async {
|
||||
final button = find.descendant(
|
||||
of: find.byType(ListView),
|
||||
matching: find.byWidgetPredicate(
|
||||
(widget) =>
|
||||
widget is ViewAction && widget.type == ViewActionType.delete,
|
||||
),
|
||||
);
|
||||
await tap(button);
|
||||
await pump();
|
||||
}
|
||||
}
|
||||
|
||||
extension SettingsFinder on CommonFinders {
|
||||
|
@ -661,10 +661,13 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
||||
|
||||
Future<void> changeFieldTypeOfFieldWithName(
|
||||
String name,
|
||||
FieldType type,
|
||||
) async {
|
||||
FieldType type, {
|
||||
ViewLayoutPB layout = ViewLayoutPB.Grid,
|
||||
}) async {
|
||||
await tapGridFieldWithName(name);
|
||||
await tapEditFieldButton();
|
||||
if (layout == ViewLayoutPB.Grid) {
|
||||
await tapEditFieldButton();
|
||||
}
|
||||
|
||||
await tapSwitchFieldTypeButton();
|
||||
await selectFieldType(type);
|
||||
@ -881,8 +884,14 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
||||
await tapButtonWithName(LocaleKeys.grid_row_delete.tr());
|
||||
}
|
||||
|
||||
Future<void> createField(FieldType fieldType, String name) async {
|
||||
await scrollToRight(find.byType(GridPage));
|
||||
Future<void> createField(
|
||||
FieldType fieldType,
|
||||
String name, {
|
||||
ViewLayoutPB layout = ViewLayoutPB.Grid,
|
||||
}) async {
|
||||
if (layout == ViewLayoutPB.Grid) {
|
||||
await scrollToRight(find.byType(GridPage));
|
||||
}
|
||||
await tapNewPropertyButton();
|
||||
await renameField(name);
|
||||
await tapSwitchFieldTypeButton();
|
||||
|
@ -81,15 +81,12 @@ class EditorOperations {
|
||||
|
||||
/// Taps the 'Remove Icon' button in the cover toolbar and the icon popover
|
||||
Future<void> tapRemoveIconButton({bool isInPicker = false}) async {
|
||||
Finder button =
|
||||
find.text(LocaleKeys.document_plugins_cover_removeIcon.tr());
|
||||
if (isInPicker) {
|
||||
button = find.descendant(
|
||||
of: find.byType(FlowyIconPicker),
|
||||
matching: button,
|
||||
);
|
||||
}
|
||||
|
||||
final Finder button = !isInPicker
|
||||
? find.text(LocaleKeys.document_plugins_cover_removeIcon.tr())
|
||||
: find.descendant(
|
||||
of: find.byType(FlowyIconPicker),
|
||||
matching: find.text(LocaleKeys.button_remove.tr()),
|
||||
);
|
||||
await tester.tapButton(button);
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ extension Expectation on WidgetTester {
|
||||
(widget) =>
|
||||
widget is SingleInnerViewItem &&
|
||||
widget.view.isFavorite &&
|
||||
widget.categoryType == FolderCategoryType.favorite &&
|
||||
widget.spaceType == FolderSpaceType.favorite &&
|
||||
widget.view.name == name &&
|
||||
widget.view.layout == layout,
|
||||
skipOffstage: false,
|
||||
@ -175,7 +175,7 @@ extension Expectation on WidgetTester {
|
||||
(widget) =>
|
||||
widget is SingleInnerViewItem &&
|
||||
widget.view.isFavorite &&
|
||||
widget.categoryType == FolderCategoryType.favorite,
|
||||
widget.spaceType == FolderSpaceType.favorite,
|
||||
);
|
||||
|
||||
Finder findPageName(
|
||||
|
@ -5,10 +5,18 @@ class FlowyTestKeyboard {
|
||||
static Future<void> simulateKeyDownEvent(
|
||||
List<LogicalKeyboardKey> keys, {
|
||||
required flutter_test.WidgetTester tester,
|
||||
bool withKeyUp = false,
|
||||
}) async {
|
||||
for (final LogicalKeyboardKey key in keys) {
|
||||
await flutter_test.simulateKeyDownEvent(key);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
if (withKeyUp) {
|
||||
for (final LogicalKeyboardKey key in keys) {
|
||||
await flutter_test.simulateKeyUpEvent(key);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_setting.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_setting.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/settings_account_view.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/settings_workspace_view.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
|
||||
@ -12,7 +12,6 @@ import 'package:flowy_infra_ui/style_widget/text_field.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../desktop/board/board_hide_groups_test.dart';
|
||||
|
||||
import 'base.dart';
|
||||
import 'common_operations.dart';
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/base/icon/icon_picker.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_workspace.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_actions.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_icon.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_menu.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/sidebar_workspace.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'base.dart';
|
||||
import 'util.dart';
|
||||
|
||||
extension AppFlowyWorkspace on WidgetTester {
|
||||
/// Open workspace menu
|
||||
@ -36,12 +36,19 @@ extension AppFlowyWorkspace on WidgetTester {
|
||||
matching: find.byType(WorkspaceMoreActionList),
|
||||
);
|
||||
expect(moreButton, findsOneWidget);
|
||||
await tapButton(moreButton);
|
||||
await tapButton(find.findTextInFlowyText(LocaleKeys.button_rename.tr()));
|
||||
final input = find.byType(TextFormField);
|
||||
expect(input, findsOneWidget);
|
||||
await enterText(input, name);
|
||||
await tapButton(find.text(LocaleKeys.button_ok.tr()));
|
||||
await hoverOnWidget(
|
||||
moreButton,
|
||||
onHover: () async {
|
||||
await tapButton(moreButton);
|
||||
await tapButton(
|
||||
find.findTextInFlowyText(LocaleKeys.button_rename.tr()),
|
||||
);
|
||||
final input = find.byType(TextFormField);
|
||||
expect(input, findsOneWidget);
|
||||
await enterText(input, name);
|
||||
await tapButton(find.text(LocaleKeys.button_ok.tr()));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> changeWorkspaceIcon(String icon) async {
|
||||
|
@ -173,7 +173,7 @@ SPEC CHECKSUMS:
|
||||
fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265
|
||||
image_gallery_saver: cb43cc43141711190510e92c460eb1655cd343cb
|
||||
image_picker_ios: 99dfe1854b4fa34d0364e74a78448a0151025425
|
||||
integration_test: 13825b8a9334a850581300559b8839134b124670
|
||||
integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4
|
||||
irondash_engine_context: 3458bf979b90d616ffb8ae03a150bafe2e860cc9
|
||||
keyboard_height_plugin: 43fa8bba20fd5c4fdeed5076466b8b9d43cc6b86
|
||||
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
|
||||
|
@ -481,7 +481,7 @@ class _AFDropdownMenuState<T> extends State<AFDropdownMenu<T>> {
|
||||
|
||||
ButtonStyle effectiveStyle = entry.style ?? defaultStyle;
|
||||
final Color focusedBackgroundColor = effectiveStyle.foregroundColor
|
||||
?.resolve(<MaterialState>{MaterialState.focused}) ??
|
||||
?.resolve(<WidgetState>{WidgetState.focused}) ??
|
||||
Theme.of(context).colorScheme.onSurface;
|
||||
|
||||
Widget label = entry.labelWidget ?? Text(entry.label);
|
||||
@ -499,7 +499,7 @@ class _AFDropdownMenuState<T> extends State<AFDropdownMenu<T>> {
|
||||
// color will also change to foregroundColor.withOpacity(0.12).
|
||||
effectiveStyle = entry.enabled && i == focusedIndex
|
||||
? effectiveStyle.copyWith(
|
||||
backgroundColor: MaterialStatePropertyAll<Color>(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
focusedBackgroundColor.withOpacity(0.12),
|
||||
),
|
||||
)
|
||||
@ -628,17 +628,17 @@ class _AFDropdownMenuState<T> extends State<AFDropdownMenu<T>> {
|
||||
final double? anchorWidth = getWidth(_anchorKey);
|
||||
if (widget.width != null) {
|
||||
effectiveMenuStyle = effectiveMenuStyle.copyWith(
|
||||
minimumSize: MaterialStatePropertyAll<Size?>(Size(widget.width!, 0.0)),
|
||||
minimumSize: WidgetStatePropertyAll<Size?>(Size(widget.width!, 0.0)),
|
||||
);
|
||||
} else if (anchorWidth != null) {
|
||||
effectiveMenuStyle = effectiveMenuStyle.copyWith(
|
||||
minimumSize: MaterialStatePropertyAll<Size?>(Size(anchorWidth, 0.0)),
|
||||
minimumSize: WidgetStatePropertyAll<Size?>(Size(anchorWidth, 0.0)),
|
||||
);
|
||||
}
|
||||
|
||||
if (widget.menuHeight != null) {
|
||||
effectiveMenuStyle = effectiveMenuStyle.copyWith(
|
||||
maximumSize: MaterialStatePropertyAll<Size>(
|
||||
maximumSize: WidgetStatePropertyAll<Size>(
|
||||
Size(double.infinity, widget.menuHeight!),
|
||||
),
|
||||
);
|
||||
@ -1029,8 +1029,8 @@ class _DropdownMenuDefaultsM3 extends DropdownMenuThemeData {
|
||||
@override
|
||||
MenuStyle get menuStyle {
|
||||
return const MenuStyle(
|
||||
minimumSize: MaterialStatePropertyAll<Size>(Size(_kMinimumWidth, 0.0)),
|
||||
maximumSize: MaterialStatePropertyAll<Size>(Size.infinite),
|
||||
minimumSize: WidgetStatePropertyAll<Size>(Size(_kMinimumWidth, 0.0)),
|
||||
maximumSize: WidgetStatePropertyAll<Size>(Size.infinite),
|
||||
visualDensity: VisualDensity.standard,
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart' hide WidgetBuilder;
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TypeOptionMenuItemValue<T> {
|
||||
|
@ -12,6 +12,7 @@ import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/view/prelude.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -92,7 +93,7 @@ class MobileViewPageMoreButton extends StatelessWidget {
|
||||
context,
|
||||
showDragHandle: true,
|
||||
showDivider: false,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
builder: (_) => MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider.value(value: context.read<ViewBloc>()),
|
||||
@ -144,7 +145,7 @@ class MobileViewPageLayoutButton extends StatelessWidget {
|
||||
showDoneButton: true,
|
||||
showHeader: true,
|
||||
title: LocaleKeys.pageStyle_title.tr(),
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
builder: (_) => MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider.value(value: context.read<DocumentPageStyleBloc>()),
|
||||
|
@ -38,6 +38,7 @@ class MobileViewPageMoreBottomSheet extends StatelessWidget {
|
||||
case MobileViewBottomSheetBodyAction.removeFromFavorites:
|
||||
context.pop();
|
||||
context.read<FavoriteBloc>().add(FavoriteEvent.toggle(view));
|
||||
|
||||
break;
|
||||
case MobileViewBottomSheetBodyAction.undo:
|
||||
EditorNotification.undo().post();
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -19,7 +20,7 @@ class BottomSheetActionWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final iconColor =
|
||||
this.iconColor ?? Theme.of(context).colorScheme.onBackground;
|
||||
this.iconColor ?? AFThemeExtension.of(context).onBackground;
|
||||
|
||||
if (svg == null) {
|
||||
return OutlinedButton(
|
||||
|
@ -3,6 +3,7 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||
import 'package:appflowy/mobile/presentation/page_item/mobile_slide_action_button.dart';
|
||||
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
@ -54,7 +55,7 @@ enum MobilePaneActionType {
|
||||
context,
|
||||
showDragHandle: true,
|
||||
showDivider: false,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
useRootNavigator: true,
|
||||
builder: (context) {
|
||||
return MultiBlocProvider(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_buttons.dart';
|
||||
import 'package:appflowy/plugins/base/drag_handler.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart' hide WidgetBuilder;
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
extension BottomSheetPaddingExtension on BuildContext {
|
||||
|
@ -15,6 +15,7 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
|
||||
import 'package:appflowy_board/appflowy_board.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/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -265,7 +266,7 @@ class _BoardContentState extends State<_BoardContent> {
|
||||
BoxDecoration _makeBoxDecoration(BuildContext context) {
|
||||
final themeMode = context.read<AppearanceSettingsCubit>().state.themeMode;
|
||||
return BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
color: AFThemeExtension.of(context).background,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
border: themeMode == ThemeMode.light
|
||||
? Border.fromBorderSide(
|
||||
|
@ -60,7 +60,7 @@ class _MobileBoardTrailingState extends State<MobileBoardTrailing> {
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
Icons.close,
|
||||
color: style.colorScheme.onBackground,
|
||||
color: style.colorScheme.onSurface,
|
||||
),
|
||||
onPressed: () =>
|
||||
setState(() => _textController.clear()),
|
||||
@ -86,7 +86,7 @@ class _MobileBoardTrailingState extends State<MobileBoardTrailing> {
|
||||
child: Text(
|
||||
LocaleKeys.button_cancel.tr(),
|
||||
style: style.textTheme.titleSmall?.copyWith(
|
||||
color: style.colorScheme.onBackground,
|
||||
color: style.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
onPressed: () => setState(() => isEditing = false),
|
||||
@ -96,7 +96,7 @@ class _MobileBoardTrailingState extends State<MobileBoardTrailing> {
|
||||
LocaleKeys.button_add.tr(),
|
||||
style: style.textTheme.titleSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: style.colorScheme.onBackground,
|
||||
color: style.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
@ -117,14 +117,14 @@ class _MobileBoardTrailingState extends State<MobileBoardTrailing> {
|
||||
)
|
||||
: ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: style.colorScheme.onBackground,
|
||||
foregroundColor: style.colorScheme.onSurface,
|
||||
backgroundColor: style.colorScheme.secondary,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
).copyWith(
|
||||
overlayColor:
|
||||
MaterialStateProperty.all(Theme.of(context).hoverColor),
|
||||
WidgetStateProperty.all(Theme.of(context).hoverColor),
|
||||
),
|
||||
icon: const Icon(Icons.add),
|
||||
label: Text(
|
||||
|
@ -9,6 +9,7 @@ import 'package:appflowy/plugins/database/widgets/cell/card_cell_skeleton/text_c
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:collection/collection.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/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -168,7 +169,7 @@ class MobileHiddenGroup extends StatelessWidget {
|
||||
return TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: Theme.of(context).textTheme.bodyMedium,
|
||||
foregroundColor: Theme.of(context).colorScheme.onBackground,
|
||||
foregroundColor: AFThemeExtension.of(context).onBackground,
|
||||
visualDensity: VisualDensity.compact,
|
||||
),
|
||||
child: CardCellBuilder(
|
||||
|
@ -20,6 +20,7 @@ import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart'
|
||||
import 'package:appflowy/plugins/database/widgets/row/row_property.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/row_entities.pb.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/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -131,7 +132,7 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
|
||||
void _showCardActions(BuildContext context) {
|
||||
showMobileBottomSheet(
|
||||
context,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
showDragHandle: true,
|
||||
builder: (_) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
|
@ -22,17 +22,17 @@ class MobileRowDetailCreateFieldButton extends StatelessWidget {
|
||||
constraints: const BoxConstraints(minWidth: double.infinity),
|
||||
child: TextButton.icon(
|
||||
style: Theme.of(context).textButtonTheme.style?.copyWith(
|
||||
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||
shape: WidgetStateProperty.all<RoundedRectangleBorder>(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
),
|
||||
overlayColor: MaterialStateProperty.all<Color>(
|
||||
overlayColor: WidgetStateProperty.all<Color>(
|
||||
Theme.of(context).hoverColor,
|
||||
),
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
splashFactory: NoSplash.splashFactory,
|
||||
padding: const MaterialStatePropertyAll(
|
||||
padding: const WidgetStatePropertyAll(
|
||||
EdgeInsets.symmetric(vertical: 14, horizontal: 6),
|
||||
),
|
||||
),
|
||||
|
@ -1,5 +1,5 @@
|
||||
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/card/card.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/card/card_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell/card_cell_builder.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell/card_cell_style_maps/mobile_board_card_cell_style.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
@ -16,7 +16,7 @@ class MobileCardContent extends StatelessWidget {
|
||||
|
||||
final RowMetaPB rowMeta;
|
||||
final CardCellBuilder cellBuilder;
|
||||
final List<CellContext> cells;
|
||||
final List<CellMeta> cells;
|
||||
final RowCardStyleConfiguration styleConfiguration;
|
||||
|
||||
@override
|
||||
@ -26,9 +26,9 @@ class MobileCardContent extends StatelessWidget {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: cells.map(
|
||||
(cellContext) {
|
||||
(cellMeta) {
|
||||
return cellBuilder.build(
|
||||
cellContext: cellContext,
|
||||
cellContext: cellMeta.cellContext(),
|
||||
styleMap: mobileBoardCardCellStyleMap(context),
|
||||
hasNotes: !rowMeta.isDocumentEmpty,
|
||||
);
|
||||
|
@ -7,6 +7,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.da
|
||||
import 'package:appflowy/util/field_type_extension.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
@ -40,7 +41,7 @@ Future<FieldType?> showFieldTypeGridBottomSheet(
|
||||
showCloseButton: true,
|
||||
elevation: 20,
|
||||
title: title,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
enableDraggableScrollable: true,
|
||||
builder: (context) {
|
||||
final typeOptionMenuItemValue = mobileSupportedFieldTypes
|
||||
|
@ -438,7 +438,7 @@ class _SortDetailContent extends StatelessWidget {
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
splashFactory: NoSplash.splashFactory,
|
||||
overlayColor: const MaterialStatePropertyAll(
|
||||
overlayColor: const WidgetStatePropertyAll(
|
||||
Colors.transparent,
|
||||
),
|
||||
onTap: (index) {
|
||||
|
@ -11,6 +11,7 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
|
||||
import 'package:collection/collection.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/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -183,7 +184,7 @@ class MobileDatabaseViewListButton extends StatelessWidget {
|
||||
showMobileBottomSheet(
|
||||
context,
|
||||
showDragHandle: true,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
builder: (_) {
|
||||
return BlocProvider<ViewBloc>(
|
||||
create: (_) =>
|
||||
|
@ -234,7 +234,6 @@ class DatabaseViewSettingTile extends StatelessWidget {
|
||||
showHeader: true,
|
||||
showBackButton: true,
|
||||
title: LocaleKeys.grid_settings_properties.tr(),
|
||||
showDivider: true,
|
||||
builder: (_) {
|
||||
return BlocProvider.value(
|
||||
value: context.read<ViewBloc>(),
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/default_mobile_action_pane.dart';
|
||||
import 'package:appflowy/mobile/presentation/home/favorite_folder/mobile_home_favorite_folder_header.dart';
|
||||
@ -7,6 +5,7 @@ import 'package:appflowy/mobile/presentation/page_item/mobile_view_item.dart';
|
||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.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';
|
||||
|
||||
class MobileFavoriteFolder extends StatelessWidget {
|
||||
@ -28,7 +27,7 @@ class MobileFavoriteFolder extends StatelessWidget {
|
||||
}
|
||||
|
||||
return BlocProvider<FolderBloc>(
|
||||
create: (context) => FolderBloc(type: FolderCategoryType.favorite)
|
||||
create: (context) => FolderBloc(type: FolderSpaceType.favorite)
|
||||
..add(
|
||||
const FolderEvent.initial(),
|
||||
),
|
||||
@ -55,9 +54,9 @@ class MobileFavoriteFolder extends StatelessWidget {
|
||||
...views.map(
|
||||
(view) => MobileViewItem(
|
||||
key: ValueKey(
|
||||
'${FolderCategoryType.favorite.name} ${view.id}',
|
||||
'${FolderSpaceType.favorite.name} ${view.id}',
|
||||
),
|
||||
categoryType: FolderCategoryType.favorite,
|
||||
spaceType: FolderSpaceType.favorite,
|
||||
isDraggable: false,
|
||||
isFirstChild: view.id == views.first.id,
|
||||
isFeedback: false,
|
||||
|
@ -70,20 +70,20 @@ class MobileFolders extends StatelessWidget {
|
||||
? [
|
||||
MobileSectionFolder(
|
||||
title: LocaleKeys.sideBar_workspace.tr(),
|
||||
categoryType: FolderCategoryType.public,
|
||||
spaceType: FolderSpaceType.public,
|
||||
views: state.section.publicViews,
|
||||
),
|
||||
const VSpace(8.0),
|
||||
MobileSectionFolder(
|
||||
title: LocaleKeys.sideBar_private.tr(),
|
||||
categoryType: FolderCategoryType.private,
|
||||
spaceType: FolderSpaceType.private,
|
||||
views: state.section.privateViews,
|
||||
),
|
||||
]
|
||||
: [
|
||||
MobileSectionFolder(
|
||||
title: LocaleKeys.sideBar_personal.tr(),
|
||||
categoryType: FolderCategoryType.public,
|
||||
spaceType: FolderSpaceType.public,
|
||||
views: state.section.publicViews,
|
||||
),
|
||||
],
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
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.dart';
|
||||
@ -15,6 +13,7 @@ import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sid
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.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';
|
||||
|
||||
@ -126,6 +125,7 @@ class _MobileWorkspace extends StatelessWidget {
|
||||
child: WorkspaceIcon(
|
||||
workspace: currentWorkspace,
|
||||
iconSize: 26,
|
||||
fontSize: 16.0,
|
||||
enableEdit: false,
|
||||
onSelected: (result) => context.read<UserWorkspaceBloc>().add(
|
||||
UserWorkspaceEvent.updateWorkspaceIcon(
|
||||
|
@ -178,7 +178,7 @@ class _DeletedFilesListView extends StatelessWidget {
|
||||
title: Text(
|
||||
deletedFile.name,
|
||||
style: theme.textTheme.labelMedium
|
||||
?.copyWith(color: theme.colorScheme.onBackground),
|
||||
?.copyWith(color: theme.colorScheme.onSurface),
|
||||
),
|
||||
horizontalTitleGap: 0,
|
||||
tileColor: theme.colorScheme.onSurface.withOpacity(0.1),
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
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.dart';
|
||||
@ -9,7 +7,9 @@ import 'package:appflowy/workspace/application/recent/prelude.dart';
|
||||
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.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/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
@ -91,7 +91,7 @@ class _RecentViews extends StatelessWidget {
|
||||
context,
|
||||
showDivider: false,
|
||||
showDragHandle: true,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
builder: (_) {
|
||||
return Column(
|
||||
children: [
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/default_mobile_action_pane.dart';
|
||||
@ -8,9 +6,11 @@ import 'package:appflowy/mobile/presentation/page_item/mobile_view_item.dart';
|
||||
import 'package:appflowy/workspace/application/menu/sidebar_sections_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.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 MobileSectionFolder extends StatelessWidget {
|
||||
@ -18,17 +18,17 @@ class MobileSectionFolder extends StatelessWidget {
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.views,
|
||||
required this.categoryType,
|
||||
required this.spaceType,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final List<ViewPB> views;
|
||||
final FolderCategoryType categoryType;
|
||||
final FolderSpaceType spaceType;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<FolderBloc>(
|
||||
create: (context) => FolderBloc(type: categoryType)
|
||||
create: (context) => FolderBloc(type: spaceType)
|
||||
..add(
|
||||
const FolderEvent.initial(),
|
||||
),
|
||||
@ -48,7 +48,7 @@ class MobileSectionFolder extends StatelessWidget {
|
||||
name:
|
||||
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||
index: 0,
|
||||
viewSection: categoryType.toViewSectionPB,
|
||||
viewSection: spaceType.toViewSectionPB,
|
||||
),
|
||||
);
|
||||
context.read<FolderBloc>().add(
|
||||
@ -64,13 +64,13 @@ class MobileSectionFolder extends StatelessWidget {
|
||||
...views.map(
|
||||
(view) => MobileViewItem(
|
||||
key: ValueKey(
|
||||
'${FolderCategoryType.private.name} ${view.id}',
|
||||
'${FolderSpaceType.private.name} ${view.id}',
|
||||
),
|
||||
categoryType: categoryType,
|
||||
spaceType: spaceType,
|
||||
isFirstChild: view.id == views.first.id,
|
||||
view: view,
|
||||
level: 0,
|
||||
leftPadding: 16,
|
||||
leftPadding: HomeSpaceViewSizes.leftPadding,
|
||||
isFeedback: false,
|
||||
onSelected: context.pushView,
|
||||
endActionPane: (context) {
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
@ -9,6 +7,7 @@ import 'package:appflowy/workspace/presentation/settings/widgets/members/workspa
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.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';
|
||||
|
||||
// Only works on mobile.
|
||||
@ -106,6 +105,7 @@ class _WorkspaceMenuItem extends StatelessWidget {
|
||||
leftIcon: WorkspaceIcon(
|
||||
enableEdit: false,
|
||||
iconSize: 26,
|
||||
fontSize: 16.0,
|
||||
workspace: workspace,
|
||||
onSelected: (result) => context.read<UserWorkspaceBloc>().add(
|
||||
UserWorkspaceEvent.updateWorkspaceIcon(
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||
@ -12,6 +10,7 @@ import 'package:appflowy/workspace/presentation/home/menu/view/draggable_view_it
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.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:flutter_slidable/flutter_slidable.dart';
|
||||
|
||||
@ -25,7 +24,7 @@ class MobileViewItem extends StatelessWidget {
|
||||
super.key,
|
||||
required this.view,
|
||||
this.parentView,
|
||||
required this.categoryType,
|
||||
required this.spaceType,
|
||||
required this.level,
|
||||
this.leftPadding = 10,
|
||||
required this.onSelected,
|
||||
@ -39,7 +38,7 @@ class MobileViewItem extends StatelessWidget {
|
||||
final ViewPB view;
|
||||
final ViewPB? parentView;
|
||||
|
||||
final FolderCategoryType categoryType;
|
||||
final FolderSpaceType spaceType;
|
||||
|
||||
// indicate the level of the view item
|
||||
// used to calculate the left padding
|
||||
@ -80,7 +79,7 @@ class MobileViewItem extends StatelessWidget {
|
||||
view: state.view,
|
||||
parentView: parentView,
|
||||
childViews: state.view.childViews,
|
||||
categoryType: categoryType,
|
||||
spaceType: spaceType,
|
||||
level: level,
|
||||
leftPadding: leftPadding,
|
||||
showActions: true,
|
||||
@ -104,7 +103,7 @@ class InnerMobileViewItem extends StatelessWidget {
|
||||
required this.view,
|
||||
required this.parentView,
|
||||
required this.childViews,
|
||||
required this.categoryType,
|
||||
required this.spaceType,
|
||||
this.isDraggable = true,
|
||||
this.isExpanded = true,
|
||||
required this.level,
|
||||
@ -120,7 +119,7 @@ class InnerMobileViewItem extends StatelessWidget {
|
||||
final ViewPB view;
|
||||
final ViewPB? parentView;
|
||||
final List<ViewPB> childViews;
|
||||
final FolderCategoryType categoryType;
|
||||
final FolderSpaceType spaceType;
|
||||
|
||||
final bool isDraggable;
|
||||
final bool isExpanded;
|
||||
@ -144,7 +143,7 @@ class InnerMobileViewItem extends StatelessWidget {
|
||||
parentView: parentView,
|
||||
level: level,
|
||||
showActions: showActions,
|
||||
categoryType: categoryType,
|
||||
spaceType: spaceType,
|
||||
onSelected: onSelected,
|
||||
isExpanded: isExpanded,
|
||||
isDraggable: isDraggable,
|
||||
@ -159,9 +158,9 @@ class InnerMobileViewItem extends StatelessWidget {
|
||||
if (childViews.isNotEmpty) {
|
||||
final children = childViews.map((childView) {
|
||||
return MobileViewItem(
|
||||
key: ValueKey('${categoryType.name} ${childView.id}'),
|
||||
key: ValueKey('${spaceType.name} ${childView.id}'),
|
||||
parentView: view,
|
||||
categoryType: categoryType,
|
||||
spaceType: spaceType,
|
||||
isFirstChild: childView.id == childViews.first.id,
|
||||
view: childView,
|
||||
level: level + 1,
|
||||
@ -235,7 +234,7 @@ class InnerMobileViewItem extends StatelessWidget {
|
||||
return MobileViewItem(
|
||||
view: view,
|
||||
parentView: parentView,
|
||||
categoryType: categoryType,
|
||||
spaceType: spaceType,
|
||||
level: level,
|
||||
onSelected: onSelected,
|
||||
isDraggable: false,
|
||||
@ -262,7 +261,7 @@ class SingleMobileInnerViewItem extends StatefulWidget {
|
||||
required this.level,
|
||||
required this.leftPadding,
|
||||
this.isDraggable = true,
|
||||
required this.categoryType,
|
||||
required this.spaceType,
|
||||
required this.showActions,
|
||||
required this.onSelected,
|
||||
required this.isFeedback,
|
||||
@ -282,7 +281,7 @@ class SingleMobileInnerViewItem extends StatefulWidget {
|
||||
final bool isDraggable;
|
||||
final bool showActions;
|
||||
final ViewItemOnSelected onSelected;
|
||||
final FolderCategoryType categoryType;
|
||||
final FolderSpaceType spaceType;
|
||||
final ActionPaneBuilder? startActionPane;
|
||||
final ActionPaneBuilder? endActionPane;
|
||||
|
||||
@ -407,10 +406,9 @@ class _SingleMobileInnerViewItemState extends State<SingleMobileInnerViewItem> {
|
||||
ViewEvent.createView(
|
||||
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||
layout,
|
||||
section:
|
||||
widget.categoryType != FolderCategoryType.favorite
|
||||
? widget.categoryType.toViewSectionPB
|
||||
: null,
|
||||
section: widget.spaceType != FolderSpaceType.favorite
|
||||
? widget.spaceType.toViewSectionPB
|
||||
: null,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -37,7 +37,6 @@ class RTLSetting extends StatelessWidget {
|
||||
showHeader: true,
|
||||
showDragHandle: true,
|
||||
showDivider: false,
|
||||
showCloseButton: false,
|
||||
title: LocaleKeys.settings_appearance_textDirection_label.tr(),
|
||||
builder: (context) {
|
||||
final layoutDirection =
|
||||
|
@ -45,7 +45,6 @@ class TextScaleSetting extends StatelessWidget {
|
||||
showHeader: true,
|
||||
showDragHandle: true,
|
||||
showDivider: false,
|
||||
showCloseButton: false,
|
||||
title: LocaleKeys.settings_appearance_fontScaleFactor.tr(),
|
||||
builder: (context) {
|
||||
return FontSizeStepper(
|
||||
|
@ -38,7 +38,6 @@ class ThemeSetting extends StatelessWidget {
|
||||
showHeader: true,
|
||||
showDragHandle: true,
|
||||
showDivider: false,
|
||||
showCloseButton: false,
|
||||
title: LocaleKeys.settings_appearance_themeMode_label.tr(),
|
||||
builder: (context) {
|
||||
final themeMode =
|
||||
|
@ -29,9 +29,7 @@ class FontPickerScreen extends StatelessWidget {
|
||||
}
|
||||
|
||||
class LanguagePickerPage extends StatefulWidget {
|
||||
const LanguagePickerPage({
|
||||
super.key,
|
||||
});
|
||||
const LanguagePickerPage({super.key});
|
||||
|
||||
@override
|
||||
State<LanguagePickerPage> createState() => _LanguagePickerPageState();
|
||||
@ -43,7 +41,6 @@ class _LanguagePickerPageState extends State<LanguagePickerPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
availableFonts = _availableFonts;
|
||||
}
|
||||
|
||||
@ -90,7 +87,6 @@ class _FontSelectorState extends State<FontSelector> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
availableFonts = _availableFonts;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ class MobileQuickActionButton extends StatelessWidget {
|
||||
onTap: enable ? onTap : null,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
overlayColor:
|
||||
enable ? null : const MaterialStatePropertyAll(Colors.transparent),
|
||||
enable ? null : const WidgetStatePropertyAll(Colors.transparent),
|
||||
splashColor: Colors.transparent,
|
||||
child: Container(
|
||||
height: 44,
|
||||
|
@ -1,12 +1,10 @@
|
||||
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/size.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? kCachedEmojiData;
|
||||
@ -27,7 +25,6 @@ class FlowyEmojiPicker extends StatefulWidget {
|
||||
|
||||
class _FlowyEmojiPickerState extends State<FlowyEmojiPicker> {
|
||||
EmojiData? emojiData;
|
||||
List<String>? fallbackFontFamily;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -46,13 +43,6 @@ class _FlowyEmojiPickerState extends State<FlowyEmojiPicker> {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (Platform.isAndroid || Platform.isLinux) {
|
||||
final notoColorEmoji = GoogleFonts.notoColorEmoji().fontFamily;
|
||||
if (notoColorEmoji != null) {
|
||||
fallbackFontFamily = [notoColorEmoji];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -82,14 +72,18 @@ class _FlowyEmojiPickerState extends State<FlowyEmojiPicker> {
|
||||
);
|
||||
},
|
||||
itemBuilder: (context, emojiId, emoji, callback) {
|
||||
return FlowyIconButton(
|
||||
iconPadding: const EdgeInsets.all(2.0),
|
||||
icon: FlowyText(
|
||||
emoji,
|
||||
fontSize: 28.0,
|
||||
fallbackFontFamily: fallbackFontFamily,
|
||||
return SizedBox(
|
||||
width: 36,
|
||||
height: 36,
|
||||
child: FlowyButton(
|
||||
margin: EdgeInsets.zero,
|
||||
radius: Corners.s8Border,
|
||||
text: FlowyText.emoji(
|
||||
emoji,
|
||||
fontSize: 24.0,
|
||||
),
|
||||
onTap: () => callback(emojiId, emoji),
|
||||
),
|
||||
onPressed: () => callback(emojiId, emoji),
|
||||
);
|
||||
},
|
||||
searchBarBuilder: (context, keyword, skinTone) {
|
||||
|
@ -16,9 +16,14 @@ class FlowyEmojiHeader extends StatelessWidget {
|
||||
if (PlatformExtension.isDesktopOrWeb) {
|
||||
return Container(
|
||||
height: 22,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
color: Theme.of(context).cardColor,
|
||||
child: FlowyText.regular(category.id),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: FlowyText.regular(
|
||||
category.id,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Column(
|
||||
|
@ -42,7 +42,7 @@ class _FlowyEmojiSearchBarState extends State<FlowyEmojiSearchBar> {
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
vertical: 12.0,
|
||||
horizontal: PlatformExtension.isDesktopOrWeb ? 0.0 : 8.0,
|
||||
),
|
||||
child: Row(
|
||||
@ -52,16 +52,15 @@ class _FlowyEmojiSearchBarState extends State<FlowyEmojiSearchBar> {
|
||||
onKeywordChanged: widget.onKeywordChanged,
|
||||
),
|
||||
),
|
||||
const HSpace(6.0),
|
||||
const HSpace(8.0),
|
||||
_RandomEmojiButton(
|
||||
emojiData: widget.emojiData,
|
||||
onRandomEmojiSelected: widget.onRandomEmojiSelected,
|
||||
),
|
||||
const HSpace(6.0),
|
||||
const HSpace(8.0),
|
||||
FlowyEmojiSkinToneSelector(
|
||||
onEmojiSkinToneChanged: widget.onSkinToneChanged,
|
||||
),
|
||||
const HSpace(6.0),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -79,20 +78,30 @@ class _RandomEmojiButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FlowyTooltip(
|
||||
message: LocaleKeys.emoji_random.tr(),
|
||||
child: FlowyButton(
|
||||
useIntrinsicWidth: true,
|
||||
text: const Icon(
|
||||
Icons.shuffle_rounded,
|
||||
return Container(
|
||||
width: 36,
|
||||
height: 36,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: const BorderSide(color: Color(0x1E171717)),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: FlowyTooltip(
|
||||
message: LocaleKeys.emoji_random.tr(),
|
||||
child: FlowyButton(
|
||||
useIntrinsicWidth: true,
|
||||
text: const FlowySvg(
|
||||
FlowySvgs.icon_shuffle_s,
|
||||
),
|
||||
onTap: () {
|
||||
final random = emojiData.random;
|
||||
onRandomEmojiSelected(
|
||||
random.$1,
|
||||
random.$2,
|
||||
);
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
final random = emojiData.random;
|
||||
onRandomEmojiSelected(
|
||||
random.$1,
|
||||
random.$2,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -123,32 +132,35 @@ class _SearchTextFieldState extends State<_SearchTextField> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxHeight: 32.0,
|
||||
),
|
||||
return SizedBox(
|
||||
height: 36.0,
|
||||
child: FlowyTextField(
|
||||
focusNode: focusNode,
|
||||
hintText: LocaleKeys.emoji_search.tr(),
|
||||
hintText: LocaleKeys.search_label.tr(),
|
||||
hintStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
controller: controller,
|
||||
onChanged: widget.onKeywordChanged,
|
||||
prefixIcon: const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 8.0,
|
||||
right: 4.0,
|
||||
left: 14.0,
|
||||
right: 8.0,
|
||||
),
|
||||
child: FlowySvg(
|
||||
FlowySvgs.search_s,
|
||||
),
|
||||
),
|
||||
prefixIconConstraints: const BoxConstraints(
|
||||
maxHeight: 18.0,
|
||||
maxHeight: 20.0,
|
||||
),
|
||||
suffixIcon: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: FlowyButton(
|
||||
text: const FlowySvg(
|
||||
FlowySvgs.close_lg,
|
||||
FlowySvgs.m_app_bar_close_s,
|
||||
),
|
||||
margin: EdgeInsets.zero,
|
||||
useIntrinsicWidth: true,
|
||||
|
@ -57,7 +57,7 @@ class _FlowyEmojiSkinToneSelectorState
|
||||
child: FlowyTooltip(
|
||||
message: LocaleKeys.emoji_selectSkinTone.tr(),
|
||||
child: _buildIconButton(
|
||||
lastSelectedEmojiSkinTone?.icon ?? '✋',
|
||||
lastSelectedEmojiSkinTone?.icon ?? '👋',
|
||||
() => controller.show(),
|
||||
),
|
||||
),
|
||||
@ -65,19 +65,22 @@ class _FlowyEmojiSkinToneSelectorState
|
||||
}
|
||||
|
||||
Widget _buildIconButton(String icon, VoidCallback onPressed) {
|
||||
return FlowyIconButton(
|
||||
key: emojiSkinToneKey(icon),
|
||||
icon: Padding(
|
||||
// add a left padding to align the emoji center
|
||||
padding: const EdgeInsets.only(
|
||||
left: 3.0,
|
||||
),
|
||||
child: FlowyText(
|
||||
icon,
|
||||
fontSize: 22.0,
|
||||
),
|
||||
return Container(
|
||||
width: 36,
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: const Color(0x1E171717)),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: FlowyButton(
|
||||
key: emojiSkinToneKey(icon),
|
||||
margin: EdgeInsets.zero,
|
||||
text: FlowyText.emoji(
|
||||
icon,
|
||||
fontSize: 24.0,
|
||||
),
|
||||
onTap: onPressed,
|
||||
),
|
||||
onPressed: onPressed,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -86,17 +89,17 @@ extension EmojiSkinToneIcon on EmojiSkinTone {
|
||||
String get icon {
|
||||
switch (this) {
|
||||
case EmojiSkinTone.none:
|
||||
return '✋';
|
||||
return '👋';
|
||||
case EmojiSkinTone.light:
|
||||
return '✋🏻';
|
||||
return '👋🏻';
|
||||
case EmojiSkinTone.mediumLight:
|
||||
return '✋🏼';
|
||||
return '👋🏼';
|
||||
case EmojiSkinTone.medium:
|
||||
return '✋🏽';
|
||||
return '👋🏽';
|
||||
case EmojiSkinTone.mediumDark:
|
||||
return '✋🏾';
|
||||
return '👋🏾';
|
||||
case EmojiSkinTone.dark:
|
||||
return '✋🏿';
|
||||
return '👋🏿';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ class EmojiText extends StatelessWidget {
|
||||
emoji,
|
||||
fontSize: fontSize,
|
||||
textAlign: textAlign,
|
||||
strutStyle: const StrutStyle(forceStrutHeight: true),
|
||||
fallbackFontFamily: _cachedFallbackFontFamily,
|
||||
lineHeight: lineHeight,
|
||||
);
|
||||
|
@ -1,13 +1,10 @@
|
||||
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/base/emoji/emoji_picker.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/icon.pbenum.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';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
extension ToProto on FlowyIconType {
|
||||
ViewIconTypePB toProto() {
|
||||
@ -54,57 +51,28 @@ class FlowyIconPicker extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// ONLY supports emoji picker for now
|
||||
return DefaultTabController(
|
||||
length: 1,
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const VSpace(8.0),
|
||||
Row(
|
||||
children: [
|
||||
_buildTabs(context),
|
||||
FlowyText(LocaleKeys.newSettings_workplace_chooseAnIcon.tr()),
|
||||
const Spacer(),
|
||||
_RemoveIconButton(
|
||||
onTap: () => onSelected(EmojiPickerResult.none()),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(height: 2),
|
||||
const VSpace(12.0),
|
||||
const Divider(height: 0.5),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
children: [
|
||||
FlowyEmojiPicker(
|
||||
emojiPerLine: _getEmojiPerLine(context),
|
||||
onEmojiSelected: (_, emoji) =>
|
||||
onSelected(EmojiPickerResult.emoji(emoji)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTabs(BuildContext context) {
|
||||
return Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: TabBar(
|
||||
indicatorSize: TabBarIndicatorSize.label,
|
||||
isScrollable: true,
|
||||
overlayColor: MaterialStatePropertyAll(
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
tabs: [
|
||||
FlowyHover(
|
||||
style: const HoverStyle(borderRadius: BorderRadius.zero),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: FlowyText(LocaleKeys.emoji_emojiTab.tr()),
|
||||
child: FlowyEmojiPicker(
|
||||
emojiPerLine: _getEmojiPerLine(context),
|
||||
onEmojiSelected: (_, emoji) =>
|
||||
onSelected(EmojiPickerResult.emoji(emoji)),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -117,7 +85,7 @@ class FlowyIconPicker extends StatelessWidget {
|
||||
return 9;
|
||||
}
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
return width ~/ 46.0; // the size of the emoji
|
||||
return width ~/ 40.0; // the size of the emoji
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,14 +97,14 @@ class _RemoveIconButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 28,
|
||||
height: 24,
|
||||
child: FlowyButton(
|
||||
onTap: onTap,
|
||||
useIntrinsicWidth: true,
|
||||
text: FlowyText.small(
|
||||
LocaleKeys.document_plugins_cover_removeIcon.tr(),
|
||||
text: FlowyText.regular(
|
||||
LocaleKeys.button_remove.tr(),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
leftIcon: const FlowySvg(FlowySvgs.delete_s),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:appflowy_board/appflowy_board.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.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/error_page.dart';
|
||||
@ -671,7 +672,7 @@ class _BoardCardState extends State<_BoardCard> {
|
||||
? const Color(0x0F1F2329)
|
||||
: const Color(0x0FEFF4FB),
|
||||
foregroundColorOnHover:
|
||||
Theme.of(context).colorScheme.onBackground,
|
||||
AFThemeExtension.of(context).onBackground,
|
||||
),
|
||||
),
|
||||
onStartEditing: () =>
|
||||
|
@ -238,7 +238,7 @@ class NewEventButton extends StatelessWidget {
|
||||
child: FlowyIconButton(
|
||||
onPressed: onCreate,
|
||||
icon: const FlowySvg(FlowySvgs.add_s),
|
||||
fillColor: Theme.of(context).colorScheme.background,
|
||||
fillColor: Theme.of(context).colorScheme.surface,
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
width: 22,
|
||||
tooltipText: LocaleKeys.calendar_newEventButtonTooltip.tr(),
|
||||
@ -289,8 +289,8 @@ class _DayBadge extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color dayTextColor = Theme.of(context).colorScheme.onBackground;
|
||||
Color monthTextColor = Theme.of(context).colorScheme.onBackground;
|
||||
Color dayTextColor = AFThemeExtension.of(context).onBackground;
|
||||
Color monthTextColor = AFThemeExtension.of(context).onBackground;
|
||||
final String monthString =
|
||||
DateFormat("MMM ", context.locale.toLanguageTag()).format(date);
|
||||
final String dayString = date.day.toString();
|
||||
|
@ -8,6 +8,7 @@ import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra/size.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:flutter/material.dart';
|
||||
@ -15,7 +16,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../application/calendar_bloc.dart';
|
||||
|
||||
import 'calendar_event_editor.dart';
|
||||
|
||||
class EventCard extends StatefulWidget {
|
||||
@ -102,7 +102,7 @@ class _EventCardState extends State<EventCard> {
|
||||
hoverColor: Theme.of(context).brightness == Brightness.light
|
||||
? const Color(0x0F1F2329)
|
||||
: const Color(0x0FEFF4FB),
|
||||
foregroundColorOnHover: Theme.of(context).colorScheme.onBackground,
|
||||
foregroundColorOnHover: AFThemeExtension.of(context).onBackground,
|
||||
),
|
||||
),
|
||||
onStartEditing: () {},
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
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.dart';
|
||||
@ -21,12 +19,12 @@ import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../application/row/row_controller.dart';
|
||||
import '../../widgets/row/row_detail.dart';
|
||||
|
||||
import 'calendar_day.dart';
|
||||
import 'layout/sizes.dart';
|
||||
import 'toolbar/calendar_setting_bar.dart';
|
||||
|
@ -43,7 +43,7 @@ Widget getGridFabs(BuildContext context) {
|
||||
.read<GridBloc>()
|
||||
.add(const GridEvent.createRow(openRowDetail: true));
|
||||
},
|
||||
overlayColor: const MaterialStatePropertyAll<Color>(Color(0xFF009FD1)),
|
||||
overlayColor: const WidgetStatePropertyAll<Color>(Color(0xFF009FD1)),
|
||||
boxShadow: const BoxShadow(
|
||||
offset: Offset(0, 8),
|
||||
color: Color(0x6612BFEF),
|
||||
@ -75,7 +75,7 @@ class MobileGridFab extends StatelessWidget {
|
||||
final VoidCallback onTap;
|
||||
final FlowySvgData icon;
|
||||
final Size iconSize;
|
||||
final MaterialStateProperty<Color?>? overlayColor;
|
||||
final WidgetStateProperty<Color?>? overlayColor;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -77,22 +77,22 @@ class _DatabaseViewSelectorButton extends StatelessWidget {
|
||||
|
||||
return TextButton(
|
||||
style: ButtonStyle(
|
||||
padding: const MaterialStatePropertyAll(
|
||||
padding: const WidgetStatePropertyAll(
|
||||
EdgeInsets.fromLTRB(12, 8, 8, 8),
|
||||
),
|
||||
maximumSize: const MaterialStatePropertyAll(Size(200, 48)),
|
||||
minimumSize: const MaterialStatePropertyAll(Size(48, 0)),
|
||||
shape: const MaterialStatePropertyAll(
|
||||
maximumSize: const WidgetStatePropertyAll(Size(200, 48)),
|
||||
minimumSize: const WidgetStatePropertyAll(Size(48, 0)),
|
||||
shape: const WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
),
|
||||
backgroundColor: MaterialStatePropertyAll(
|
||||
backgroundColor: WidgetStatePropertyAll(
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? const Color(0x0F212729)
|
||||
: const Color(0x0FFFFFFF),
|
||||
),
|
||||
overlayColor: MaterialStatePropertyAll(
|
||||
overlayColor: WidgetStatePropertyAll(
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
@ -119,7 +119,6 @@ class _DatabaseViewSelectorButton extends StatelessWidget {
|
||||
showTransitionMobileBottomSheet(
|
||||
context,
|
||||
showDivider: false,
|
||||
initialStop: 1.0,
|
||||
builder: (_) {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
|
@ -236,7 +236,8 @@ class DatabasePluginWidgetBuilder extends PluginWidgetBuilder {
|
||||
final String? initialRowId;
|
||||
|
||||
@override
|
||||
Widget get leftBarItem => ViewTitleBar(view: notifier.view);
|
||||
Widget get leftBarItem =>
|
||||
ViewTitleBar(key: ValueKey(notifier.view.id), view: notifier.view);
|
||||
|
||||
@override
|
||||
Widget tabBarItem(String pluginId) => ViewTabBarItem(view: notifier.view);
|
||||
@ -278,7 +279,7 @@ class DatabasePluginWidgetBuilder extends PluginWidgetBuilder {
|
||||
]
|
||||
: [],
|
||||
DatabaseShareButton(key: ValueKey(view.id), view: view),
|
||||
const HSpace(4),
|
||||
const HSpace(10),
|
||||
ViewFavoriteButton(view: view),
|
||||
const HSpace(4),
|
||||
MoreViewActions(view: view, isDocument: false),
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
||||
import 'package:appflowy/plugins/database/application/row/row_cache.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/widgets/row/action.dart';
|
||||
@ -186,7 +185,7 @@ class _CardContent extends StatelessWidget {
|
||||
|
||||
final RowMetaPB rowMeta;
|
||||
final CardCellBuilder cellBuilder;
|
||||
final List<CellContext> cells;
|
||||
final List<CellMeta> cells;
|
||||
final RowCardStyleConfiguration styleConfiguration;
|
||||
|
||||
@override
|
||||
@ -210,9 +209,9 @@ class _CardContent extends StatelessWidget {
|
||||
List<Widget> _makeCells(
|
||||
BuildContext context,
|
||||
RowMetaPB rowMeta,
|
||||
List<CellContext> cells,
|
||||
List<CellMeta> cells,
|
||||
) {
|
||||
return cells.mapIndexed((int index, CellContext cellContext) {
|
||||
return cells.mapIndexed((int index, CellMeta cellMeta) {
|
||||
EditableCardNotifier? cellNotifier;
|
||||
|
||||
if (index == 0) {
|
||||
@ -225,7 +224,7 @@ class _CardContent extends StatelessWidget {
|
||||
}
|
||||
|
||||
return cellBuilder.build(
|
||||
cellContext: cellContext,
|
||||
cellContext: cellMeta.cellContext(),
|
||||
cellNotifier: cellNotifier,
|
||||
styleMap: styleConfiguration.cellStyleMap,
|
||||
hasNotes: !rowMeta.isDocumentEmpty,
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:appflowy/plugins/database/application/row/row_service.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
|
||||
@ -7,7 +9,6 @@ import 'package:appflowy/plugins/database/application/field/field_controller.dar
|
||||
import 'package:appflowy/plugins/database/application/row/row_cache.dart';
|
||||
import 'package:appflowy/plugins/database/domain/row_listener.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/setting/field_visibility_extension.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/row_entities.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
@ -104,7 +105,7 @@ class CardBloc extends Bloc<CardEvent, CardState> {
|
||||
}
|
||||
}
|
||||
|
||||
List<CellContext> _makeCells(
|
||||
List<CellMeta> _makeCells(
|
||||
FieldController fieldController,
|
||||
String? groupFieldId,
|
||||
List<CellContext> cellContexts,
|
||||
@ -116,7 +117,15 @@ List<CellContext> _makeCells(
|
||||
!(fieldInfo.visibility?.isVisibleState() ?? false) ||
|
||||
(groupFieldId != null && cellContext.fieldId == groupFieldId);
|
||||
});
|
||||
return cellContexts.toList();
|
||||
return cellContexts
|
||||
.map(
|
||||
(cellCtx) => CellMeta(
|
||||
fieldId: cellCtx.fieldId,
|
||||
rowId: cellCtx.rowId,
|
||||
fieldType: fieldController.getField(cellCtx.fieldId)!.fieldType,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -124,17 +133,30 @@ class CardEvent with _$CardEvent {
|
||||
const factory CardEvent.initial() = _InitialRow;
|
||||
const factory CardEvent.setIsEditing(bool isEditing) = _IsEditing;
|
||||
const factory CardEvent.didReceiveCells(
|
||||
List<CellContext> cells,
|
||||
List<CellMeta> cells,
|
||||
ChangedReason reason,
|
||||
) = _DidReceiveCells;
|
||||
const factory CardEvent.didUpdateRowMeta(RowMetaPB rowMeta) =
|
||||
_DidUpdateRowMeta;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class CellMeta with _$CellMeta {
|
||||
const CellMeta._();
|
||||
|
||||
const factory CellMeta({
|
||||
required String fieldId,
|
||||
required RowId rowId,
|
||||
required FieldType fieldType,
|
||||
}) = _DatabaseCellMeta;
|
||||
|
||||
CellContext cellContext() => CellContext(fieldId: fieldId, rowId: rowId);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class CardState with _$CardState {
|
||||
const factory CardState({
|
||||
required List<CellContext> cells,
|
||||
required List<CellMeta> cells,
|
||||
required RowMetaPB rowMeta,
|
||||
required bool isEditing,
|
||||
ChangedReason? changeReason,
|
||||
@ -142,7 +164,7 @@ class CardState with _$CardState {
|
||||
|
||||
factory CardState.initial(
|
||||
RowMetaPB rowMeta,
|
||||
List<CellContext> cells,
|
||||
List<CellMeta> cells,
|
||||
bool isEditing,
|
||||
) =>
|
||||
CardState(
|
||||
|
@ -42,7 +42,6 @@ class MobileGridRelationCellSkin extends IEditableRelationCellSkin {
|
||||
onTap: () {
|
||||
showMobileBottomSheet(
|
||||
context,
|
||||
padding: EdgeInsets.zero,
|
||||
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||
builder: (context) {
|
||||
return const FlowyText("Coming soon");
|
||||
|
@ -2,6 +2,7 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_she
|
||||
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@ -51,7 +52,7 @@ class MobileGridURLCellSkin extends IEditableURLCellSkin {
|
||||
showMobileBottomSheet(
|
||||
context,
|
||||
showDragHandle: true,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
builder: (context) => BlocProvider.value(
|
||||
value: bloc,
|
||||
child: MobileURLEditor(
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/bloc/checkbox_cell_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../editable_cell_skeleton/checkbox.dart';
|
||||
@ -31,7 +32,7 @@ class MobileRowDetailCheckboxCellSkin extends IEditableCheckboxCellSkin {
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: FlowySvg(
|
||||
state.isSelected ? FlowySvgs.check_filled_s : FlowySvgs.uncheck_s,
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
color: AFThemeExtension.of(context).onBackground,
|
||||
blendMode: BlendMode.dst,
|
||||
size: const Size.square(24),
|
||||
),
|
||||
|
@ -1,11 +1,12 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/bloc/checklist_cell_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_progress_bar.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell_editor/mobile_checklist_cell_editor.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.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/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -25,7 +26,7 @@ class MobileRowDetailChecklistCellSkin extends IEditableChecklistCellSkin {
|
||||
borderRadius: const BorderRadius.all(Radius.circular(14)),
|
||||
onTap: () => showMobileBottomSheet(
|
||||
context,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
builder: (context) {
|
||||
return BlocProvider.value(
|
||||
value: bloc,
|
||||
|
@ -19,7 +19,6 @@ class MobileRowDetailRelationCellSkin extends IEditableRelationCellSkin {
|
||||
borderRadius: const BorderRadius.all(Radius.circular(14)),
|
||||
onTap: () => showMobileBottomSheet(
|
||||
context,
|
||||
padding: EdgeInsets.zero,
|
||||
builder: (context) {
|
||||
return const FlowyText("Coming soon");
|
||||
},
|
||||
|
@ -1,12 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
|
||||
import '../editable_cell_skeleton/url.dart';
|
||||
|
||||
@ -28,7 +28,7 @@ class MobileRowDetailURLCellSkin extends IEditableURLCellSkin {
|
||||
onTap: () => showMobileBottomSheet(
|
||||
context,
|
||||
showDragHandle: true,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
builder: (_) {
|
||||
return BlocProvider.value(
|
||||
value: bloc,
|
||||
|
@ -423,7 +423,7 @@ class _DeleteTaskButton extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _DeleteTaskButtonState extends State<_DeleteTaskButton> {
|
||||
final _materialStatesController = MaterialStatesController();
|
||||
final _materialStatesController = WidgetStatesController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@ -438,16 +438,16 @@ class _DeleteTaskButtonState extends State<_DeleteTaskButton> {
|
||||
onHover: (_) => setState(() {}),
|
||||
onFocusChange: (_) => setState(() {}),
|
||||
style: ButtonStyle(
|
||||
fixedSize: const MaterialStatePropertyAll(Size.square(32)),
|
||||
minimumSize: const MaterialStatePropertyAll(Size.square(32)),
|
||||
maximumSize: const MaterialStatePropertyAll(Size.square(32)),
|
||||
overlayColor: MaterialStateProperty.resolveWith((state) {
|
||||
if (state.contains(MaterialState.focused)) {
|
||||
fixedSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
minimumSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
maximumSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
overlayColor: WidgetStateProperty.resolveWith((state) {
|
||||
if (state.contains(WidgetState.focused)) {
|
||||
return AFThemeExtension.of(context).greyHover;
|
||||
}
|
||||
return Colors.transparent;
|
||||
}),
|
||||
shape: const MaterialStatePropertyAll(
|
||||
shape: const WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: Corners.s6Border),
|
||||
),
|
||||
),
|
||||
@ -455,8 +455,8 @@ class _DeleteTaskButtonState extends State<_DeleteTaskButton> {
|
||||
child: FlowySvg(
|
||||
FlowySvgs.delete_s,
|
||||
color: _materialStatesController.value
|
||||
.contains(MaterialState.hovered) ||
|
||||
_materialStatesController.value.contains(MaterialState.focused)
|
||||
.contains(WidgetState.hovered) ||
|
||||
_materialStatesController.value.contains(WidgetState.focused)
|
||||
? Theme.of(context).colorScheme.error
|
||||
: null,
|
||||
),
|
||||
|
@ -422,7 +422,7 @@ class _UnselectRowButton extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _UnselectRowButtonState extends State<_UnselectRowButton> {
|
||||
final _materialStatesController = MaterialStatesController();
|
||||
final _materialStatesController = WidgetStatesController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@ -437,26 +437,25 @@ class _UnselectRowButtonState extends State<_UnselectRowButton> {
|
||||
onHover: (_) => setState(() {}),
|
||||
onFocusChange: (_) => setState(() {}),
|
||||
style: ButtonStyle(
|
||||
fixedSize: const MaterialStatePropertyAll(Size.square(32)),
|
||||
minimumSize: const MaterialStatePropertyAll(Size.square(32)),
|
||||
maximumSize: const MaterialStatePropertyAll(Size.square(32)),
|
||||
overlayColor: MaterialStateProperty.resolveWith((state) {
|
||||
if (state.contains(MaterialState.focused)) {
|
||||
fixedSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
minimumSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
maximumSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
overlayColor: WidgetStateProperty.resolveWith((state) {
|
||||
if (state.contains(WidgetState.focused)) {
|
||||
return AFThemeExtension.of(context).greyHover;
|
||||
}
|
||||
return Colors.transparent;
|
||||
}),
|
||||
shape: const MaterialStatePropertyAll(
|
||||
shape: const WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: Corners.s6Border),
|
||||
),
|
||||
),
|
||||
statesController: _materialStatesController,
|
||||
child: Container(
|
||||
color: _materialStatesController.value
|
||||
.contains(MaterialState.hovered) ||
|
||||
_materialStatesController.value.contains(MaterialState.focused)
|
||||
color: _materialStatesController.value.contains(WidgetState.hovered) ||
|
||||
_materialStatesController.value.contains(WidgetState.focused)
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onBackground,
|
||||
: AFThemeExtension.of(context).onBackground,
|
||||
width: 12,
|
||||
height: 1,
|
||||
),
|
||||
|
@ -380,7 +380,7 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
|
||||
icon: FlowySvg(
|
||||
FlowySvgs.three_dots_s,
|
||||
size: const Size.square(16),
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
color: AFThemeExtension.of(context).onBackground,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -462,7 +462,7 @@ class SelectOptionTagCell extends StatelessWidget {
|
||||
child: FlowySvg(
|
||||
FlowySvgs.drag_element_s,
|
||||
size: const Size.square(14),
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
color: AFThemeExtension.of(context).onBackground,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -20,7 +20,7 @@ const List<FieldType> _supportedFieldTypes = [
|
||||
FieldType.LastEditedTime,
|
||||
FieldType.CreatedTime,
|
||||
FieldType.Relation,
|
||||
// FieldType.Summary,
|
||||
FieldType.Summary,
|
||||
];
|
||||
|
||||
class FieldTypeList extends StatelessWidget with FlowyOverlayDelegate {
|
||||
|
@ -314,17 +314,17 @@ class ToggleHiddenFieldsVisibilityButton extends StatelessWidget {
|
||||
constraints: const BoxConstraints(minWidth: double.infinity),
|
||||
child: TextButton.icon(
|
||||
style: Theme.of(context).textButtonTheme.style?.copyWith(
|
||||
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||
shape: WidgetStateProperty.all<RoundedRectangleBorder>(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
),
|
||||
overlayColor: MaterialStateProperty.all<Color>(
|
||||
overlayColor: WidgetStateProperty.all<Color>(
|
||||
Theme.of(context).hoverColor,
|
||||
),
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
splashFactory: NoSplash.splashFactory,
|
||||
padding: const MaterialStatePropertyAll(
|
||||
padding: const WidgetStatePropertyAll(
|
||||
EdgeInsets.symmetric(vertical: 14, horizontal: 6),
|
||||
),
|
||||
),
|
||||
|
@ -9,6 +9,7 @@ import 'package:appflowy/plugins/database/grid/application/sort/sort_editor_bloc
|
||||
import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.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/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -128,7 +129,6 @@ void _showDatabaseFieldListFromToolbar(
|
||||
showHeader: true,
|
||||
showBackButton: true,
|
||||
title: LocaleKeys.grid_settings_properties.tr(),
|
||||
showDivider: true,
|
||||
builder: (_) {
|
||||
return BlocProvider.value(
|
||||
value: context.read<ViewBloc>(),
|
||||
@ -150,7 +150,7 @@ void _showEditSortPanelFromToolbar(
|
||||
showDragHandle: true,
|
||||
showDivider: false,
|
||||
useSafeArea: false,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
backgroundColor: AFThemeExtension.of(context).background,
|
||||
builder: (_) {
|
||||
return BlocProvider.value(
|
||||
value: context.read<SortEditorBloc>(),
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/application/share_bloc.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
@ -13,6 +11,7 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/file_picker/file_picker_service.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class DatabaseShareButton extends StatelessWidget {
|
||||
@ -39,11 +38,7 @@ class DatabaseShareButton extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
child: BlocBuilder<DatabaseShareBloc, DatabaseShareState>(
|
||||
builder: (context, state) => ConstrainedBox(
|
||||
constraints: const BoxConstraints.expand(
|
||||
height: 30,
|
||||
width: 100,
|
||||
),
|
||||
builder: (context, state) => IntrinsicWidth(
|
||||
child: DatabaseShareActionList(view: view),
|
||||
),
|
||||
),
|
||||
@ -106,6 +101,8 @@ class DatabaseShareActionListState extends State<DatabaseShareActionList> {
|
||||
onPointerDown: (_) => controller.show(),
|
||||
child: RoundedTextButton(
|
||||
title: LocaleKeys.shareAction_buttonText.tr(),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
fontSize: 14.0,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
onPressed: () {},
|
||||
),
|
||||
|
@ -20,7 +20,6 @@ import 'package:appflowy/util/debounce.dart';
|
||||
import 'package:appflowy/util/throttle.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_listener.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_service.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
@ -76,13 +75,15 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
||||
|
||||
StreamSubscription? _transactionSubscription;
|
||||
|
||||
final _updateSelectionDebounce = Debounce();
|
||||
final _syncThrottle = Throttler(duration: const Duration(milliseconds: 500));
|
||||
bool isClosing = false;
|
||||
|
||||
static const _syncDuration = Duration(milliseconds: 250);
|
||||
final _updateSelectionDebounce = Debounce(duration: _syncDuration);
|
||||
final _syncThrottle = Throttler(duration: _syncDuration);
|
||||
|
||||
// The conflict handle logic is not fully implemented yet
|
||||
// use the syncTimer to force to reload the document state when the conflict happens.
|
||||
Timer? _syncTimer;
|
||||
bool _shouldSync = false;
|
||||
|
||||
bool get isLocalMode {
|
||||
final userProfilePB = state.userProfilePB;
|
||||
@ -92,6 +93,10 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
isClosing = true;
|
||||
_updateSelectionDebounce.dispose();
|
||||
_syncThrottle.dispose();
|
||||
await _documentService.syncAwarenessStates(documentId: documentId);
|
||||
await _documentListener.stop();
|
||||
await _syncStateListener.stop();
|
||||
await _viewListener?.stop();
|
||||
@ -110,7 +115,6 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
||||
) async {
|
||||
await event.when(
|
||||
initial: () async {
|
||||
_resetSyncTimer();
|
||||
final result = await _fetchDocumentState();
|
||||
_onViewChanged();
|
||||
_onDocumentChanged();
|
||||
@ -205,19 +209,6 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
||||
);
|
||||
}
|
||||
|
||||
void _resetSyncTimer() {
|
||||
_syncTimer?.cancel();
|
||||
_syncTimer = null;
|
||||
_syncTimer = Timer.periodic(const Duration(seconds: 10), (_) {
|
||||
if (!_shouldSync) {
|
||||
return;
|
||||
}
|
||||
Log.debug('auto sync document');
|
||||
// unawaited(_documentCollabAdapter.forceReload());
|
||||
_shouldSync = false;
|
||||
});
|
||||
}
|
||||
|
||||
/// Fetch document
|
||||
Future<FlowyResult<EditorState?, FlowyError>> _fetchDocumentState() async {
|
||||
final result = await _documentService.openDocument(documentId: documentId);
|
||||
@ -257,10 +248,6 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
||||
// ignore: invalid_use_of_visible_for_testing_member
|
||||
emit(state.copyWith(isDocumentEmpty: editorState.document.isEmpty));
|
||||
}
|
||||
|
||||
// reset the sync timer
|
||||
_shouldSync = true;
|
||||
_resetSyncTimer();
|
||||
},
|
||||
);
|
||||
|
||||
@ -322,8 +309,6 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
||||
}
|
||||
|
||||
unawaited(_documentCollabAdapter.syncV3(docEvent: docEvent));
|
||||
|
||||
_resetSyncTimer();
|
||||
}
|
||||
|
||||
Future<void> _onAwarenessStatesUpdate(
|
||||
@ -347,13 +332,15 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
||||
}
|
||||
|
||||
void _throttleSyncDoc(DocEventPB docEvent) {
|
||||
_shouldSync = true;
|
||||
_syncThrottle.call(() {
|
||||
_onDocumentStateUpdate(docEvent);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _onSelectionUpdate() async {
|
||||
if (isClosing) {
|
||||
return;
|
||||
}
|
||||
final user = state.userProfilePB;
|
||||
final deviceId = ApplicationInfo.deviceId;
|
||||
if (!FeatureFlag.syncDocument.isOn || user == null) {
|
||||
|
@ -183,7 +183,7 @@ class DocumentCollabAdapter {
|
||||
for (final state in values) {
|
||||
// the following code is only for version 1
|
||||
if (state.version != 1 || state.metadata.isEmpty) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
final uid = state.user.uid.toString();
|
||||
final did = state.user.deviceId;
|
||||
@ -244,9 +244,8 @@ class DocumentCollabAdapter {
|
||||
);
|
||||
remoteSelections.add(remoteSelection);
|
||||
}
|
||||
if (remoteSelections.isNotEmpty) {
|
||||
editorState.remoteSelections.value = remoteSelections;
|
||||
}
|
||||
|
||||
editorState.remoteSelections.value = remoteSelections;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart'
|
||||
@ -10,7 +11,13 @@ import 'package:appflowy_editor/appflowy_editor.dart'
|
||||
Delta,
|
||||
ParagraphBlockKeys,
|
||||
NodeIterator,
|
||||
NodeExternalValues;
|
||||
NodeExternalValues,
|
||||
HeadingBlockKeys,
|
||||
QuoteBlockKeys,
|
||||
NumberedListBlockKeys,
|
||||
BulletedListBlockKeys,
|
||||
blockComponentDelta;
|
||||
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:nanoid/nanoid.dart';
|
||||
|
||||
@ -144,21 +151,25 @@ extension BlockToNode on BlockPB {
|
||||
final deltaString = meta.textMap[externalId];
|
||||
if (deltaString != null) {
|
||||
final delta = jsonDecode(deltaString);
|
||||
map['delta'] = delta;
|
||||
// map.putIfAbsent(
|
||||
// 'delta',
|
||||
// () => delta,
|
||||
// );
|
||||
map[blockComponentDelta] = delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Attributes adapterCallback(Attributes map) => map
|
||||
..putIfAbsent(
|
||||
blockComponentDelta,
|
||||
() => Delta().toJson(),
|
||||
);
|
||||
|
||||
final adapter = {
|
||||
ParagraphBlockKeys.type: (Attributes map) => map
|
||||
..putIfAbsent(
|
||||
'delta',
|
||||
() => Delta().toJson(),
|
||||
),
|
||||
ParagraphBlockKeys.type: adapterCallback,
|
||||
HeadingBlockKeys.type: adapterCallback,
|
||||
CodeBlockKeys.type: adapterCallback,
|
||||
QuoteBlockKeys.type: adapterCallback,
|
||||
NumberedListBlockKeys.type: adapterCallback,
|
||||
BulletedListBlockKeys.type: adapterCallback,
|
||||
ToggleListBlockKeys.type: adapterCallback,
|
||||
};
|
||||
return adapter[ty]?.call(map) ?? map;
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
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';
|
||||
@ -22,6 +20,7 @@ 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 {
|
||||
@ -130,7 +129,7 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
|
||||
}
|
||||
|
||||
@override
|
||||
Widget get leftBarItem => ViewTitleBar(view: view);
|
||||
Widget get leftBarItem => ViewTitleBar(key: ValueKey(view.id), view: view);
|
||||
|
||||
@override
|
||||
Widget tabBarItem(String pluginId) => ViewTabBarItem(view: notifier.view);
|
||||
@ -162,7 +161,7 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
|
||||
key: ValueKey('share_button_${view.id}'),
|
||||
view: view,
|
||||
),
|
||||
const HSpace(4),
|
||||
const HSpace(10),
|
||||
ViewFavoriteButton(
|
||||
key: ValueKey('favorite_button_${view.id}'),
|
||||
view: view,
|
||||
|
@ -23,7 +23,7 @@ class DocumentBanner extends StatelessWidget {
|
||||
constraints: const BoxConstraints(minHeight: 60),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
color: colorScheme.surfaceVariant,
|
||||
color: colorScheme.surfaceContainerHighest,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Row(
|
||||
|
@ -1,6 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_page.dart';
|
||||
@ -13,6 +10,8 @@ import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
|
||||
import 'package:easy_localization/easy_localization.dart' hide TextDirection;
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
Map<String, BlockComponentBuilder> getEditorBuilderMap({
|
||||
@ -93,8 +92,9 @@ Map<String, BlockComponentBuilder> getEditorBuilderMap({
|
||||
final factor = pageStyle.fontLayout.factor;
|
||||
final headingPaddings = pageStyle.lineHeightLayout.headingPaddings
|
||||
.map((e) => e * factor);
|
||||
final level = node.attributes[HeadingBlockKeys.level] ?? 6;
|
||||
return EdgeInsets.only(top: headingPaddings.elementAt(level));
|
||||
int level = node.attributes[HeadingBlockKeys.level] ?? 6;
|
||||
level = level.clamp(1, 6);
|
||||
return EdgeInsets.only(top: headingPaddings.elementAt(level - 1));
|
||||
}
|
||||
|
||||
return const EdgeInsets.only(top: 12.0, bottom: 4.0);
|
||||
|
@ -56,7 +56,18 @@ final List<CommandShortcutEvent> commandShortcutEvents = [
|
||||
customPasteCommand,
|
||||
customCutCommand,
|
||||
...customTextAlignCommands,
|
||||
...standardCommandShortcutEvents,
|
||||
|
||||
// remove standard shortcuts for copy, cut, paste, todo
|
||||
...standardCommandShortcutEvents
|
||||
..removeWhere(
|
||||
(shortcut) => [
|
||||
copyCommand,
|
||||
cutCommand,
|
||||
pasteCommand,
|
||||
toggleTodoListCommand,
|
||||
].contains(shortcut),
|
||||
),
|
||||
|
||||
emojiShortcutEvent,
|
||||
];
|
||||
|
||||
@ -90,7 +101,6 @@ class AppFlowyEditorPage extends StatefulWidget {
|
||||
final String Function(Node)? placeholderText;
|
||||
|
||||
/// Used to provide an initial selection on Page-load
|
||||
///
|
||||
final Selection? initialSelection;
|
||||
|
||||
final bool useViewInfoBloc;
|
||||
@ -111,15 +121,8 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
],
|
||||
);
|
||||
|
||||
late final List<CommandShortcutEvent> commandShortcutEvents = [
|
||||
toggleToggleListCommand,
|
||||
...localizedCodeBlockCommands,
|
||||
customCopyCommand,
|
||||
customPasteCommand,
|
||||
customCutCommand,
|
||||
...customTextAlignCommands,
|
||||
...standardCommandShortcutEvents,
|
||||
emojiShortcutEvent,
|
||||
late final List<CommandShortcutEvent> cmdShortcutEvents = [
|
||||
...commandShortcutEvents,
|
||||
..._buildFindAndReplaceCommands(),
|
||||
];
|
||||
|
||||
@ -309,7 +312,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
),
|
||||
// customize the shortcuts
|
||||
characterShortcutEvents: characterShortcutEvents,
|
||||
commandShortcutEvents: commandShortcutEvents,
|
||||
commandShortcutEvents: cmdShortcutEvents,
|
||||
// customize the context menu items
|
||||
contextMenuItems: customContextMenuItems,
|
||||
// customize the header and footer.
|
||||
@ -392,12 +395,6 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
if (widget.editorState.document.isEmpty) {
|
||||
return (true, Selection.collapsed(Position(path: [0])));
|
||||
}
|
||||
final nodes =
|
||||
widget.editorState.document.root.children.where((e) => e.delta != null);
|
||||
final isAllEmpty = nodes.isNotEmpty && nodes.every((e) => e.delta!.isEmpty);
|
||||
if (isAllEmpty) {
|
||||
return (true, Selection.collapsed(Position(path: nodes.first.path)));
|
||||
}
|
||||
return const (false, null);
|
||||
}
|
||||
|
||||
@ -407,7 +404,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
final customizeShortcuts =
|
||||
await settingsShortcutService.getCustomizeShortcuts();
|
||||
await settingsShortcutService.updateCommandShortcuts(
|
||||
commandShortcutEvents,
|
||||
cmdShortcutEvents,
|
||||
customizeShortcuts,
|
||||
);
|
||||
}
|
||||
@ -437,7 +434,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
Material(
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: FindAndReplaceMenuWidget(
|
||||
|
@ -74,7 +74,6 @@ class MobileBlockActionButtons extends StatelessWidget {
|
||||
context,
|
||||
showHeader: true,
|
||||
showCloseButton: true,
|
||||
showDivider: true,
|
||||
showDragHandle: true,
|
||||
title: LocaleKeys.document_plugins_action.tr(),
|
||||
builder: (context) {
|
||||
|
@ -141,7 +141,7 @@ enum OptionDepthType {
|
||||
|
||||
class DividerOptionAction extends CustomActionCell {
|
||||
@override
|
||||
Widget buildWithContext(BuildContext context) {
|
||||
Widget buildWithContext(BuildContext context, PopoverController controller) {
|
||||
return const Divider(
|
||||
height: 1.0,
|
||||
thickness: 1.0,
|
||||
@ -300,7 +300,7 @@ class ColorOptionAction extends PopoverActionCell {
|
||||
colors: colors,
|
||||
selected: selectedColor,
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
color: AFThemeExtension.of(context).onBackground,
|
||||
),
|
||||
onTap: (option, index) async {
|
||||
final transaction = editorState.transaction;
|
||||
|
@ -1,11 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_picker_screen.dart';
|
||||
import 'package:appflowy/plugins/base/icon/icon_picker.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class EmojiPickerButton extends StatelessWidget {
|
||||
@ -19,6 +18,7 @@ class EmojiPickerButton extends StatelessWidget {
|
||||
this.offset,
|
||||
this.direction,
|
||||
this.title,
|
||||
this.showBorder = true,
|
||||
});
|
||||
|
||||
final String emoji;
|
||||
@ -30,6 +30,7 @@ class EmojiPickerButton extends StatelessWidget {
|
||||
final Offset? offset;
|
||||
final PopoverDirection? direction;
|
||||
final String? title;
|
||||
final bool showBorder;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -51,22 +52,28 @@ class EmojiPickerButton extends StatelessWidget {
|
||||
onExit: () {},
|
||||
),
|
||||
),
|
||||
child: emoji.isEmpty && defaultIcon != null
|
||||
? FlowyButton(
|
||||
useIntrinsicWidth: true,
|
||||
text: defaultIcon!,
|
||||
onTap: popoverController.show,
|
||||
)
|
||||
: FlowyTextButton(
|
||||
emoji,
|
||||
overflow: TextOverflow.visible,
|
||||
fontSize: emojiSize,
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(minWidth: 35.0),
|
||||
fillColor: Colors.transparent,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
onPressed: popoverController.show,
|
||||
),
|
||||
child: Container(
|
||||
width: 30.0,
|
||||
height: 30.0,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: showBorder
|
||||
? Border.all(
|
||||
color: Theme.of(context).dividerColor,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
child: FlowyButton(
|
||||
margin: emoji.isEmpty && defaultIcon != null
|
||||
? EdgeInsets.zero
|
||||
: const EdgeInsets.only(left: 2.0),
|
||||
expandText: false,
|
||||
text: emoji.isEmpty && defaultIcon != null
|
||||
? defaultIcon!
|
||||
: FlowyText.emoji(emoji, fontSize: emojiSize),
|
||||
onTap: popoverController.show,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return FlowyTextButton(
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/selectable_item_list_menu.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/string_extension.dart';
|
||||
@ -8,7 +6,9 @@ import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.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/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
CodeBlockLanguagePickerBuilder codeBlockLanguagePickerBuilder = (
|
||||
@ -70,7 +70,7 @@ class _CodeBlockLanguageSelectorState
|
||||
widget.language?.capitalize() ??
|
||||
LocaleKeys.document_codeBlock_language_auto.tr(),
|
||||
constraints: const BoxConstraints(minWidth: 50),
|
||||
fontColor: Theme.of(context).colorScheme.onBackground,
|
||||
fontColor: AFThemeExtension.of(context).onBackground,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 4),
|
||||
fillColor: Colors.transparent,
|
||||
hoverColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||
|
@ -61,7 +61,7 @@ class _ErrorBlockComponentWidgetState extends State<ErrorBlockComponentWidget>
|
||||
Widget build(BuildContext context) {
|
||||
Widget child = DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: FlowyButton(
|
||||
@ -74,17 +74,9 @@ class _ErrorBlockComponentWidgetState extends State<ErrorBlockComponentWidget>
|
||||
ClipboardServiceData(plainText: jsonEncode(node.toJson())),
|
||||
);
|
||||
},
|
||||
text: SizedBox(
|
||||
height: 52,
|
||||
child: Row(
|
||||
children: [
|
||||
const HSpace(4),
|
||||
FlowyText(
|
||||
LocaleKeys.document_errorBlock_theBlockIsNotSupported.tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
text: PlatformExtension.isDesktopOrWeb
|
||||
? _buildDesktopErrorBlock(context)
|
||||
: _buildMobileErrorBlock(context),
|
||||
),
|
||||
);
|
||||
|
||||
@ -111,4 +103,44 @@ class _ErrorBlockComponentWidgetState extends State<ErrorBlockComponentWidget>
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
Widget _buildDesktopErrorBlock(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
const HSpace(4),
|
||||
FlowyText.regular(
|
||||
LocaleKeys.document_errorBlock_theBlockIsNotSupported.tr(),
|
||||
),
|
||||
const HSpace(4),
|
||||
FlowyText.regular(
|
||||
'(${LocaleKeys.document_errorBlock_clickToCopyTheBlockContent.tr()})',
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMobileErrorBlock(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
FlowyText.regular(
|
||||
LocaleKeys.document_errorBlock_theBlockIsNotSupported.tr(),
|
||||
),
|
||||
const VSpace(6),
|
||||
FlowyText.regular(
|
||||
'(${LocaleKeys.document_errorBlock_clickToCopyTheBlockContent.tr()})',
|
||||
color: Theme.of(context).hintColor,
|
||||
fontSize: 12.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ 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:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart' hide WidgetBuilder;
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text_input.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
@ -300,9 +300,10 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
|
||||
: (CoverType.color, '0xffe8e0ff'),
|
||||
),
|
||||
useIntrinsicWidth: true,
|
||||
leftIcon: const FlowySvg(FlowySvgs.image_s),
|
||||
leftIcon: const FlowySvg(FlowySvgs.add_cover_s),
|
||||
text: FlowyText.small(
|
||||
LocaleKeys.document_plugins_cover_addCover.tr(),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -311,28 +312,24 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
|
||||
if (widget.hasIcon) {
|
||||
children.add(
|
||||
FlowyButton(
|
||||
leftIconSize: const Size.square(18),
|
||||
onTap: () => widget.onIconOrCoverChanged(icon: ""),
|
||||
useIntrinsicWidth: true,
|
||||
leftIcon: const Icon(
|
||||
Icons.emoji_emotions_outlined,
|
||||
size: 18,
|
||||
),
|
||||
leftIcon: const FlowySvg(FlowySvgs.add_icon_s),
|
||||
iconPadding: 4.0,
|
||||
text: FlowyText.small(
|
||||
LocaleKeys.document_plugins_cover_removeIcon.tr(),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
Widget child = FlowyButton(
|
||||
leftIconSize: const Size.square(18),
|
||||
useIntrinsicWidth: true,
|
||||
leftIcon: const Icon(
|
||||
Icons.emoji_emotions_outlined,
|
||||
size: 18,
|
||||
),
|
||||
leftIcon: const FlowySvg(FlowySvgs.add_icon_s),
|
||||
iconPadding: 4.0,
|
||||
text: FlowyText.small(
|
||||
LocaleKeys.document_plugins_cover_addIcon.tr(),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
onTap: PlatformExtension.isDesktop
|
||||
? null
|
||||
|
@ -49,7 +49,7 @@ class ImagePlaceholderState extends State<ImagePlaceholder> {
|
||||
Widget build(BuildContext context) {
|
||||
final Widget child = DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: FlowyHover(
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user