ソースを参照

chore: Merge branch 'main' into develop

nathan 2 年 前
コミット
b8ade5af12
100 ファイル変更1477 行追加899 行削除
  1. 27 0
      .github/PULL_REQUEST_TEMPLATE/pull_request_template.md
  2. 1 1
      .github/workflows/flutter_ci.yaml
  3. 17 23
      .github/workflows/integration_test.yml
  4. 24 8
      .github/workflows/release.yml
  5. 1 1
      .github/workflows/rust_ci.yaml
  6. 1 1
      .github/workflows/rust_coverage.yml
  7. 224 222
      frontend/.vscode/tasks.json
  8. 2 2
      frontend/appflowy_flutter/.gitignore
  9. 10 6
      frontend/appflowy_flutter/README.md
  10. 16 4
      frontend/appflowy_flutter/assets/images/home/new_app.svg
  11. 0 5
      frontend/appflowy_flutter/assets/images/home/new_app_dark.svg
  12. BIN
      frontend/appflowy_flutter/assets/test/workspaces/board.zip
  13. BIN
      frontend/appflowy_flutter/assets/test/workspaces/empty_document.zip
  14. 4 2
      frontend/appflowy_flutter/assets/translations/en.json
  15. 43 0
      frontend/appflowy_flutter/integration_test/board_test.dart
  16. 120 0
      frontend/appflowy_flutter/integration_test/empty_document_test.dart
  17. 19 0
      frontend/appflowy_flutter/integration_test/runner.dart
  18. 0 135
      frontend/appflowy_flutter/integration_test/switch_folder_test.dart
  19. 66 0
      frontend/appflowy_flutter/integration_test/util/data.dart
  20. 12 0
      frontend/appflowy_flutter/integration_test/util/keyboard.dart
  21. 1 0
      frontend/appflowy_flutter/integration_test/util/util.dart
  22. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/application/database_service.dart
  23. 0 6
      frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_action_sheet_bloc.dart
  24. 1 8
      frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_editor_bloc.dart
  25. 0 6
      frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/date_bloc.dart
  26. 0 6
      frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/edit_select_option_bloc.dart
  27. 0 6
      frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_bloc.dart
  28. 0 6
      frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_format_bloc.dart
  29. 0 5
      frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/select_option_type_option_bloc.dart
  30. 0 6
      frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_bloc.dart
  31. 0 6
      frontend/appflowy_flutter/lib/plugins/database_view/board/application/toolbar/board_setting_bloc.dart
  32. 0 2
      frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_setting_bloc.dart
  33. 0 7
      frontend/appflowy_flutter/lib/plugins/database_view/grid/application/filter/select_option_filter_list_bloc.dart
  34. 0 5
      frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_header_bloc.dart
  35. 0 6
      frontend/appflowy_flutter/lib/plugins/database_view/grid/application/row/row_action_sheet_bloc.dart
  36. 6 2
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/choicechip/choicechip.dart
  37. 7 2
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/condition_button.dart
  38. 15 13
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/create_filter_list.dart
  39. 2 0
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/disclosure_button.dart
  40. 4 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_menu.dart
  41. 5 2
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/footer/grid_footer.dart
  42. 3 4
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell.dart
  43. 8 2
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell_action_sheet.dart
  44. 6 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_list.dart
  45. 3 0
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_option_editor.dart
  46. 2 5
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/grid_header.dart
  47. 2 8
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart
  48. 6 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option.dart
  49. 6 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option_editor.dart
  50. 5 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/action.dart
  51. 11 2
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/row.dart
  52. 15 13
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/create_sort_list.dart
  53. 4 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_choice_button.dart
  54. 3 8
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_editor.dart
  55. 4 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_menu.dart
  56. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/filter_button.dart
  57. 6 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_property.dart
  58. 5 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_setting.dart
  59. 1 0
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/setting_button.dart
  60. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/sort_button.dart
  61. 7 1
      frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_cell_editor.dart
  62. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_progress_bar.dart
  63. 1 4
      frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart
  64. 9 2
      frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart
  65. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/select_option_editor.dart
  66. 3 4
      frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/url_cell/url_cell.dart
  67. 47 2
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart
  68. 92 7
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart
  69. 5 2
      frontend/appflowy_flutter/lib/workspace/application/appearance.dart
  70. 9 6
      frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/create_button.dart
  71. 3 3
      frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_panel.dart
  72. 1 1
      frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart
  73. 1 1
      frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart
  74. 1 1
      frontend/appflowy_flutter/macos/Podfile
  75. 6 5
      frontend/appflowy_flutter/macos/Runner.xcodeproj/project.pbxproj
  76. 1 1
      frontend/appflowy_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
  77. 2 2
      frontend/appflowy_flutter/packages/appflowy_backend/pubspec.yaml
  78. 0 1
      frontend/appflowy_flutter/packages/appflowy_editor/lib/appflowy_editor.dart
  79. 2 1
      frontend/appflowy_flutter/packages/appflowy_editor/lib/src/infra/flowy_svg.dart
  80. 1 1
      frontend/appflowy_flutter/packages/appflowy_editor/pubspec.yaml
  81. 1 1
      frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/emoji_picker/emoji_menu_item.dart
  82. 1 1
      frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/extensions/theme_extension.dart
  83. 2 1
      frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/infra/svg.dart
  84. 10 8
      frontend/appflowy_flutter/packages/appflowy_editor_plugins/pubspec.yaml
  85. 1 1
      frontend/appflowy_flutter/packages/appflowy_popover/lib/src/mask.dart
  86. 6 2
      frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart
  87. 15 10
      frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart
  88. 6 1
      frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart
  89. 15 10
      frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart
  90. 11 3
      frontend/appflowy_flutter/packages/flowy_infra/lib/image.dart
  91. 3 3
      frontend/appflowy_flutter/packages/flowy_infra/lib/theme.dart
  92. 11 0
      frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart
  93. 2 2
      frontend/appflowy_flutter/packages/flowy_infra/pubspec.yaml
  94. 0 1
      frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart
  95. 1 1
      frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart
  96. 317 209
      frontend/appflowy_flutter/pubspec.lock
  97. 12 34
      frontend/appflowy_flutter/pubspec.yaml
  98. 28 0
      frontend/scripts/flutter_release_build/build_flowy.dart
  99. 115 0
      frontend/scripts/flutter_release_build/tool.dart
  100. 6 6
      frontend/scripts/install_dev_env/install_linux.sh

+ 27 - 0
.github/PULL_REQUEST_TEMPLATE/pull_request_template.md

