Compare commits
45
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f78b5b4561 | ||
|
|
f6e002edbd | ||
|
|
82effbf8e4 | ||
|
|
54096b391f | ||
|
|
39eee12f53 | ||
|
|
bae19b9c3a | ||
|
|
f00e1ebf20 | ||
|
|
939e28d2e1 | ||
|
|
3fbdcab7b0 | ||
|
|
a1d0dba0a5 | ||
|
|
5e41849f69 | ||
|
|
cf56e20be9 | ||
|
|
1b9b2a5f8d | ||
|
|
690b46a59a | ||
|
|
4d33c87b33 | ||
|
|
7cf0c4b16b | ||
|
|
910b643db0 | ||
|
|
0e5ff844b6 | ||
|
|
a9a784f0f0 | ||
|
|
af390f584e | ||
|
|
eff37d74dc | ||
|
|
0ea2da424f | ||
|
|
07e34609e7 | ||
|
|
74c757d0c8 | ||
|
|
e6357a9d6c | ||
|
|
5a047b9d2d | ||
|
|
873ab6cdc7 | ||
|
|
af6736d352 | ||
|
|
d5c1955ea3 | ||
|
|
8bb8131dd4 | ||
|
|
7f4abb5866 | ||
|
|
fbe87cc536 | ||
|
|
74165ace0f | ||
|
|
b576287ac6 | ||
|
|
68d7211735 | ||
|
|
dd0dcace87 | ||
|
|
8f58c39448 | ||
|
|
cee0e2ed42 | ||
|
|
557ce7e006 | ||
|
|
d50521d9b6 | ||
|
|
28aa2329fb | ||
|
|
9707148b86 | ||
|
|
4e739c857b | ||
|
|
363fecc7d6 | ||
|
|
6bbaad59a4 |
No files matched your search
@@ -28,7 +28,7 @@ env:
|
||||
FLUTTER_VERSION: "3.22.2"
|
||||
RUST_TOOLCHAIN: "1.80.1"
|
||||
CARGO_MAKE_VERSION: "0.37.18"
|
||||
CLOUD_VERSION: 0.6.50
|
||||
CLOUD_VERSION: 0.6.54-amd64
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
os: [ubuntu-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
flutter_profile: development-linux-x86_64
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ windows-latest ]
|
||||
os: [windows-latest]
|
||||
include:
|
||||
- os: windows-latest
|
||||
flutter_profile: development-windows-x86
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ macos-latest ]
|
||||
os: [macos-latest]
|
||||
include:
|
||||
- os: macos-latest
|
||||
flutter_profile: development-mac-x86_64
|
||||
@@ -123,12 +123,12 @@ jobs:
|
||||
flutter_profile: ${{ matrix.flutter_profile }}
|
||||
|
||||
unit_test:
|
||||
needs: [ prepare-linux ]
|
||||
needs: [prepare-linux]
|
||||
if: github.event.pull_request.draft != true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
os: [ubuntu-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
flutter_profile: development-linux-x86_64
|
||||
@@ -217,11 +217,11 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
cloud_integration_test:
|
||||
needs: [ prepare-linux ]
|
||||
needs: [prepare-linux]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
os: [ubuntu-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
flutter_profile: development-linux-x86_64
|
||||
@@ -262,9 +262,20 @@ jobs:
|
||||
else
|
||||
running_image=$(docker inspect --format='{{index .Config.Image}}' "$container_id")
|
||||
if [ "$running_image" != "appflowy-cloud:$APPFLOWY_CLOUD_VERSION" ]; then
|
||||
echo "AppFlowy-Cloud is running with an incorrect version. Pulling the correct version..."
|
||||
docker rm -f $(docker ps -aq)
|
||||
docker volume rm $(docker volume ls -q)
|
||||
echo "AppFlowy-Cloud is running with an incorrect version. Restarting with the correct version..."
|
||||
# Remove all containers if any exist
|
||||
if [ "$(docker ps -aq)" ]; then
|
||||
docker rm -f $(docker ps -aq)
|
||||
else
|
||||
echo "No containers to remove."
|
||||
fi
|
||||
|
||||
# Remove all volumes if any exist
|
||||
if [ "$(docker volume ls -q)" ]; then
|
||||
docker volume rm $(docker volume ls -q)
|
||||
else
|
||||
echo "No volumes to remove."
|
||||
fi
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
echo "Waiting for the container to be ready..."
|
||||
@@ -328,14 +339,14 @@ jobs:
|
||||
flutter test integration_test/desktop/cloud/cloud_runner.dart -d Linux --coverage
|
||||
shell: bash
|
||||
|
||||
# split the integration tests into different machines to minimize the time
|
||||
integration_test_1:
|
||||
needs: [ prepare-linux ]
|
||||
integration_test:
|
||||
needs: [prepare-linux]
|
||||
if: github.event.pull_request.draft != true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
os: [ubuntu-latest]
|
||||
test_number: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: "x86_64-unknown-linux-gnu"
|
||||
@@ -344,82 +355,10 @@ jobs:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Flutter Integration Test 1
|
||||
- name: Flutter Integration Test ${{ matrix.test_number }}
|
||||
uses: ./.github/actions/flutter_integration_test
|
||||
with:
|
||||
test_path: integration_test/desktop_runner_1.dart
|
||||
flutter_version: ${{ env.FLUTTER_VERSION }}
|
||||
rust_toolchain: ${{ env.RUST_TOOLCHAIN }}
|
||||
cargo_make_version: ${{ env.CARGO_MAKE_VERSION }}
|
||||
rust_target: ${{ matrix.target }}
|
||||
|
||||
integration_test_2:
|
||||
needs: [ prepare-linux ]
|
||||
if: github.event.pull_request.draft != true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: "x86_64-unknown-linux-gnu"
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Flutter Integration Test 2
|
||||
uses: ./.github/actions/flutter_integration_test
|
||||
with:
|
||||
test_path: integration_test/desktop_runner_2.dart
|
||||
flutter_version: ${{ env.FLUTTER_VERSION }}
|
||||
rust_toolchain: ${{ env.RUST_TOOLCHAIN }}
|
||||
cargo_make_version: ${{ env.CARGO_MAKE_VERSION }}
|
||||
rust_target: ${{ matrix.target }}
|
||||
|
||||
integration_test_3:
|
||||
needs: [ prepare-linux ]
|
||||
if: github.event.pull_request.draft != true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: "x86_64-unknown-linux-gnu"
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Flutter Integration Test 3
|
||||
uses: ./.github/actions/flutter_integration_test
|
||||
with:
|
||||
test_path: integration_test/desktop_runner_3.dart
|
||||
flutter_version: ${{ env.FLUTTER_VERSION }}
|
||||
rust_toolchain: ${{ env.RUST_TOOLCHAIN }}
|
||||
cargo_make_version: ${{ env.CARGO_MAKE_VERSION }}
|
||||
rust_target: ${{ matrix.target }}
|
||||
|
||||
integration_test_4:
|
||||
needs: [ prepare-linux ]
|
||||
if: github.event.pull_request.draft != true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: "x86_64-unknown-linux-gnu"
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Flutter Integration Test 4
|
||||
uses: ./.github/actions/flutter_integration_test
|
||||
with:
|
||||
test_path: integration_test/desktop_runner_4.dart
|
||||
test_path: integration_test/desktop_runner_${{ matrix.test_number }}.dart
|
||||
flutter_version: ${{ env.FLUTTER_VERSION }}
|
||||
rust_toolchain: ${{ env.RUST_TOOLCHAIN }}
|
||||
cargo_make_version: ${{ env.CARGO_MAKE_VERSION }}
|
||||
|
||||
@@ -22,7 +22,7 @@ on:
|
||||
env:
|
||||
FLUTTER_VERSION: "3.22.0"
|
||||
RUST_TOOLCHAIN: "1.80.1"
|
||||
CLOUD_VERSION: 0.6.50
|
||||
CLOUD_VERSION: 0.6.51
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
|
||||
@@ -20,7 +20,7 @@ on:
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
CLOUD_VERSION: 0.6.50
|
||||
CLOUD_VERSION: 0.6.51-amd64
|
||||
RUST_TOOLCHAIN: "1.77.2"
|
||||
|
||||
jobs:
|
||||
@@ -62,8 +62,6 @@ jobs:
|
||||
running_image=$(docker inspect --format='{{index .Config.Image}}' "$container_id")
|
||||
if [ "$running_image" != "appflowy-cloud:$APPFLOWY_CLOUD_VERSION" ]; then
|
||||
echo "AppFlowy-Cloud is running with an incorrect version. Pulling the correct version..."
|
||||
docker rm -f $(docker ps -aq)
|
||||
docker volume rm $(docker volume ls -q)
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
echo "Waiting for the container to be ready..."
|
||||
@@ -149,8 +147,20 @@ jobs:
|
||||
APPFLOWY_HISTORY_VERSION: ${{ env.CLOUD_VERSION }}
|
||||
APPFLOWY_WORKER_VERSION: ${{ env.CLOUD_VERSION }}
|
||||
run: |
|
||||
docker rm -f $(docker ps -aq)
|
||||
docker volume rm $(docker volume ls -q)
|
||||
# Remove all containers if any exist
|
||||
if [ "$(docker ps -aq)" ]; then
|
||||
docker rm -f $(docker ps -aq)
|
||||
else
|
||||
echo "No containers to remove."
|
||||
fi
|
||||
|
||||
# Remove all volumes if any exist
|
||||
if [ "$(docker volume ls -q)" ]; then
|
||||
docker volume rm $(docker volume ls -q)
|
||||
else
|
||||
echo "No volumes to remove."
|
||||
fi
|
||||
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
echo "Waiting for the container to be ready..."
|
||||
|
||||
@@ -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.7.2"
|
||||
APPFLOWY_VERSION = "0.7.3"
|
||||
FLUTTER_DESKTOP_FEATURES = "dart"
|
||||
PRODUCT_NAME = "AppFlowy"
|
||||
MACOSX_DEPLOYMENT_TARGET = "11.0"
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:time/time.dart';
|
||||
|
||||
import '../../shared/database_test_op.dart';
|
||||
import '../../shared/util.dart';
|
||||
@@ -14,6 +15,31 @@ void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('board row test', () {
|
||||
testWidgets('edit item in ToDo card', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
|
||||
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Board);
|
||||
const name = 'Card 1';
|
||||
final card1 = find.ancestor(
|
||||
matching: find.byType(RowCard),
|
||||
of: find.text(name),
|
||||
);
|
||||
await tester.hoverOnWidget(
|
||||
card1,
|
||||
onHover: () async {
|
||||
final editCard = find.byType(EditCardAccessory);
|
||||
await tester.tapButton(editCard);
|
||||
},
|
||||
);
|
||||
await tester.showKeyboard(card1);
|
||||
tester.testTextInput.enterText("");
|
||||
await tester.pump(300.milliseconds);
|
||||
tester.testTextInput.enterText("a");
|
||||
await tester.pump(300.milliseconds);
|
||||
expect(find.text('a'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('delete item in ToDo card', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
import 'package:appflowy/env/cloud_env.dart';
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart';
|
||||
import 'package:appflowy/plugins/shared/share/constants.dart';
|
||||
import 'package:appflowy/plugins/shared/share/publish_tab.dart';
|
||||
import 'package:appflowy/plugins/shared/share/share_menu.dart';
|
||||
import 'package:appflowy/shared/feature_flags.dart';
|
||||
import 'package:appflowy/shared/patterns/common_patterns.dart';
|
||||
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/workspace/_sidebar_workspace_icon.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.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/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
import '../../../shared/constants.dart';
|
||||
import '../../../shared/mock/mock_file_picker.dart';
|
||||
import '../../../shared/util.dart';
|
||||
import '../../../shared/workspace.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('Publish:', () {
|
||||
testWidgets('publish document', (tester) async {
|
||||
await tester.initializeAppFlowy(
|
||||
cloudType: AuthenticatorType.appflowyCloudSelfHost,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
await tester.expectToSeeHomePageWithGetStartedPage();
|
||||
|
||||
const pageName = 'Document';
|
||||
|
||||
await tester.createNewPageInSpace(
|
||||
spaceName: Constants.generalSpaceName,
|
||||
layout: ViewLayoutPB.Document,
|
||||
pageName: pageName,
|
||||
);
|
||||
|
||||
// open the publish menu
|
||||
await tester.openPublishMenu();
|
||||
|
||||
// publish the document
|
||||
final publishButton = find.byType(PublishButton);
|
||||
final unpublishButton = find.byType(UnPublishButton);
|
||||
await tester.tapButton(publishButton);
|
||||
|
||||
// expect to see unpublish, visit site and manage all sites button
|
||||
expect(unpublishButton, findsOneWidget);
|
||||
expect(find.text(LocaleKeys.shareAction_visitSite.tr()), findsOneWidget);
|
||||
|
||||
// unpublish the document
|
||||
await tester.tapButton(unpublishButton);
|
||||
|
||||
// expect to see publish button
|
||||
expect(publishButton, findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('rename path name', (tester) async {
|
||||
await tester.initializeAppFlowy(
|
||||
cloudType: AuthenticatorType.appflowyCloudSelfHost,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
await tester.expectToSeeHomePageWithGetStartedPage();
|
||||
|
||||
const pageName = 'Document';
|
||||
|
||||
await tester.createNewPageInSpace(
|
||||
spaceName: Constants.generalSpaceName,
|
||||
layout: ViewLayoutPB.Document,
|
||||
pageName: pageName,
|
||||
);
|
||||
|
||||
// open the publish menu
|
||||
await tester.openPublishMenu();
|
||||
|
||||
// publish the document
|
||||
final publishButton = find.byType(PublishButton);
|
||||
await tester.tapButton(publishButton);
|
||||
|
||||
// rename the path name
|
||||
final inputField = find.descendant(
|
||||
of: find.byType(ShareMenu),
|
||||
matching: find.byType(TextField),
|
||||
);
|
||||
|
||||
// rename with invalid name
|
||||
await tester.tap(inputField);
|
||||
await tester.enterText(inputField, '&&&&????');
|
||||
await tester.tapButton(find.text(LocaleKeys.button_save.tr()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// expect to see the toast with error message
|
||||
final errorToast1 = find.text(
|
||||
LocaleKeys.settings_sites_error_publishNameContainsInvalidCharacters
|
||||
.tr(),
|
||||
);
|
||||
await tester.pumpUntilFound(errorToast1);
|
||||
await tester.pumpUntilNotFound(errorToast1);
|
||||
|
||||
// rename with long name
|
||||
await tester.tap(inputField);
|
||||
await tester.enterText(inputField, 'long-path-name' * 200);
|
||||
await tester.tapButton(find.text(LocaleKeys.button_save.tr()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// expect to see the toast with error message
|
||||
final errorToast2 = find.text(
|
||||
LocaleKeys.settings_sites_error_publishNameTooLong.tr(),
|
||||
);
|
||||
await tester.pumpUntilFound(errorToast2);
|
||||
await tester.pumpUntilNotFound(errorToast2);
|
||||
|
||||
await tester.tap(inputField);
|
||||
|
||||
// input the new path name
|
||||
await tester.enterText(inputField, 'new-path-name');
|
||||
// click save button
|
||||
await tester.tapButton(find.text(LocaleKeys.button_save.tr()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// expect to see the toast with success message
|
||||
final successToast = find.text(
|
||||
LocaleKeys.settings_sites_success_updatePathNameSuccess.tr(),
|
||||
);
|
||||
await tester.pumpUntilFound(successToast);
|
||||
await tester.pumpUntilNotFound(successToast);
|
||||
|
||||
// click the copy link button
|
||||
await tester.tapButton(
|
||||
find.byWidgetPredicate(
|
||||
(widget) =>
|
||||
widget is FlowySvg &&
|
||||
widget.svg.path == FlowySvgs.m_toolbar_link_m.path,
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
// check the clipboard has the link
|
||||
final content = await Clipboard.getData(Clipboard.kTextPlain);
|
||||
expect(
|
||||
content?.text?.contains('new-path-name'),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
+2
@@ -3,10 +3,12 @@ import 'package:integration_test/integration_test.dart';
|
||||
import 'document_copy_link_to_block_test.dart'
|
||||
as document_copy_link_to_block_test;
|
||||
import 'document_option_actions_test.dart' as document_option_actions_test;
|
||||
import 'document_publish_test.dart' as document_publish_test;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
document_option_actions_test.main();
|
||||
document_copy_link_to_block_test.main();
|
||||
document_publish_test.main();
|
||||
}
|
||||
+3
-2
@@ -6,6 +6,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_p
|
||||
import 'package:appflowy/plugins/shared/share/constants.dart';
|
||||
import 'package:appflowy/plugins/shared/share/share_menu.dart';
|
||||
import 'package:appflowy/shared/feature_flags.dart';
|
||||
import 'package:appflowy/shared/patterns/common_patterns.dart';
|
||||
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';
|
||||
@@ -61,11 +62,11 @@ void main() {
|
||||
final plainText = clipboardContent.plainText;
|
||||
expect(
|
||||
plainText,
|
||||
startsWith(ShareConstants.shareBaseUrl),
|
||||
matches(appflowySharePageLinkPattern),
|
||||
);
|
||||
|
||||
final shareValues = plainText!
|
||||
.replaceAll('${ShareConstants.shareBaseUrl}/', '')
|
||||
.replaceAll('https://${ShareConstants.shareBaseUrl}/', '')
|
||||
.split('/');
|
||||
final workspaceId = shareValues[0];
|
||||
expect(workspaceId, isNotEmpty);
|
||||
|
||||
+272
@@ -4,8 +4,10 @@ import 'dart:io';
|
||||
|
||||
import 'package:appflowy/env/cloud_env.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
||||
import 'package:appflowy/plugins/shared/share/publish_tab.dart';
|
||||
import 'package:appflowy/shared/feature_flags.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/application/auth/af_cloud_mock_auth_service.dart';
|
||||
@@ -15,6 +17,13 @@ import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sid
|
||||
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/pages/settings_workspace_view.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/sites/domain/domain_item.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/sites/domain/domain_more_action.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/sites/domain/domain_settings_dialog.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/sites/domain/home_page_menu.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/sites/published_page/published_view_item.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/sites/published_page/published_view_more_action.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/sites/published_page/published_view_settings_dialog.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/setting_list_tile.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/user_avatar.dart';
|
||||
@@ -27,6 +36,7 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
import '../../../shared/constants.dart';
|
||||
import '../../../shared/database_test_op.dart';
|
||||
import '../../../shared/dir.dart';
|
||||
import '../../../shared/emoji.dart';
|
||||
@@ -93,4 +103,266 @@ void main() {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('sites settings:', () {
|
||||
testWidgets(
|
||||
'manage published page, set it as homepage, remove the homepage',
|
||||
(tester) async {
|
||||
await tester.initializeAppFlowy(
|
||||
cloudType: AuthenticatorType.appflowyCloudSelfHost,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
await tester.expectToSeeHomePageWithGetStartedPage();
|
||||
|
||||
const pageName = 'Document';
|
||||
|
||||
await tester.createNewPageInSpace(
|
||||
spaceName: Constants.generalSpaceName,
|
||||
layout: ViewLayoutPB.Document,
|
||||
pageName: pageName,
|
||||
);
|
||||
|
||||
// open the publish menu
|
||||
await tester.openPublishMenu();
|
||||
|
||||
// publish the document
|
||||
await tester.tapButton(find.byType(PublishButton));
|
||||
|
||||
// click empty area to close the publish menu
|
||||
await tester.tapAt(Offset.zero);
|
||||
await tester.pumpAndSettle();
|
||||
// check if the page is published in sites page
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.sites);
|
||||
// wait the backend return the sites data
|
||||
await tester.wait(1000);
|
||||
|
||||
// check if the page is published in sites page
|
||||
final pageItem = find.byWidgetPredicate(
|
||||
(widget) =>
|
||||
widget is PublishedViewItem &&
|
||||
widget.publishInfoView.view.name == pageName,
|
||||
);
|
||||
expect(pageItem, findsOneWidget);
|
||||
|
||||
// comment it out because it's not allowed to update the namespace in free plan
|
||||
// // set it to homepage
|
||||
// await tester.tapButton(
|
||||
// find.textContaining(
|
||||
// LocaleKeys.settings_sites_selectHomePage.tr(),
|
||||
// ),
|
||||
// );
|
||||
// await tester.tapButton(
|
||||
// find.descendant(
|
||||
// of: find.byType(SelectHomePageMenu),
|
||||
// matching: find.text(pageName),
|
||||
// ),
|
||||
// );
|
||||
// await tester.pumpAndSettle();
|
||||
|
||||
// // check if the page is set to homepage
|
||||
// final homePageItem = find.descendant(
|
||||
// of: find.byType(DomainItem),
|
||||
// matching: find.text(pageName),
|
||||
// );
|
||||
// expect(homePageItem, findsOneWidget);
|
||||
|
||||
// // remove the homepage
|
||||
// await tester.tapButton(find.byType(DomainMoreAction));
|
||||
// await tester.tapButton(
|
||||
// find.text(LocaleKeys.settings_sites_removeHomepage.tr()),
|
||||
// );
|
||||
// await tester.pumpAndSettle();
|
||||
|
||||
// // check if the page is removed from homepage
|
||||
// expect(homePageItem, findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('update namespace', (tester) async {
|
||||
await tester.initializeAppFlowy(
|
||||
cloudType: AuthenticatorType.appflowyCloudSelfHost,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
await tester.expectToSeeHomePageWithGetStartedPage();
|
||||
|
||||
// check if the page is published in sites page
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.sites);
|
||||
// wait the backend return the sites data
|
||||
await tester.wait(1000);
|
||||
|
||||
// update the domain
|
||||
final domainMoreAction = find.byType(DomainMoreAction);
|
||||
await tester.tapButton(domainMoreAction);
|
||||
final updateNamespaceButton = find.text(
|
||||
LocaleKeys.settings_sites_updateNamespace.tr(),
|
||||
);
|
||||
await tester.pumpUntilFound(updateNamespaceButton);
|
||||
|
||||
// click the update namespace button
|
||||
|
||||
await tester.tapButton(updateNamespaceButton);
|
||||
|
||||
// comment it out because it's not allowed to update the namespace in free plan
|
||||
// expect to see the dialog
|
||||
// await tester.updateNamespace('&&&???');
|
||||
|
||||
// // need to upgrade to pro plan to update the namespace
|
||||
// final errorToast = find.text(
|
||||
// LocaleKeys.settings_sites_error_proPlanLimitation.tr(),
|
||||
// );
|
||||
// await tester.pumpUntilFound(errorToast);
|
||||
// expect(errorToast, findsOneWidget);
|
||||
// await tester.pumpUntilNotFound(errorToast);
|
||||
|
||||
// comment it out because it's not allowed to update the namespace in free plan
|
||||
// // short namespace
|
||||
// await tester.updateNamespace('a');
|
||||
|
||||
// // expect to see the toast with error message
|
||||
// final errorToast2 = find.text(
|
||||
// LocaleKeys.settings_sites_error_namespaceTooShort.tr(),
|
||||
// );
|
||||
// await tester.pumpUntilFound(errorToast2);
|
||||
// expect(errorToast2, findsOneWidget);
|
||||
// await tester.pumpUntilNotFound(errorToast2);
|
||||
// // valid namespace
|
||||
// await tester.updateNamespace('AppFlowy');
|
||||
|
||||
// // expect to see the toast with success message
|
||||
// final successToast = find.text(
|
||||
// LocaleKeys.settings_sites_success_namespaceUpdated.tr(),
|
||||
// );
|
||||
// await tester.pumpUntilFound(successToast);
|
||||
// expect(successToast, findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('''
|
||||
More actions for published page:
|
||||
1. visit site
|
||||
2. copy link
|
||||
3. settings
|
||||
4. unpublish
|
||||
5. custom url
|
||||
''', (tester) async {
|
||||
await tester.initializeAppFlowy(
|
||||
cloudType: AuthenticatorType.appflowyCloudSelfHost,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
await tester.expectToSeeHomePageWithGetStartedPage();
|
||||
|
||||
const pageName = 'Document';
|
||||
|
||||
await tester.createNewPageInSpace(
|
||||
spaceName: Constants.generalSpaceName,
|
||||
layout: ViewLayoutPB.Document,
|
||||
pageName: pageName,
|
||||
);
|
||||
|
||||
// open the publish menu
|
||||
await tester.openPublishMenu();
|
||||
|
||||
// publish the document
|
||||
await tester.tapButton(find.byType(PublishButton));
|
||||
|
||||
// click empty area to close the publish menu
|
||||
await tester.tapAt(Offset.zero);
|
||||
await tester.pumpAndSettle();
|
||||
// check if the page is published in sites page
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.sites);
|
||||
// wait the backend return the sites data
|
||||
await tester.wait(1000);
|
||||
|
||||
// check if the page is published in sites page
|
||||
final pageItem = find.byWidgetPredicate(
|
||||
(widget) =>
|
||||
widget is PublishedViewItem &&
|
||||
widget.publishInfoView.view.name == pageName,
|
||||
);
|
||||
expect(pageItem, findsOneWidget);
|
||||
|
||||
final copyLinkItem = find.text(LocaleKeys.shareAction_copyLink.tr());
|
||||
final customUrlItem = find.text(LocaleKeys.settings_sites_customUrl.tr());
|
||||
final unpublishItem = find.text(LocaleKeys.shareAction_unPublish.tr());
|
||||
|
||||
// custom url
|
||||
final publishMoreAction = find.byType(PublishedViewMoreAction);
|
||||
|
||||
// click the copy link button
|
||||
{
|
||||
await tester.tapButton(publishMoreAction);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.pumpUntilFound(copyLinkItem);
|
||||
await tester.tapButton(copyLinkItem);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.pumpUntilNotFound(copyLinkItem);
|
||||
|
||||
final clipboardContent = await getIt<ClipboardService>().getData();
|
||||
final plainText = clipboardContent.plainText;
|
||||
expect(
|
||||
plainText,
|
||||
contains(pageName),
|
||||
);
|
||||
}
|
||||
|
||||
// custom url
|
||||
{
|
||||
await tester.tapButton(publishMoreAction);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.pumpUntilFound(customUrlItem);
|
||||
await tester.tapButton(customUrlItem);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.pumpUntilNotFound(customUrlItem);
|
||||
|
||||
// see the custom url dialog
|
||||
final customUrlDialog = find.byType(PublishedViewSettingsDialog);
|
||||
expect(customUrlDialog, findsOneWidget);
|
||||
|
||||
// rename the custom url
|
||||
final textField = find.descendant(
|
||||
of: customUrlDialog,
|
||||
matching: find.byType(TextField),
|
||||
);
|
||||
await tester.enterText(textField, 'hello-world');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// click the save button
|
||||
final saveButton = find.descendant(
|
||||
of: customUrlDialog,
|
||||
matching: find.text(LocaleKeys.button_save.tr()),
|
||||
);
|
||||
await tester.tapButton(saveButton);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// expect to see the toast with success message
|
||||
final successToast = find.text(
|
||||
LocaleKeys.settings_sites_success_updatePathNameSuccess.tr(),
|
||||
);
|
||||
await tester.pumpUntilFound(successToast);
|
||||
expect(successToast, findsOneWidget);
|
||||
}
|
||||
|
||||
// unpublish
|
||||
{
|
||||
await tester.tapButton(publishMoreAction);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.pumpUntilFound(unpublishItem);
|
||||
await tester.tapButton(unpublishItem);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.pumpUntilNotFound(unpublishItem);
|
||||
|
||||
// expect to see the toast with success message
|
||||
final successToast = find.text(
|
||||
LocaleKeys.publish_unpublishSuccessfully.tr(),
|
||||
);
|
||||
await tester.pumpUntilFound(successToast);
|
||||
expect(successToast, findsOneWidget);
|
||||
await tester.pumpUntilNotFound(successToast);
|
||||
|
||||
// check if the page is unpublished in sites page
|
||||
expect(pageItem, findsNothing);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -211,8 +211,7 @@ void main() {
|
||||
await tester.toggleIncludeTime();
|
||||
|
||||
// Select a date
|
||||
final now = DateTime.now();
|
||||
final expected = DateTime(now.year, now.month, now.day);
|
||||
DateTime now = DateTime.now();
|
||||
await tester.selectDay(content: now.day);
|
||||
|
||||
await tester.dismissCellEditor();
|
||||
@@ -220,13 +219,13 @@ void main() {
|
||||
tester.assertCellContent(
|
||||
rowIndex: 0,
|
||||
fieldType: FieldType.DateTime,
|
||||
content: DateFormat('MMM dd, y').format(expected),
|
||||
content: DateFormat('MMM dd, y').format(now),
|
||||
);
|
||||
|
||||
await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
|
||||
|
||||
// Toggle include time
|
||||
// When toggling include time, the time value is from the previous existing date time, not the current time
|
||||
now = DateTime.now();
|
||||
await tester.toggleIncludeTime();
|
||||
|
||||
await tester.dismissCellEditor();
|
||||
@@ -234,7 +233,7 @@ void main() {
|
||||
tester.assertCellContent(
|
||||
rowIndex: 0,
|
||||
fieldType: FieldType.DateTime,
|
||||
content: DateFormat('MMM dd, y HH:mm').format(expected),
|
||||
content: DateFormat('MMM dd, y HH:mm').format(now),
|
||||
);
|
||||
|
||||
await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
|
||||
@@ -249,7 +248,7 @@ void main() {
|
||||
tester.assertCellContent(
|
||||
rowIndex: 0,
|
||||
fieldType: FieldType.DateTime,
|
||||
content: DateFormat('dd/MM/y HH:mm').format(expected),
|
||||
content: DateFormat('dd/MM/y HH:mm').format(now),
|
||||
);
|
||||
|
||||
await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
|
||||
@@ -264,7 +263,7 @@ void main() {
|
||||
tester.assertCellContent(
|
||||
rowIndex: 0,
|
||||
fieldType: FieldType.DateTime,
|
||||
content: DateFormat('dd/MM/y hh:mm a').format(expected),
|
||||
content: DateFormat('dd/MM/y hh:mm a').format(now),
|
||||
);
|
||||
|
||||
await tester.tapCellInGrid(rowIndex: 0, fieldType: fieldType);
|
||||
|
||||
+5
-7
@@ -292,7 +292,6 @@ void main() {
|
||||
await tester.tapCellInGrid(rowIndex: 0, fieldType: FieldType.DateTime);
|
||||
await tester.toggleIncludeTime();
|
||||
final now = DateTime.now();
|
||||
final expected = DateTime(now.year, now.month, now.day);
|
||||
await tester.selectDay(content: now.day);
|
||||
|
||||
await tester.dismissCellEditor();
|
||||
@@ -300,7 +299,7 @@ void main() {
|
||||
tester.assertCellContent(
|
||||
rowIndex: 0,
|
||||
fieldType: FieldType.DateTime,
|
||||
content: DateFormat('MMM dd, y HH:mm').format(expected),
|
||||
content: DateFormat('MMM dd, y HH:mm').format(now),
|
||||
);
|
||||
|
||||
// open editor and change date & time format
|
||||
@@ -314,7 +313,7 @@ void main() {
|
||||
tester.assertCellContent(
|
||||
rowIndex: 0,
|
||||
fieldType: FieldType.DateTime,
|
||||
content: DateFormat('dd/MM/y hh:mm a').format(expected),
|
||||
content: DateFormat('dd/MM/y hh:mm a').format(now),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -541,7 +540,6 @@ void main() {
|
||||
await tester.tapCellInGrid(rowIndex: 0, fieldType: FieldType.DateTime);
|
||||
await tester.toggleIncludeTime();
|
||||
final now = DateTime.now();
|
||||
final expected = DateTime(now.year, now.month, now.day);
|
||||
await tester.selectDay(content: now.day);
|
||||
|
||||
await tester.dismissCellEditor();
|
||||
@@ -549,7 +547,7 @@ void main() {
|
||||
tester.assertCellContent(
|
||||
rowIndex: 0,
|
||||
fieldType: FieldType.DateTime,
|
||||
content: DateFormat('MMM dd, y HH:mm').format(expected),
|
||||
content: DateFormat('MMM dd, y HH:mm').format(now),
|
||||
);
|
||||
|
||||
await tester.changeFieldTypeOfFieldWithName(
|
||||
@@ -559,7 +557,7 @@ void main() {
|
||||
tester.assertCellContent(
|
||||
rowIndex: 0,
|
||||
fieldType: FieldType.RichText,
|
||||
content: DateFormat('MMM dd, y HH:mm').format(expected),
|
||||
content: DateFormat('MMM dd, y HH:mm').format(now),
|
||||
cellIndex: 1,
|
||||
);
|
||||
|
||||
@@ -583,7 +581,7 @@ void main() {
|
||||
tester.assertCellContent(
|
||||
rowIndex: 0,
|
||||
fieldType: FieldType.DateTime,
|
||||
content: DateFormat('MMM dd, y').format(expected),
|
||||
content: DateFormat('MMM dd, y').format(now),
|
||||
);
|
||||
tester.assertCellContent(
|
||||
rowIndex: 1,
|
||||
|
||||
+18
-32
@@ -68,10 +68,7 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Tap on the upload interaction
|
||||
await tester.tapButtonWithName(
|
||||
LocaleKeys.document_plugins_file_fileUploadHint.tr(),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tapFileUploadHint();
|
||||
|
||||
// Expect one file
|
||||
expect(find.byType(RenderMedia), findsOneWidget);
|
||||
@@ -84,9 +81,7 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Tap on the upload interaction
|
||||
await tester.tapButtonWithName(
|
||||
LocaleKeys.document_plugins_file_fileUploadHint.tr(),
|
||||
);
|
||||
await tester.tapFileUploadHint();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Expect two files
|
||||
@@ -138,10 +133,7 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Tap on the upload interaction
|
||||
await tester.tapButtonWithName(
|
||||
LocaleKeys.document_plugins_file_fileUploadHint.tr(),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tapFileUploadHint();
|
||||
|
||||
// Expect two files
|
||||
expect(find.byType(RenderMedia), findsNWidgets(2));
|
||||
@@ -192,10 +184,7 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Tap on the upload interaction
|
||||
await tester.tapButtonWithName(
|
||||
LocaleKeys.document_plugins_file_fileUploadHint.tr(),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tapFileUploadHint();
|
||||
|
||||
// Expect two files
|
||||
expect(find.byType(RenderMedia), findsNWidgets(2));
|
||||
@@ -229,7 +218,7 @@ void main() {
|
||||
await Future.wait([firstFile.delete(), secondFile.delete()]);
|
||||
});
|
||||
|
||||
testWidgets('hide file names', (tester) async {
|
||||
testWidgets('show file names', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
|
||||
@@ -271,10 +260,7 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Tap on the upload interaction
|
||||
await tester.tapButtonWithName(
|
||||
LocaleKeys.document_plugins_file_fileUploadHint.tr(),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tapFileUploadHint();
|
||||
|
||||
// Expect two files
|
||||
expect(find.byType(RenderMedia), findsNWidgets(2));
|
||||
@@ -282,28 +268,28 @@ void main() {
|
||||
await tester.dismissCellEditor();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Open first row in row detail view then toggle hide file names
|
||||
// Open first row in row detail view then toggle show file names
|
||||
await tester.openFirstRowDetailPage();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Expect file names to not be shown (hidden)
|
||||
expect(find.text('sample.jpeg'), findsNothing);
|
||||
expect(find.text('sample.gif'), findsNothing);
|
||||
|
||||
await tester.tapGridFieldWithNameInRowDetailPage('Type');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Toggle show file names
|
||||
await tester.tap(find.byType(Toggle));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Expect file names to be shown
|
||||
expect(find.text('sample.jpeg'), findsOneWidget);
|
||||
expect(find.text('sample.gif'), findsOneWidget);
|
||||
|
||||
await tester.tapGridFieldWithNameInRowDetailPage('Type');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Toggle hide file names
|
||||
await tester.tap(find.byType(Toggle));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.dismissRowDetailPage();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Expect file names to be hidden
|
||||
expect(find.text('sample.jpeg'), findsNothing);
|
||||
expect(find.text('sample.gif'), findsNothing);
|
||||
|
||||
// Remove the temp files
|
||||
await Future.wait([firstFile.delete(), secondFile.delete()]);
|
||||
});
|
||||
|
||||
+1
-3
@@ -62,9 +62,7 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Tap on the upload interaction
|
||||
await tester.tapButtonWithName(
|
||||
LocaleKeys.document_plugins_file_fileUploadHint.tr(),
|
||||
);
|
||||
await tester.tapFileUploadHint();
|
||||
|
||||
// Expect one file
|
||||
expect(find.byType(RenderMedia), findsOneWidget);
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'database_cell_test.dart' as database_cell_test;
|
||||
import 'database_field_settings_test.dart' as database_field_settings_test;
|
||||
import 'database_field_test.dart' as database_field_test;
|
||||
import 'database_row_page_test.dart' as database_row_page_test;
|
||||
import 'database_setting_test.dart' as database_setting_test;
|
||||
import 'database_share_test.dart' as database_share_test;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
database_cell_test.main();
|
||||
database_field_test.main();
|
||||
database_field_settings_test.main();
|
||||
database_share_test.main();
|
||||
database_row_page_test.main();
|
||||
database_setting_test.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'database_calendar_test.dart' as database_calendar_test;
|
||||
import 'database_filter_test.dart' as database_filter_test;
|
||||
import 'database_media_test.dart' as database_media_test;
|
||||
import 'database_row_cover_test.dart' as database_row_cover_test;
|
||||
import 'database_share_test.dart' as database_share_test;
|
||||
import 'database_sort_test.dart' as database_sort_test;
|
||||
import 'database_view_test.dart' as database_view_test;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
database_filter_test.main();
|
||||
database_sort_test.main();
|
||||
database_view_test.main();
|
||||
database_calendar_test.main();
|
||||
database_media_test.main();
|
||||
database_row_cover_test.main();
|
||||
database_share_test.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
-12
@@ -1,6 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_action_type.dart';
|
||||
@@ -51,7 +50,6 @@ void main() {
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byType(MentionSubPageBlock), findsOneWidget);
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsOneWidget);
|
||||
|
||||
// Delete from editor
|
||||
await tester.editor.updateSelection(
|
||||
@@ -125,7 +123,6 @@ void main() {
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byType(MentionSubPageBlock), findsOneWidget);
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsOneWidget);
|
||||
|
||||
// Cut from editor
|
||||
await tester.editor.updateSelection(
|
||||
@@ -151,7 +148,6 @@ void main() {
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byType(MentionSubPageBlock), findsOneWidget);
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsOneWidget);
|
||||
|
||||
// Cut again
|
||||
await tester.editor.updateSelection(
|
||||
@@ -195,7 +191,6 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsOneWidget);
|
||||
});
|
||||
testWidgets(
|
||||
'Cut+paste in same docuemnt and then paste again in same document',
|
||||
@@ -214,7 +209,6 @@ void main() {
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byType(MentionSubPageBlock), findsOneWidget);
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsOneWidget);
|
||||
|
||||
// Cut from editor
|
||||
await tester.editor.updateSelection(
|
||||
@@ -240,7 +234,6 @@ void main() {
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byType(MentionSubPageBlock), findsOneWidget);
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsOneWidget);
|
||||
|
||||
// Paste again
|
||||
await tester.simulateKeyEvent(
|
||||
@@ -252,7 +245,6 @@ void main() {
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byType(MentionSubPageBlock), findsNWidgets(2));
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsNWidgets(2));
|
||||
expect(find.text('$_createdPageName (copy)'), findsNWidgets(2));
|
||||
});
|
||||
|
||||
@@ -271,7 +263,6 @@ void main() {
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byType(MentionSubPageBlock), findsOneWidget);
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsOneWidget);
|
||||
|
||||
final headingText = LocaleKeys.document_slashMenu_name_heading1.tr();
|
||||
final paragraphText = LocaleKeys.document_slashMenu_name_text.tr();
|
||||
@@ -283,7 +274,6 @@ void main() {
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byType(MentionSubPageBlock), findsOneWidget);
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsOneWidget);
|
||||
|
||||
// Turn into paragraph
|
||||
await tester.editor.openTurnIntoMenu([0]);
|
||||
@@ -292,7 +282,6 @@ void main() {
|
||||
|
||||
expect(find.text(_createdPageName), findsNWidgets(2));
|
||||
expect(find.byType(MentionSubPageBlock), findsOneWidget);
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Duplicate a block containing two sub page mentions',
|
||||
@@ -331,7 +320,6 @@ void main() {
|
||||
expect(find.text(_createdPageName), findsOneWidget);
|
||||
expect(find.text("$_createdPageName (copy)"), findsOneWidget);
|
||||
expect(find.byType(MentionSubPageBlock), findsNWidgets(2));
|
||||
expect(find.byFlowySvg(FlowySvgs.child_page_s), findsNWidgets(2));
|
||||
|
||||
// Duplicate node from block action menu
|
||||
await tester.editor.hoverAndClickOptionMenuButton([0]);
|
||||
|
||||
+76
-38
@@ -1,5 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_action_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
@@ -73,10 +74,7 @@ void main() {
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.hoverOnPageName(_defaultPageName);
|
||||
await tester.renamePage('Child page');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.renamePageWithSecondary(_defaultPageName, 'Child page');
|
||||
expect(find.text('Child page'), findsNWidgets(2));
|
||||
|
||||
await tester.editor.hoverAndClickOptionMenuButton([0]);
|
||||
@@ -99,10 +97,7 @@ void main() {
|
||||
layout: ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(_defaultPageName);
|
||||
await tester.renamePage('Child page');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.renamePageWithSecondary(_defaultPageName, 'Child page');
|
||||
expect(find.text('Child page'), findsNWidgets(2));
|
||||
|
||||
await tester.editor.hoverAndClickOptionAddButton([0], false);
|
||||
@@ -155,10 +150,7 @@ void main() {
|
||||
layout: ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(_defaultPageName);
|
||||
await tester.renamePage('Child page');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.renamePageWithSecondary(_defaultPageName, 'Child page');
|
||||
expect(find.text('Child page'), findsNWidgets(2));
|
||||
|
||||
await tester.editor.hoverAndClickOptionAddButton([0], false);
|
||||
@@ -216,10 +208,7 @@ void main() {
|
||||
layout: ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(_defaultPageName);
|
||||
await tester.renamePage('Child page');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.renamePageWithSecondary(_defaultPageName, 'Child page');
|
||||
expect(find.text('Child page'), findsNWidgets(2));
|
||||
|
||||
await tester.editor
|
||||
@@ -260,10 +249,7 @@ void main() {
|
||||
layout: ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(_defaultPageName);
|
||||
await tester.renamePage('Child page');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.renamePageWithSecondary(_defaultPageName, 'Child page');
|
||||
expect(find.text('Child page'), findsNWidgets(2));
|
||||
|
||||
await tester.editor
|
||||
@@ -313,10 +299,7 @@ void main() {
|
||||
layout: ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(_defaultPageName);
|
||||
await tester.renamePage('Child page');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.renamePageWithSecondary(_defaultPageName, 'Child page');
|
||||
expect(find.text('Child page'), findsNWidgets(2));
|
||||
|
||||
await tester.editor.hoverAndClickOptionMenuButton([0]);
|
||||
@@ -326,6 +309,11 @@ void main() {
|
||||
expect(find.text('Child page'), findsNothing);
|
||||
expect(find.byType(SubPageBlockComponent), findsNothing);
|
||||
|
||||
// Since there is no selection active in editor before deleting Node,
|
||||
// we need to give focus back to the editor
|
||||
await tester.editor
|
||||
.updateSelection(Selection.collapsed(Position(path: [0])));
|
||||
|
||||
await tester.simulateKeyEvent(
|
||||
LogicalKeyboardKey.keyZ,
|
||||
isControlPressed: Platform.isLinux || Platform.isWindows,
|
||||
@@ -354,10 +342,7 @@ void main() {
|
||||
layout: ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(_defaultPageName);
|
||||
await tester.renamePage('Child page');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.renamePageWithSecondary(_defaultPageName, 'Child page');
|
||||
expect(find.text('Child page'), findsNWidgets(2));
|
||||
|
||||
// Delete
|
||||
@@ -405,15 +390,16 @@ void main() {
|
||||
layout: ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(_defaultPageName);
|
||||
await tester.renamePage('Child page');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.renamePageWithSecondary(_defaultPageName, 'Child page');
|
||||
expect(find.text('Child page'), findsNWidgets(2));
|
||||
expect(find.byType(SubPageBlockComponent), findsOneWidget);
|
||||
|
||||
await tester.hoverOnPageName('Child page');
|
||||
await tester.tapDeletePageButton();
|
||||
await tester.hoverOnPageName(
|
||||
'Child page',
|
||||
onHover: () async {
|
||||
await tester.tapDeletePageButton();
|
||||
},
|
||||
);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
|
||||
expect(find.text('Child page'), findsNothing);
|
||||
@@ -432,10 +418,7 @@ void main() {
|
||||
layout: ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
await tester.hoverOnPageName(_defaultPageName);
|
||||
await tester.renamePage('Child page');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.renamePageWithSecondary(_defaultPageName, 'Child page');
|
||||
expect(find.text('Child page'), findsNWidgets(2));
|
||||
|
||||
await tester.editor.hoverAndClickOptionMenuButton([0]);
|
||||
@@ -473,6 +456,49 @@ void main() {
|
||||
expect(afterNode.type, beforeNode.type);
|
||||
expect(find.byType(SubPageBlockComponent), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('turn into page', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
await tester.createNewPageWithNameUnderParent(name: 'SubPageBlock');
|
||||
|
||||
final editorState = tester.editor.getCurrentEditorState();
|
||||
|
||||
// Insert nested list
|
||||
final transaction = editorState.transaction;
|
||||
transaction.insertNode(
|
||||
[0],
|
||||
bulletedListNode(
|
||||
text: 'Parent',
|
||||
children: [
|
||||
bulletedListNode(text: 'Child 1'),
|
||||
bulletedListNode(text: 'Child 2'),
|
||||
],
|
||||
),
|
||||
);
|
||||
await editorState.apply(transaction);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(SubPageBlockComponent), findsNothing);
|
||||
|
||||
await tester.editor.hoverAndClickOptionMenuButton([0]);
|
||||
await tester.tapButtonWithName(
|
||||
LocaleKeys.document_plugins_optionAction_turnInto.tr(),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text(LocaleKeys.editor_page.tr()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(SubPageBlockComponent), findsOneWidget);
|
||||
|
||||
await tester.expandOrCollapsePage(
|
||||
pageName: 'SubPageBlock',
|
||||
layout: ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
expect(find.text('Parent'), findsNWidgets(2));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -498,4 +524,16 @@ extension _SubPageTestHelper on WidgetTester {
|
||||
|
||||
await pumpUntilFound(find.byType(SubPageBlockComponent));
|
||||
}
|
||||
|
||||
Future<void> renamePageWithSecondary(
|
||||
String currentName,
|
||||
String newName,
|
||||
) async {
|
||||
await hoverOnPageName(currentName, onHover: () async => pumpAndSettle());
|
||||
await rightClickOnPageName(currentName);
|
||||
await tapButtonWithName(ViewMoreActionType.rename.name);
|
||||
await enterText(find.byType(TextFormField), newName);
|
||||
await tapOKButton();
|
||||
await pumpAndSettle();
|
||||
}
|
||||
}
|
||||
+1
-27
@@ -1,26 +1,12 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'document_alignment_test.dart' as document_alignment_test;
|
||||
import 'document_codeblock_paste_test.dart' as document_codeblock_paste_test;
|
||||
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_inline_page_reference_test.dart'
|
||||
as document_inline_page_reference_test;
|
||||
import 'document_more_actions_test.dart' as document_more_actions_test;
|
||||
import 'document_shortcuts_test.dart' as document_shortcuts_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;
|
||||
import 'document_with_file_test.dart' as document_with_file_test;
|
||||
import 'document_with_image_block_test.dart' as document_with_image_block_test;
|
||||
import 'document_with_inline_math_equation_test.dart'
|
||||
as document_with_inline_math_equation_test;
|
||||
import 'document_with_inline_page_test.dart' as document_with_inline_page_test;
|
||||
import 'document_with_multi_image_block_test.dart'
|
||||
as document_with_multi_image_block_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;
|
||||
|
||||
void main() {
|
||||
@@ -33,17 +19,5 @@ void main() {
|
||||
document_with_inline_page_test.main();
|
||||
document_with_inline_math_equation_test.main();
|
||||
document_with_cover_image_test.main();
|
||||
document_with_outline_block.main();
|
||||
document_with_toggle_list_test.main();
|
||||
document_copy_and_paste_test.main();
|
||||
document_codeblock_paste_test.main();
|
||||
document_alignment_test.main();
|
||||
document_text_direction_test.main();
|
||||
document_with_image_block_test.main();
|
||||
document_with_multi_image_block_test.main();
|
||||
document_inline_page_reference_test.main();
|
||||
document_more_actions_test.main();
|
||||
document_with_file_test.main();
|
||||
document_shortcuts_test.main();
|
||||
// Don't add new tests here. Add them to document_test_runner_2.dart
|
||||
// Don't add new tests here.
|
||||
}
|
||||
+2
-2
@@ -9,18 +9,18 @@ import 'document_with_date_reminder_test.dart'
|
||||
as document_with_date_reminder_test;
|
||||
import 'document_with_toggle_heading_block_test.dart'
|
||||
as document_with_toggle_heading_block_test;
|
||||
import 'document_sub_page_test.dart' as document_sub_page_test;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Document integration tests
|
||||
document_title_test.main();
|
||||
// Disable subPage test temporarily, enable it in version 0.7.2
|
||||
// document_sub_page_test.main();
|
||||
document_app_lifecycle_test.main();
|
||||
document_with_date_reminder_test.main();
|
||||
document_deletion_test.main();
|
||||
document_option_action_test.main();
|
||||
document_inline_sub_page_test.main();
|
||||
document_with_toggle_heading_block_test.main();
|
||||
document_sub_page_test.main();
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'document_alignment_test.dart' as document_alignment_test;
|
||||
import 'document_codeblock_paste_test.dart' as document_codeblock_paste_test;
|
||||
import 'document_copy_and_paste_test.dart' as document_copy_and_paste_test;
|
||||
import 'document_text_direction_test.dart' as document_text_direction_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;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Document integration tests
|
||||
document_with_outline_block.main();
|
||||
document_with_toggle_list_test.main();
|
||||
document_copy_and_paste_test.main();
|
||||
document_codeblock_paste_test.main();
|
||||
document_alignment_test.main();
|
||||
document_text_direction_test.main();
|
||||
|
||||
// Don't add new tests here.
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
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_shortcuts_test.dart' as document_shortcuts_test;
|
||||
import 'document_with_file_test.dart' as document_with_file_test;
|
||||
import 'document_with_image_block_test.dart' as document_with_image_block_test;
|
||||
import 'document_with_multi_image_block_test.dart'
|
||||
as document_with_multi_image_block_test;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Document integration tests
|
||||
document_with_image_block_test.main();
|
||||
document_with_multi_image_block_test.main();
|
||||
document_inline_page_reference_test.main();
|
||||
document_more_actions_test.main();
|
||||
document_with_file_test.main();
|
||||
document_shortcuts_test.main();
|
||||
|
||||
// Disable subPage test temporarily, enable it in version 0.7.2
|
||||
// document_sub_page_test.main();
|
||||
}
|
||||
+8
-7
@@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart';
|
||||
import 'package:appflowy/workspace/application/settings/date_time/date_format_ext.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/date_picker/desktop_date_picker.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
@@ -32,7 +33,6 @@ void main() {
|
||||
await tester.editor.showSlashMenu();
|
||||
await tester.editor.tapSlashMenuItemWithName(
|
||||
LocaleKeys.document_slashMenu_name_dateOrReminder.tr(),
|
||||
offset: 100,
|
||||
);
|
||||
|
||||
final dateTimeSettings = DateTimeSettingsPB(
|
||||
@@ -56,11 +56,13 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// add time 11:12
|
||||
final currentTime = DateFormat('HH:mm').format(DateTime.now());
|
||||
final textField = find.byWidgetPredicate(
|
||||
(widget) =>
|
||||
widget is TextField && widget.controller!.text == currentTime,
|
||||
);
|
||||
final textField = find
|
||||
.descendant(
|
||||
of: find.byType(DesktopAppFlowyDatePicker),
|
||||
matching: find.byType(TextField),
|
||||
)
|
||||
.last;
|
||||
await tester.pumpUntilFound(textField);
|
||||
await tester.enterText(textField, "11:12");
|
||||
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||
await tester.pumpAndSettle();
|
||||
@@ -84,7 +86,6 @@ void main() {
|
||||
await tester.editor.showSlashMenu();
|
||||
await tester.editor.tapSlashMenuItemWithName(
|
||||
LocaleKeys.document_slashMenu_name_dateOrReminder.tr(),
|
||||
offset: 100,
|
||||
);
|
||||
|
||||
final dateTimeSettings = DateTimeSettingsPB(
|
||||
|
||||
+1
-3
@@ -47,9 +47,7 @@ void main() {
|
||||
mockPickFilePaths(paths: [filePath]);
|
||||
|
||||
await getIt<KeyValueStorage>().set(KVKeys.kCloudType, '0');
|
||||
await tester.tap(
|
||||
find.text(LocaleKeys.document_plugins_file_fileUploadHint.tr()),
|
||||
);
|
||||
await tester.tapFileUploadHint();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(FileUploadMenu), findsNothing);
|
||||
|
||||
-1
@@ -6,7 +6,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/multi_image_block_component/image_render.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/multi_image_block_component/layouts/image_browser_layout.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/multi_image_block_component/multi_image_block_component.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/multi_image_block_component/multi_image_placeholder.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/upload_image_menu/upload_image_menu.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/upload_image_menu/widgets/embed_image_url_widget.dart';
|
||||
|
||||
-1
@@ -169,7 +169,6 @@ Future<void> insertOutlineInDocument(WidgetTester tester) async {
|
||||
await tester.editor.showSlashMenu();
|
||||
await tester.editor.tapSlashMenuItemWithName(
|
||||
LocaleKeys.document_slashMenu_name_outline.tr(),
|
||||
offset: 100,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
+47
-1
@@ -1,6 +1,8 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
@@ -60,6 +62,50 @@ void main() {
|
||||
findsNWidgets(6),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('insert toggle heading and convert it to heading',
|
||||
(tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
|
||||
await tester.createNewPageWithNameUnderParent(
|
||||
name: 'toggle heading block test',
|
||||
);
|
||||
|
||||
await tester.editor.tapLineOfEditorAt(0);
|
||||
await tester.ime.insertText('# > $_heading1\n');
|
||||
await tester.simulateKeyEvent(LogicalKeyboardKey.enter);
|
||||
await tester.ime.insertText('item 1');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.editor.updateSelection(
|
||||
Selection(
|
||||
start: Position(path: [0]),
|
||||
end: Position(path: [0], offset: _heading1.length),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tapButton(find.byType(HeadingPopup));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
find.byType(HeadingButton),
|
||||
findsNWidgets(3),
|
||||
);
|
||||
|
||||
// tap the H1 button
|
||||
await tester.tapButton(find.byType(HeadingButton).at(0));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final editorState = tester.editor.getCurrentEditorState();
|
||||
final node1 = editorState.document.nodeAtPath([0])!;
|
||||
expect(node1.type, HeadingBlockKeys.type);
|
||||
expect(node1.attributes[HeadingBlockKeys.level], 1);
|
||||
|
||||
final node2 = editorState.document.nodeAtPath([1])!;
|
||||
expect(node2.type, ParagraphBlockKeys.type);
|
||||
expect(node2.delta!.toPlainText(), 'item 1');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,7 +122,7 @@ Future<void> _insertToggleHeadingBlockInDocument(
|
||||
await tester.editor.showSlashMenu();
|
||||
await tester.editor.tapSlashMenuItemWithName(
|
||||
name,
|
||||
offset: 100,
|
||||
offset: 150,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
+1
-1
@@ -11,7 +11,7 @@ void main() {
|
||||
testWidgets('empty test', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
await tester.wait(1000);
|
||||
await tester.wait(500);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'grid_edit_row_test.dart' as grid_edit_row_test_runner;
|
||||
import 'grid_filter_and_sort_test.dart' as grid_filter_and_sort_test_runner;
|
||||
import 'grid_reopen_test.dart' as grid_reopen_test_runner;
|
||||
import 'grid_reorder_row_test.dart' as grid_reorder_row_test_runner;
|
||||
import 'grid_row_test.dart' as grid_row_test_runner;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
grid_reopen_test_runner.main();
|
||||
grid_row_test_runner.main();
|
||||
grid_reorder_row_test_runner.main();
|
||||
grid_filter_and_sort_test_runner.main();
|
||||
grid_edit_row_test_runner.main();
|
||||
// grid_calculations_test_runner.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
+7
-2
@@ -19,8 +19,13 @@ void main() {
|
||||
await tester.tapAnonymousSignInButton();
|
||||
|
||||
// Right click on the view item and change icon
|
||||
await tester.tap(find.byType(ViewItem), buttons: kSecondaryButton);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.hoverOnWidget(
|
||||
find.byType(ViewItem),
|
||||
onHover: () async {
|
||||
await tester.tap(find.byType(ViewItem), buttons: kSecondaryButton);
|
||||
await tester.pumpAndSettle();
|
||||
},
|
||||
);
|
||||
|
||||
// Change icon
|
||||
final changeIconButton =
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'emoji_shortcut_test.dart' as emoji_shortcut_test;
|
||||
import 'hotkeys_test.dart' as hotkeys_test;
|
||||
import 'import_files_test.dart' as import_files_test;
|
||||
import 'share_markdown_test.dart' as share_markdown_test;
|
||||
import 'tabs_test.dart' as tabs_test;
|
||||
import 'zoom_in_out_test.dart' as zoom_in_out_test;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// This test must be run first, otherwise the CI will fail.
|
||||
hotkeys_test.main();
|
||||
emoji_shortcut_test.main();
|
||||
hotkeys_test.main();
|
||||
emoji_shortcut_test.main();
|
||||
share_markdown_test.main();
|
||||
import_files_test.main();
|
||||
tabs_test.main();
|
||||
zoom_in_out_test.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'desktop/document/document_test_runner_1.dart' as document_test_runner;
|
||||
import 'desktop/uncategorized/empty_test.dart' as first_test;
|
||||
import 'desktop/document/document_test_runner_1.dart' as document_test_runner_1;
|
||||
import 'desktop/uncategorized/switch_folder_test.dart' as switch_folder_test;
|
||||
|
||||
Future<void> main() async {
|
||||
@@ -11,11 +10,7 @@ Future<void> main() async {
|
||||
Future<void> runIntegration1OnDesktop() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// This test must be run first, otherwise the CI will fail.
|
||||
first_test.main();
|
||||
|
||||
switch_folder_test.main();
|
||||
document_test_runner.main();
|
||||
|
||||
document_test_runner_1.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
@@ -1,18 +1,7 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'desktop/database/database_calendar_test.dart' as database_calendar_test;
|
||||
import 'desktop/database/database_cell_test.dart' as database_cell_test;
|
||||
import 'desktop/database/database_field_settings_test.dart'
|
||||
as database_field_settings_test;
|
||||
import 'desktop/database/database_field_test.dart' as database_field_test;
|
||||
import 'desktop/database/database_filter_test.dart' as database_filter_test;
|
||||
import 'desktop/database/database_media_test.dart' as database_media_test;
|
||||
import 'desktop/database/database_row_page_test.dart' as database_row_page_test;
|
||||
import 'desktop/database/database_setting_test.dart' as database_setting_test;
|
||||
import 'desktop/database/database_share_test.dart' as database_share_test;
|
||||
import 'desktop/database/database_sort_test.dart' as database_sort_test;
|
||||
import 'desktop/database/database_view_test.dart' as database_view_test;
|
||||
import 'desktop/uncategorized/empty_test.dart' as first_test;
|
||||
import 'desktop/database/database_test_runner_1.dart' as database_test_runner_1;
|
||||
import 'desktop/first_test/first_test.dart' as first_test;
|
||||
|
||||
Future<void> main() async {
|
||||
await runIntegration2OnDesktop();
|
||||
@@ -21,20 +10,8 @@ Future<void> main() async {
|
||||
Future<void> runIntegration2OnDesktop() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// This test must be run first, otherwise the CI will fail.
|
||||
first_test.main();
|
||||
|
||||
database_cell_test.main();
|
||||
database_field_test.main();
|
||||
database_field_settings_test.main();
|
||||
database_share_test.main();
|
||||
database_row_page_test.main();
|
||||
database_setting_test.main();
|
||||
database_filter_test.main();
|
||||
database_sort_test.main();
|
||||
database_view_test.main();
|
||||
database_calendar_test.main();
|
||||
database_media_test.main();
|
||||
|
||||
database_test_runner_1.main();
|
||||
// DON'T add more tests here. This is the second test runner for desktop.
|
||||
}
|
||||
@@ -1,24 +1,8 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'desktop/board/board_test_runner.dart' as board_test_runner;
|
||||
import 'desktop/database/database_row_cover_test.dart'
|
||||
as database_row_cover_test;
|
||||
import 'desktop/grid/grid_edit_row_test.dart' as grid_edit_row_test_runner;
|
||||
import 'desktop/grid/grid_filter_and_sort_test.dart'
|
||||
as grid_filter_and_sort_test_runner;
|
||||
import 'desktop/grid/grid_reopen_test.dart' as grid_reopen_test_runner;
|
||||
import 'desktop/grid/grid_reorder_row_test.dart'
|
||||
as grid_reorder_row_test_runner;
|
||||
import 'desktop/grid/grid_row_test.dart' as grid_create_row_test_runner;
|
||||
import 'desktop/settings/settings_runner.dart' as settings_test_runner;
|
||||
import 'desktop/sidebar/sidebar_test_runner.dart' as sidebar_test_runner;
|
||||
import 'desktop/uncategorized/emoji_shortcut_test.dart' as emoji_shortcut_test;
|
||||
import 'desktop/uncategorized/empty_test.dart' as first_test;
|
||||
import 'desktop/uncategorized/hotkeys_test.dart' as hotkeys_test;
|
||||
import 'desktop/uncategorized/import_files_test.dart' as import_files_test;
|
||||
import 'desktop/uncategorized/share_markdown_test.dart' as share_markdown_test;
|
||||
import 'desktop/uncategorized/tabs_test.dart' as tabs_test;
|
||||
import 'desktop/uncategorized/zoom_in_out_test.dart' as zoom_in_out_test;
|
||||
import 'desktop/first_test/first_test.dart' as first_test;
|
||||
import 'desktop/grid/grid_test_runner_1.dart' as grid_test_runner_1;
|
||||
|
||||
Future<void> main() async {
|
||||
await runIntegration3OnDesktop();
|
||||
@@ -27,26 +11,9 @@ Future<void> main() async {
|
||||
Future<void> runIntegration3OnDesktop() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// This test must be run first, otherwise the CI will fail.
|
||||
first_test.main();
|
||||
|
||||
hotkeys_test.main();
|
||||
emoji_shortcut_test.main();
|
||||
hotkeys_test.main();
|
||||
emoji_shortcut_test.main();
|
||||
settings_test_runner.main();
|
||||
share_markdown_test.main();
|
||||
import_files_test.main();
|
||||
sidebar_test_runner.main();
|
||||
board_test_runner.main();
|
||||
tabs_test.main();
|
||||
database_row_cover_test.main();
|
||||
grid_reopen_test_runner.main();
|
||||
grid_create_row_test_runner.main();
|
||||
grid_reorder_row_test_runner.main();
|
||||
grid_filter_and_sort_test_runner.main();
|
||||
grid_edit_row_test_runner.main();
|
||||
zoom_in_out_test.main();
|
||||
|
||||
// DON'T add more tests here. Add them to desktop_runner_4.dart
|
||||
grid_test_runner_1.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'desktop/document/document_test_runner_2.dart' as document_test_runner_2;
|
||||
import 'desktop/uncategorized/empty_test.dart' as first_test;
|
||||
import 'desktop/first_test/first_test.dart' as first_test;
|
||||
|
||||
Future<void> main() async {
|
||||
await runIntegration4OnDesktop();
|
||||
@@ -10,8 +10,8 @@ Future<void> main() async {
|
||||
Future<void> runIntegration4OnDesktop() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// This test must be run first, otherwise the CI will fail.
|
||||
first_test.main();
|
||||
|
||||
document_test_runner_2.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'desktop/database/database_test_runner_2.dart' as database_test_runner_2;
|
||||
import 'desktop/first_test/first_test.dart' as first_test;
|
||||
|
||||
Future<void> main() async {
|
||||
await runIntegration5OnDesktop();
|
||||
}
|
||||
|
||||
Future<void> runIntegration5OnDesktop() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
first_test.main();
|
||||
|
||||
database_test_runner_2.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'desktop/first_test/first_test.dart' as first_test;
|
||||
import 'desktop/settings/settings_runner.dart' as settings_test_runner;
|
||||
import 'desktop/sidebar/sidebar_test_runner.dart' as sidebar_test_runner;
|
||||
import 'desktop/uncategorized/uncategorized_test_runner_1.dart'
|
||||
as uncategorized_test_runner_1;
|
||||
|
||||
Future<void> main() async {
|
||||
await runIntegration6OnDesktop();
|
||||
}
|
||||
|
||||
Future<void> runIntegration6OnDesktop() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
first_test.main();
|
||||
|
||||
settings_test_runner.main();
|
||||
sidebar_test_runner.main();
|
||||
uncategorized_test_runner_1.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'desktop/document/document_test_runner_3.dart' as document_test_runner_3;
|
||||
import 'desktop/first_test/first_test.dart' as first_test;
|
||||
|
||||
Future<void> main() async {
|
||||
await runIntegration7OnDesktop();
|
||||
}
|
||||
|
||||
Future<void> runIntegration7OnDesktop() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
first_test.main();
|
||||
|
||||
document_test_runner_3.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'desktop/document/document_test_runner_4.dart' as document_test_runner_4;
|
||||
import 'desktop/first_test/first_test.dart' as first_test;
|
||||
|
||||
Future<void> main() async {
|
||||
await runIntegration8OnDesktop();
|
||||
}
|
||||
|
||||
Future<void> runIntegration8OnDesktop() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
first_test.main();
|
||||
|
||||
document_test_runner_4.main();
|
||||
// DON'T add more tests here.
|
||||
}
|
||||
@@ -4,6 +4,10 @@ import 'desktop_runner_1.dart';
|
||||
import 'desktop_runner_2.dart';
|
||||
import 'desktop_runner_3.dart';
|
||||
import 'desktop_runner_4.dart';
|
||||
import 'desktop_runner_5.dart';
|
||||
import 'desktop_runner_6.dart';
|
||||
import 'desktop_runner_7.dart';
|
||||
import 'desktop_runner_8.dart';
|
||||
import 'mobile_runner.dart';
|
||||
|
||||
/// The main task runner for all integration tests in AppFlowy.
|
||||
@@ -19,6 +23,10 @@ Future<void> main() async {
|
||||
await runIntegration2OnDesktop();
|
||||
await runIntegration3OnDesktop();
|
||||
await runIntegration4OnDesktop();
|
||||
await runIntegration5OnDesktop();
|
||||
await runIntegration6OnDesktop();
|
||||
await runIntegration7OnDesktop();
|
||||
await runIntegration8OnDesktop();
|
||||
} else if (Platform.isIOS || Platform.isAndroid) {
|
||||
await runIntegrationOnMobile();
|
||||
} else {
|
||||
|
||||
@@ -192,8 +192,13 @@ extension CommonOperations on WidgetTester {
|
||||
ViewLayoutPB layout = ViewLayoutPB.Document,
|
||||
}) async {
|
||||
final page = findPageName(name, layout: layout);
|
||||
await tap(page, buttons: kSecondaryMouseButton);
|
||||
await pumpAndSettle();
|
||||
await hoverOnPageName(
|
||||
name,
|
||||
onHover: () async {
|
||||
await tap(page, buttons: kSecondaryMouseButton);
|
||||
await pumpAndSettle();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// open the page with given name.
|
||||
@@ -311,6 +316,15 @@ extension CommonOperations on WidgetTester {
|
||||
await tapButton(shareButton);
|
||||
}
|
||||
|
||||
// open the share menu and then click the publish tab
|
||||
Future<void> openPublishMenu() async {
|
||||
await tapShareButton();
|
||||
final publishButton = find.textContaining(
|
||||
LocaleKeys.shareAction_publishTab.tr(),
|
||||
);
|
||||
await tapButton(publishButton);
|
||||
}
|
||||
|
||||
/// Tap the export markdown button
|
||||
///
|
||||
/// Must call [tapShareButton] first.
|
||||
@@ -761,6 +775,18 @@ extension CommonOperations on WidgetTester {
|
||||
await tap(button);
|
||||
await pump();
|
||||
}
|
||||
|
||||
Future<void> tapFileUploadHint() async {
|
||||
final finder = find.byWidgetPredicate(
|
||||
(w) =>
|
||||
w is RichText &&
|
||||
w.text.toPlainText().contains(
|
||||
LocaleKeys.document_plugins_file_fileUploadHint.tr(),
|
||||
),
|
||||
);
|
||||
await tap(finder);
|
||||
await pumpAndSettle(const Duration(seconds: 2));
|
||||
}
|
||||
}
|
||||
|
||||
extension SettingsFinder on CommonFinders {
|
||||
|
||||
@@ -596,7 +596,10 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
||||
final banner = find.byType(RowBanner);
|
||||
expect(banner, findsOneWidget);
|
||||
|
||||
await startGesture(getCenter(banner), kind: PointerDeviceKind.mouse);
|
||||
await startGesture(
|
||||
getCenter(banner) + const Offset(0, -10),
|
||||
kind: PointerDeviceKind.mouse,
|
||||
);
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
@@ -608,7 +611,6 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
||||
await tapButtonWithName(
|
||||
LocaleKeys.document_plugins_cover_addCover.tr(),
|
||||
);
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> openEmojiPicker() async =>
|
||||
|
||||
@@ -4,11 +4,13 @@ import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_setting.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/account/account_user_profile.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/settings_workspace_view.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/sites/domain/domain_settings_dialog.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text_field.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'base.dart';
|
||||
@@ -116,4 +118,20 @@ extension AppFlowySettings on WidgetTester {
|
||||
await tapAt(Offset.zero);
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> updateNamespace(String namespace) async {
|
||||
final dialog = find.byType(DomainSettingsDialog);
|
||||
expect(dialog, findsOneWidget);
|
||||
|
||||
// input the new namespace
|
||||
await enterText(
|
||||
find.descendant(
|
||||
of: dialog,
|
||||
matching: find.byType(TextField),
|
||||
),
|
||||
namespace,
|
||||
);
|
||||
await tapButton(find.text(LocaleKeys.button_save.tr()));
|
||||
await pumpAndSettle();
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ extension MobileRouter on BuildContext {
|
||||
bool addInRecent = true,
|
||||
bool showMoreButton = true,
|
||||
String? fixedTitle,
|
||||
String? blockId,
|
||||
}) async {
|
||||
// set the current view before pushing the new view
|
||||
getIt<MenuSharedState>().latestOpenView = view;
|
||||
@@ -32,6 +33,9 @@ extension MobileRouter on BuildContext {
|
||||
if (fixedTitle != null) {
|
||||
queryParameters[MobileDocumentScreen.viewFixedTitle] = fixedTitle;
|
||||
}
|
||||
if (blockId != null) {
|
||||
queryParameters[MobileDocumentScreen.viewBlockId] = blockId;
|
||||
}
|
||||
}
|
||||
|
||||
final uri = Uri(
|
||||
|
||||
+2
@@ -61,6 +61,7 @@ class NotificationReminderBloc
|
||||
reminderContent: node.delta?.toPlainText() ?? '',
|
||||
nodes: [node],
|
||||
status: NotificationReminderStatus.loaded,
|
||||
blockId: reminder.meta[ReminderMetaKeys.blockId],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -205,6 +206,7 @@ class NotificationReminderState with _$NotificationReminderState {
|
||||
@Default(NotificationReminderStatus.initial)
|
||||
NotificationReminderStatus status,
|
||||
@Default([]) List<Node> nodes,
|
||||
String? blockId,
|
||||
ViewPB? view,
|
||||
}) = _NotificationReminderState;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ class MobileViewPage extends StatefulWidget {
|
||||
this.arguments,
|
||||
this.fixedTitle,
|
||||
this.showMoreButton = true,
|
||||
this.blockId,
|
||||
});
|
||||
|
||||
/// view id
|
||||
@@ -38,6 +39,7 @@ class MobileViewPage extends StatefulWidget {
|
||||
final String? title;
|
||||
final Map<String, dynamic>? arguments;
|
||||
final bool showMoreButton;
|
||||
final String? blockId;
|
||||
|
||||
// only used in row page
|
||||
final String? fixedTitle;
|
||||
@@ -63,6 +65,7 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
||||
@override
|
||||
void dispose() {
|
||||
_appBarOpacity.dispose();
|
||||
_scrollNotificationObserver?.removeListener(_onScrollNotification);
|
||||
_scrollNotificationObserver = null;
|
||||
|
||||
super.dispose();
|
||||
@@ -177,6 +180,7 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
||||
context: PluginContext(userProfile: state.userProfilePB),
|
||||
data: {
|
||||
MobileDocumentScreen.viewFixedTitle: widget.fixedTitle,
|
||||
MobileDocumentScreen.viewBlockId: widget.blockId,
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
import 'package:appflowy/plugins/database/application/cell/bloc/media_cell_bloc.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/file/file_util.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/file/mobile_file_upload_menu.dart';
|
||||
import 'package:appflowy/util/xfile_ext.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/file_entities.pbenum.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/media_entities.pbenum.dart';
|
||||
import 'package:cross_file/cross_file.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MobileMediaUploadSheetContent extends StatelessWidget {
|
||||
const MobileMediaUploadSheetContent({super.key, required this.dialogContext});
|
||||
|
||||
final BuildContext dialogContext;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(top: 12),
|
||||
constraints: const BoxConstraints(
|
||||
maxHeight: 340,
|
||||
minHeight: 80,
|
||||
),
|
||||
child: MobileFileUploadMenu(
|
||||
onInsertLocalFile: (files) async {
|
||||
dialogContext.pop();
|
||||
|
||||
await insertLocalFiles(
|
||||
context,
|
||||
files,
|
||||
userProfile: context.read<MediaCellBloc>().state.userProfile,
|
||||
documentId: context.read<MediaCellBloc>().rowId,
|
||||
onUploadSuccess: (file, path, isLocalMode) {
|
||||
final mediaCellBloc = context.read<MediaCellBloc>();
|
||||
if (mediaCellBloc.isClosed) {
|
||||
return;
|
||||
}
|
||||
|
||||
mediaCellBloc.add(
|
||||
MediaCellEvent.addFile(
|
||||
url: path,
|
||||
name: file.name,
|
||||
uploadType: isLocalMode
|
||||
? FileUploadTypePB.LocalFile
|
||||
: FileUploadTypePB.CloudFile,
|
||||
fileType: file.fileType.toMediaFileTypePB(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
onInsertNetworkFile: (url) async => _onInsertNetworkFile(
|
||||
url,
|
||||
dialogContext,
|
||||
context,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onInsertNetworkFile(
|
||||
String url,
|
||||
BuildContext dialogContext,
|
||||
BuildContext context,
|
||||
) async {
|
||||
dialogContext.pop();
|
||||
|
||||
if (url.isEmpty) return;
|
||||
final uri = Uri.tryParse(url);
|
||||
if (uri == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final fakeFile = XFile(uri.path);
|
||||
MediaFileTypePB fileType = fakeFile.fileType.toMediaFileTypePB();
|
||||
fileType =
|
||||
fileType == MediaFileTypePB.Other ? MediaFileTypePB.Link : fileType;
|
||||
|
||||
String name = uri.pathSegments.isNotEmpty ? uri.pathSegments.last : "";
|
||||
if (name.isEmpty && uri.pathSegments.length > 1) {
|
||||
name = uri.pathSegments[uri.pathSegments.length - 2];
|
||||
} else if (name.isEmpty) {
|
||||
name = uri.host;
|
||||
}
|
||||
|
||||
context.read<MediaCellBloc>().add(
|
||||
MediaCellEvent.addFile(
|
||||
url: url,
|
||||
name: name,
|
||||
uploadType: FileUploadTypePB.NetworkFile,
|
||||
fileType: fileType,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+1
@@ -143,6 +143,7 @@ Future<T?> showMobileBottomSheet<T>(
|
||||
) ??
|
||||
Expanded(
|
||||
child: Scrollbar(
|
||||
controller: scrollController,
|
||||
child: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: child,
|
||||
|
||||
+3
@@ -11,6 +11,7 @@ class OptionTextField extends StatelessWidget {
|
||||
const OptionTextField({
|
||||
super.key,
|
||||
required this.controller,
|
||||
this.autoFocus = false,
|
||||
required this.isPrimary,
|
||||
required this.fieldType,
|
||||
required this.onTextChanged,
|
||||
@@ -18,6 +19,7 @@ class OptionTextField extends StatelessWidget {
|
||||
});
|
||||
|
||||
final TextEditingController controller;
|
||||
final bool autoFocus;
|
||||
final bool isPrimary;
|
||||
final FieldType fieldType;
|
||||
final void Function(String value) onTextChanged;
|
||||
@@ -27,6 +29,7 @@ class OptionTextField extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return FlowyOptionTile.textField(
|
||||
controller: controller,
|
||||
autofocus: autoFocus,
|
||||
textFieldPadding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
onTextChanged: onTextChanged,
|
||||
leftIcon: GestureDetector(
|
||||
|
||||
+13
-5
@@ -5,7 +5,7 @@ import 'package:appflowy/plugins/database/application/cell/bloc/date_cell_editor
|
||||
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/date_picker/mobile_appflowy_date_picker.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/date_picker/mobile_date_picker.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/date_picker/widgets/mobile_date_header.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -93,11 +93,19 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
|
||||
onRangeSelected: (start, end) {
|
||||
dateCellBloc.add(DateCellEditorEvent.updateDateRange(start, end));
|
||||
},
|
||||
onIsRangeChanged: (value) {
|
||||
dateCellBloc.add(DateCellEditorEvent.setIsRange(value));
|
||||
onIsRangeChanged: (value, dateTime, endDateTime) {
|
||||
dateCellBloc.add(
|
||||
DateCellEditorEvent.setIsRange(value, dateTime, endDateTime),
|
||||
);
|
||||
},
|
||||
onIncludeTimeChanged: (value) {
|
||||
dateCellBloc.add(DateCellEditorEvent.setIncludeTime(value));
|
||||
onIncludeTimeChanged: (value, dateTime, endDateTime) {
|
||||
dateCellBloc.add(
|
||||
DateCellEditorEvent.setIncludeTime(
|
||||
value,
|
||||
dateTime,
|
||||
endDateTime,
|
||||
),
|
||||
);
|
||||
},
|
||||
onClearDate: () {
|
||||
dateCellBloc.add(const DateCellEditorEvent.clearDate());
|
||||
|
||||
+4
-4
@@ -21,15 +21,15 @@ import 'mobile_quick_field_editor.dart';
|
||||
const mobileSupportedFieldTypes = [
|
||||
FieldType.RichText,
|
||||
FieldType.Number,
|
||||
FieldType.URL,
|
||||
FieldType.SingleSelect,
|
||||
FieldType.MultiSelect,
|
||||
FieldType.DateTime,
|
||||
FieldType.LastEditedTime,
|
||||
FieldType.CreatedTime,
|
||||
FieldType.Media,
|
||||
FieldType.URL,
|
||||
FieldType.Checkbox,
|
||||
FieldType.Checklist,
|
||||
FieldType.Media,
|
||||
FieldType.LastEditedTime,
|
||||
FieldType.CreatedTime,
|
||||
// FieldType.Time,
|
||||
];
|
||||
|
||||
|
||||
+1
@@ -224,6 +224,7 @@ class _MobileFieldEditorState extends State<MobileFieldEditor> {
|
||||
const _Divider(),
|
||||
OptionTextField(
|
||||
controller: controller,
|
||||
autoFocus: widget.mode == FieldOptionMode.add,
|
||||
fieldType: values.type,
|
||||
isPrimary: widget.isPrimary,
|
||||
onTextChanged: (value) {
|
||||
|
||||
@@ -9,6 +9,7 @@ class MobileDocumentScreen extends StatelessWidget {
|
||||
this.title,
|
||||
this.showMoreButton = true,
|
||||
this.fixedTitle,
|
||||
this.blockId,
|
||||
});
|
||||
|
||||
/// view id
|
||||
@@ -16,12 +17,14 @@ class MobileDocumentScreen extends StatelessWidget {
|
||||
final String? title;
|
||||
final bool showMoreButton;
|
||||
final String? fixedTitle;
|
||||
final String? blockId;
|
||||
|
||||
static const routeName = '/docs';
|
||||
static const viewId = 'id';
|
||||
static const viewTitle = 'title';
|
||||
static const viewShowMoreButton = 'show_more_button';
|
||||
static const viewFixedTitle = 'fixed_title';
|
||||
static const viewBlockId = 'block_id';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -31,6 +34,7 @@ class MobileDocumentScreen extends StatelessWidget {
|
||||
viewLayout: ViewLayoutPB.Document,
|
||||
showMoreButton: showMoreButton,
|
||||
fixedTitle: fixedTitle,
|
||||
blockId: blockId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -138,11 +138,9 @@ class _MobileSpaceTabState extends State<MobileSpaceTab>
|
||||
if (tabController == null) {
|
||||
return;
|
||||
}
|
||||
context.read<SpaceOrderBloc>().add(
|
||||
SpaceOrderEvent.open(
|
||||
tabController!.index,
|
||||
),
|
||||
);
|
||||
context
|
||||
.read<SpaceOrderBloc>()
|
||||
.add(SpaceOrderEvent.open(tabController!.index));
|
||||
}
|
||||
|
||||
List<Widget> _buildTabs(SpaceOrderState state) {
|
||||
@@ -174,13 +172,9 @@ class _MobileSpaceTabState extends State<MobileSpaceTab>
|
||||
}
|
||||
|
||||
// quick create new page when clicking the add button in navigation bar
|
||||
void _createNewDocument() {
|
||||
_createNewPage(ViewLayoutPB.Document);
|
||||
}
|
||||
void _createNewDocument() => _createNewPage(ViewLayoutPB.Document);
|
||||
|
||||
void _createNewAIChat() {
|
||||
_createNewPage(ViewLayoutPB.Chat);
|
||||
}
|
||||
void _createNewAIChat() => _createNewPage(ViewLayoutPB.Chat);
|
||||
|
||||
void _createNewPage(ViewLayoutPB layout) {
|
||||
if (context.read<SpaceBloc>().state.spaces.isNotEmpty) {
|
||||
@@ -206,8 +200,7 @@ class _MobileSpaceTabState extends State<MobileSpaceTab>
|
||||
final workspaceId =
|
||||
context.read<UserWorkspaceBloc>().state.currentWorkspace?.workspaceId;
|
||||
if (workspaceId == null) {
|
||||
Log.error('Workspace ID is null');
|
||||
return;
|
||||
return Log.error('Workspace ID is null');
|
||||
}
|
||||
context
|
||||
.read<UserWorkspaceBloc>()
|
||||
|
||||
+5
-9
@@ -28,8 +28,8 @@ class MobileNotificationsScreen extends StatefulWidget {
|
||||
|
||||
class _MobileNotificationsScreenState extends State<MobileNotificationsScreen>
|
||||
with SingleTickerProviderStateMixin {
|
||||
final ReminderBloc _reminderBloc = getIt<ReminderBloc>();
|
||||
late final TabController _controller = TabController(length: 2, vsync: this);
|
||||
final ReminderBloc reminderBloc = getIt<ReminderBloc>();
|
||||
late final TabController controller = TabController(length: 2, vsync: this);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -39,7 +39,7 @@ class _MobileNotificationsScreenState extends State<MobileNotificationsScreen>
|
||||
create: (context) =>
|
||||
UserProfileBloc()..add(const UserProfileEvent.started()),
|
||||
),
|
||||
BlocProvider<ReminderBloc>.value(value: _reminderBloc),
|
||||
BlocProvider<ReminderBloc>.value(value: reminderBloc),
|
||||
BlocProvider<NotificationFilterBloc>(
|
||||
create: (_) => NotificationFilterBloc(),
|
||||
),
|
||||
@@ -54,8 +54,8 @@ class _MobileNotificationsScreenState extends State<MobileNotificationsScreen>
|
||||
_NotificationScreenContent(
|
||||
workspaceSetting: workspaceSetting,
|
||||
userProfile: userProfile,
|
||||
controller: _controller,
|
||||
reminderBloc: _reminderBloc,
|
||||
controller: controller,
|
||||
reminderBloc: reminderBloc,
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -124,7 +124,6 @@ class _NotificationScreenContent extends StatelessWidget {
|
||||
reminderBloc: reminderBloc,
|
||||
views: sectionState.section.publicViews,
|
||||
onAction: _onAction,
|
||||
onDelete: _onDelete,
|
||||
onReadChanged: _onReadChanged,
|
||||
actionBar: InboxActionBar(
|
||||
hasUnreads: state.hasUnreads,
|
||||
@@ -161,9 +160,6 @@ class _NotificationScreenContent extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
|
||||
void _onDelete(ReminderPB reminder) =>
|
||||
reminderBloc.add(ReminderEvent.remove(reminderId: reminder.id));
|
||||
|
||||
void _onReadChanged(ReminderPB reminder, bool isRead) => reminderBloc.add(
|
||||
ReminderEvent.update(ReminderUpdate(id: reminder.id, isRead: isRead)),
|
||||
);
|
||||
|
||||
+3
-12
@@ -61,15 +61,11 @@ class _MobileNotificationsScreenV2State
|
||||
);
|
||||
}
|
||||
|
||||
void _onRefresh() {
|
||||
getIt<ReminderBloc>().add(const ReminderEvent.refresh());
|
||||
}
|
||||
void _onRefresh() => getIt<ReminderBloc>().add(const ReminderEvent.refresh());
|
||||
}
|
||||
|
||||
class MobileNotificationsTab extends StatefulWidget {
|
||||
const MobileNotificationsTab({
|
||||
super.key,
|
||||
});
|
||||
const MobileNotificationsTab({super.key});
|
||||
|
||||
@override
|
||||
State<MobileNotificationsTab> createState() => _MobileNotificationsTabState();
|
||||
@@ -88,17 +84,12 @@ class _MobileNotificationsTabState extends State<MobileNotificationsTab>
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
tabController = TabController(
|
||||
length: 3,
|
||||
vsync: this,
|
||||
);
|
||||
tabController = TabController(length: 3, vsync: this);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
tabController.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -21,6 +21,12 @@ class _MobileNotificationTabBarState extends State<MobileNotificationTabBar> {
|
||||
widget.controller.addListener(_updateState);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.controller.removeListener(_updateState);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _updateState() => setState(() {});
|
||||
|
||||
@override
|
||||
|
||||
+5
-1
@@ -64,11 +64,15 @@ class NotificationItem extends StatelessWidget {
|
||||
child: child,
|
||||
onTapUp: () async {
|
||||
final view = state.view;
|
||||
final blockId = state.blockId;
|
||||
if (view == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
await context.pushView(view);
|
||||
await context.pushView(
|
||||
view,
|
||||
blockId: blockId,
|
||||
);
|
||||
|
||||
if (!reminder.isRead && context.mounted) {
|
||||
context.read<ReminderBloc>().add(
|
||||
|
||||
@@ -98,12 +98,7 @@ class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder
|
||||
required bool shrinkWrap,
|
||||
Map<String, dynamic>? data,
|
||||
}) {
|
||||
notifier.isDeleted.addListener(() {
|
||||
final deletedView = notifier.isDeleted.value;
|
||||
if (deletedView != null && deletedView.hasIndex()) {
|
||||
deletedViewIndex = deletedView.index;
|
||||
}
|
||||
});
|
||||
notifier.isDeleted.addListener(_onDeleted);
|
||||
|
||||
if (context.userProfile == null) {
|
||||
Log.error("User profile is null when opening AI Chat plugin");
|
||||
@@ -122,6 +117,13 @@ class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder
|
||||
);
|
||||
}
|
||||
|
||||
void _onDeleted() {
|
||||
final deletedView = notifier.isDeleted.value;
|
||||
if (deletedView != null && deletedView.hasIndex()) {
|
||||
deletedViewIndex = deletedView.index;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<NavigationItem> get navigationItems => [this];
|
||||
|
||||
|
||||
+4
-3
@@ -86,9 +86,7 @@ class _ChatInputState extends State<ChatInput> {
|
||||
},
|
||||
);
|
||||
|
||||
_inputFocusNode.addListener(() {
|
||||
setState(() {});
|
||||
});
|
||||
_inputFocusNode.addListener(_updateState);
|
||||
|
||||
_inputActionControl = ChatInputActionControl(
|
||||
chatId: widget.chatId,
|
||||
@@ -101,12 +99,15 @@ class _ChatInputState extends State<ChatInput> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_inputFocusNode.removeListener(_updateState);
|
||||
_inputFocusNode.dispose();
|
||||
_textController.dispose();
|
||||
_inputActionControl.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _updateState() => setState(() {});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
|
||||
+24
-14
@@ -137,11 +137,11 @@ class DateCellEditorBloc
|
||||
}
|
||||
await _updateDateData(date: start, endDate: end);
|
||||
},
|
||||
setIncludeTime: (includeTime) async {
|
||||
await _updateIncludeTime(includeTime);
|
||||
setIncludeTime: (includeTime, dateTime, endDateTime) async {
|
||||
await _updateIncludeTime(includeTime, dateTime, endDateTime);
|
||||
},
|
||||
setIsRange: (isRange) async {
|
||||
await _updateIsRange(isRange);
|
||||
setIsRange: (isRange, dateTime, endDateTime) async {
|
||||
await _updateIsRange(isRange, dateTime, endDateTime);
|
||||
},
|
||||
setDateFormat: (DateFormatPB dateFormat) async {
|
||||
await _updateTypeOption(emit, dateFormat: dateFormat);
|
||||
@@ -209,10 +209,11 @@ class DateCellEditorBloc
|
||||
result.onFailure(Log.error);
|
||||
}
|
||||
|
||||
Future<void> _updateIsRange(bool isRange) async {
|
||||
final dateTime = state.dateTime == null ? DateTime.now().withoutTime : null;
|
||||
final endDateTime = dateTime;
|
||||
|
||||
Future<void> _updateIsRange(
|
||||
bool isRange,
|
||||
DateTime? dateTime,
|
||||
DateTime? endDateTime,
|
||||
) async {
|
||||
final result = await _dateCellBackendService.update(
|
||||
date: dateTime,
|
||||
endDate: endDateTime,
|
||||
@@ -221,9 +222,11 @@ class DateCellEditorBloc
|
||||
result.onFailure(Log.error);
|
||||
}
|
||||
|
||||
Future<void> _updateIncludeTime(bool includeTime) async {
|
||||
final dateTime = state.dateTime ?? DateTime.now().withoutTime;
|
||||
final endDateTime = state.isRange ? state.endDateTime ?? dateTime : null;
|
||||
Future<void> _updateIncludeTime(
|
||||
bool includeTime,
|
||||
DateTime? dateTime,
|
||||
DateTime? endDateTime,
|
||||
) async {
|
||||
final result = await _dateCellBackendService.update(
|
||||
date: dateTime,
|
||||
endDate: endDateTime,
|
||||
@@ -320,10 +323,17 @@ class DateCellEditorEvent with _$DateCellEditorEvent {
|
||||
DateTime end,
|
||||
) = _UpdateDateRange;
|
||||
|
||||
const factory DateCellEditorEvent.setIncludeTime(bool includeTime) =
|
||||
_IncludeTime;
|
||||
const factory DateCellEditorEvent.setIncludeTime(
|
||||
bool includeTime,
|
||||
DateTime? dateTime,
|
||||
DateTime? endDateTime,
|
||||
) = _IncludeTime;
|
||||
|
||||
const factory DateCellEditorEvent.setIsRange(bool isRange) = _SetIsRange;
|
||||
const factory DateCellEditorEvent.setIsRange(
|
||||
bool isRange,
|
||||
DateTime? dateTime,
|
||||
DateTime? endDateTime,
|
||||
) = _SetIsRange;
|
||||
|
||||
const factory DateCellEditorEvent.setReminderOption(ReminderOption option) =
|
||||
_SetReminderOption;
|
||||
|
||||
+12
-5
@@ -3,12 +3,14 @@ import 'dart:async';
|
||||
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/type_option/type_option_data_parser.dart';
|
||||
import 'package:appflowy/plugins/database/application/row/row_service.dart';
|
||||
import 'package:appflowy/user/application/user_service.dart';
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/cell_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/file_entities.pbenum.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/media_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/row_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
||||
import 'package:flowy_infra/uuid.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -24,7 +26,10 @@ class MediaCellBloc extends Bloc<MediaCellEvent, MediaCellState> {
|
||||
_startListening();
|
||||
}
|
||||
|
||||
late final RowBackendService _rowService =
|
||||
RowBackendService(viewId: cellController.viewId);
|
||||
final MediaCellController cellController;
|
||||
|
||||
void Function()? _onCellChangedFn;
|
||||
|
||||
String get databaseId => cellController.viewId;
|
||||
@@ -110,10 +115,6 @@ class MediaCellBloc extends Bloc<MediaCellEvent, MediaCellState> {
|
||||
},
|
||||
reorderFiles: (from, to) async {
|
||||
final files = List<MediaFilePB>.from(state.files);
|
||||
if (from < to) {
|
||||
to--;
|
||||
}
|
||||
|
||||
files.insert(to, files.removeAt(from));
|
||||
|
||||
// We emit the new state first to update the UI
|
||||
@@ -153,6 +154,10 @@ class MediaCellBloc extends Bloc<MediaCellEvent, MediaCellState> {
|
||||
toggleShowAllFiles: () {
|
||||
emit(state.copyWith(showAllFiles: !state.showAllFiles));
|
||||
},
|
||||
setCover: (cover) => _rowService.updateMeta(
|
||||
rowId: cellController.rowId,
|
||||
cover: cover,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -214,6 +219,8 @@ class MediaCellEvent with _$MediaCellEvent {
|
||||
}) = _RenameFile;
|
||||
|
||||
const factory MediaCellEvent.toggleShowAllFiles() = _ToggleShowAllFiles;
|
||||
|
||||
const factory MediaCellEvent.setCover(RowCoverPB cover) = _SetCover;
|
||||
}
|
||||
|
||||
@freezed
|
||||
@@ -223,7 +230,7 @@ class MediaCellState with _$MediaCellState {
|
||||
required String fieldName,
|
||||
@Default([]) List<MediaFilePB> files,
|
||||
@Default(false) showAllFiles,
|
||||
@Default(false) hideFileNames,
|
||||
@Default(true) hideFileNames,
|
||||
}) = _MediaCellState;
|
||||
|
||||
factory MediaCellState.initial(MediaCellController cellController) {
|
||||
|
||||
@@ -132,6 +132,24 @@ class DatabaseController {
|
||||
}
|
||||
}
|
||||
|
||||
void removeListener({
|
||||
DatabaseCallbacks? onDatabaseChanged,
|
||||
DatabaseLayoutSettingCallbacks? onLayoutSettingsChanged,
|
||||
GroupCallbacks? onGroupChanged,
|
||||
}) {
|
||||
if (onDatabaseChanged != null) {
|
||||
_databaseCallbacks.remove(onDatabaseChanged);
|
||||
}
|
||||
|
||||
if (onLayoutSettingsChanged != null) {
|
||||
_layoutCallbacks.remove(onLayoutSettingsChanged);
|
||||
}
|
||||
|
||||
if (onGroupChanged != null) {
|
||||
_groupCallbacks.remove(onGroupChanged);
|
||||
}
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> open() async {
|
||||
return _databaseViewBackendSvc.openDatabase().then((result) {
|
||||
return result.fold(
|
||||
|
||||
+1
@@ -40,6 +40,7 @@ class BoardActionsCubit extends Cubit<BoardActionsState> {
|
||||
}
|
||||
|
||||
void startCreateBottomRow(String groupId) {
|
||||
emit(const BoardActionsState.setFocus(groupedRowIds: []));
|
||||
emit(BoardActionsState.startCreateBottomRow(groupId: groupId));
|
||||
emit(const BoardActionsState.initial());
|
||||
}
|
||||
|
||||
@@ -55,6 +55,10 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
FieldController get fieldController => databaseController.fieldController;
|
||||
String get viewId => databaseController.viewId;
|
||||
|
||||
DatabaseCallbacks? _databaseCallbacks;
|
||||
DatabaseLayoutSettingCallbacks? _layoutSettingsCallback;
|
||||
GroupCallbacks? _groupCallbacks;
|
||||
|
||||
void _initBoardController(AppFlowyBoardController? controller) {
|
||||
boardController = controller ??
|
||||
AppFlowyBoardController(
|
||||
@@ -330,6 +334,17 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
for (final controller in groupControllers.values) {
|
||||
await controller.dispose();
|
||||
}
|
||||
|
||||
databaseController.removeListener(
|
||||
onDatabaseChanged: _databaseCallbacks,
|
||||
onLayoutSettingsChanged: _layoutSettingsCallback,
|
||||
onGroupChanged: _groupCallbacks,
|
||||
);
|
||||
|
||||
_databaseCallbacks = null;
|
||||
_layoutSettingsCallback = null;
|
||||
_groupCallbacks = null;
|
||||
|
||||
boardController.dispose();
|
||||
return super.close();
|
||||
}
|
||||
@@ -380,7 +395,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
RowCache get rowCache => databaseController.rowCache;
|
||||
|
||||
void _startListening() {
|
||||
final onLayoutSettingsChanged = DatabaseLayoutSettingCallbacks(
|
||||
_layoutSettingsCallback = DatabaseLayoutSettingCallbacks(
|
||||
onLayoutSettingsChanged: (layoutSettings) {
|
||||
if (isClosed) {
|
||||
return;
|
||||
@@ -403,7 +418,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
add(BoardEvent.didUpdateLayoutSettings(layoutSettings.board));
|
||||
},
|
||||
);
|
||||
final onGroupChanged = GroupCallbacks(
|
||||
_groupCallbacks = GroupCallbacks(
|
||||
onGroupByField: (groups) {
|
||||
if (isClosed) {
|
||||
return;
|
||||
@@ -482,7 +497,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
add(BoardEvent.didReceiveGroups(groupList));
|
||||
},
|
||||
);
|
||||
final onDatabaseChanged = DatabaseCallbacks(
|
||||
_databaseCallbacks = DatabaseCallbacks(
|
||||
onRowsCreated: (rows) {
|
||||
for (final row in rows) {
|
||||
if (!isClosed && row.isHiddenInView) {
|
||||
@@ -493,9 +508,9 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
);
|
||||
|
||||
databaseController.addListener(
|
||||
onDatabaseChanged: onDatabaseChanged,
|
||||
onLayoutSettingsChanged: onLayoutSettingsChanged,
|
||||
onGroupChanged: onGroupChanged,
|
||||
onDatabaseChanged: _databaseCallbacks,
|
||||
onLayoutSettingsChanged: _layoutSettingsCallback,
|
||||
onGroupChanged: _groupCallbacks,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -534,7 +534,9 @@ class _BoardColumnFooterState extends State<BoardColumnFooter> {
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
onTap: () {
|
||||
setState(() => _isCreating = true);
|
||||
context
|
||||
.read<BoardActionsCubit>()
|
||||
.startCreateBottomRow(widget.columnData.id);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
-1
@@ -8,7 +8,6 @@ import 'package:appflowy/util/field_type_extension.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_board/appflowy_board.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
+16
-12
@@ -51,17 +51,7 @@ class _EditableColumnHeaderState extends State<EditableColumnHeader> {
|
||||
}
|
||||
return KeyEventResult.ignored;
|
||||
},
|
||||
)..addListener(() {
|
||||
if (!focusNode.hasFocus) {
|
||||
widget.isEditing.value = false;
|
||||
widget.onSubmitted(textController.text);
|
||||
} else {
|
||||
textController.selection = TextSelection(
|
||||
baseOffset: 0,
|
||||
extentOffset: textController.text.length,
|
||||
);
|
||||
}
|
||||
});
|
||||
)..addListener(onFocusChanged);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -74,11 +64,25 @@ class _EditableColumnHeaderState extends State<EditableColumnHeader> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
focusNode.dispose();
|
||||
focusNode
|
||||
..removeListener(onFocusChanged)
|
||||
..dispose();
|
||||
textController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void onFocusChanged() {
|
||||
if (!focusNode.hasFocus) {
|
||||
widget.isEditing.value = false;
|
||||
widget.onSubmitted(textController.text);
|
||||
} else {
|
||||
textController.selection = TextSelection(
|
||||
baseOffset: 0,
|
||||
extentOffset: textController.text.length,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
|
||||
-1
@@ -16,7 +16,6 @@ import 'package:appflowy/plugins/database/widgets/cell/card_cell_builder.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell/card_cell_skeleton/text_card_cell.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/row_detail.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
|
||||
+18
-4
@@ -37,6 +37,20 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
||||
UserProfilePB? _userProfile;
|
||||
UserProfilePB? get userProfile => _userProfile;
|
||||
|
||||
DatabaseCallbacks? _databaseCallbacks;
|
||||
DatabaseLayoutSettingCallbacks? _layoutSettingCallbacks;
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
databaseController.removeListener(
|
||||
onDatabaseChanged: _databaseCallbacks,
|
||||
onLayoutSettingsChanged: _layoutSettingCallbacks,
|
||||
);
|
||||
_databaseCallbacks = null;
|
||||
_layoutSettingCallbacks = null;
|
||||
await super.close();
|
||||
}
|
||||
|
||||
void _dispatch() {
|
||||
on<CalendarEvent>(
|
||||
(event, emit) async {
|
||||
@@ -300,7 +314,7 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
final onDatabaseChanged = DatabaseCallbacks(
|
||||
_databaseCallbacks = DatabaseCallbacks(
|
||||
onDatabaseChanged: (database) {
|
||||
if (isClosed) return;
|
||||
},
|
||||
@@ -375,13 +389,13 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
||||
},
|
||||
);
|
||||
|
||||
final onLayoutSettingsChanged = DatabaseLayoutSettingCallbacks(
|
||||
_layoutSettingCallbacks = DatabaseLayoutSettingCallbacks(
|
||||
onLayoutSettingsChanged: _didReceiveLayoutSetting,
|
||||
);
|
||||
|
||||
databaseController.addListener(
|
||||
onDatabaseChanged: onDatabaseChanged,
|
||||
onLayoutSettingsChanged: onLayoutSettingsChanged,
|
||||
onDatabaseChanged: _databaseCallbacks,
|
||||
onLayoutSettingsChanged: _layoutSettingCallbacks,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+11
-2
@@ -29,6 +29,15 @@ class UnscheduleEventsBloc
|
||||
CellMemCache get cellCache => databaseController.rowCache.cellCache;
|
||||
RowCache get rowCache => databaseController.rowCache;
|
||||
|
||||
DatabaseCallbacks? _databaseCallbacks;
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
databaseController.removeListener(onDatabaseChanged: _databaseCallbacks);
|
||||
_databaseCallbacks = null;
|
||||
await super.close();
|
||||
}
|
||||
|
||||
void _dispatch() {
|
||||
on<UnscheduleEventsEvent>(
|
||||
(event, emit) async {
|
||||
@@ -103,7 +112,7 @@ class UnscheduleEventsBloc
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
final onDatabaseChanged = DatabaseCallbacks(
|
||||
_databaseCallbacks = DatabaseCallbacks(
|
||||
onRowsCreated: (rows) async {
|
||||
if (isClosed) {
|
||||
return;
|
||||
@@ -135,7 +144,7 @@ class UnscheduleEventsBloc
|
||||
},
|
||||
);
|
||||
|
||||
databaseController.addListener(onDatabaseChanged: onDatabaseChanged);
|
||||
databaseController.addListener(onDatabaseChanged: _databaseCallbacks);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -242,6 +242,7 @@ class NewEventButton extends StatelessWidget {
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
width: 22,
|
||||
tooltipText: LocaleKeys.calendar_newEventButtonTooltip.tr(),
|
||||
radius: Corners.s6Border,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.fromBorderSide(
|
||||
BorderSide(
|
||||
@@ -251,7 +252,7 @@ class NewEventButton extends StatelessWidget {
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
borderRadius: Corners.s5Border,
|
||||
borderRadius: Corners.s6Border,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
spreadRadius: -2,
|
||||
|
||||
-1
@@ -9,7 +9,6 @@ import 'package:appflowy/plugins/database/widgets/card/card.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell/card_cell_builder.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell/card_cell_style_maps/calendar_card_cell_style.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.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';
|
||||
|
||||
-1
@@ -13,7 +13,6 @@ import 'package:appflowy/plugins/database/widgets/cell/editable_cell_skeleton/te
|
||||
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
|
||||
-2
@@ -15,7 +15,6 @@ import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||
import 'package:appflowy/plugins/database/tab_bar/tab_bar_view.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:calendar_view/calendar_view.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
@@ -437,7 +436,6 @@ class _UnscheduledEventsButtonState extends State<UnscheduledEventsButton> {
|
||||
),
|
||||
side: BorderSide(color: Theme.of(context).dividerColor),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
visualDensity: VisualDensity.compact,
|
||||
),
|
||||
onPressed: () {
|
||||
if (state.unscheduleEvents.isNotEmpty) {
|
||||
|
||||
-1
@@ -8,7 +8,6 @@ import 'package:appflowy/plugins/database/calendar/application/calendar_setting_
|
||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
+2
-6
@@ -80,12 +80,8 @@ class FilterEditorBloc extends Bloc<FilterEditorEvent, FilterEditorState> {
|
||||
};
|
||||
|
||||
fieldController.addListener(
|
||||
onFilters: (filters) {
|
||||
_onFilterFn?.call(filters);
|
||||
},
|
||||
onReceiveFields: (fields) {
|
||||
_onFieldFn?.call(fields);
|
||||
},
|
||||
onFilters: _onFilterFn,
|
||||
onReceiveFields: _onFieldFn,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,15 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
UserProfilePB? _userProfile;
|
||||
UserProfilePB? get userProfile => _userProfile;
|
||||
|
||||
DatabaseCallbacks? _databaseCallbacks;
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
databaseController.removeListener(onDatabaseChanged: _databaseCallbacks);
|
||||
_databaseCallbacks = null;
|
||||
await super.close();
|
||||
}
|
||||
|
||||
void _dispatch() {
|
||||
on<GridEvent>(
|
||||
(event, emit) async {
|
||||
@@ -120,7 +129,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
RowCache get rowCache => databaseController.rowCache;
|
||||
|
||||
void _startListening() {
|
||||
final onDatabaseChanged = DatabaseCallbacks(
|
||||
_databaseCallbacks = DatabaseCallbacks(
|
||||
onNumOfRowsChanged: (rowInfos, _, reason) {
|
||||
if (!isClosed) {
|
||||
add(GridEvent.didLoadRows(rowInfos, reason));
|
||||
@@ -157,7 +166,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
}
|
||||
},
|
||||
);
|
||||
databaseController.addListener(onDatabaseChanged: onDatabaseChanged);
|
||||
databaseController.addListener(onDatabaseChanged: _databaseCallbacks);
|
||||
}
|
||||
|
||||
Future<void> _openGrid(Emitter<GridState> emit) async {
|
||||
|
||||
+10
-2
@@ -20,6 +20,12 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
||||
final String viewId;
|
||||
final FieldController fieldController;
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
fieldController.removeListener(onFieldsListener: _onReceiveFields);
|
||||
await super.close();
|
||||
}
|
||||
|
||||
void _dispatch() {
|
||||
on<GridHeaderEvent>(
|
||||
(event, emit) async {
|
||||
@@ -82,11 +88,13 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
||||
|
||||
void _startListening() {
|
||||
fieldController.addListener(
|
||||
onReceiveFields: (fields) =>
|
||||
add(GridHeaderEvent.didReceiveFieldUpdate(fields)),
|
||||
onReceiveFields: _onReceiveFields,
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
}
|
||||
|
||||
void _onReceiveFields(List<FieldInfo> fields) =>
|
||||
add(GridHeaderEvent.didReceiveFieldUpdate(fields));
|
||||
}
|
||||
|
||||
@freezed
|
||||
|
||||
+11
-2
@@ -24,6 +24,15 @@ class MobileRowDetailBloc
|
||||
UserProfilePB? _userProfile;
|
||||
UserProfilePB? get userProfile => _userProfile;
|
||||
|
||||
DatabaseCallbacks? _databaseCallbacks;
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
databaseController.removeListener(onDatabaseChanged: _databaseCallbacks);
|
||||
_databaseCallbacks = null;
|
||||
await super.close();
|
||||
}
|
||||
|
||||
void _dispatch() {
|
||||
on<MobileRowDetailEvent>(
|
||||
(event, emit) {
|
||||
@@ -67,7 +76,7 @@ class MobileRowDetailBloc
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
final onDatabaseChanged = DatabaseCallbacks(
|
||||
_databaseCallbacks = DatabaseCallbacks(
|
||||
onNumOfRowsChanged: (rowInfos, _, reason) {
|
||||
if (!isClosed) {
|
||||
add(MobileRowDetailEvent.didLoadRows(rowInfos));
|
||||
@@ -83,7 +92,7 @@ class MobileRowDetailBloc
|
||||
}
|
||||
},
|
||||
);
|
||||
databaseController.addListener(onDatabaseChanged: onDatabaseChanged);
|
||||
databaseController.addListener(onDatabaseChanged: _databaseCallbacks);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,14 +70,13 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
);
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
_rowController.addListener(
|
||||
onRowChanged: (cells, reason) {
|
||||
if (!isClosed) {
|
||||
add(RowEvent.didReceiveCells(cells, reason));
|
||||
}
|
||||
},
|
||||
);
|
||||
void _startListening() =>
|
||||
_rowController.addListener(onRowChanged: _onRowChanged);
|
||||
|
||||
void _onRowChanged(List<CellContext> cells, ChangedReason reason) {
|
||||
if (!isClosed) {
|
||||
add(RowEvent.didReceiveCells(cells, reason));
|
||||
}
|
||||
}
|
||||
|
||||
void _init() {
|
||||
|
||||
-1
@@ -10,7 +10,6 @@ import 'package:appflowy/shared/patterns/common_patterns.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/calculation_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/number_entities.pb.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
-1
@@ -4,7 +4,6 @@ import 'package:appflowy/plugins/database/application/field/filter_entities.dart
|
||||
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/checkbox_filter.pbenum.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
-1
@@ -3,7 +3,6 @@ import 'package:appflowy/plugins/database/application/field/filter_entities.dart
|
||||
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/checklist_filter.pbenum.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
+2
-3
@@ -6,8 +6,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/date_picker/appflowy_date_picker.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/date_picker/desktop_date_picker.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -199,7 +198,7 @@ class _DateFilterEditorState extends State<DateFilterEditor> {
|
||||
child: SingleFilterBlocSelector<DateTimeFilter>(
|
||||
filterId: widget.filterId,
|
||||
builder: (context, filter, field) {
|
||||
return AppFlowyDatePicker(
|
||||
return DesktopAppFlowyDatePicker(
|
||||
isRange: isRange,
|
||||
includeTime: false,
|
||||
dateFormat: DateFormatPB.Friendly,
|
||||
|
||||
-1
@@ -5,7 +5,6 @@ import 'package:appflowy/plugins/database/application/field/filter_entities.dart
|
||||
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
-1
@@ -1,7 +1,6 @@
|
||||
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/filter_entities.dart';
|
||||
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
-1
@@ -5,7 +5,6 @@ import 'package:appflowy/plugins/database/application/field/filter_entities.dart
|
||||
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
-1
@@ -5,7 +5,6 @@ import 'package:appflowy/plugins/database/application/field/filter_entities.dart
|
||||
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
-1
@@ -1,7 +1,6 @@
|
||||
import 'package:appflowy/plugins/database/application/field/filter_entities.dart';
|
||||
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
-1
@@ -2,7 +2,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
||||
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.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';
|
||||
|
||||
-1
@@ -9,7 +9,6 @@ import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/field/field_editor.dart';
|
||||
import 'package:appflowy/util/field_type_extension.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.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';
|
||||
|
||||
-1
@@ -6,7 +6,6 @@ import 'package:appflowy/plugins/database/grid/application/grid_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -12,7 +12,6 @@ import 'package:appflowy/plugins/database/application/row/row_service.dart';
|
||||
import 'package:appflowy/plugins/database/grid/application/row/row_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/tab_bar/tab_bar_view.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.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';
|
||||
|
||||
-1
@@ -10,7 +10,6 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/grid/application/sort/sort_editor_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pbenum.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';
|
||||
|
||||
-1
@@ -4,7 +4,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/sort_entities.dart';
|
||||
import 'package:appflowy/plugins/database/grid/application/sort/sort_editor_bloc.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
-2
@@ -1,7 +1,6 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
@@ -40,7 +39,6 @@ class _FilterButtonState extends State<FilterButton> {
|
||||
LocaleKeys.grid_settings_filter.tr(),
|
||||
fontColor: textColor,
|
||||
fontSize: FontSizes.s12,
|
||||
fontWeight: FontWeight.w400,
|
||||
fillColor: Colors.transparent,
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
padding: GridSize.toolbarSettingButtonInsets,
|
||||
|
||||
-2
@@ -1,7 +1,6 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/grid/application/sort/sort_editor_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
@@ -37,7 +36,6 @@ class _SortButtonState extends State<SortButton> {
|
||||
LocaleKeys.grid_settings_sort.tr(),
|
||||
fontColor: textColor,
|
||||
fontSize: FontSizes.s12,
|
||||
fontWeight: FontWeight.w400,
|
||||
fillColor: Colors.transparent,
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
padding: GridSize.toolbarSettingButtonInsets,
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/database_layout_ext.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pbenum.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
|
||||
+10
-10
@@ -6,7 +6,6 @@ import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
@@ -47,16 +46,15 @@ class TabBarHeader extends StatelessWidget {
|
||||
const Expanded(
|
||||
child: DatabaseTabBar(),
|
||||
),
|
||||
BlocBuilder<DatabaseTabBarBloc, DatabaseTabBarState>(
|
||||
builder: (context, state) {
|
||||
return SizedBox(
|
||||
width: 200,
|
||||
child: Padding(
|
||||
Flexible(
|
||||
child: BlocBuilder<DatabaseTabBarBloc, DatabaseTabBarState>(
|
||||
builder: (context, state) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 6.0),
|
||||
child: pageSettingBarFromState(context, state),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -221,7 +219,9 @@ class TabBarItemButton extends StatelessWidget {
|
||||
color: color,
|
||||
),
|
||||
text: FlowyText(
|
||||
view.name,
|
||||
view.name.isEmpty
|
||||
? LocaleKeys.document_title_placeholder.tr()
|
||||
: view.name,
|
||||
lineHeight: 1.0,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
||||
+5
-1
@@ -1,4 +1,6 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
@@ -105,7 +107,9 @@ class _DatabaseViewSelectorButton extends StatelessWidget {
|
||||
const HSpace(6),
|
||||
Flexible(
|
||||
child: FlowyText.medium(
|
||||
tabBar.view.name,
|
||||
tabBar.view.name.isEmpty
|
||||
? LocaleKeys.document_title_placeholder.tr()
|
||||
: tabBar.view.name,
|
||||
fontSize: 14,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
|
||||
Loaded 100 of 473 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user