@@ -0,0 +1,27 @@
+<!---
+Thank you for submitting a pull request to AppFlowy. The team will dedicate their best efforts to reviewing and approving your pull request. If you have any questions about the project or feedback for us, please join our [Discord](https://discord.gg/wdjWUXXhtw).
+-->
+
+<!---
+If your pull request adds a new feature, please drag and drop a video into this section to showcase what you've done! If not, you may delete this section.
+-->
+
+### Feature Preview
+
+<!---
+List at least one issue here that this PR addresses. If it fixes the issue, please use the [fixes](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests) keyword to close the issue. For example:
+fixes https://github.com/AppFlowy-IO/AppFlowy/pull/2106
+-->
+
+---
+
+<!---
+Before you mark this PR ready for review, run through this checklist!
+-->
+
+#### PR Checklist
+
+- [ ] My code adheres to the [AppFlowy Style Guide](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/style-guides)
+- [ ] I've listed at least one issue that this PR fixes in the description above.
+- [ ] I've added a test(s) to validate changes in this PR, or this PR only contains semantic changes.
+- [ ] All existing tests are passing.

+ 1 - 1
.github/workflows/flutter_ci.yaml

@@ -16,7 +16,7 @@ on:
       - "frontend/**"
       - "frontend/**"
 
 
 env:
 env:
-  FLUTTER_VERSION: "3.3.9"
+  FLUTTER_VERSION: "3.7.5"
   RUST_TOOLCHAIN: "1.65"
   RUST_TOOLCHAIN: "1.65"
 
 
 jobs:
 jobs:

+ 17 - 23
.github/workflows/integration_test.yml

@@ -35,7 +35,7 @@ jobs:
       - uses: subosito/flutter-action@v2
       - uses: subosito/flutter-action@v2
         with:
         with:
           channel: "stable"
           channel: "stable"
-          flutter-version: "3.3.9"
+          flutter-version: "3.7.5"
           cache: true
           cache: true
 
 
       - name: Cache Cargo
       - name: Cache Cargo
@@ -56,15 +56,16 @@ jobs:
 
 
       - name: Setup Environment
       - name: Setup Environment
         run: |
         run: |
+          cargo install --force cargo-make
+          cargo install --force duckscript_cli
           if [ "$RUNNER_OS" == "Linux" ]; then
           if [ "$RUNNER_OS" == "Linux" ]; then
             sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
             sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
             sudo wget -qO /etc/apt/sources.list.d/dart_stable.list https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list
             sudo wget -qO /etc/apt/sources.list.d/dart_stable.list https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list
             sudo apt-get update
             sudo apt-get update
-            sudo apt-get install -y dart curl build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
+            sudo apt-get install -y dart curl build-essential libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
             sudo apt-get install keybinder-3.0
             sudo apt-get install keybinder-3.0
           elif [ "$RUNNER_OS" == "Windows" ]; then
           elif [ "$RUNNER_OS" == "Windows" ]; then
             vcpkg integrate install
             vcpkg integrate install
-            cargo install --force duckscript_cli
           elif [ "$RUNNER_OS" == "macOS" ]; then
           elif [ "$RUNNER_OS" == "macOS" ]; then
             echo 'do nothing'
             echo 'do nothing'
           fi
           fi
@@ -77,17 +78,6 @@ jobs:
           cargo install cargo-make
           cargo install cargo-make
           cargo make appflowy-flutter-deps-tools
           cargo make appflowy-flutter-deps-tools
 
 
-      - name: Build Test lib
-        working-directory: frontend
-        run: |
-          if [ "$RUNNER_OS" == "Linux" ]; then
-            cargo make --profile production-linux-x86_64 appflowy
-          elif [ "$RUNNER_OS" == "macOS" ]; then
-            cargo make --profile production-mac-x86_64 appflowy
-          elif [ "$RUNNER_OS" == "Windows" ]; then
-            cargo make --profile production-windows-x86 appflowy
-          fi
-
       - name: Config Flutter
       - name: Config Flutter
         run: |
         run: |
           if [ "$RUNNER_OS" == "Linux" ]; then
           if [ "$RUNNER_OS" == "Linux" ]; then
@@ -99,22 +89,27 @@ jobs:
           fi
           fi
         shell: bash
         shell: bash
 
 
-      - name: Flutter Code Generation
-        working-directory: frontend/appflowy_flutter
+      - name: Build Test lib
+        working-directory: frontend
         run: |
         run: |
-          flutter packages pub get
-          flutter packages pub run easy_localization:generate -f keys -o locale_keys.g.dart -S assets/translations -s en.json
-          flutter packages pub run build_runner build --delete-conflicting-outputs
+          if [ "$RUNNER_OS" == "Linux" ]; then
+            cargo make --profile development-linux-x86_64 appflowy-dev
+          elif [ "$RUNNER_OS" == "macOS" ]; then
+            cargo make --profile development-mac-x86_64 appflowy-dev
+          elif [ "$RUNNER_OS" == "Windows" ]; then
+            cargo make --profile development-windows-x86 appflowy-dev
+          fi
+        shell: bash
 
 
       - name: Run AppFlowy tests
       - name: Run AppFlowy tests
         working-directory: frontend/appflowy_flutter
         working-directory: frontend/appflowy_flutter
         run: |
         run: |
           if [ "$RUNNER_OS" == "Linux" ]; then
           if [ "$RUNNER_OS" == "Linux" ]; then
-            flutter test integration_test -d Linux --coverage
+            flutter test integration_test/runner.dart -d Linux --coverage
           elif [ "$RUNNER_OS" == "macOS" ]; then
           elif [ "$RUNNER_OS" == "macOS" ]; then
-            flutter test integration_test -d macOS --coverage
+            flutter test integration_test/runner.dart -d macOS --coverage
           elif [ "$RUNNER_OS" == "Windows" ]; then
           elif [ "$RUNNER_OS" == "Windows" ]; then
-            flutter test integration_test -d Windows --coverage
+            flutter test integration_test/runner.dart -d Windows --coverage
           fi
           fi
         shell: bash
         shell: bash
 
 
@@ -125,4 +120,3 @@ jobs:
       #     env_vars: ${{ matrix.os }}
       #     env_vars: ${{ matrix.os }}
       #     fail_ci_if_error: true
       #     fail_ci_if_error: true
       #     verbose: true
       #     verbose: true
-

+ 24 - 8
.github/workflows/release.yml

@@ -3,10 +3,10 @@ name: release
 on:
 on:
   push:
   push:
     tags:
     tags:
-      - '*'
+      - "*"
 
 
 env:
 env:
-  FLUTTER_VERSION: "3.3.9"
+  FLUTTER_VERSION: "3.7.5"
   RUST_TOOLCHAIN: "1.65"
   RUST_TOOLCHAIN: "1.65"
 
 
 jobs:
 jobs:
@@ -136,7 +136,11 @@ jobs:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
         job:
         job:
-          - { target: x86_64-apple-darwin, os: macos-10.15, extra-build-args: "" }
+          - {
+              target: x86_64-apple-darwin,
+              os: macos-10.15,
+              extra-build-args: "",
+            }
     steps:
     steps:
       - name: Checkout source code
       - name: Checkout source code
         uses: actions/checkout@v3
         uses: actions/checkout@v3
@@ -172,7 +176,7 @@ jobs:
         working-directory: frontend
         working-directory: frontend
         run: |
         run: |
           flutter config --enable-macos-desktop
           flutter config --enable-macos-desktop
-          cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-mac-x86_64 appflowy
+          dart ./scripts/flutter_release_build/build_flowy.dart . ${{ github.ref_name }}
 
 
       - name: Create macOS dmg
       - name: Create macOS dmg
         run: |
         run: |
@@ -225,9 +229,21 @@ jobs:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
         job:
         job:
-          - { arch: x86_64, target: x86_64-unknown-linux-gnu, os: ubuntu-20.04, extra-build-args: "", flutter_profile: production-linux-x86_64 }
+          - {
+              arch: x86_64,
+              target: x86_64-unknown-linux-gnu,
+              os: ubuntu-20.04,
+              extra-build-args: "",
+              flutter_profile: production-linux-x86_64,
+            }
           # - { arch: aarch64, target: aarch64-unknown-linux-gnu, os: ubuntu-20.04, extra-build-args: "", flutter_profile: production-linux-aarch64 }
           # - { arch: aarch64, target: aarch64-unknown-linux-gnu, os: ubuntu-20.04, extra-build-args: "", flutter_profile: production-linux-aarch64 }
-          - { arch: x86_64, target: x86_64-unknown-linux-gnu, os: ubuntu-18.04, extra-build-args: "", flutter_profile: production-linux-x86_64}
+          - {
+              arch: x86_64,
+              target: x86_64-unknown-linux-gnu,
+              os: ubuntu-18.04,
+              extra-build-args: "",
+              flutter_profile: production-linux-x86_64,
+            }
     steps:
     steps:
       - name: Checkout source code
       - name: Checkout source code
         uses: actions/checkout@v3
         uses: actions/checkout@v3
@@ -275,7 +291,7 @@ jobs:
         working-directory: frontend
         working-directory: frontend
         run: |
         run: |
           flutter config --enable-linux-desktop
           flutter config --enable-linux-desktop
-          cargo make --env APP_VERSION=${{ github.ref_name }} --profile ${{ matrix.job.flutter_profile}} appflowy
+          dart ./scripts/flutter_release_build/build_flowy.dart . ${{ github.ref_name }}
 
 
       - name: Archive Assert
       - name: Archive Assert
         working-directory: ${{ env.LINUX_APP_RELEASE_PATH }}
         working-directory: ${{ env.LINUX_APP_RELEASE_PATH }}
@@ -361,4 +377,4 @@ jobs:
       - name: Notify Discord
       - name: Notify Discord
         run: |
         run: |
           curl -H "Content-Type: application/json" -d '{"username": "release@appflowy", "content": "🎉 AppFlowy ${{ github.ref_name }} is available. https://github.com/AppFlowy-IO/AppFlowy/releases/tag/'${{ github.ref_name }}'"}' "https://discord.com/api/webhooks/${{ secrets.DISCORD }}"
           curl -H "Content-Type: application/json" -d '{"username": "release@appflowy", "content": "🎉 AppFlowy ${{ github.ref_name }} is available. https://github.com/AppFlowy-IO/AppFlowy/releases/tag/'${{ github.ref_name }}'"}' "https://discord.com/api/webhooks/${{ secrets.DISCORD }}"
-        shell: bash
+        shell: bash

+ 1 - 1
.github/workflows/rust_ci.yaml

@@ -20,7 +20,7 @@ on:
 env:
 env:
   CARGO_TERM_COLOR: always
   CARGO_TERM_COLOR: always
   RUST_TOOLCHAIN: "1.65"
   RUST_TOOLCHAIN: "1.65"
-  FLUTTER_VERSION: "3.3.9"
+  FLUTTER_VERSION: "3.7.5"
 
 
 jobs:
 jobs:
   test-on-ubuntu:
   test-on-ubuntu:

+ 1 - 1
.github/workflows/rust_coverage.yml

@@ -11,7 +11,7 @@ on:
 
 
 env:
 env:
   CARGO_TERM_COLOR: always
   CARGO_TERM_COLOR: always
-  FLUTTER_VERSION: "3.3.9"
+  FLUTTER_VERSION: "3.7.5"
   RUST_TOOLCHAIN: "1.65"
   RUST_TOOLCHAIN: "1.65"
 
 
 jobs:
 jobs:

+ 224 - 222
frontend/.vscode/tasks.json

@@ -1,223 +1,225 @@
 {
 {
-	"version": "2.0.0",
-	// https://code.visualstudio.com/docs/editor/tasks
-	// https://gist.github.com/deadalusai/9e13e36d61ec7fb72148
-	// ${workspaceRoot}: the root folder of the team
-	// ${file}: the current opened file
-	// ${fileBasename}: the current opened file's basename
-	// ${fileDirname}: the current opened file's dirname
-	// ${fileExtname}: the current opened file's extension
-	// ${cwd}: the current working directory of the spawned process
-	"tasks": [
-		{
-			"label": "AF: Clean + Rebuild All",
-			"type": "shell",
-			"dependsOrder": "sequence",
-			"dependsOn": [
-				"AF: Dart Clean",
-				"AF: Flutter Clean",
-				"AF: Build Appflowy Core",
-				"AF: Flutter Pub Get",
-				"AF: Flutter Package Get",
-				"AF: Generate Language Files",
-				"AF: Generate Freezed Files"
-			],
-			"presentation": {
-				"reveal": "always",
-				"panel": "new"
-			}
-		},
-		{
-			"label": "AF: Clean + Rebuild All (Android)",
-			"type": "shell",
-			"dependsOrder": "sequence",
-			"dependsOn": [
-				"AF: Dart Clean",
-				"AF: Flutter Clean",
-				"AF: Build Appflowy Core_for_android",
-				"AF: Flutter Pub Get",
-				"AF: Flutter Package Get",
-				"AF: Generate Language Files",
-				"AF: Generate Freezed Files"
-			],
-			"presentation": {
-				"reveal": "always",
-				"panel": "new"
-			}
-		},
-		{
-			"label": "AF: Build Appflowy Core_for_android",
-			"type": "shell",
-			"command": "cargo make --profile development-android appflowy-core-dev-android",
-			"group": "build",
-			"options": {
-				"cwd": "${workspaceFolder}"
-			}
-		},
-		{
-			"label": "AF: Build Appflowy Core",
-			"type": "shell",
-			"windows": {
-				"command": "cargo make --profile development-windows-x86 appflowy-core-dev"
-			},
-			"linux": {
-				"command": "cargo make --profile \"development-linux-$(uname -m)\" appflowy-core-dev"
-			},
-			"osx": {
-				"command": "cargo make --profile \"development-mac-$(uname -m)\" appflowy-core-dev"
-			},
-			"group": "build",
-			"options": {
-				"cwd": "${workspaceFolder}"
-			}
-		},
-		{
-			"label": "AF: Code Gen",
-			"type": "shell",
-			"dependsOrder": "sequence",
-			"dependsOn": [
-				"AF: Flutter Clean",
-				"AF: Flutter Pub Get",
-				"AF: Flutter Package Get",
-				"AF: Generate Language Files",
-				"AF: Generate Freezed Files"
-			],
-			"group": {
-				"kind": "build",
-				"isDefault": true
-			},
-			"presentation": {
-				"reveal": "always",
-				"panel": "new"
-			}
-		},
-		{
-			"label": "AF: Flutter Clean",
-			"type": "shell",
-			"command": "flutter clean",
-			"options": {
-				"cwd": "${workspaceFolder}/appflowy_flutter"
-			}
-		},
-		{
-			"label": "AF: Flutter Pub Get",
-			"type": "shell",
-			"command": "flutter pub get",
-			"options": {
-				"cwd": "${workspaceFolder}/appflowy_flutter"
-			}
-		},
-		{
-			"label": "AF: Flutter Package Get",
-			"type": "shell",
-			"command": "flutter packages pub get",
-			"options": {
-				"cwd": "${workspaceFolder}/appflowy_flutter"
-			}
-		},
-		{
-			"label": "AF: Generate Freezed Files",
-			"type": "shell",
-			"command": "flutter pub run build_runner build --delete-conflicting-outputs",
-			"options": {
-				"cwd": "${workspaceFolder}/appflowy_flutter"
-			}
-		},
-		{
-			"label": "AF: Generate Language Files",
-			"type": "shell",
-			"command": "sh ./scripts/generate_language_files.sh",
-			"windows": {
-				"options": {
-					"shell": {
-						"executable": "cmd.exe",
-						"args": [
-							"/d",
-							"/c",
-							".\\scripts\\generate_language_files.cmd"
-						]
-					}
-				}
-			},
-			"group": "build",
-			"options": {
-				"cwd": "${workspaceFolder}"
-			}
-		},
-		{
-			"label": "AF: Flutter Clean",
-			"type": "shell",
-			"command": "cargo make flutter_clean",
-			"group": "build",
-			"options": {
-				"cwd": "${workspaceFolder}"
-			}
-		},
-		{
-			"label": "AF: flutter build aar",
-			"type": "flutter",
-			"command": "flutter",
-			"args": [
-				"build",
-				"aar"
-			],
-			"group": "build",
-			"problemMatcher": [],
-			"detail": "appflowy_flutter"
-		},
-		{
-			"label": "AF: Tauri UI Dev",
-			"type": "shell",
-			"isBackground": true,
-			"command": "yarn",
-			"args": ["dev"],
-			"options": {
-				"cwd": "${workspaceFolder}/appflowy_tauri"
-			}
-		},
-		{
-			"label": "AF: Tauri UI Build",
-			"type": "shell",
-			"command": "npm run build",
-			"options": {
-				"cwd": "${workspaceFolder}/appflowy_tauri"
-			}
-		},
-		{
-			"label": "AF: Tauri Dev",
-			"type": "shell",
-			"command": "npm run tauri:dev",
-			"options": {
-				"cwd": "${workspaceFolder}/appflowy_tauri"
-			}
-		},
-		{
-			"label": "AF: Tauri Clean",
-			"type": "shell",
-			"command": "cargo make tauri_clean",
-			"options": {
-				"cwd": "${workspaceFolder}"
-			}
-		},
-		{
-			"label": "AF: Tauri Clean + Dev",
-			"type": "shell",
-			"dependsOrder": "sequence",
-			"dependsOn": [
-				"AF: Tauri Clean",
-				"AF: Tauri UI Dev"
-			],
-			"options": {
-				"cwd": "${workspaceFolder}"
-			}
-		},
-		{
-			"label": "AF: Tauri ESLint",
-			"type": "shell",
-			"command": "npx eslint --fix src",
-			"options": {
-				"cwd": "${workspaceFolder}/appflowy_tauri"
-			}
-		},	
-	]
-}
+  "version": "2.0.0",
+  // https://code.visualstudio.com/docs/editor/tasks
+  // https://gist.github.com/deadalusai/9e13e36d61ec7fb72148
+  // ${workspaceRoot}: the root folder of the team
+  // ${file}: the current opened file
+  // ${fileBasename}: the current opened file's basename
+  // ${fileDirname}: the current opened file's dirname
+  // ${fileExtname}: the current opened file's extension
+  // ${cwd}: the current working directory of the spawned process
+  "tasks": [
+    {
+      "label": "AF: Clean + Rebuild All",
+      "type": "shell",
+      "dependsOrder": "sequence",
+      "dependsOn": [
+        "AF: Dart Clean",
+        "AF: Flutter Clean",
+        "AF: Build Appflowy Core",
+        "AF: Flutter Pub Get",
+        "AF: Flutter Package Get",
+        "AF: Generate Language Files",
+        "AF: Generate Freezed Files"
+      ],
+      "presentation": {
+        "reveal": "always",
+        "panel": "new"
+      }
+    },
+    {
+      "label": "AF: Clean + Rebuild All (Android)",
+      "type": "shell",
+      "dependsOrder": "sequence",
+      "dependsOn": [
+        "AF: Dart Clean",
+        "AF: Flutter Clean",
+        "AF: Build Appflowy Core_for_android",
+        "AF: Flutter Pub Get",
+        "AF: Flutter Package Get",
+        "AF: Generate Language Files",
+        "AF: Generate Freezed Files"
+      ],
+      "presentation": {
+        "reveal": "always",
+        "panel": "new"
+      }
+    },
+    {
+      "label": "AF: Build Appflowy Core_for_android",
+      "type": "shell",
+      "command": "cargo make --profile development-android appflowy-core-dev-android",
+      "group": "build",
+      "options": {
+        "cwd": "${workspaceFolder}"
+      }
+    },
+    {
+      "label": "AF: Build Appflowy Core",
+      "type": "shell",
+      "windows": {
+        "command": "cargo make --profile development-windows-x86 appflowy-core-dev"
+      },
+      "linux": {
+        "command": "cargo make --profile \"development-linux-$(uname -m)\" appflowy-core-dev"
+      },
+      "osx": {
+        "command": "cargo make --profile \"development-mac-$(uname -m)\" appflowy-core-dev"
+      },
+      "group": "build",
+      "options": {
+        "cwd": "${workspaceFolder}"
+      }
+    },
+    {
+      "label": "AF: Code Gen",
+      "type": "shell",
+      "dependsOrder": "sequence",
+      "dependsOn": [
+        "AF: Flutter Clean",
+        "AF: Flutter Pub Get",
+        "AF: Flutter Package Get",
+        "AF: Generate Language Files",
+        "AF: Generate Freezed Files"
+      ],
+      "group": {
+        "kind": "build",
+        "isDefault": true
+      },
+      "presentation": {
+        "reveal": "always",
+        "panel": "new"
+      }
+    },
+    {
+      "label": "AF: Flutter Clean",
+      "type": "shell",
+      "command": "flutter clean",
+      "options": {
+        "cwd": "${workspaceFolder}/appflowy_flutter"
+      }
+    },
+    {
+      "label": "AF: Flutter Pub Get",
+      "type": "shell",
+      "command": "flutter pub get",
+      "options": {
+        "cwd": "${workspaceFolder}/appflowy_flutter"
+      }
+    },
+    {
+      "label": "AF: Flutter Package Get",
+      "type": "shell",
+      "command": "flutter packages pub get",
+      "options": {
+        "cwd": "${workspaceFolder}/appflowy_flutter"
+      }
+    },
+    {
+      "label": "AF: Generate Freezed Files",
+      "type": "shell",
+      "command": "flutter pub run build_runner build --delete-conflicting-outputs",
+      "options": {
+        "cwd": "${workspaceFolder}/appflowy_flutter"
+      }
+    },
+    {
+      "label": "AF: Generate Language Files",
+      "type": "shell",
+      "command": "sh ./scripts/generate_language_files.sh",
+      "windows": {
+        "options": {
+          "shell": {
+            "executable": "cmd.exe",
+            "args": [
+              "/d",
+              "/c",
+              ".\\scripts\\generate_language_files.cmd"
+            ]
+          }
+        }
+      },
+      "group": "build",
+      "options": {
+        "cwd": "${workspaceFolder}"
+      }
+    },
+    {
+      "label": "AF: Flutter Clean",
+      "type": "shell",
+      "command": "cargo make flutter_clean",
+      "group": "build",
+      "options": {
+        "cwd": "${workspaceFolder}"
+      }
+    },
+    {
+      "label": "AF: flutter build aar",
+      "type": "flutter",
+      "command": "flutter",
+      "args": [
+        "build",
+        "aar"
+      ],
+      "group": "build",
+      "problemMatcher": [],
+      "detail": "appflowy_flutter"
+    },
+    {
+      "label": "AF: Tauri UI Dev",
+      "type": "shell",
+      "isBackground": true,
+      "command": "yarn",
+      "args": [
+        "dev"
+      ],
+      "options": {
+        "cwd": "${workspaceFolder}/appflowy_tauri"
+      }
+    },
+    {
+      "label": "AF: Tauri UI Build",
+      "type": "shell",
+      "command": "npm run build",
+      "options": {
+        "cwd": "${workspaceFolder}/appflowy_tauri"
+      }
+    },
+    {
+      "label": "AF: Tauri Dev",
+      "type": "shell",
+      "command": "npm run tauri:dev",
+      "options": {
+        "cwd": "${workspaceFolder}/appflowy_tauri"
+      }
+    },
+    {
+      "label": "AF: Tauri Clean",
+      "type": "shell",
+      "command": "cargo make tauri_clean",
+      "options": {
+        "cwd": "${workspaceFolder}"
+      }
+    },
+    {
+      "label": "AF: Tauri Clean + Dev",
+      "type": "shell",
+      "dependsOrder": "sequence",
+      "dependsOn": [
+        "AF: Tauri Clean",
+        "AF: Tauri UI Dev"
+      ],
+      "options": {
+        "cwd": "${workspaceFolder}"
+      }
+    },
+    {
+      "label": "AF: Tauri ESLint",
+      "type": "shell",
+      "command": "npx eslint --fix src",
+      "options": {
+        "cwd": "${workspaceFolder}/appflowy_tauri"
+      }
+    },
+  ]
+}

+ 2 - 2
frontend/appflowy_flutter/.gitignore

@@ -40,7 +40,7 @@ lib/generated_plugin_registrant.dart
 lib/generated/
 lib/generated/
 
 
 # Freezed generated files
 # Freezed generated files
-*.g.dart 
+*.g.dart
 *.freezed.dart
 *.freezed.dart
 
 
 # Symbolication related
 # Symbolication related
@@ -67,4 +67,4 @@ windows/flutter/dart_ffi/
 **/**/*.so
 **/**/*.so
 **/**/Brewfile.lock.json
 **/**/Brewfile.lock.json
 **/.sandbox
 **/.sandbox
-**/.vscode/
+**/.vscode/

+ 10 - 6
frontend/appflowy_flutter/README.md

@@ -1,6 +1,6 @@
 <h1 align="center" style="margin:0"> AppFlowy_Flutter</h1>
 <h1 align="center" style="margin:0"> AppFlowy_Flutter</h1>
 <div align="center">
 <div align="center">
-  <img src="https://img.shields.io/badge/Flutter-v3.3.10-blue"/>
+  <img src="https://img.shields.io/badge/Flutter-v3.7.5-blue"/>
   <img src="https://img.shields.io/badge/Rust-v1.65-orange"/>
   <img src="https://img.shields.io/badge/Rust-v1.65-orange"/>
 </div>
 </div>
 
 
@@ -9,13 +9,16 @@
 This Repository contains the codebase for the frontend of the application, currently we use Flutter as our frontend framework.
 This Repository contains the codebase for the frontend of the application, currently we use Flutter as our frontend framework.
 
 
 ### Platforms Supported Using Flutter 💻
 ### Platforms Supported Using Flutter 💻
+
 - Linux
 - Linux
 - macOS
 - macOS
 - Windows
 - Windows
-> We later expect to extend support to Android and iOS devices using Flutter.
+  > We later expect to extend support to Android and iOS devices using Flutter.
 
 
 ### Am I Eligible to Contribute?
 ### Am I Eligible to Contribute?
+
 Yes! You are eligible to contribute, check out the ways in which you can [contribute to AppFlowy](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/contributing-to-appflowy). Some of the ways in which you can contribute are:
 Yes! You are eligible to contribute, check out the ways in which you can [contribute to AppFlowy](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/contributing-to-appflowy). Some of the ways in which you can contribute are:
+
 - Non-Coding Contributions
 - Non-Coding Contributions
   - Documentation
   - Documentation
   - Feature Requests and Feedbacks
   - Feature Requests and Feedbacks
@@ -23,26 +26,27 @@ Yes! You are eligible to contribute, check out the ways in which you can [contri
   - Improve Translations
   - Improve Translations
 - Coding Contributions
 - Coding Contributions
 
 
-
 To contribute to `AppFlowy_Flutter` codebase specifically (coding contribution) we suggest you to have basic knowledge of Flutter. In case you are new to Flutter, we may suggest you to learn the basics and then try to contribute, get started with Flutter [here](https://flutter.dev/docs/get-started/codelab).
 To contribute to `AppFlowy_Flutter` codebase specifically (coding contribution) we suggest you to have basic knowledge of Flutter. In case you are new to Flutter, we may suggest you to learn the basics and then try to contribute, get started with Flutter [here](https://flutter.dev/docs/get-started/codelab).
 
 
 ### What OS Should I Use for Development?
 ### What OS Should I Use for Development?
-We support all OS for Development i.e Linux, macOS and Windows. However, most of us promote macOS and Linux over Windows. We have detailed [docs](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/environment-setup) on How to Setup `AppFlowy_Flutter` in your local system in each OS.
 
 
+We support all OS for Development i.e Linux, macOS and Windows. However, most of us promote macOS and Linux over Windows. We have detailed [docs](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/environment-setup) on How to Setup `AppFlowy_Flutter` in your local system in each OS.
 
 
 ### Getting Started ❇
 ### Getting Started ❇
+
 We have a detailed documentation, on how to [get started](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/contributing-to-appflowy) with the project, and make your first contribution. However, we do have some specific picks for you.
 We have a detailed documentation, on how to [get started](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/contributing-to-appflowy) with the project, and make your first contribution. However, we do have some specific picks for you.
+
 - [Code Architecture](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/frontend/codemap)
 - [Code Architecture](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/frontend/codemap)
 - [Making Your First PR](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/submitting-your-first-pull-request)
 - [Making Your First PR](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/submitting-your-first-pull-request)
 - [The Style Guide](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/style-guides)
 - [The Style Guide](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/style-guides)
 - [How to run/debug the application](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/launcher-and-tasks)
 - [How to run/debug the application](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/launcher-and-tasks)
 
 
-
 ### Need Help?
 ### Need Help?
+
 - New to GitHub? Follow [these](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/setting-up-your-repositories) steps to get started
 - New to GitHub? Follow [these](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/setting-up-your-repositories) steps to get started
 - Stuck Somewhere? Join the [Discord](https://discord.gg/9Q2xaN37tV) Group and we are there to help you!
 - Stuck Somewhere? Join the [Discord](https://discord.gg/9Q2xaN37tV) Group and we are there to help you!
 
 
-<!-- 
+<!--
 ## release check
 ## release check
 1. [entitlements](https://flutter.dev/desktop#setting-up-entitlements)
 1. [entitlements](https://flutter.dev/desktop#setting-up-entitlements)
 2. [symbols stripped](https://flutter.dev/docs/development/platform-integration/c-interop) -->
 2. [symbols stripped](https://flutter.dev/docs/development/platform-integration/c-interop) -->

+ 16 - 4
frontend/appflowy_flutter/assets/images/home/new_app.svg

@@ -1,5 +1,17 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<rect width="16" height="16" rx="8" fill="#00BCF0"/>
-<rect x="7.5" y="4" width="1" height="8" rx="0.5" fill="white"/>
-<rect x="12" y="7.5" width="1" height="8" rx="0.5" transform="rotate(90 12 7.5)" fill="white"/>
+<svg
+   width="16"
+   height="16"
+   viewBox="0 0 16 16"
+   fill="none"
+   version="1.1"
+   id="svg808"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+   <defs
+      id="defs812" />
+   <path
+      id="path930"
+      style="fill:#00bcf0;fill-opacity:1"
+      transform="rotate(-90)"
+      d="M 0,7.9238281 A 8,8 0 0 0 -8.0585938,0 8,8 0 0 0 -16,8.0390625 8,8 0 0 0 -7.9804688,16 8,8 0 0 0 0,8 Z M -4,8 c 0,0.2769988 -0.2230012,0.5 -0.5,0.5 h -3 v 3 c 0,0.277 -0.2230012,0.5 -0.5,0.5 -0.2769988,0 -0.5,-0.223 -0.5,-0.5 v -3 h -3 C -11.777,8.5 -12,8.2769988 -12,8 c 0,-0.2769988 0.223,-0.5 0.5,-0.5 h 3 v -3 C -8.5,4.2230012 -8.2769988,4 -8,4 c 0.2769988,0 0.5,0.2230012 0.5,0.5 v 3 h 3 C -4.2230012,7.5 -4,7.7230012 -4,8 Z" />
 </svg>
 </svg>

+ 0 - 5
frontend/appflowy_flutter/assets/images/home/new_app_dark.svg

@@ -1,5 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<rect width="16" height="16" rx="8" fill="#00BCF0"/>
-<rect x="7.5" y="4" width="1" height="8" rx="0.5" fill="#131720"/>
-<rect x="12" y="7.5" width="1" height="8" rx="0.5" transform="rotate(90 12 7.5)" fill="#131720"/>
-</svg>

BIN
frontend/appflowy_flutter/assets/test/workspaces/board.zip


BIN
frontend/appflowy_flutter/assets/test/workspaces/empty_document.zip


+ 4 - 2
frontend/appflowy_flutter/assets/translations/en.json

@@ -326,7 +326,8 @@
     "checklist": {
     "checklist": {
       "panelTitle": "Add an item"
       "panelTitle": "Add an item"
     },
     },
-    "menuName": "Grid"
+    "menuName": "Grid",
+    "referencedGridPrefix": "View of"
   },
   },
   "document": {
   "document": {
     "menuName": "Document",
     "menuName": "Document",
@@ -390,7 +391,8 @@
     "column": {
     "column": {
       "create_new_card": "New"
       "create_new_card": "New"
     },
     },
-    "menuName": "Board"
+    "menuName": "Board",
+    "referencedBoardPrefix": "View of"
   },
   },
   "calendar": {
   "calendar": {
     "menuName": "Calendar",
     "menuName": "Calendar",

+ 43 - 0
frontend/appflowy_flutter/integration_test/board_test.dart

@@ -0,0 +1,43 @@
+import 'package:appflowy_board/appflowy_board.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+import 'util/util.dart';
+
+/// Integration tests for an empty board. The [TestWorkspaceService] will load
+/// a workspace from an empty board `assets/test/workspaces/board.zip` for all
+/// tests.
+///
+/// To create another integration test with a preconfigured workspace.
+/// Use the following steps.
+/// 1. Create a new workspace from the AppFlowy launch screen.
+/// 2. Modify the workspace until it is suitable as the starting point for
+///    the integration test you need to land.
+/// 3. Use a zip utility program to zip the workspace folder that you created.
+/// 4. Add the zip file under `assets/test/workspaces/`
+/// 5. Add a new enumeration to [TestWorkspace] in `integration_test/utils/data.dart`.
+///    For example, if you added a workspace called `empty_calendar.zip`,
+///    then [TestWorkspace] should have the following value:
+/// ```dart
+/// enum TestWorkspace {
+///   board('board'),
+///   empty_calendar('empty_calendar');
+///
+///   /* code */
+/// }
+/// ```
+/// 6. Double check that the .zip file that you added is included as an asset in
+///    the pubspec.yaml file under appflowy_flutter.
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+  const service = TestWorkspaceService(TestWorkspace.board);
+
+  group('board', () {
+    setUpAll(() async => await service.setUpAll());
+    setUp(() async => await service.setUp());
+
+    testWidgets('integration test unzips the proper workspace and loads it correctly.', (tester) async {
+      await tester.initializeAppFlowy();
+      expect(find.byType(AppFlowyBoard), findsOneWidget);
+    });
+  });
+}

+ 120 - 0
frontend/appflowy_flutter/integration_test/empty_document_test.dart

@@ -0,0 +1,120 @@
+import 'package:appflowy/plugins/document/presentation/plugins/base/built_in_page_widget.dart';
+import 'package:appflowy_editor/appflowy_editor.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+import 'util/keyboard.dart';
+import 'util/util.dart';
+
+/// Integration tests for an empty document. The [TestWorkspaceService] will load a workspace from an empty document `assets/test/workspaces/empty_document.zip` for all tests.
+///
+/// To create another integration test with a preconfigured workspace. Use the following steps:
+/// 1. Create a new workspace from the AppFlowy launch screen.
+/// 2. Modify the workspace until it is suitable as the starting point for the integration test you need to land.
+/// 3. Use a zip utility program to zip the workspace folder that you created.
+/// 4. Add the zip file under `assets/test/workspaces/`
+/// 5. Add a new enumeration to [TestWorkspace] in `integration_test/utils/data.dart`. For example, if you added a workspace called `empty_calendar.zip`, then [TestWorkspace] should have the following value:
+/// ```dart
+/// enum TestWorkspace {
+///   board('board'),
+///   empty_calendar('empty_calendar');
+///
+///   /* code */
+/// }
+/// ```
+/// 6. Double check that the .zip file that you added is included as an asset in the pubspec.yaml file under appflowy_flutter.
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+  const service = TestWorkspaceService(TestWorkspace.emptyDocument);
+
+  group('Tests on a workspace with only an empty document', () {
+    setUpAll(() async => await service.setUpAll());
+    setUp(() async => await service.setUp());
+
+    testWidgets('/board shortcut creates a new board and view of the board', (tester) async {
+      await tester.initializeAppFlowy();
+
+      // Needs tab to obtain focus for the app flowy editor.
+      // by default the tap appears at the center of the widget.
+      final Finder editor = find.byType(AppFlowyEditor);
+      await tester.tap(editor);
+      await tester.pumpAndSettle();
+
+      // tester.sendText() cannot be used since the editor
+      // does not contain any EditableText widgets.
+      // to interact with the app during an integration test,
+      // simulate physical keyboard events.
+      await FlowyTestKeyboard.simulateKeyDownEvent([
+        LogicalKeyboardKey.slash,
+        LogicalKeyboardKey.keyB,
+        LogicalKeyboardKey.keyO,
+        LogicalKeyboardKey.keyA,
+        LogicalKeyboardKey.keyR,
+        LogicalKeyboardKey.keyD,
+        LogicalKeyboardKey.arrowDown,
+      ], tester: tester);
+
+      // Checks whether the options in the selection menu
+      // for /board exist.
+      expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2));
+
+      // Finalizes the slash command that creates the board.
+      await FlowyTestKeyboard.simulateKeyDownEvent([
+        LogicalKeyboardKey.enter,
+      ], tester: tester);
+
+      // Checks whether new board is referenced and properly on the page.
+      expect(find.byType(BuiltInPageWidget), findsOneWidget);
+
+      // Checks whether the new database was created
+      const newBoardLabel = "Untitled";
+      expect(find.text(newBoardLabel), findsOneWidget);
+
+      // Checks whether a view of the database was created
+      const viewOfBoardLabel = "View of Untitled";
+      expect(find.text(viewOfBoardLabel), findsNWidgets(2));
+    });
+
+    testWidgets('/grid shortcut creates a new grid and view of the grid', (tester) async {
+      await tester.initializeAppFlowy();
+
+      // Needs tab to obtain focus for the app flowy editor.
+      // by default the tap appears at the center of the widget.
+      final Finder editor = find.byType(AppFlowyEditor);
+      await tester.tap(editor);
+      await tester.pumpAndSettle();
+
+      // tester.sendText() cannot be used since the editor
+      // does not contain any EditableText widgets.
+      // to interact with the app during an integration test,
+      // simulate physical keyboard events.
+      await FlowyTestKeyboard.simulateKeyDownEvent([
+        LogicalKeyboardKey.slash,
+        LogicalKeyboardKey.keyG,
+        LogicalKeyboardKey.keyR,
+        LogicalKeyboardKey.keyI,
+        LogicalKeyboardKey.keyD,
+        LogicalKeyboardKey.arrowDown,
+      ], tester: tester);
+
+      // Checks whether the options in the selection menu
+      // for /grid exist.
+      expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2));
+
+      // Finalizes the slash command that creates the board.
+      await simulateKeyDownEvent(LogicalKeyboardKey.enter);
+      await tester.pumpAndSettle();
+
+      // Checks whether new board is referenced and properly on the page.
+      expect(find.byType(BuiltInPageWidget), findsOneWidget);
+
+      // Checks whether the new database was created
+      const newTableLabel = "Untitled";
+      expect(find.text(newTableLabel), findsOneWidget);
+
+      // Checks whether a view of the database was created
+      const viewOfTableLabel = "View of Untitled";
+      expect(find.text(viewOfTableLabel), findsNWidgets(2));
+    });
+  });
+}

+ 19 - 0
frontend/appflowy_flutter/integration_test/runner.dart

@@ -0,0 +1,19 @@
+import 'package:integration_test/integration_test.dart';
+
+import 'board_test.dart' as board_test;
+import 'switch_folder_test.dart' as switch_folder_test;
+import 'empty_document_test.dart' as empty_document_test;
+
+/// The main task runner for all integration tests in AppFlowy.
+///
+/// Having a single entrypoint for integration tests is necessary due to an
+/// [issue caused by switching files with integration testing](https://github.com/flutter/flutter/issues/101031).
+/// If flutter/flutter#101031 is resolved, this file can be removed completely.
+/// Once removed, the integration_test.yaml must be updated to exclude this as
+/// as the test target.
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+  switch_folder_test.main();
+  board_test.main();
+  empty_document_test.main();
+}

+ 0 - 135
frontend/appflowy_flutter/integration_test/switch_folder_test.dart

@@ -1,10 +1,5 @@
-import 'package:appflowy/generated/locale_keys.g.dart';
-import 'package:appflowy/plugins/document/presentation/plugins/base/built_in_page_widget.dart';
 import 'package:appflowy/user/presentation/folder/folder_widget.dart';
 import 'package:appflowy/user/presentation/folder/folder_widget.dart';
-import 'package:appflowy_editor/appflowy_editor.dart';
-import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra_ui/style_widget/text_field.dart';
 import 'package:flowy_infra_ui/style_widget/text_field.dart';
-import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:integration_test/integration_test.dart';
 import 'package:integration_test/integration_test.dart';
 
 
@@ -162,135 +157,5 @@ void main() {
         await TestFolder.currentLocation(),
         await TestFolder.currentLocation(),
       );
       );
     });
     });
-
-    testWidgets('/board shortcut creates a new board', (tester) async {
-      const folderName = 'appflowy';
-      await TestFolder.cleanTestLocation(folderName);
-      await TestFolder.setTestLocation(folderName);
-
-      await tester.initializeAppFlowy();
-
-      // tap open button
-      await mockGetDirectoryPath(folderName);
-      await tester.tapOpenFolderButton();
-
-      await tester.wait(1000);
-      await tester.expectToSeeWelcomePage();
-
-      final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
-
-      // Necessary for being able to enterText when not in debug mode
-      binding.testTextInput.register();
-
-      // Needs tab to obtain focus for the app flowy editor.
-      // by default the tap appears at the center of the widget.
-      final Finder editor = find.byType(AppFlowyEditor);
-      await tester.tap(editor);
-      await tester.pumpAndSettle();
-
-      // tester.sendText() cannot be used since the editor
-      // does not contain any EditableText widgets.
-      // to interact with the app during an integration test,
-      // simulate physical keyboard events.
-      await simulateKeyDownEvent(LogicalKeyboardKey.enter);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.enter);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.arrowLeft);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.slash);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.keyB);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.keyO);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.keyA);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.keyR);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.keyD);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
-      await tester.pumpAndSettle();
-
-      // Checks whether the options in the selection menu
-      // for /board exist.
-      expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2));
-
-      // Finalizes the slash command that creates the board.
-      await simulateKeyDownEvent(LogicalKeyboardKey.enter);
-      await tester.pumpAndSettle();
-
-      // Checks whether new board is referenced and properly on the page.
-      expect(find.byType(BuiltInPageWidget), findsOneWidget);
-
-      // Checks whether the new board is in the side bar.
-      final sidebarLabel = LocaleKeys.newPageText.tr();
-      expect(find.text(sidebarLabel), findsOneWidget);
-    });
-
-    testWidgets('/grid shortcut creates a new grid', (tester) async {
-      const folderName = 'appflowy';
-      await TestFolder.cleanTestLocation(folderName);
-      await TestFolder.setTestLocation(folderName);
-
-      await tester.initializeAppFlowy();
-
-      // tap open button
-      await mockGetDirectoryPath(folderName);
-      await tester.tapOpenFolderButton();
-
-      await tester.wait(1000);
-      await tester.expectToSeeWelcomePage();
-
-      final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
-
-      // Necessary for being able to enterText when not in debug mode
-      binding.testTextInput.register();
-
-      // Needs tab to obtain focus for the app flowy editor.
-      // by default the tap appears at the center of the widget.
-      final Finder editor = find.byType(AppFlowyEditor);
-      await tester.tap(editor);
-      await tester.pumpAndSettle();
-
-      // tester.sendText() cannot be used since the editor
-      // does not contain any EditableText widgets.
-      // to interact with the app during an integration test,
-      // simulate physical keyboard events.
-      await simulateKeyDownEvent(LogicalKeyboardKey.enter);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.enter);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.arrowLeft);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.slash);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.keyG);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.keyR);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.keyI);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.keyD);
-      await tester.pumpAndSettle();
-      await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
-      await tester.pumpAndSettle();
-
-      // Checks whether the options in the selection menu
-      // for /grid exist.
-      expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2));
-
-      // Finalizes the slash command that creates the board.
-      await simulateKeyDownEvent(LogicalKeyboardKey.enter);
-      await tester.pumpAndSettle();
-
-      // Checks whether new board is referenced and properly on the page.
-      expect(find.byType(BuiltInPageWidget), findsOneWidget);
-
-      // Checks whether the new board is in the side bar.
-      final sidebarLabel = LocaleKeys.newPageText.tr();
-      expect(find.text(sidebarLabel), findsOneWidget);
-    });
   });
   });
 }
 }

+ 66 - 0
frontend/appflowy_flutter/integration_test/util/data.dart

@@ -0,0 +1,66 @@
+import 'dart:io';
+
+import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart';
+import 'package:archive/archive_io.dart';
+import 'package:flutter/services.dart';
+import 'package:path/path.dart' as p;
+import 'package:path_provider/path_provider.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+enum TestWorkspace {
+  board("board"),
+  emptyDocument("empty_document");
+
+  const TestWorkspace(this._name);
+
+  final String _name;
+
+  Future<File> get zip async {
+    final Directory parent = await TestWorkspace._parent;
+    final File out = File(p.join(parent.path, '$_name.zip'));
+    if (await out.exists()) return out;
+    await out.create();
+    final ByteData data = await rootBundle.load(_asset);
+    await out.writeAsBytes(data.buffer.asUint8List());
+    return out;
+  }
+
+  Future<Directory> get root async {
+    final Directory parent = await TestWorkspace._parent;
+    return Directory(p.join(parent.path, _name));
+  }
+
+  static Future<Directory> get _parent async {
+    final Directory root = await getTemporaryDirectory();
+    if (await root.exists()) return root;
+    await root.create();
+    return root;
+  }
+
+  String get _asset => 'assets/test/workspaces/$_name.zip';
+}
+
+class TestWorkspaceService {
+  const TestWorkspaceService(this.workspace);
+
+  final TestWorkspace workspace;
+
+  /// Instructs the application to read workspace data from the workspace found under this [TestWorkspace]'s path.
+  Future<void> setUpAll() async {
+    SharedPreferences.setMockInitialValues(
+      {
+        kSettingsLocationDefaultLocation:
+            await workspace.root.then((value) => value.path),
+      },
+    );
+  }
+
+  /// Workspaces that are checked into source are compressed. [TestWorkspaceService.setUp()] decompresses the file into an ephemeral directory that will be ignored by source control.
+  Future<void> setUp() async {
+    final inputStream =
+        InputFileStream(await workspace.zip.then((value) => value.path));
+    final archive = ZipDecoder().decodeBuffer(inputStream);
+    extractArchiveToDisk(
+        archive, await TestWorkspace._parent.then((value) => value.path));
+  }
+}

+ 12 - 0
frontend/appflowy_flutter/integration_test/util/keyboard.dart

@@ -0,0 +1,12 @@
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart' as flutter_test;
+
+class FlowyTestKeyboard {
+  static Future<void> simulateKeyDownEvent(List<LogicalKeyboardKey> keys,
+      {required flutter_test.WidgetTester tester}) async {
+    for (final LogicalKeyboardKey key in keys) {
+      await flutter_test.simulateKeyDownEvent(key);
+      await tester.pumpAndSettle();
+    }
+  }
+}

+ 1 - 0
frontend/appflowy_flutter/integration_test/util/util.dart

@@ -1,3 +1,4 @@
 export 'base.dart';
 export 'base.dart';
 export 'launch.dart';
 export 'launch.dart';
 export 'settings.dart';
 export 'settings.dart';
+export 'data.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/application/database_service.dart

@@ -5,7 +5,7 @@ import 'package:dartz/dartz.dart';
 
 
 class DatabaseBackendService {
 class DatabaseBackendService {
   static Future<Either<List<DatabaseDescriptionPB>, FlowyError>>
   static Future<Either<List<DatabaseDescriptionPB>, FlowyError>>
-      getAllDatabase() {
+      getAllDatabases() {
     return DatabaseEventGetDatabases().send().then((result) {
     return DatabaseEventGetDatabases().send().then((result) {
       return result.fold((l) => left(l.items), (r) => right(r));
       return result.fold((l) => left(l.items), (r) => right(r));
     });
     });

+ 0 - 6
frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_action_sheet_bloc.dart

@@ -2,7 +2,6 @@ import 'package:appflowy_backend/log.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
-import 'dart:async';
 import 'field_service.dart';
 import 'field_service.dart';
 
 
 part 'field_action_sheet_bloc.freezed.dart';
 part 'field_action_sheet_bloc.freezed.dart';
@@ -64,11 +63,6 @@ class FieldActionSheetBloc
       },
       },
     );
     );
   }
   }
-
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
 }
 }
 
 
 @freezed
 @freezed

+ 1 - 8
frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_editor_bloc.dart

@@ -1,6 +1,5 @@
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:dartz/dartz.dart';
 import 'field_service.dart';
 import 'field_service.dart';
 import 'type_option/type_option_context.dart';
 import 'type_option/type_option_context.dart';
@@ -17,8 +16,7 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
     required String fieldName,
     required String fieldName,
     required bool isGroupField,
     required bool isGroupField,
     required IFieldTypeOptionLoader loader,
     required IFieldTypeOptionLoader loader,
-  })  : dataController =
-            TypeOptionController(viewId: viewId, loader: loader),
+  })  : dataController = TypeOptionController(viewId: viewId, loader: loader),
         super(FieldEditorState.initial(viewId, fieldName, isGroupField)) {
         super(FieldEditorState.initial(viewId, fieldName, isGroupField)) {
     on<FieldEditorEvent>(
     on<FieldEditorEvent>(
       (event, emit) async {
       (event, emit) async {
@@ -63,11 +61,6 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
       },
       },
     );
     );
   }
   }
-
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
 }
 }
 
 
 @freezed
 @freezed

+ 0 - 6
frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/date_bloc.dart

@@ -2,7 +2,6 @@ import 'package:appflowy_backend/protobuf/flowy-database/date_type_option.pb.dar
 import 'package:appflowy_backend/protobuf/flowy-database/date_type_option_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/date_type_option_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
-import 'dart:async';
 import 'package:protobuf/protobuf.dart';
 import 'package:protobuf/protobuf.dart';
 
 
 import 'type_option_context.dart';
 import 'type_option_context.dart';
@@ -52,11 +51,6 @@ class DateTypeOptionBloc
       }
       }
     });
     });
   }
   }
-
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
 }
 }
 
 
 @freezed
 @freezed

+ 0 - 6
frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/edit_select_option_bloc.dart

@@ -1,7 +1,6 @@
 import 'package:appflowy_backend/protobuf/flowy-database/select_type_option.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/select_type_option.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
-import 'dart:async';
 import 'package:protobuf/protobuf.dart';
 import 'package:protobuf/protobuf.dart';
 import 'package:dartz/dartz.dart';
 import 'package:dartz/dartz.dart';
 part 'edit_select_option_bloc.freezed.dart';
 part 'edit_select_option_bloc.freezed.dart';
@@ -27,11 +26,6 @@ class EditSelectOptionBloc
     );
     );
   }
   }
 
 
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
-
   SelectOptionPB _updateColor(SelectOptionColorPB color) {
   SelectOptionPB _updateColor(SelectOptionColorPB color) {
     state.option.freeze();
     state.option.freeze();
     return state.option.rebuild((option) {
     return state.option.rebuild((option) {

+ 0 - 6
frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_bloc.dart

@@ -2,7 +2,6 @@ import 'package:appflowy_backend/protobuf/flowy-database/format.pbenum.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/number_type_option.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/number_type_option.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
-import 'dart:async';
 import 'package:protobuf/protobuf.dart';
 import 'package:protobuf/protobuf.dart';
 import 'type_option_context.dart';
 import 'type_option_context.dart';
 
 
@@ -29,11 +28,6 @@ class NumberTypeOptionBloc
       typeOption.format = format;
       typeOption.format = format;
     });
     });
   }
   }
-
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
 }
 }
 
 
 @freezed
 @freezed

+ 0 - 6
frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_format_bloc.dart

@@ -1,7 +1,6 @@
 import 'package:appflowy_backend/protobuf/flowy-database/format.pbenum.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/format.pbenum.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
-import 'dart:async';
 part 'number_format_bloc.freezed.dart';
 part 'number_format_bloc.freezed.dart';
 
 
 class NumberFormatBloc extends Bloc<NumberFormatEvent, NumberFormatState> {
 class NumberFormatBloc extends Bloc<NumberFormatEvent, NumberFormatState> {
@@ -21,11 +20,6 @@ class NumberFormatBloc extends Bloc<NumberFormatEvent, NumberFormatState> {
       },
       },
     );
     );
   }
   }
-
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
 }
 }
 
 
 @freezed
 @freezed

+ 0 - 5
frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/select_option_type_option_bloc.dart

@@ -49,11 +49,6 @@ class SelectOptionTypeOptionBloc
       },
       },
     );
     );
   }
   }
-
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
 }
 }
 
 
 @freezed
 @freezed

+ 0 - 6
frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_bloc.dart

@@ -1,6 +1,5 @@
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
-import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:dartz/dartz.dart';
 
 
 part 'setting_bloc.freezed.dart';
 part 'setting_bloc.freezed.dart';
@@ -18,11 +17,6 @@ class DatabaseSettingBloc
       },
       },
     );
     );
   }
   }
-
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
 }
 }
 
 
 @freezed
 @freezed

+ 0 - 6
frontend/appflowy_flutter/lib/plugins/database_view/board/application/toolbar/board_setting_bloc.dart

@@ -1,6 +1,5 @@
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
-import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:dartz/dartz.dart';
 
 
 part 'board_setting_bloc.freezed.dart';
 part 'board_setting_bloc.freezed.dart';
@@ -17,11 +16,6 @@ class BoardSettingBloc extends Bloc<BoardSettingEvent, BoardSettingState> {
       },
       },
     );
     );
   }
   }
-
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
 }
 }
 
 
 @freezed
 @freezed

+ 0 - 2
frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_setting_bloc.dart

@@ -23,8 +23,6 @@ class CalendarSettingBloc
     });
     });
   }
   }
 
 
-  @override
-  Future<void> close() async => super.close();
 }
 }
 
 
 @freezed
 @freezed

+ 0 - 7
frontend/appflowy_flutter/lib/plugins/database_view/grid/application/filter/select_option_filter_list_bloc.dart

@@ -1,5 +1,3 @@
-import 'dart:async';
-
 import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/choicechip/select_option/select_option_loader.dart';
 import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/choicechip/select_option/select_option_loader.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/select_type_option.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/select_type_option.pb.dart';
@@ -63,11 +61,6 @@ class SelectOptionFilterListBloc<T>
     );
     );
   }
   }
 
 
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
-
   void _updateSelectOptions({
   void _updateSelectOptions({
     String? predicate,
     String? predicate,
     Set<String>? selectedOptionIds,
     Set<String>? selectedOptionIds,

+ 0 - 5
frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_header_bloc.dart

@@ -61,11 +61,6 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
       listenWhen: () => !isClosed,
       listenWhen: () => !isClosed,
     );
     );
   }
   }
-
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
 }
 }
 
 
 @freezed
 @freezed

+ 0 - 6
frontend/appflowy_flutter/lib/plugins/database_view/grid/application/row/row_action_sheet_bloc.dart

@@ -2,7 +2,6 @@ import 'package:appflowy_backend/log.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
-import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:dartz/dartz.dart';
 
 
 import '../../../application/row/row_cache.dart';
 import '../../../application/row/row_cache.dart';
@@ -34,11 +33,6 @@ class RowActionSheetBloc
     );
     );
   }
   }
 
 
-  @override
-  Future<void> close() async {
-    return super.close();
-  }
-
   void logResult(Either<Unit, FlowyError> result) {
   void logResult(Either<Unit, FlowyError> result) {
     result.fold((l) => null, (err) => Log.error(err));
     result.fold((l) => null, (err) => Log.error(err));
   }
   }

+ 6 - 2
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/choicechip/choicechip.dart

@@ -38,7 +38,10 @@ class ChoiceChipButton extends StatelessWidget {
       child: FlowyButton(
       child: FlowyButton(
         decoration: decoration,
         decoration: decoration,
         useIntrinsicWidth: true,
         useIntrinsicWidth: true,
-        text: FlowyText(filterInfo.fieldInfo.name),
+        text: FlowyText(
+          filterInfo.fieldInfo.name,
+          color: AFThemeExtension.of(context).textColor,
+        ),
         margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
         margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
         radius: const BorderRadius.all(Radius.circular(14)),
         radius: const BorderRadius.all(Radius.circular(14)),
         leftIcon: svgWidget(
         leftIcon: svgWidget(
@@ -62,7 +65,8 @@ class _ChoicechipFilterDesc extends StatelessWidget {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     final arrow = Transform.rotate(
     final arrow = Transform.rotate(
       angle: -math.pi / 2,
       angle: -math.pi / 2,
-      child: svgWidget("home/arrow_left"),
+      child: svgWidget("home/arrow_left",
+          color: AFThemeExtension.of(context).textColor),
     );
     );
     return Padding(
     return Padding(
       padding: const EdgeInsets.symmetric(horizontal: 2),
       padding: const EdgeInsets.symmetric(horizontal: 2),

+ 7 - 2
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/condition_button.dart

@@ -18,14 +18,19 @@ class ConditionButton extends StatelessWidget {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     final arrow = Transform.rotate(
     final arrow = Transform.rotate(
       angle: -math.pi / 2,
       angle: -math.pi / 2,
-      child: svgWidget("home/arrow_left"),
+      child: svgWidget("home/arrow_left",
+          color: AFThemeExtension.of(context).textColor),
     );
     );
 
 
     return SizedBox(
     return SizedBox(
       height: 20,
       height: 20,
       child: FlowyButton(
       child: FlowyButton(
         useIntrinsicWidth: true,
         useIntrinsicWidth: true,
-        text: FlowyText(conditionName, fontSize: 10),
+        text: FlowyText(
+          conditionName,
+          fontSize: 10,
+          color: AFThemeExtension.of(context).textColor,
+        ),
         margin: const EdgeInsets.symmetric(horizontal: 4),
         margin: const EdgeInsets.symmetric(horizontal: 4),
         radius: const BorderRadius.all(Radius.circular(2)),
         radius: const BorderRadius.all(Radius.circular(2)),
         rightIcon: arrow,
         rightIcon: arrow,

+ 15 - 13
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/create_filter_list.dart

@@ -3,6 +3,7 @@ import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.da
 import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart';
 import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -117,19 +118,16 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate {
   @override
   @override
   Widget build(
   Widget build(
       BuildContext context, double shrinkOffset, bool overlapsContent) {
       BuildContext context, double shrinkOffset, bool overlapsContent) {
-    return Padding(
+    return Container(
       padding: const EdgeInsets.only(top: 4),
       padding: const EdgeInsets.only(top: 4),
-      child: Container(
-        color: Theme.of(context).colorScheme.background,
-        height: fixHeight,
-        child: FlowyTextField(
-          hintText: LocaleKeys.grid_settings_filterBy.tr(),
-          onChanged: (text) {
-            context
-                .read<GridCreateFilterBloc>()
-                .add(GridCreateFilterEvent.didReceiveFilterText(text));
-          },
-        ),
+      height: fixHeight,
+      child: FlowyTextField(
+        hintText: LocaleKeys.grid_settings_filterBy.tr(),
+        onChanged: (text) {
+          context
+              .read<GridCreateFilterBloc>()
+              .add(GridCreateFilterEvent.didReceiveFilterText(text));
+        },
       ),
       ),
     );
     );
   }
   }
@@ -158,7 +156,11 @@ class _FilterPropertyCell extends StatelessWidget {
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return FlowyButton(
     return FlowyButton(
-      text: FlowyText.medium(fieldInfo.name),
+      hoverColor: AFThemeExtension.of(context).lightGreyHover,
+      text: FlowyText.medium(
+        fieldInfo.name,
+        color: AFThemeExtension.of(context).textColor,
+      ),
       onTap: () => onTap(fieldInfo),
       onTap: () => onTap(fieldInfo),
       leftIcon: svgWidget(
       leftIcon: svgWidget(
         fieldInfo.fieldType.iconName(),
         fieldInfo.fieldType.iconName(),

+ 2 - 0
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/disclosure_button.dart

@@ -3,6 +3,7 @@ import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 
 
@@ -31,6 +32,7 @@ class _DisclosureButtonState extends State<DisclosureButton> {
           .toList(),
           .toList(),
       buildChild: (controller) {
       buildChild: (controller) {
         return FlowyIconButton(
         return FlowyIconButton(
+          hoverColor: AFThemeExtension.of(context).lightGreyHover,
           width: 20,
           width: 20,
           icon: svgWidget(
           icon: svgWidget(
             "editor/details",
             "editor/details",

+ 4 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_menu.dart

@@ -71,7 +71,10 @@ class _AddFilterButtonState extends State<AddFilterButton> {
       SizedBox(
       SizedBox(
         height: 28,
         height: 28,
         child: FlowyButton(
         child: FlowyButton(
-          text: FlowyText(LocaleKeys.grid_settings_addFilter.tr()),
+          text: FlowyText(
+            LocaleKeys.grid_settings_addFilter.tr(),
+            color: AFThemeExtension.of(context).textColor,
+          ),
           useIntrinsicWidth: true,
           useIntrinsicWidth: true,
           hoverColor: AFThemeExtension.of(context).lightGreyHover,
           hoverColor: AFThemeExtension.of(context).lightGreyHover,
           leftIcon: svgWidget(
           leftIcon: svgWidget(

+ 5 - 2
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/footer/grid_footer.dart

@@ -14,12 +14,15 @@ class GridAddRowButton extends StatelessWidget {
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return FlowyButton(
     return FlowyButton(
-      text: FlowyText.medium(LocaleKeys.grid_row_newRow.tr()),
+      text: FlowyText.medium(
+        LocaleKeys.grid_row_newRow.tr(),
+        color: Theme.of(context).colorScheme.tertiary,
+      ),
       hoverColor: AFThemeExtension.of(context).lightGreyHover,
       hoverColor: AFThemeExtension.of(context).lightGreyHover,
       onTap: () => context.read<GridBloc>().add(const GridEvent.createRow()),
       onTap: () => context.read<GridBloc>().add(const GridEvent.createRow()),
       leftIcon: svgWidget(
       leftIcon: svgWidget(
         "home/add",
         "home/add",
-        color: Theme.of(context).iconTheme.color,
+        color: Theme.of(context).colorScheme.tertiary,
       ),
       ),
     );
     );
   }
   }

+ 3 - 4
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell.dart

@@ -164,11 +164,10 @@ class FieldCellButton extends StatelessWidget {
         .replaceAll(Characters(''), Characters('\u{200B}'))
         .replaceAll(Characters(''), Characters('\u{200B}'))
         .toString();
         .toString();
     return FlowyButton(
     return FlowyButton(
-      hoverColor: AFThemeExtension.of(context).lightGreyHover,
+      hoverColor: AFThemeExtension.of(context).greyHover,
       onTap: onTap,
       onTap: onTap,
-      leftIcon: svgWidget(
-        field.fieldType.iconName(),
-        color: Theme.of(context).iconTheme.color,
+      leftIcon: FlowySvg(
+        name: field.fieldType.iconName(),
       ),
       ),
       radius: BorderRadius.zero,
       radius: BorderRadius.zero,
       text: FlowyText.medium(
       text: FlowyText.medium(

+ 8 - 2
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell_action_sheet.dart

@@ -5,6 +5,7 @@ import 'package:appflowy/startup/startup.dart';
 import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
 import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
@@ -81,8 +82,10 @@ class _EditFieldButton extends StatelessWidget {
         return SizedBox(
         return SizedBox(
           height: GridSize.popoverItemHeight,
           height: GridSize.popoverItemHeight,
           child: FlowyButton(
           child: FlowyButton(
+            hoverColor: AFThemeExtension.of(context).lightGreyHover,
             text: FlowyText.medium(
             text: FlowyText.medium(
               LocaleKeys.grid_field_editProperty.tr(),
               LocaleKeys.grid_field_editProperty.tr(),
+              color: AFThemeExtension.of(context).textColor,
             ),
             ),
             onTap: onTap,
             onTap: onTap,
           ),
           ),
@@ -148,9 +151,12 @@ class FieldActionCell extends StatelessWidget {
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return FlowyButton(
     return FlowyButton(
+      hoverColor: AFThemeExtension.of(context).lightGreyHover,
       text: FlowyText.medium(
       text: FlowyText.medium(
         action.title(),
         action.title(),
-        color: enable ? null : Theme.of(context).disabledColor,
+        color: enable
+            ? AFThemeExtension.of(context).textColor
+            : Theme.of(context).disabledColor,
       ),
       ),
       onTap: () {
       onTap: () {
         if (enable) {
         if (enable) {
@@ -160,7 +166,7 @@ class FieldActionCell extends StatelessWidget {
       leftIcon: svgWidget(
       leftIcon: svgWidget(
         action.iconName(),
         action.iconName(),
         color: enable
         color: enable
-            ? Theme.of(context).colorScheme.onSurface
+            ? AFThemeExtension.of(context).textColor
             : Theme.of(context).disabledColor,
             : Theme.of(context).disabledColor,
       ),
       ),
     );
     );

+ 6 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_list.dart

@@ -1,5 +1,6 @@
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
@@ -57,7 +58,11 @@ class FieldTypeCell extends StatelessWidget {
     return SizedBox(
     return SizedBox(
       height: GridSize.popoverItemHeight,
       height: GridSize.popoverItemHeight,
       child: FlowyButton(
       child: FlowyButton(
-        text: FlowyText.medium(fieldType.title()),
+        hoverColor: AFThemeExtension.of(context).lightGreyHover,
+        text: FlowyText.medium(
+          fieldType.title(),
+          color: AFThemeExtension.of(context).textColor,
+        ),
         onTap: () => onSelectField(fieldType),
         onTap: () => onSelectField(fieldType),
         leftIcon: svgWidget(
         leftIcon: svgWidget(
           fieldType.iconName(),
           fieldType.iconName(),

+ 3 - 0
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_option_editor.dart

@@ -4,6 +4,7 @@ import 'package:appflowy/plugins/database_view/application/field/type_option/typ
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:dartz/dartz.dart' show Either;
 import 'package:dartz/dartz.dart' show Either;
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
@@ -110,8 +111,10 @@ class _SwitchFieldButton extends StatelessWidget {
   Widget _buildMoreButton(BuildContext context) {
   Widget _buildMoreButton(BuildContext context) {
     final bloc = context.read<FieldTypeOptionEditBloc>();
     final bloc = context.read<FieldTypeOptionEditBloc>();
     return FlowyButton(
     return FlowyButton(
+      hoverColor: AFThemeExtension.of(context).lightGreyHover,
       text: FlowyText.medium(
       text: FlowyText.medium(
         bloc.state.field.fieldType.title(),
         bloc.state.field.fieldType.title(),
+        color: AFThemeExtension.of(context).textColor,
       ),
       ),
       margin: GridSize.typeOptionContentInsets,
       margin: GridSize.typeOptionContentInsets,
       leftIcon: svgWidget(
       leftIcon: svgWidget(

+ 2 - 5
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/grid_header.dart

@@ -178,12 +178,9 @@ class CreateFieldButton extends StatelessWidget {
       child: FlowyButton(
       child: FlowyButton(
         radius: BorderRadius.zero,
         radius: BorderRadius.zero,
         text: FlowyText.medium(LocaleKeys.grid_field_newColumn.tr()),
         text: FlowyText.medium(LocaleKeys.grid_field_newColumn.tr()),
-        hoverColor: AFThemeExtension.of(context).lightGreyHover,
+        hoverColor: AFThemeExtension.of(context).greyHover,
         onTap: () {},
         onTap: () {},
-        leftIcon: svgWidget(
-          "home/add",
-          color: Theme.of(context).iconTheme.color,
-        ),
+        leftIcon: const FlowySvg(name: 'home/add'),
       ),
       ),
       popupBuilder: (BuildContext popover) {
       popupBuilder: (BuildContext popover) {
         return FieldEditor(
         return FieldEditor(

+ 2 - 8
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart

@@ -151,10 +151,7 @@ class DateFormatButton extends StatelessWidget {
         margin: buttonMargins,
         margin: buttonMargins,
         onTap: onTap,
         onTap: onTap,
         onHover: onHover,
         onHover: onHover,
-        rightIcon: svgWidget(
-          "grid/more",
-          color: Theme.of(context).iconTheme.color,
-        ),
+        rightIcon: const FlowySvg(name: 'grid/more'),
       ),
       ),
     );
     );
   }
   }
@@ -182,10 +179,7 @@ class TimeFormatButton extends StatelessWidget {
         margin: buttonMargins,
         margin: buttonMargins,
         onTap: onTap,
         onTap: onTap,
         onHover: onHover,
         onHover: onHover,
-        rightIcon: svgWidget(
-          "grid/more",
-          color: Theme.of(context).iconTheme.color,
-        ),
+        rightIcon: const FlowySvg(name: 'grid/more'),
       ),
       ),
     );
     );
   }
   }

+ 6 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option.dart

@@ -1,6 +1,7 @@
 import 'package:appflowy/plugins/database_view/application/field/type_option/select_option_type_option_bloc.dart';
 import 'package:appflowy/plugins/database_view/application/field/type_option/select_option_type_option_bloc.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/select_type_option.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/select_type_option.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
@@ -243,7 +244,11 @@ class _AddOptionButton extends StatelessWidget {
       child: SizedBox(
       child: SizedBox(
         height: GridSize.popoverItemHeight,
         height: GridSize.popoverItemHeight,
         child: FlowyButton(
         child: FlowyButton(
-          text: FlowyText.medium(LocaleKeys.grid_field_addSelectOption.tr()),
+          hoverColor: AFThemeExtension.of(context).lightGreyHover,
+          text: FlowyText.medium(
+            LocaleKeys.grid_field_addSelectOption.tr(),
+            color: AFThemeExtension.of(context).textColor,
+          ),
           onTap: () {
           onTap: () {
             context
             context
                 .read<SelectOptionTypeOptionBloc>()
                 .read<SelectOptionTypeOptionBloc>()

+ 6 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option_editor.dart

@@ -1,6 +1,7 @@
 import 'package:appflowy/plugins/database_view/application/field/type_option/edit_select_option_bloc.dart';
 import 'package:appflowy/plugins/database_view/application/field/type_option/edit_select_option_bloc.dart';
 import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart';
 import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -103,7 +104,11 @@ class _DeleteTag extends StatelessWidget {
     return SizedBox(
     return SizedBox(
       height: GridSize.popoverItemHeight,
       height: GridSize.popoverItemHeight,
       child: FlowyButton(
       child: FlowyButton(
-        text: FlowyText.medium(LocaleKeys.grid_selectOption_deleteTag.tr()),
+        hoverColor: AFThemeExtension.of(context).lightGreyHover,
+        text: FlowyText.medium(
+          LocaleKeys.grid_selectOption_deleteTag.tr(),
+          color: AFThemeExtension.of(context).textColor,
+        ),
         leftIcon: svgWidget(
         leftIcon: svgWidget(
           "grid/delete",
           "grid/delete",
           color: Theme.of(context).iconTheme.color,
           color: Theme.of(context).iconTheme.color,

+ 5 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/action.dart

@@ -3,6 +3,7 @@ import 'package:appflowy/plugins/database_view/grid/application/row/row_action_s
 import 'package:easy_localization/easy_localization.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -56,9 +57,12 @@ class _ActionCell extends StatelessWidget {
     return SizedBox(
     return SizedBox(
       height: GridSize.popoverItemHeight,
       height: GridSize.popoverItemHeight,
       child: FlowyButton(
       child: FlowyButton(
+        hoverColor: AFThemeExtension.of(context).lightGreyHover,
         text: FlowyText.medium(
         text: FlowyText.medium(
           action.title(),
           action.title(),
-          color: action.enable() ? null : Theme.of(context).disabledColor,
+          color: action.enable()
+              ? AFThemeExtension.of(context).textColor
+              : Theme.of(context).disabledColor,
         ),
         ),
         onTap: () {
         onTap: () {
           if (action.enable()) {
           if (action.enable()) {

+ 11 - 2
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/row.dart

@@ -5,6 +5,7 @@ import 'package:appflowy/plugins/database_view/grid/application/row/row_bloc.dar
 import 'package:appflowy/plugins/database_view/widgets/row/cell_builder.dart';
 import 'package:appflowy/plugins/database_view/widgets/row/cell_builder.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
@@ -152,11 +153,15 @@ class _InsertButton extends StatelessWidget {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return FlowyIconButton(
     return FlowyIconButton(
       tooltipText: LocaleKeys.tooltip_addNewRow.tr(),
       tooltipText: LocaleKeys.tooltip_addNewRow.tr(),
+      hoverColor: AFThemeExtension.of(context).lightGreyHover,
       width: 20,
       width: 20,
       height: 30,
       height: 30,
       onPressed: () => context.read<RowBloc>().add(const RowEvent.createRow()),
       onPressed: () => context.read<RowBloc>().add(const RowEvent.createRow()),
       iconPadding: const EdgeInsets.all(3),
       iconPadding: const EdgeInsets.all(3),
-      icon: svgWidget("home/add"),
+      icon: svgWidget(
+        'home/add',
+        color: Theme.of(context).colorScheme.tertiary,
+      ),
     );
     );
   }
   }
 }
 }
@@ -182,11 +187,15 @@ class _MenuButtonState extends State<_MenuButton> {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return FlowyIconButton(
     return FlowyIconButton(
       tooltipText: LocaleKeys.tooltip_openMenu.tr(),
       tooltipText: LocaleKeys.tooltip_openMenu.tr(),
+      hoverColor: AFThemeExtension.of(context).lightGreyHover,
       width: 20,
       width: 20,
       height: 30,
       height: 30,
       onPressed: () => widget.openMenu(),
       onPressed: () => widget.openMenu(),
       iconPadding: const EdgeInsets.all(3),
       iconPadding: const EdgeInsets.all(3),
-      icon: svgWidget("editor/details"),
+      icon: svgWidget(
+        'editor/details',
+        color: Theme.of(context).colorScheme.tertiary,
+      ),
     );
     );
   }
   }
 }
 }

+ 15 - 13
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/create_sort_list.dart

@@ -5,6 +5,7 @@ import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.da
 import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart';
 import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -116,19 +117,16 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate {
   @override
   @override
   Widget build(
   Widget build(
       BuildContext context, double shrinkOffset, bool overlapsContent) {
       BuildContext context, double shrinkOffset, bool overlapsContent) {
-    return Padding(
+    return Container(
       padding: const EdgeInsets.only(top: 4),
       padding: const EdgeInsets.only(top: 4),
-      child: Container(
-        color: Theme.of(context).colorScheme.background,
-        height: fixHeight,
-        child: FlowyTextField(
-          hintText: LocaleKeys.grid_settings_sortBy.tr(),
-          onChanged: (text) {
-            context
-                .read<CreateSortBloc>()
-                .add(CreateSortEvent.didReceiveFilterText(text));
-          },
-        ),
+      height: fixHeight,
+      child: FlowyTextField(
+        hintText: LocaleKeys.grid_settings_sortBy.tr(),
+        onChanged: (text) {
+          context
+              .read<CreateSortBloc>()
+              .add(CreateSortEvent.didReceiveFilterText(text));
+        },
       ),
       ),
     );
     );
   }
   }
@@ -157,7 +155,11 @@ class _SortPropertyCell extends StatelessWidget {
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return FlowyButton(
     return FlowyButton(
-      text: FlowyText.medium(fieldInfo.name),
+      hoverColor: AFThemeExtension.of(context).lightGreyHover,
+      text: FlowyText.medium(
+        fieldInfo.name,
+        color: AFThemeExtension.of(context).textColor,
+      ),
       onTap: () => onTap(fieldInfo),
       onTap: () => onTap(fieldInfo),
       leftIcon: svgWidget(
       leftIcon: svgWidget(
         fieldInfo.fieldType.iconName(),
         fieldInfo.fieldType.iconName(),

+ 4 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_choice_button.dart

@@ -37,7 +37,10 @@ class SortChoiceButton extends StatelessWidget {
     return FlowyButton(
     return FlowyButton(
       decoration: decoration,
       decoration: decoration,
       useIntrinsicWidth: true,
       useIntrinsicWidth: true,
-      text: FlowyText(text),
+      text: FlowyText(
+        text,
+        color: AFThemeExtension.of(context).textColor,
+      ),
       margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
       margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
       radius: BorderRadius.all(radius),
       radius: BorderRadius.all(radius),
       leftIcon: leftIcon,
       leftIcon: leftIcon,

+ 3 - 8
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_editor.dart

@@ -182,13 +182,11 @@ class _AddSortButtonState extends State<_AddSortButton> {
       child: SizedBox(
       child: SizedBox(
         height: GridSize.popoverItemHeight,
         height: GridSize.popoverItemHeight,
         child: FlowyButton(
         child: FlowyButton(
+          hoverColor: AFThemeExtension.of(context).greyHover,
           disable: getCreatableSorts(widget.fieldController.fieldInfos).isEmpty,
           disable: getCreatableSorts(widget.fieldController.fieldInfos).isEmpty,
           text: FlowyText.medium(LocaleKeys.grid_sort_addSort.tr()),
           text: FlowyText.medium(LocaleKeys.grid_sort_addSort.tr()),
           onTap: () => _popoverController.show(),
           onTap: () => _popoverController.show(),
-          leftIcon: svgWidget(
-            "home/add",
-            color: Theme.of(context).iconTheme.color,
-          ),
+          leftIcon: const FlowySvg(name: 'home/add'),
         ),
         ),
       ),
       ),
       popupBuilder: (BuildContext context) {
       popupBuilder: (BuildContext context) {
@@ -220,10 +218,7 @@ class _DeleteSortButton extends StatelessWidget {
                   .read<SortEditorBloc>()
                   .read<SortEditorBloc>()
                   .add(const SortEditorEvent.deleteAllSorts());
                   .add(const SortEditorEvent.deleteAllSorts());
             },
             },
-            leftIcon: svgWidget(
-              "editor/delete",
-              color: Theme.of(context).iconTheme.color,
-            ),
+            leftIcon: const FlowySvg(name: 'editor/delete'),
           ),
           ),
         );
         );
       },
       },

+ 4 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_menu.dart

@@ -55,7 +55,10 @@ class SortChoiceChip extends StatelessWidget {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     final arrow = Transform.rotate(
     final arrow = Transform.rotate(
       angle: -math.pi / 2,
       angle: -math.pi / 2,
-      child: svgWidget("home/arrow_left"),
+      child: svgWidget(
+        "home/arrow_left",
+        color: Theme.of(context).iconTheme.color,
+      ),
     );
     );
 
 
     final text = LocaleKeys.grid_settings_sort.tr();
     final text = LocaleKeys.grid_settings_sort.tr();

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/filter_button.dart

@@ -25,7 +25,7 @@ class _FilterButtonState extends State<FilterButton> {
     return BlocBuilder<GridFilterMenuBloc, GridFilterMenuState>(
     return BlocBuilder<GridFilterMenuBloc, GridFilterMenuState>(
       builder: (context, state) {
       builder: (context, state) {
         final textColor = state.filters.isEmpty
         final textColor = state.filters.isEmpty
-            ? null
+            ? AFThemeExtension.of(context).textColor
             : Theme.of(context).colorScheme.primary;
             : Theme.of(context).colorScheme.primary;
 
 
         return _wrapPopover(
         return _wrapPopover(

+ 6 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_property.dart

@@ -5,6 +5,7 @@ import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/
 import 'package:appflowy/startup/startup.dart';
 import 'package:appflowy/startup/startup.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -115,7 +116,11 @@ class _GridPropertyCellState extends State<_GridPropertyCell> {
       triggerActions: PopoverTriggerFlags.none,
       triggerActions: PopoverTriggerFlags.none,
       margin: EdgeInsets.zero,
       margin: EdgeInsets.zero,
       child: FlowyButton(
       child: FlowyButton(
-        text: FlowyText.medium(widget.fieldInfo.name),
+        hoverColor: AFThemeExtension.of(context).lightGreyHover,
+        text: FlowyText.medium(
+          widget.fieldInfo.name,
+          color: AFThemeExtension.of(context).textColor,
+        ),
         leftIcon: svgWidget(
         leftIcon: svgWidget(
           widget.fieldInfo.fieldType.iconName(),
           widget.fieldInfo.fieldType.iconName(),
           color: Theme.of(context).iconTheme.color,
           color: Theme.of(context).iconTheme.color,

+ 5 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_setting.dart

@@ -2,6 +2,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_controlle
 import 'package:appflowy/plugins/database_view/application/setting/setting_bloc.dart';
 import 'package:appflowy/plugins/database_view/application/setting/setting_bloc.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -71,9 +72,12 @@ class _SettingItem extends StatelessWidget {
     return SizedBox(
     return SizedBox(
       height: GridSize.popoverItemHeight,
       height: GridSize.popoverItemHeight,
       child: FlowyButton(
       child: FlowyButton(
+        hoverColor: AFThemeExtension.of(context).lightGreyHover,
         text: FlowyText.medium(
         text: FlowyText.medium(
           action.title(),
           action.title(),
-          color: action.enable() ? null : Theme.of(context).disabledColor,
+          color: action.enable()
+              ? AFThemeExtension.of(context).textColor
+              : Theme.of(context).disabledColor,
         ),
         ),
         onTap: () => onAction(action),
         onTap: () => onAction(action),
         leftIcon: svgWidget(
         leftIcon: svgWidget(

+ 1 - 0
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/setting_button.dart

@@ -52,6 +52,7 @@ class _SettingButtonState extends State<SettingButton> {
             triggerActions: PopoverTriggerFlags.none,
             triggerActions: PopoverTriggerFlags.none,
             child: FlowyTextButton(
             child: FlowyTextButton(
               LocaleKeys.settings_title.tr(),
               LocaleKeys.settings_title.tr(),
+              fontColor: AFThemeExtension.of(context).textColor,
               fillColor: Colors.transparent,
               fillColor: Colors.transparent,
               hoverColor: AFThemeExtension.of(context).lightGreyHover,
               hoverColor: AFThemeExtension.of(context).lightGreyHover,
               padding: GridSize.typeOptionContentInsets,
               padding: GridSize.typeOptionContentInsets,

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/sort_button.dart

@@ -24,7 +24,7 @@ class _SortButtonState extends State<SortButton> {
     return BlocBuilder<SortMenuBloc, SortMenuState>(
     return BlocBuilder<SortMenuBloc, SortMenuState>(
       builder: (context, state) {
       builder: (context, state) {
         final textColor = state.sortInfos.isEmpty
         final textColor = state.sortInfos.isEmpty
-            ? null
+            ? AFThemeExtension.of(context).textColor
             : Theme.of(context).colorScheme.primary;
             : Theme.of(context).colorScheme.primary;
 
 
         return wrapPopover(
         return wrapPopover(

+ 7 - 1
frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_cell_editor.dart

@@ -1,6 +1,7 @@
 import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
 import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -116,7 +117,11 @@ class _ChecklistOptionCellState extends State<_ChecklistOptionCell> {
           children: [
           children: [
             Expanded(
             Expanded(
               child: FlowyButton(
               child: FlowyButton(
-                text: FlowyText(widget.option.data.name),
+                hoverColor: AFThemeExtension.of(context).lightGreyHover,
+                text: FlowyText(
+                  widget.option.data.name,
+                  color: AFThemeExtension.of(context).textColor,
+                ),
                 leftIcon: icon,
                 leftIcon: icon,
                 onTap: () => context
                 onTap: () => context
                     .read<ChecklistCellEditorBloc>()
                     .read<ChecklistCellEditorBloc>()
@@ -132,6 +137,7 @@ class _ChecklistOptionCellState extends State<_ChecklistOptionCell> {
 
 
   Widget _disclosureButton() {
   Widget _disclosureButton() {
     return FlowyIconButton(
     return FlowyIconButton(
+      hoverColor: AFThemeExtension.of(context).lightGreyHover,
       width: 20,
       width: 20,
       onPressed: () => _popoverController.show(),
       onPressed: () => _popoverController.show(),
       iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),
       iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_progress_bar.dart

@@ -20,7 +20,7 @@ class ChecklistProgressBar extends StatelessWidget {
       percent: percent,
       percent: percent,
       padding: EdgeInsets.zero,
       padding: EdgeInsets.zero,
       progressColor: Theme.of(context).colorScheme.primary,
       progressColor: Theme.of(context).colorScheme.primary,
-      backgroundColor: AFThemeExtension.of(context).tint9,
+      backgroundColor: AFThemeExtension.of(context).progressBarBGcolor,
       barRadius: const Radius.circular(5),
       barRadius: const Radius.circular(5),
     );
     );
   }
   }

+ 1 - 4
frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart

@@ -385,10 +385,7 @@ class _DateTypeOptionButton extends StatelessWidget {
               child: FlowyButton(
               child: FlowyButton(
                 text: FlowyText.medium(title),
                 text: FlowyText.medium(title),
                 margin: GridSize.typeOptionContentInsets,
                 margin: GridSize.typeOptionContentInsets,
-                rightIcon: svgWidget(
-                  "grid/more",
-                  color: Theme.of(context).iconTheme.color,
-                ),
+                rightIcon: const FlowySvg(name: 'grid/more'),
               ),
               ),
             ),
             ),
           ),
           ),

+ 9 - 2
frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart

@@ -106,7 +106,11 @@ class SelectOptionTag extends StatelessWidget {
         mainAxisSize: MainAxisSize.min,
         mainAxisSize: MainAxisSize.min,
         children: [
         children: [
           Flexible(
           Flexible(
-            child: FlowyText.medium(name, overflow: TextOverflow.ellipsis),
+            child: FlowyText.medium(
+              name,
+              overflow: TextOverflow.ellipsis,
+              color: Theme.of(context).colorScheme.onSurface,
+            ),
           ),
           ),
           if (onRemove != null)
           if (onRemove != null)
             FlowyIconButton(
             FlowyIconButton(
@@ -116,7 +120,7 @@ class SelectOptionTag extends StatelessWidget {
               hoverColor: Colors.transparent,
               hoverColor: Colors.transparent,
               icon: svgWidget(
               icon: svgWidget(
                 'home/close',
                 'home/close',
-                color: Theme.of(context).iconTheme.color,
+                color: Theme.of(context).colorScheme.onSurface,
               ),
               ),
             ),
             ),
         ],
         ],
@@ -139,6 +143,9 @@ class SelectOptionTagCell extends StatelessWidget {
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return FlowyHover(
     return FlowyHover(
+      style: HoverStyle(
+        hoverColor: AFThemeExtension.of(context).lightGreyHover,
+      ),
       child: InkWell(
       child: InkWell(
         child: Row(
         child: Row(
           mainAxisAlignment: MainAxisAlignment.spaceBetween,
           mainAxisAlignment: MainAxisAlignment.spaceBetween,

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/select_option_editor.dart

@@ -210,7 +210,7 @@ class _CreateOptionCell extends StatelessWidget {
                 alignment: Alignment.centerLeft,
                 alignment: Alignment.centerLeft,
                 child: SelectOptionTag(
                 child: SelectOptionTag(
                   name: name,
                   name: name,
-                  color: AFThemeExtension.of(context).lightGreyHover,
+                  color: AFThemeExtension.of(context).greyHover,
                   onSelected: () => context
                   onSelected: () => context
                       .read<SelectOptionCellEditorBloc>()
                       .read<SelectOptionCellEditorBloc>()
                       .add(SelectOptionEditorEvent.newOption(name)),
                       .add(SelectOptionEditorEvent.newOption(name)),

+ 3 - 4
frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/url_cell/url_cell.dart

@@ -5,6 +5,7 @@ import 'package:appflowy/workspace/presentation/home/toast.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter/services.dart';
@@ -211,10 +212,8 @@ class _EditURLAccessoryState extends State<_EditURLAccessory>
       controller: _popoverController,
       controller: _popoverController,
       direction: PopoverDirection.bottomWithLeftAligned,
       direction: PopoverDirection.bottomWithLeftAligned,
       offset: const Offset(0, 8),
       offset: const Offset(0, 8),
-      child: svgWidget(
-        "editor/edit",
-        color: Theme.of(context).iconTheme.color,
-      ),
+      child: svgWidget("editor/edit",
+          color: AFThemeExtension.of(context).textColor),
       popupBuilder: (BuildContext popoverContext) {
       popupBuilder: (BuildContext popoverContext) {
         return URLEditorPopover(
         return URLEditorPopover(
           cellController:
           cellController:

+ 47 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart

@@ -1,19 +1,53 @@
+import 'package:appflowy/generated/locale_keys.g.dart';
+import 'package:appflowy/plugins/database_view/application/database_view_service.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/board/board_node_widget.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/board/board_node_widget.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/grid/grid_node_widget.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/grid/grid_node_widget.dart';
 import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
+import 'package:appflowy/workspace/application/app/app_service.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
+import 'package:easy_localization/easy_localization.dart';
 
 
 const String kAppID = 'app_id';
 const String kAppID = 'app_id';
 const String kViewID = 'view_id';
 const String kViewID = 'view_id';
 
 
 extension InsertPage on EditorState {
 extension InsertPage on EditorState {
-  void insertPage(ViewPB appPB, ViewPB viewPB) {
+  Future<void> insertPage(ViewPB appPB, ViewPB viewPB) async {
     final selection = service.selectionService.currentSelection.value;
     final selection = service.selectionService.currentSelection.value;
     final textNodes =
     final textNodes =
         service.selectionService.currentSelectedNodes.whereType<TextNode>();
         service.selectionService.currentSelectedNodes.whereType<TextNode>();
     if (selection == null || textNodes.isEmpty) {
     if (selection == null || textNodes.isEmpty) {
       return;
       return;
     }
     }
+
+    // get the database that the view is associated with
+    final database =
+        await DatabaseViewBackendService(viewId: viewPB.id).openGrid().then(
+              (value) => value.getLeftOrNull(),
+            );
+
+    if (database == null) {
+      throw StateError(
+          'The database associated with ${viewPB.id} could not be found while attempting to create a referenced ${viewPB.layout.name}.');
+    }
+
+    final prefix = referencedBoardPrefix(viewPB.layout);
+
+    final ref = await AppBackendService().createView(
+      appId: appPB.id,
+      name: "$prefix ${viewPB.name}",
+      layoutType: viewPB.layout,
+      ext: {
+        'database_id': database.id,
+      },
+    ).then(
+      (value) => value.getLeftOrNull(),
+    );
+
+    // TODO(a-wallen): Show error dialog here.
+    if (ref == null) {
+      return;
+    }
+
     final transaction = this.transaction;
     final transaction = this.transaction;
     transaction.insertNode(
     transaction.insertNode(
       selection.end.path,
       selection.end.path,
@@ -21,13 +55,24 @@ extension InsertPage on EditorState {
         type: _convertPageType(viewPB),
         type: _convertPageType(viewPB),
         attributes: {
         attributes: {
           kAppID: appPB.id,
           kAppID: appPB.id,
-          kViewID: viewPB.id,
+          kViewID: ref.id,
         },
         },
       ),
       ),
     );
     );
     apply(transaction);
     apply(transaction);
   }
   }
 
 
+  String referencedBoardPrefix(ViewLayoutPB layout) {
+    switch (layout) {
+      case ViewLayoutPB.Grid:
+        return LocaleKeys.grid_referencedGridPrefix.tr();
+      case ViewLayoutPB.Board:
+        return LocaleKeys.board_referencedBoardPrefix.tr();
+      default:
+        throw UnimplementedError();
+    }
+  }
+
   String _convertPageType(ViewPB viewPB) {
   String _convertPageType(ViewPB viewPB) {
     switch (viewPB.layout) {
     switch (viewPB.layout) {
       case ViewLayoutPB.Grid:
       case ViewLayoutPB.Grid:

+ 92 - 7
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart

@@ -6,6 +6,7 @@ import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 import 'insert_page_command.dart';
 import 'insert_page_command.dart';
 import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:easy_localization/easy_localization.dart';
@@ -57,7 +58,7 @@ void showLinkToPageMenu(
     );
     );
   });
   });
 
 
-  Overlay.of(context)?.insert(_linkToPageMenu!);
+  Overlay.of(context).insert(_linkToPageMenu!);
 
 
   editorState.service.selectionService.currentSelection
   editorState.service.selectionService.currentSelection
       .addListener(dismissLinkToPageMenu);
       .addListener(dismissLinkToPageMenu);
@@ -91,14 +92,50 @@ class LinkToPageMenu extends StatefulWidget {
 }
 }
 
 
 class _LinkToPageMenuState extends State<LinkToPageMenu> {
 class _LinkToPageMenuState extends State<LinkToPageMenu> {
+  final _focusNode = FocusNode(debugLabel: 'reference_list_widget');
   EditorStyle get style => widget.editorState.editorStyle;
   EditorStyle get style => widget.editorState.editorStyle;
+  int _selectedIndex = 0;
+  int _totalItems = 0;
+  Future<List<dartz.Tuple2<ViewPB, List<ViewPB>>>>? _availableLayout;
+  final Map<int, dartz.Tuple2<ViewPB, ViewPB>> _items = {};
+
+  Future<List<dartz.Tuple2<ViewPB, List<ViewPB>>>> fetchItems() async {
+    final items = await AppBackendService().fetchViews(widget.layoutType);
+
+    int index = 0;
+    for (final app in items) {
+      for (final view in app.value2) {
+        _items.putIfAbsent(index, () => dartz.Tuple2(app.value1, view));
+        index += 1;
+      }
+    }
+
+    _totalItems = _items.length;
+    return items;
+  }
+
+  @override
+  void initState() {
+    _availableLayout = fetchItems();
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      _focusNode.requestFocus();
+    });
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    _focusNode.dispose();
+    super.dispose();
+  }
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    return Container(
-      color: Colors.transparent,
-      width: 300,
+    return Focus(
+      focusNode: _focusNode,
+      onKey: _onKey,
       child: Container(
       child: Container(
+        width: 300,
         padding: const EdgeInsets.fromLTRB(10, 6, 10, 6),
         padding: const EdgeInsets.fromLTRB(10, 6, 10, 6),
         decoration: BoxDecoration(
         decoration: BoxDecoration(
           color: style.selectionMenuBackgroundColor,
           color: style.selectionMenuBackgroundColor,
@@ -111,12 +148,57 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> {
           ],
           ],
           borderRadius: BorderRadius.circular(6.0),
           borderRadius: BorderRadius.circular(6.0),
         ),
         ),
-        child: _buildListWidget(context),
+        child: _buildListWidget(context, _selectedIndex, _availableLayout),
       ),
       ),
     );
     );
   }
   }
 
 
-  Widget _buildListWidget(BuildContext context) {
+  KeyEventResult _onKey(FocusNode node, RawKeyEvent event) {
+    if (event is! RawKeyDownEvent ||
+        _availableLayout == null ||
+        _items.isEmpty) {
+      return KeyEventResult.ignored;
+    }
+
+    final acceptedKeys = [
+      LogicalKeyboardKey.arrowUp,
+      LogicalKeyboardKey.arrowDown,
+      LogicalKeyboardKey.tab,
+      LogicalKeyboardKey.enter
+    ];
+
+    if (!acceptedKeys.contains(event.logicalKey)) {
+      return KeyEventResult.handled;
+    }
+
+    var newSelectedIndex = _selectedIndex;
+    if (event.logicalKey == LogicalKeyboardKey.arrowDown &&
+        newSelectedIndex != _totalItems - 1) {
+      newSelectedIndex += 1;
+    } else if (event.logicalKey == LogicalKeyboardKey.arrowUp &&
+        newSelectedIndex != 0) {
+      newSelectedIndex -= 1;
+    } else if (event.logicalKey == LogicalKeyboardKey.tab) {
+      newSelectedIndex += 1;
+      newSelectedIndex %= _totalItems;
+    } else if (event.logicalKey == LogicalKeyboardKey.enter) {
+      widget.onSelected(
+          _items[_selectedIndex]!.value1, _items[_selectedIndex]!.value2);
+    }
+
+    setState(() {
+      _selectedIndex = newSelectedIndex;
+    });
+
+    return KeyEventResult.handled;
+  }
+
+  Widget _buildListWidget(
+    BuildContext context,
+    int selectedIndex,
+    Future<List<dartz.Tuple2<ViewPB, List<ViewPB>>>>? items,
+  ) {
+    int index = 0;
     return FutureBuilder<List<dartz.Tuple2<ViewPB, List<ViewPB>>>>(
     return FutureBuilder<List<dartz.Tuple2<ViewPB, List<ViewPB>>>>(
       builder: (context, snapshot) {
       builder: (context, snapshot) {
         if (snapshot.hasData &&
         if (snapshot.hasData &&
@@ -146,6 +228,7 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> {
                 for (final value in view.value2) {
                 for (final value in view.value2) {
                   children.add(
                   children.add(
                     FlowyButton(
                     FlowyButton(
+                      isSelected: index == _selectedIndex,
                       leftIcon: svgWidget(
                       leftIcon: svgWidget(
                         _iconName(value),
                         _iconName(value),
                         color: Theme.of(context).iconTheme.color,
                         color: Theme.of(context).iconTheme.color,
@@ -154,6 +237,8 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> {
                       onTap: () => widget.onSelected(view.value1, value),
                       onTap: () => widget.onSelected(view.value1, value),
                     ),
                     ),
                   );
                   );
+
+                  index += 1;
                 }
                 }
               }
               }
             }
             }
@@ -168,7 +253,7 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> {
           );
           );
         }
         }
       },
       },
-      future: AppBackendService().fetchViews(widget.layoutType),
+      future: items,
     );
     );
   }
   }
 
 

+ 5 - 2
frontend/appflowy_flutter/lib/workspace/application/appearance.dart

@@ -226,6 +226,7 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
           fontColor: theme.surface,
           fontColor: theme.surface,
         ),
         ),
       ),
       ),
+      scaffoldBackgroundColor: theme.surface,
       scrollbarTheme: ScrollbarThemeData(
       scrollbarTheme: ScrollbarThemeData(
         thumbColor: MaterialStateProperty.all(theme.shader3),
         thumbColor: MaterialStateProperty.all(theme.shader3),
         thickness: MaterialStateProperty.resolveWith((states) {
         thickness: MaterialStateProperty.resolveWith((states) {
@@ -292,10 +293,12 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
           tint7: theme.tint7,
           tint7: theme.tint7,
           tint8: theme.tint8,
           tint8: theme.tint8,
           tint9: theme.tint9,
           tint9: theme.tint9,
+          textColor: theme.text,
           greyHover: theme.hoverBG1,
           greyHover: theme.hoverBG1,
           greySelect: theme.bg3,
           greySelect: theme.bg3,
-          lightGreyHover: theme.shader6,
+          lightGreyHover: theme.hoverBG3,
           toggleOffFill: theme.shader5,
           toggleOffFill: theme.shader5,
+          progressBarBGcolor: theme.progressBarBGcolor,
           code: _getFontStyle(
           code: _getFontStyle(
             fontFamily: monospaceFontFamily,
             fontFamily: monospaceFontFamily,
             fontColor: theme.shader3,
             fontColor: theme.shader3,
@@ -309,7 +312,7 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
             fontFamily: fontFamily,
             fontFamily: fontFamily,
             fontSize: FontSizes.s11,
             fontSize: FontSizes.s11,
             fontWeight: FontWeight.w400,
             fontWeight: FontWeight.w400,
-            fontColor: theme.shader3,
+            fontColor: theme.hint,
           ),
           ),
         )
         )
       ],
       ],

+ 9 - 6
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/create_button.dart

@@ -20,12 +20,15 @@ class NewAppButton extends StatelessWidget {
       hoverColor: Colors.transparent,
       hoverColor: Colors.transparent,
       fontColor: Theme.of(context).colorScheme.tertiary,
       fontColor: Theme.of(context).colorScheme.tertiary,
       onPressed: () async => await _showCreateAppDialog(context),
       onPressed: () async => await _showCreateAppDialog(context),
-      heading: Theme.of(context).brightness == Brightness.light
-          ? svgWidget("home/new_app", size: const Size(16, 16))
-          : svgWidget(
-              "home/new_app_dark",
-              size: const Size(16, 16),
-            ),
+      heading: Container(
+        width: 16,
+        height: 16,
+        decoration: BoxDecoration(
+          shape: BoxShape.circle,
+          color: Theme.of(context).colorScheme.surface,
+        ),
+        child: svgWidget("home/new_app"),
+      ),
       padding: EdgeInsets.symmetric(horizontal: Insets.l, vertical: 20),
       padding: EdgeInsets.symmetric(horizontal: Insets.l, vertical: 20),
     );
     );
 
 

+ 3 - 3
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_panel.dart

@@ -45,7 +45,7 @@ enum _ImportType {
       case _ImportType.markdownOrText:
       case _ImportType.markdownOrText:
         return 'Text & Markdown';
         return 'Text & Markdown';
       default:
       default:
-        assert(false, 'Unsupported Type ${this}');
+        assert(false, 'Unsupported Type $this');
         return '';
         return '';
     }
     }
   }
   }
@@ -55,7 +55,7 @@ enum _ImportType {
       case _ImportType.markdownOrText:
       case _ImportType.markdownOrText:
         return svgWidget('editor/documents');
         return svgWidget('editor/documents');
       default:
       default:
-        assert(false, 'Unsupported Type ${this}');
+        assert(false, 'Unsupported Type $this');
         return null;
         return null;
     }
     }
   }
   }
@@ -65,7 +65,7 @@ enum _ImportType {
       case _ImportType.markdownOrText:
       case _ImportType.markdownOrText:
         return ['md', 'txt'];
         return ['md', 'txt'];
       default:
       default:
-        assert(false, 'Unsupported Type ${this}');
+        assert(false, 'Unsupported Type $this');
         return [];
         return [];
     }
     }
   }
   }

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart

@@ -59,7 +59,7 @@ class ThemeSetting extends StatelessWidget {
               child: Column(
               child: Column(
                 mainAxisSize: MainAxisSize.min,
                 mainAxisSize: MainAxisSize.min,
                 children: [
                 children: [
-                  _themeItemButton(context, BuiltInTheme.light),
+                  _themeItemButton(context, BuiltInTheme.defaultTheme),
                   _themeItemButton(context, BuiltInTheme.dandelion),
                   _themeItemButton(context, BuiltInTheme.dandelion),
                   _themeItemButton(context, BuiltInTheme.lavender),
                   _themeItemButton(context, BuiltInTheme.lavender),
                 ],
                 ],

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart

@@ -119,7 +119,7 @@ class _CreateFlowyAlertDialog extends State<NavigatorAlertDialog> {
             FlowyText.medium(
             FlowyText.medium(
               widget.title,
               widget.title,
               fontSize: FontSizes.s16,
               fontSize: FontSizes.s16,
-              color: Theme.of(context).disabledColor,
+              color: Theme.of(context).colorScheme.tertiary,
             ),
             ),
           ],
           ],
           if (widget.confirm != null) ...[
           if (widget.confirm != null) ...[

+ 1 - 1
frontend/appflowy_flutter/macos/Podfile

@@ -1,4 +1,4 @@
-platform :osx, '10.11'
+platform :osx, '10.14'
 
 
 # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
 # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
 ENV['COCOAPODS_DISABLE_STATS'] = 'true'
 ENV['COCOAPODS_DISABLE_STATS'] = 'true'

+ 6 - 5
frontend/appflowy_flutter/macos/Runner.xcodeproj/project.pbxproj

@@ -3,7 +3,7 @@
 	archiveVersion = 1;
 	archiveVersion = 1;
 	classes = {
 	classes = {
 	};
 	};
-	objectVersion = 51;
+	objectVersion = 54;
 	objects = {
 	objects = {
 
 
 /* Begin PBXAggregateTarget section */
 /* Begin PBXAggregateTarget section */
@@ -202,7 +202,7 @@
 			isa = PBXProject;
 			isa = PBXProject;
 			attributes = {
 			attributes = {
 				LastSwiftUpdateCheck = 0920;
 				LastSwiftUpdateCheck = 0920;
-				LastUpgradeCheck = 0930;
+				LastUpgradeCheck = 1300;
 				ORGANIZATIONNAME = "";
 				ORGANIZATIONNAME = "";
 				TargetAttributes = {
 				TargetAttributes = {
 					33CC10EC2044A3C60003C045 = {
 					33CC10EC2044A3C60003C045 = {
@@ -255,6 +255,7 @@
 /* Begin PBXShellScriptBuildPhase section */
 /* Begin PBXShellScriptBuildPhase section */
 		3399D490228B24CF009A79C7 /* ShellScript */ = {
 		3399D490228B24CF009A79C7 /* ShellScript */ = {
 			isa = PBXShellScriptBuildPhase;
 			isa = PBXShellScriptBuildPhase;
+			alwaysOutOfDate = 1;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
 			);
 			);
@@ -403,7 +404,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = macosx;
 				SDKROOT = macosx;
 				STRIP_STYLE = "non-global";
 				STRIP_STYLE = "non-global";
@@ -489,7 +490,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx;
 				SDKROOT = macosx;
@@ -537,7 +538,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = macosx;
 				SDKROOT = macosx;
 				STRIP_STYLE = "non-global";
 				STRIP_STYLE = "non-global";

+ 1 - 1
frontend/appflowy_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
 <Scheme
-   LastUpgradeVersion = "1000"
+   LastUpgradeVersion = "1300"
    version = "1.3">
    version = "1.3">
    <BuildAction
    <BuildAction
       parallelizeBuildables = "YES"
       parallelizeBuildables = "YES"

+ 2 - 2
frontend/appflowy_flutter/packages/appflowy_backend/pubspec.yaml

@@ -11,9 +11,9 @@ environment:
 dependencies:
 dependencies:
   flutter:
   flutter:
     sdk: flutter
     sdk: flutter
-  ffi: ^1.0.0
+  ffi: ^2.0.1
   isolates: ^3.0.3+8
   isolates: ^3.0.3+8
-  protobuf: "2.0.0"
+  protobuf: ^2.0.0
   dartz: ^0.10.1
   dartz: ^0.10.1
   freezed_annotation:
   freezed_annotation:
   logger: ^1.0.0
   logger: ^1.0.0

+ 0 - 1
frontend/appflowy_flutter/packages/appflowy_editor/lib/appflowy_editor.dart

@@ -34,7 +34,6 @@ export 'src/render/selection_menu/selection_menu_widget.dart';
 export 'src/render/selection_menu/selection_menu_item_widget.dart';
 export 'src/render/selection_menu/selection_menu_item_widget.dart';
 export 'src/l10n/l10n.dart';
 export 'src/l10n/l10n.dart';
 export 'src/render/style/plugin_styles.dart';
 export 'src/render/style/plugin_styles.dart';
-export 'src/render/style/editor_style.dart';
 export 'src/plugins/markdown/encoder/delta_markdown_encoder.dart';
 export 'src/plugins/markdown/encoder/delta_markdown_encoder.dart';
 export 'src/plugins/markdown/encoder/document_markdown_encoder.dart';
 export 'src/plugins/markdown/encoder/document_markdown_encoder.dart';
 export 'src/plugins/markdown/encoder/parser/node_parser.dart';
 export 'src/plugins/markdown/encoder/parser/node_parser.dart';

+ 2 - 1
frontend/appflowy_flutter/packages/appflowy_editor/lib/src/infra/flowy_svg.dart

@@ -34,7 +34,8 @@ class FlowySvg extends StatelessWidget {
     if (name != null) {
     if (name != null) {
       return SvgPicture.asset(
       return SvgPicture.asset(
         'assets/images/$name.svg',
         'assets/images/$name.svg',
-        color: color,
+        colorFilter:
+            color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null,
         fit: BoxFit.fill,
         fit: BoxFit.fill,
         height: height,
         height: height,
         width: width,
         width: width,

+ 1 - 1
frontend/appflowy_flutter/packages/appflowy_editor/pubspec.yaml

@@ -19,7 +19,7 @@ dependencies:
 
 
   rich_clipboard: ^1.0.0
   rich_clipboard: ^1.0.0
   html: ^0.15.0
   html: ^0.15.0
-  flutter_svg: ^1.1.1+1
+  flutter_svg: ^2.0.2
   provider: ^6.0.3
   provider: ^6.0.3
   url_launcher: ^6.1.5
   url_launcher: ^6.1.5
   logging: ^1.0.2
   logging: ^1.0.2

+ 1 - 1
frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/emoji_picker/emoji_menu_item.dart

@@ -50,7 +50,7 @@ void _showEmojiSelectionMenu(
     );
     );
   });
   });
 
 
-  Overlay.of(context)?.insert(_emojiSelectionMenu!);
+  Overlay.of(context).insert(_emojiSelectionMenu!);
 
 
   editorState.service.selectionService.currentSelection
   editorState.service.selectionService.currentSelection
       .addListener(_dismissEmojiSelectionMenu);
       .addListener(_dismissEmojiSelectionMenu);

+ 1 - 1
frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/extensions/theme_extension.dart

@@ -9,7 +9,7 @@ extension FlowyTintExtension on FlowyTint {
     ThemeMode? themeMode,
     ThemeMode? themeMode,
     String? theme,
     String? theme,
   }) {
   }) {
-    if (themeMode == ThemeMode.light && theme == BuiltInTheme.light) {
+    if (themeMode == ThemeMode.light && theme == BuiltInTheme.defaultTheme) {
       switch (this) {
       switch (this) {
         case FlowyTint.tint1:
         case FlowyTint.tint1:
           return l10n.lightLightTint1;
           return l10n.lightLightTint1;

+ 2 - 1
frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/infra/svg.dart

@@ -34,7 +34,8 @@ class Svg extends StatelessWidget {
     if (name != null) {
     if (name != null) {
       return SvgPicture.asset(
       return SvgPicture.asset(
         'assets/images/$name.svg',
         'assets/images/$name.svg',
-        color: color,
+        colorFilter:
+            color != null ? ColorFilter.mode(color!, BlendMode.srcIn) : null,
         fit: BoxFit.fill,
         fit: BoxFit.fill,
         height: height,
         height: height,
         width: width,
         width: width,

+ 10 - 8
frontend/appflowy_flutter/packages/appflowy_editor_plugins/pubspec.yaml

@@ -6,24 +6,26 @@ homepage: https://github.com/AppFlowy-IO/AppFlowy
 publish_to: none
 publish_to: none
 
 
 environment:
 environment:
-  sdk: ">=2.18.0 <3.0.0"
-  flutter: ">=3.3.0"
+  sdk: ">=2.19.0 <3.0.0"
+  flutter: ">=3.7.0"
 
 
 dependencies:
 dependencies:
   flutter:
   flutter:
     sdk: flutter
     sdk: flutter
-  appflowy_editor:
-    path: ../appflowy_editor
-  flowy_infra: 
+  appflowy_editor: ^0.1.4
+  flowy_infra:
     path: ../flowy_infra
     path: ../flowy_infra
   flowy_infra_ui:
   flowy_infra_ui:
     path: ../flowy_infra_ui
     path: ../flowy_infra_ui
-  appflowy_popover: 
+  appflowy_popover:
     path: ../appflowy_popover
     path: ../appflowy_popover
-  flutter_math_fork: ^0.6.3+1
+  flutter_math_fork:
+    git:
+      url: https://github.com/LucasXu0/flutter_math_fork.git
+      ref: master
   highlight: ^0.7.0
   highlight: ^0.7.0
   shared_preferences: ^2.0.15
   shared_preferences: ^2.0.15
-  flutter_svg: ^1.1.1+1
+  flutter_svg: ^2.0.2
   provider: ^6.0.3
   provider: ^6.0.3
 
 
 dev_dependencies:
 dev_dependencies:

+ 1 - 1
frontend/appflowy_flutter/packages/appflowy_popover/lib/src/mask.dart

@@ -17,7 +17,7 @@ class RootOverlayEntry {
     bool asBarrier,
     bool asBarrier,
   ) {
   ) {
     _entries[newState] = OverlayEntryContext(entry, newState, asBarrier);
     _entries[newState] = OverlayEntryContext(entry, newState, asBarrier);
-    Overlay.of(context)?.insert(entry);
+    Overlay.of(context).insert(entry);
   }
   }
 
 
   bool contains(PopoverState oldState) {
   bool contains(PopoverState oldState) {

+ 6 - 2
frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart

@@ -1,9 +1,9 @@
-import 'package:flowy_infra/colorscheme/lavender.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 
 
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra/theme.dart';
 import 'default_colorscheme.dart';
 import 'default_colorscheme.dart';
 import 'dandelion.dart';
 import 'dandelion.dart';
+import 'lavender.dart';
 
 
 /// A map of all the built-in themes.
 /// A map of all the built-in themes.
 ///
 ///
@@ -11,7 +11,7 @@ import 'dandelion.dart';
 /// the first is for light mode, and the second is for dark mode.
 /// the first is for light mode, and the second is for dark mode.
 
 
 const Map<String, List<FlowyColorScheme>> themeMap = {
 const Map<String, List<FlowyColorScheme>> themeMap = {
-  BuiltInTheme.light: [
+  BuiltInTheme.defaultTheme: [
     DefaultColorScheme.light(),
     DefaultColorScheme.light(),
     DefaultColorScheme.dark(),
     DefaultColorScheme.dark(),
   ],
   ],
@@ -69,9 +69,11 @@ abstract class FlowyColorScheme {
   final Color hoverBG1;
   final Color hoverBG1;
   //action item hover effect
   //action item hover effect
   final Color hoverBG2;
   final Color hoverBG2;
+  final Color hoverBG3;
   //the text color when it is hovered
   //the text color when it is hovered
   final Color hoverFG;
   final Color hoverFG;
   final Color questionBubbleBG;
   final Color questionBubbleBG;
+  final Color progressBarBGcolor;
 
 
   const FlowyColorScheme({
   const FlowyColorScheme({
     required this.surface,
     required this.surface,
@@ -114,8 +116,10 @@ abstract class FlowyColorScheme {
     required this.onPrimary,
     required this.onPrimary,
     required this.hoverBG1,
     required this.hoverBG1,
     required this.hoverBG2,
     required this.hoverBG2,
+    required this.hoverBG3,
     required this.hoverFG,
     required this.hoverFG,
     required this.questionBubbleBG,
     required this.questionBubbleBG,
+    required this.progressBarBGcolor,
   });
   });
 
 
   factory FlowyColorScheme.builtIn(String themeName, Brightness brightness) {
   factory FlowyColorScheme.builtIn(String themeName, Brightness brightness) {

+ 15 - 10
frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart

@@ -12,6 +12,7 @@ const _lightShader1 = Color(0xff333333);
 const _lightShader3 = Color(0xff828282);
 const _lightShader3 = Color(0xff828282);
 const _lightShader6 = Color(0xfff2f2f2);
 const _lightShader6 = Color(0xfff2f2f2);
 const _lightMain1 = Color(0xffe21f74);
 const _lightMain1 = Color(0xffe21f74);
+const _lightTint9 = Color(0xffe1fbff);
 
 
 const _darkShader1 = Color(0xff131720);
 const _darkShader1 = Color(0xff131720);
 const _darkShader2 = Color(0xff1A202C);
 const _darkShader2 = Color(0xff1A202C);
@@ -48,7 +49,7 @@ class DandelionColorScheme extends FlowyColorScheme {
           tint6: const Color(0xfff5ffdc),
           tint6: const Color(0xfff5ffdc),
           tint7: const Color(0xffddffd6),
           tint7: const Color(0xffddffd6),
           tint8: const Color(0xffdefff1),
           tint8: const Color(0xffdefff1),
-          tint9: const Color(0xffe1fbff),
+          tint9: _lightTint9,
           main1: _lightMain1,
           main1: _lightMain1,
           main2: const Color.fromARGB(255, 224, 25, 111),
           main2: const Color.fromARGB(255, 224, 25, 111),
           shadow: _black,
           shadow: _black,
@@ -63,8 +64,10 @@ class DandelionColorScheme extends FlowyColorScheme {
           onPrimary: _white,
           onPrimary: _white,
           hoverBG1: _lightBg2,
           hoverBG1: _lightBg2,
           hoverBG2: _lightHover,
           hoverBG2: _lightHover,
+          hoverBG3: _lightShader6,
           hoverFG: _lightShader1,
           hoverFG: _lightShader1,
           questionBubbleBG: _lightSelector,
           questionBubbleBG: _lightSelector,
+          progressBarBGcolor: _lightTint9,
         );
         );
 
 
   const DandelionColorScheme.dark()
   const DandelionColorScheme.dark()
@@ -86,15 +89,15 @@ class DandelionColorScheme extends FlowyColorScheme {
           bg2: _black,
           bg2: _black,
           bg3: const Color(0xff4f4f4f),
           bg3: const Color(0xff4f4f4f),
           bg4: const Color(0xff2c144b),
           bg4: const Color(0xff2c144b),
-          tint1: const Color(0xffc3adff),
-          tint2: const Color(0xffffadf9),
-          tint3: const Color(0xffffadad),
-          tint4: const Color(0xffffcfad),
-          tint5: const Color(0xfffffead),
-          tint6: const Color(0xffe6ffa3),
-          tint7: const Color(0xffbcffad),
-          tint8: const Color(0xffadffe2),
-          tint9: const Color(0xffade4ff),
+          tint1: const Color(0xff8738F5),
+          tint2: const Color(0xffE6336E),
+          tint3: const Color(0xffFF2D9E),
+          tint4: const Color(0xffE9973E),
+          tint5: const Color(0xffFBF000),
+          tint6: const Color(0xffC0F000),
+          tint7: const Color(0xff15F74E),
+          tint8: const Color(0xff00F0E2),
+          tint9: const Color(0xff00BCF0),
           main1: _darkMain1,
           main1: _darkMain1,
           main2: const Color.fromARGB(255, 224, 25, 111),
           main2: const Color.fromARGB(255, 224, 25, 111),
           shadow: _black,
           shadow: _black,
@@ -109,7 +112,9 @@ class DandelionColorScheme extends FlowyColorScheme {
           onPrimary: _darkShader1,
           onPrimary: _darkShader1,
           hoverBG1: _darkMain1,
           hoverBG1: _darkMain1,
           hoverBG2: _darkMain1,
           hoverBG2: _darkMain1,
+          hoverBG3: _darkShader3,
           hoverFG: _darkShader1,
           hoverFG: _darkShader1,
           questionBubbleBG: _darkShader3,
           questionBubbleBG: _darkShader3,
+          progressBarBGcolor: _darkShader3,
         );
         );
 }
 }

+ 6 - 1
frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart

@@ -12,6 +12,7 @@ const _lightShader1 = Color(0xff333333);
 const _lightShader3 = Color(0xff828282);
 const _lightShader3 = Color(0xff828282);
 const _lightShader6 = Color(0xfff2f2f2);
 const _lightShader6 = Color(0xfff2f2f2);
 const _lightMain1 = Color(0xff00bcf0);
 const _lightMain1 = Color(0xff00bcf0);
+const _lightTint9 = Color(0xffe1fbff);
 const _darkShader1 = Color(0xff131720);
 const _darkShader1 = Color(0xff131720);
 const _darkShader2 = Color(0xff1A202C);
 const _darkShader2 = Color(0xff1A202C);
 const _darkShader3 = Color(0xff363D49);
 const _darkShader3 = Color(0xff363D49);
@@ -47,7 +48,7 @@ class DefaultColorScheme extends FlowyColorScheme {
           tint6: const Color(0xfff5ffdc),
           tint6: const Color(0xfff5ffdc),
           tint7: const Color(0xffddffd6),
           tint7: const Color(0xffddffd6),
           tint8: const Color(0xffdefff1),
           tint8: const Color(0xffdefff1),
-          tint9: const Color(0xffe1fbff),
+          tint9: _lightTint9,
           main1: _lightMain1,
           main1: _lightMain1,
           main2: const Color(0xff00b7ea),
           main2: const Color(0xff00b7ea),
           shadow: _black,
           shadow: _black,
@@ -64,6 +65,8 @@ class DefaultColorScheme extends FlowyColorScheme {
           hoverBG2: _lightHover,
           hoverBG2: _lightHover,
           hoverFG: _lightShader1,
           hoverFG: _lightShader1,
           questionBubbleBG: _lightSelector,
           questionBubbleBG: _lightSelector,
+          hoverBG3: _lightShader6,
+          progressBarBGcolor: _lightTint9,
         );
         );
 
 
   const DefaultColorScheme.dark()
   const DefaultColorScheme.dark()
@@ -108,7 +111,9 @@ class DefaultColorScheme extends FlowyColorScheme {
           onPrimary: _darkShader1,
           onPrimary: _darkShader1,
           hoverBG1: _darkMain1,
           hoverBG1: _darkMain1,
           hoverBG2: _darkMain1,
           hoverBG2: _darkMain1,
+          hoverBG3: _darkShader3,
           hoverFG: _darkShader1,
           hoverFG: _darkShader1,
           questionBubbleBG: _darkShader3,
           questionBubbleBG: _darkShader3,
+          progressBarBGcolor: _darkShader3,
         );
         );
 }
 }

+ 15 - 10
frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart

@@ -13,6 +13,7 @@ const _lightShader1 = Color(0xff333333);
 const _lightShader3 = Color(0xff828282);
 const _lightShader3 = Color(0xff828282);
 const _lightShader6 = Color(0xfff2f2f2);
 const _lightShader6 = Color(0xfff2f2f2);
 const _lightMain1 = Color(0xffA652FB);
 const _lightMain1 = Color(0xffA652FB);
+const _lightTint9 = Color(0xffe1fbff);
 
 
 const _darkShader1 = Color(0xff131720);
 const _darkShader1 = Color(0xff131720);
 const _darkShader2 = Color(0xff1A202C);
 const _darkShader2 = Color(0xff1A202C);
@@ -49,7 +50,7 @@ class LavenderColorScheme extends FlowyColorScheme {
           tint6: const Color(0xfff5ffdc),
           tint6: const Color(0xfff5ffdc),
           tint7: const Color(0xffddffd6),
           tint7: const Color(0xffddffd6),
           tint8: const Color(0xffdefff1),
           tint8: const Color(0xffdefff1),
-          tint9: const Color(0xffe1fbff),
+          tint9: _lightTint9,
           main1: _lightMain1,
           main1: _lightMain1,
           main2: const Color(0xff9327FF),
           main2: const Color(0xff9327FF),
           shadow: _black,
           shadow: _black,
@@ -64,8 +65,10 @@ class LavenderColorScheme extends FlowyColorScheme {
           onPrimary: _white,
           onPrimary: _white,
           hoverBG1: _lightBg2,
           hoverBG1: _lightBg2,
           hoverBG2: _lightHover,
           hoverBG2: _lightHover,
+          hoverBG3: _lightShader6,
           hoverFG: _lightShader1,
           hoverFG: _lightShader1,
           questionBubbleBG: _lightSelector,
           questionBubbleBG: _lightSelector,
+          progressBarBGcolor: _lightTint9,
         );
         );
 
 
   const LavenderColorScheme.dark()
   const LavenderColorScheme.dark()
@@ -87,15 +90,15 @@ class LavenderColorScheme extends FlowyColorScheme {
           bg2: _black,
           bg2: _black,
           bg3: const Color(0xff4f4f4f),
           bg3: const Color(0xff4f4f4f),
           bg4: const Color(0xff2c144b),
           bg4: const Color(0xff2c144b),
-          tint1: const Color(0xffc3adff),
-          tint2: const Color(0xffffadf9),
-          tint3: const Color(0xffffadad),
-          tint4: const Color(0xffffcfad),
-          tint5: const Color(0xfffffead),
-          tint6: const Color(0xffe6ffa3),
-          tint7: const Color(0xffbcffad),
-          tint8: const Color(0xffadffe2),
-          tint9: const Color(0xffade4ff),
+          tint1: const Color(0xff8738F5),
+          tint2: const Color(0xffE6336E),
+          tint3: const Color(0xffFF2D9E),
+          tint4: const Color(0xffE9973E),
+          tint5: const Color(0xffFBF000),
+          tint6: const Color(0xffC0F000),
+          tint7: const Color(0xff15F74E),
+          tint8: const Color(0xff00F0E2),
+          tint9: const Color(0xff00BCF0),
           main1: _darkMain1,
           main1: _darkMain1,
           main2: const Color(0xff9327FF),
           main2: const Color(0xff9327FF),
           shadow: _black,
           shadow: _black,
@@ -110,7 +113,9 @@ class LavenderColorScheme extends FlowyColorScheme {
           onPrimary: _darkShader1,
           onPrimary: _darkShader1,
           hoverBG1: _darkMain1,
           hoverBG1: _darkMain1,
           hoverBG2: _darkMain1,
           hoverBG2: _darkMain1,
+          hoverBG3: _darkShader3,
           hoverFG: _darkShader1,
           hoverFG: _darkShader1,
           questionBubbleBG: _darkShader3,
           questionBubbleBG: _darkShader3,
+          progressBarBGcolor: _darkShader3,
         );
         );
 }
 }

+ 11 - 3
frontend/appflowy_flutter/packages/flowy_infra/lib/image.dart

@@ -1,6 +1,6 @@
+import 'package:flutter/material.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 
 
-import 'package:flutter/material.dart';
 
 
 /// For icon that needs to change color when it is on hovered
 /// For icon that needs to change color when it is on hovered
 ///
 ///
@@ -29,9 +29,17 @@ Widget svgWidget(String name, {Size? size, Color? color}) {
   if (size != null) {
   if (size != null) {
     return SizedBox.fromSize(
     return SizedBox.fromSize(
       size: size,
       size: size,
-      child: SvgPicture.asset('assets/images/$name.svg', color: color),
+      child: SvgPicture.asset(
+        'assets/images/$name.svg',
+        colorFilter:
+            color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null,
+      ),
     );
     );
   } else {
   } else {
-    return SvgPicture.asset('assets/images/$name.svg', color: color);
+    return SvgPicture.asset(
+      'assets/images/$name.svg',
+      colorFilter:
+          color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null,
+    );
   }
   }
 }
 }

+ 3 - 3
frontend/appflowy_flutter/packages/flowy_infra/lib/theme.dart

@@ -2,9 +2,9 @@ import 'package:flowy_infra/colorscheme/colorscheme.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 
 
 class BuiltInTheme {
 class BuiltInTheme {
-  static const String light = 'light';
-  static const String dandelion = 'dandelion';
-  static const String lavender = 'lavender';
+  static const String defaultTheme = 'Default';
+  static const String dandelion = 'Dandelion';
+  static const String lavender = 'Lavender';
 }
 }
 
 
 class AppTheme {
 class AppTheme {

+ 11 - 0
frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart

@@ -15,10 +15,12 @@ class AFThemeExtension extends ThemeExtension<AFThemeExtension> {
   final Color tint8;
   final Color tint8;
   final Color tint9;
   final Color tint9;
 
 
+  final Color textColor;
   final Color greyHover;
   final Color greyHover;
   final Color greySelect;
   final Color greySelect;
   final Color lightGreyHover;
   final Color lightGreyHover;
   final Color toggleOffFill;
   final Color toggleOffFill;
+  final Color progressBarBGcolor;
 
 
   final TextStyle code;
   final TextStyle code;
   final TextStyle callout;
   final TextStyle callout;
@@ -40,9 +42,11 @@ class AFThemeExtension extends ThemeExtension<AFThemeExtension> {
     required this.greySelect,
     required this.greySelect,
     required this.lightGreyHover,
     required this.lightGreyHover,
     required this.toggleOffFill,
     required this.toggleOffFill,
+    required this.textColor,
     required this.code,
     required this.code,
     required this.callout,
     required this.callout,
     required this.caption,
     required this.caption,
+    required this.progressBarBGcolor,
   });
   });
 
 
   static AFThemeExtension of(BuildContext context) {
   static AFThemeExtension of(BuildContext context) {
@@ -62,10 +66,12 @@ class AFThemeExtension extends ThemeExtension<AFThemeExtension> {
     Color? tint7,
     Color? tint7,
     Color? tint8,
     Color? tint8,
     Color? tint9,
     Color? tint9,
+    Color? textColor,
     Color? greyHover,
     Color? greyHover,
     Color? greySelect,
     Color? greySelect,
     Color? lightGreyHover,
     Color? lightGreyHover,
     Color? toggleOffFill,
     Color? toggleOffFill,
+    Color? progressBarBGcolor,
     TextStyle? code,
     TextStyle? code,
     TextStyle? callout,
     TextStyle? callout,
     TextStyle? caption,
     TextStyle? caption,
@@ -82,10 +88,12 @@ class AFThemeExtension extends ThemeExtension<AFThemeExtension> {
       tint7: tint7 ?? this.tint7,
       tint7: tint7 ?? this.tint7,
       tint8: tint8 ?? this.tint8,
       tint8: tint8 ?? this.tint8,
       tint9: tint9 ?? this.tint9,
       tint9: tint9 ?? this.tint9,
+      textColor: textColor ?? this.textColor,
       greyHover: greyHover ?? this.greyHover,
       greyHover: greyHover ?? this.greyHover,
       greySelect: greySelect ?? this.greySelect,
       greySelect: greySelect ?? this.greySelect,
       lightGreyHover: lightGreyHover ?? this.lightGreyHover,
       lightGreyHover: lightGreyHover ?? this.lightGreyHover,
       toggleOffFill: toggleOffFill ?? this.toggleOffFill,
       toggleOffFill: toggleOffFill ?? this.toggleOffFill,
+      progressBarBGcolor: progressBarBGcolor ?? this.progressBarBGcolor,
       code: code ?? this.code,
       code: code ?? this.code,
       callout: callout ?? this.callout,
       callout: callout ?? this.callout,
       caption: caption ?? this.caption,
       caption: caption ?? this.caption,
@@ -110,10 +118,13 @@ class AFThemeExtension extends ThemeExtension<AFThemeExtension> {
       tint7: Color.lerp(tint7, other.tint7, t)!,
       tint7: Color.lerp(tint7, other.tint7, t)!,
       tint8: Color.lerp(tint8, other.tint8, t)!,
       tint8: Color.lerp(tint8, other.tint8, t)!,
       tint9: Color.lerp(tint9, other.tint9, t)!,
       tint9: Color.lerp(tint9, other.tint9, t)!,
+      textColor: Color.lerp(textColor, other.textColor, t)!,
       greyHover: Color.lerp(greyHover, other.greyHover, t)!,
       greyHover: Color.lerp(greyHover, other.greyHover, t)!,
       greySelect: Color.lerp(greySelect, other.greySelect, t)!,
       greySelect: Color.lerp(greySelect, other.greySelect, t)!,
       lightGreyHover: Color.lerp(lightGreyHover, other.lightGreyHover, t)!,
       lightGreyHover: Color.lerp(lightGreyHover, other.lightGreyHover, t)!,
       toggleOffFill: Color.lerp(toggleOffFill, other.toggleOffFill, t)!,
       toggleOffFill: Color.lerp(toggleOffFill, other.toggleOffFill, t)!,
+      progressBarBGcolor:
+          Color.lerp(progressBarBGcolor, other.progressBarBGcolor, t)!,
       code: other.code,
       code: other.code,
       callout: other.callout,
       callout: other.callout,
       caption: other.caption,
       caption: other.caption,

+ 2 - 2
frontend/appflowy_flutter/packages/flowy_infra/pubspec.yaml

@@ -13,12 +13,12 @@ dependencies:
   time: '>=2.0.0'
   time: '>=2.0.0'
   uuid: ">=2.2.2"
   uuid: ">=2.2.2"
   textstyle_extensions: '2.0.0-nullsafety'
   textstyle_extensions: '2.0.0-nullsafety'
-  flutter_svg: ^1.1.1
+  flutter_svg: ^2.0.2
 
 
 dev_dependencies:
 dev_dependencies:
   flutter_test:
   flutter_test:
     sdk: flutter
     sdk: flutter
-  flutter_lints: ^2.0.1 
+  flutter_lints: ^2.0.1
 
 
 # For information on the generic Dart part of this file, see the
 # For information on the generic Dart part of this file, see the
 # following page: https://dart.dev/tools/pub/pubspec
 # following page: https://dart.dev/tools/pub/pubspec

+ 0 - 1
frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart

@@ -18,5 +18,4 @@ export 'style_widget/icon_button.dart';
 export 'style_widget/scrolling/styled_scroll_bar.dart';
 export 'style_widget/scrolling/styled_scroll_bar.dart';
 export '/widget/spacing.dart';
 export '/widget/spacing.dart';
 export 'style_widget/scrolling/styled_list.dart';
 export 'style_widget/scrolling/styled_list.dart';
-export 'style_widget/button.dart';
 export 'style_widget/color_picker.dart';
 export 'style_widget/color_picker.dart';

+ 1 - 1
frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart

@@ -138,7 +138,7 @@ class ScrollbarState extends State<StyledScrollbar> {
         // Handle color
         // Handle color
         var handleColor = widget.handleColor ??
         var handleColor = widget.handleColor ??
             (Theme.of(context).brightness == Brightness.dark
             (Theme.of(context).brightness == Brightness.dark
-                ? AFThemeExtension.of(context).greyHover.withOpacity(.2)
+                ? AFThemeExtension.of(context).lightGreyHover
                 : AFThemeExtension.of(context).greyHover);
                 : AFThemeExtension.of(context).greyHover);
         // Track color
         // Track color
         var trackColor = widget.trackColor ??
         var trackColor = widget.trackColor ??

ファイルの差分が大きいため隠しています
+ 317 - 209
frontend/appflowy_flutter/pubspec.lock


+ 12 - 34
frontend/appflowy_flutter/pubspec.yaml

@@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
 version: 0.1.2
 version: 0.1.2
 
 
 environment:
 environment:
-  sdk: ">=2.18.0 <3.0.0"
+  sdk: ">=2.19.0 <3.0.0"
 
 
 # Dependencies specify other packages that your package needs in order to work.
 # Dependencies specify other packages that your package needs in order to work.
 # To automatically upgrade your package dependencies to the latest versions
 # To automatically upgrade your package dependencies to the latest versions
@@ -42,8 +42,7 @@ dependencies:
     git:
     git:
       url: https://github.com/AppFlowy-IO/appflowy-board.git
       url: https://github.com/AppFlowy-IO/appflowy-board.git
       ref: a183c57
       ref: a183c57
-  appflowy_editor:
-    path: packages/appflowy_editor
+  appflowy_editor: ^0.1.4
   appflowy_popover:
   appflowy_popover:
     path: packages/appflowy_popover
     path: packages/appflowy_popover
 
 
@@ -60,22 +59,22 @@ dependencies:
   sized_context: ^1.0.0+1
   sized_context: ^1.0.0+1
   styled_widget: "^0.3.1"
   styled_widget: "^0.3.1"
   expandable: ^5.0.1
   expandable: ^5.0.1
-  flutter_colorpicker: ^0.6.0
+  flutter_colorpicker: ^1.0.3
   package_info_plus: ^1.3.0
   package_info_plus: ^1.3.0
   url_launcher: ^6.0.2
   url_launcher: ^6.0.2
   # file_picker: ^4.2.1
   # file_picker: ^4.2.1
   clipboard: ^0.1.3
   clipboard: ^0.1.3
-  connectivity_plus: ^2.3.6+1
+  connectivity_plus: ^3.0.3
   connectivity_plus_platform_interface: ^1.2.2
   connectivity_plus_platform_interface: ^1.2.2
   easy_localization: ^3.0.0
   easy_localization: ^3.0.0
   textfield_tags: ^2.0.2
   textfield_tags: ^2.0.2
   # The following adds the Cupertino Icons font to your application.
   # The following adds the Cupertino Icons font to your application.
   # Use with the CupertinoIcons class for iOS style icons.
   # Use with the CupertinoIcons class for iOS style icons.
   cupertino_icons: ^1.0.2
   cupertino_icons: ^1.0.2
-  device_info_plus: ^3.2.1
+  device_info_plus: ^4.0.0
   fluttertoast: ^8.0.9
   fluttertoast: ^8.0.9
   table_calendar: ^3.0.5
   table_calendar: ^3.0.5
-  reorderables: ^0.5.1
+  reorderables: ^0.6.0
   linked_scroll_controller: ^0.2.0
   linked_scroll_controller: ^0.2.0
   hotkey_manager: ^0.1.7
   hotkey_manager: ^0.1.7
   fixnum: ^1.0.1
   fixnum: ^1.0.1
@@ -86,7 +85,7 @@ dependencies:
   bloc: ^8.1.0
   bloc: ^8.1.0
   textstyle_extensions: "2.0.0-nullsafety"
   textstyle_extensions: "2.0.0-nullsafety"
   shared_preferences: ^2.0.15
   shared_preferences: ^2.0.15
-  google_fonts: ^3.0.1
+  google_fonts: ^4.0.3
   file_picker: <=5.0.0
   file_picker: <=5.0.0
   percent_indicator: ^4.0.1
   percent_indicator: ^4.0.1
   appflowy_editor_plugins:
   appflowy_editor_plugins:
@@ -96,6 +95,7 @@ dependencies:
   http: ^0.13.5
   http: ^0.13.5
   json_annotation: ^4.7.0
   json_annotation: ^4.7.0
   path: ^1.8.2
   path: ^1.8.2
+  archive: ^3.3.0
 
 
 dev_dependencies:
 dev_dependencies:
   flutter_lints: ^2.0.1
   flutter_lints: ^2.0.1
@@ -164,30 +164,8 @@ flutter:
     - assets/images/common/
     - assets/images/common/
     - assets/images/grid/setting/
     - assets/images/grid/setting/
     - assets/translations/
     - assets/translations/
-  #   - images/a_dot_ham.jpeg
 
 
-  # An image asset can refer to one or more resolution-specific "variants", see
-  # https://flutter.dev/assets-and-images/#resolution-aware.
-
-  # For details regarding adding assets from package dependencies, see
-  # https://flutter.dev/assets-and-images/#from-packages
-
-  # To add custom fonts to your application, add a fonts section here,
-  # in this "flutter" section. Each entry in this list should have a
-  # "family" key with the font family name, and a "fonts" key with a
-  # list giving the asset and other descriptors for the font. For
-  # example:
-  # fonts:
-  #   - family: Schyler
-  #     fonts:
-  #       - asset: fonts/Schyler-Regular.ttf
-  #       - asset: fonts/Schyler-Italic.ttf
-  #         style: italic
-  #   - family: Trajan Pro
-  #     fonts:
-  #       - asset: fonts/TrajanPro.ttf
-  #       - asset: fonts/TrajanPro_Bold.ttf
-  #         weight: 700
-  #
-  # For details regarding fonts from package dependencies,
-  # see https://flutter.dev/custom-fonts/#from-packages
+    # The following assets will be excluded in release.
+    # BEGIN: EXCLUDE_IN_RELEASE
+    - assets/test/workspaces/
+    # END: EXCLUDE_IN_RELEASE

+ 28 - 0
frontend/scripts/flutter_release_build/build_flowy.dart

@@ -0,0 +1,28 @@
+import 'dart:io';
+
+part 'tool.dart';
+
+const excludeTagBegin = 'BEGIN: EXCLUDE_IN_RELEASE';
+const excludeTagEnd = 'END: EXCLUDE_IN_RELEASE';
+
+Future<void> main(List<String> args) async {
+  const help = '''
+A build script that modifies build assets before building the release version of AppFlowy.
+
+args[0]: The directory that contains the AppFlowy git repository. Should be the parent to appflowy_flutter. (absolute path)
+args[1]: The appflowy version to be built (github ref_name).
+''';
+  const numArgs = 2;
+  assert(args.length == numArgs,
+      'Expected ${numArgs}, got ${args.length}. Read the following for instructions about how to use this script.\n\n$help');
+  if (args[0] == '-h' || args[0] == '--help') {
+    stdout.write(help);
+    stdout.flush();
+  }
+  final repositoryRoot = Directory(args[0]);
+  assert(await repositoryRoot.exists(),
+      '$repositoryRoot is an invalid directory. Please try again with a valid directory.\n\n$help');
+  final appVersion = args[1];
+  await _BuildTool(repositoryRoot: repositoryRoot.path, appVersion: appVersion)
+      .run();
+}

+ 115 - 0
frontend/scripts/flutter_release_build/tool.dart

@@ -0,0 +1,115 @@
+part of 'build_flowy.dart';
+
+enum _ScanMode {
+  ignore,
+  target,
+}
+
+enum _ModifyMode {
+  include,
+  exclude,
+}
+
+class _BuildTool {
+  const _BuildTool({
+    required this.repositoryRoot,
+    required this.appVersion,
+  });
+
+  final String repositoryRoot;
+  final String appVersion;
+
+  String get projectRoot =>
+      [repositoryRoot, 'appflowy_flutter'].join(Platform.pathSeparator);
+
+  File get pubspec =>
+      File([projectRoot, 'pubspec.yaml'].join(Platform.pathSeparator));
+
+  Future<String> get _architecture async =>
+      await Process.run('uname', ['-m']).then((value) => value.stdout.trim());
+
+  Future<String> get _commandForOS async {
+    // Check the operating system and CPU architecture
+    var os = Platform.operatingSystem;
+    var arch = Platform.isMacOS ? await _architecture : Platform.localHostname;
+
+    // Determine the appropriate command based on the OS and architecture
+    if (os == 'windows') {
+      return 'cargo make --env APP_VERSION=$appVersion --profile production-windows-x86 appflowy';
+    }
+
+    if (os == 'linux') {
+      return 'cargo make --env APP_VERSION=$appVersion --profile production-linux-x86_64 appflowy';
+    }
+
+    if (os == 'macos') {
+      if (arch == 'x86_64') {
+        return 'cargo make --env APP_VERSION=$appVersion --profile production-mac-x86_64 appflowy';
+      }
+      if (arch == 'arm64') {
+        return 'cargo make --env APP_VERSION=$appVersion --profile production-mac-arm64 appflowy';
+      }
+      throw 'Unsupported CPU architecture: $arch';
+    }
+
+    throw 'Unsupported operating system: $os';
+  }
+
+  /// Scans a file for lines between # BEGIN: EXCLUDE_IN_RELEASE and
+  /// END: EXCLUDE_IN_RELEASE. Will add a comment to remove those assets
+  /// from the build.
+  Future<void> _process_directives(
+    File file, {
+    required _ModifyMode mode,
+  }) async {
+    // Read the contents of the file into a list
+    var lines = await file.readAsLines();
+
+    // Find the lines between BEGIN: EXCLUDE_IN_RELEASE and END: EXCLUDE_IN_RELEASE
+    var scanMode = _ScanMode.ignore;
+    for (var i = 0; i < lines.length; i++) {
+      var line = lines[i];
+      if (line.contains(excludeTagBegin)) {
+        scanMode = _ScanMode.target;
+      } else if (line.contains(excludeTagEnd)) {
+        scanMode = _ScanMode.ignore;
+      } else if (scanMode == _ScanMode.target) {
+        lines[i] = _modify(line, mode: mode);
+      }
+    }
+
+    // Write the modified contents back to the file
+    await file.writeAsString(lines.join('\n'));
+  }
+
+  String _modify(String line, {required _ModifyMode mode}) {
+    switch (mode) {
+      case _ModifyMode.include:
+        return line.split('#').where((element) => element != '#').join();
+      case _ModifyMode.exclude:
+        return '#$line';
+    }
+  }
+
+  Future<void> _build() async {
+    final cwd = Directory.current;
+    Directory.current = repositoryRoot;
+
+    final cmd = await _commandForOS;
+    // Run the command using the Process.run() function
+    // final build = await Process.run('echo', ['hello'], runInShell: true);
+    final build =
+        await Process.start(cmd.split(' ')[0], cmd.split(' ').sublist(1));
+    await stdout.addStream(build.stdout);
+    await stderr.addStream(build.stderr);
+    Directory.current = cwd;
+  }
+
+  Future<void> run() async {
+    final pubspec = this.pubspec;
+
+    await _process_directives(pubspec, mode: _ModifyMode.exclude);
+    await _build();
+    await _process_directives(pubspec, mode: _ModifyMode.include);
+  }
+}

+ 6 - 6
frontend/scripts/install_dev_env/install_linux.sh

@@ -38,9 +38,9 @@ fi
 printMessage "Setting up Flutter"
 printMessage "Setting up Flutter"
 # Get the current Flutter version
 # Get the current Flutter version
 FLUTTER_VERSION=$(flutter --version | grep -oP 'Flutter \K\S+')
 FLUTTER_VERSION=$(flutter --version | grep -oP 'Flutter \K\S+')
-# Check if the current version is 3.3.10
-if [ "$FLUTTER_VERSION" = "3.3.10" ]; then
-    echo "Flutter version is already 3.3.10"
+# Check if the current version is 3.7.5
+if [ "$FLUTTER_VERSION" = "3.7.5" ]; then
+    echo "Flutter version is already 3.7.5"
 else
 else
     # Get the path to the Flutter SDK
     # Get the path to the Flutter SDK
     FLUTTER_PATH=$(which flutter)
     FLUTTER_PATH=$(which flutter)
@@ -49,12 +49,12 @@ else
     current_dir=$(pwd)
     current_dir=$(pwd)
 
 
     cd $FLUTTER_PATH
     cd $FLUTTER_PATH
-    # Use git to checkout version 3.3.10 of Flutter
-    git checkout 3.3.10
+    # Use git to checkout version 3.7.5 of Flutter
+    git checkout 3.7.5
     # Get back to current working directory
     # Get back to current working directory
     cd "$current_dir"
     cd "$current_dir"
 
 
-    echo "Switched to Flutter version 3.3.10"
+    echo "Switched to Flutter version 3.7.5"
 fi
 fi
 
 
 # Enable linux desktop
 # Enable linux desktop

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません